From 92fe3670c716fe6825c4a3055e57398b6059a04b Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Mon, 1 Jan 2024 17:34:04 +0100 Subject: [PATCH 01/68] fix: filename for mip install of modulelist.txt Signed-off-by: Jos Verlinde --- mip/full.json | 56 +++++++++++++++++++++++------------------------ mip/minified.json | 48 ++++++++++++++++++++-------------------- mip/package.json | 30 ------------------------- package.json | 40 ++++++++++++++++----------------- 4 files changed, 72 insertions(+), 102 deletions(-) delete mode 100644 mip/package.json diff --git a/mip/full.json b/mip/full.json index 315071fc0..2865d81f5 100644 --- a/mip/full.json +++ b/mip/full.json @@ -1,30 +1,30 @@ { - "urls": [ - [ - "createstubs.py", - "github:josverl/micropython-stubber/src/stubber/board/createstubs.py" - ], - [ - "createstubs_db.py", - "github:Josverl/micropython-stubber/src/stubber/board/createstubs_db.py" - ], - [ - "createstubs_mem.py", - "github:Josverl/micropython-stubber/src/stubber/board/createstubs_mem.py" - ], - [ - "logging.py", - "github:Josverl/micropython-stubber/src/stubber/board/logging.py" - ], - [ - "modules.txt", - "github:Josverl/micropython-stubber/src/stubber/board/modulelist.txt" - ], - [ - "board_info.csv", - "github:Josverl/micropython-stubber/src/stubber/board/board_info.csv" - ] + "urls": [ + [ + "createstubs.py", + "github:josverl/micropython-stubber/src/stubber/board/createstubs.py" ], - "deps": [], - "version": "1.16.2" -} \ No newline at end of file + [ + "createstubs_db.py", + "github:Josverl/micropython-stubber/src/stubber/board/createstubs_db.py" + ], + [ + "createstubs_mem.py", + "github:Josverl/micropython-stubber/src/stubber/board/createstubs_mem.py" + ], + [ + "logging.py", + "github:Josverl/micropython-stubber/src/stubber/board/logging.py" + ], + [ + "modulelist.txt", + "github:Josverl/micropython-stubber/src/stubber/board/modulelist.txt" + ], + [ + "board_info.csv", + "github:Josverl/micropython-stubber/src/stubber/board/board_info.csv" + ] + ], + "deps": [], + "version": "1.16.2" +} diff --git a/mip/minified.json b/mip/minified.json index b2532f514..5ed419d72 100644 --- a/mip/minified.json +++ b/mip/minified.json @@ -1,26 +1,26 @@ { - "urls": [ - [ - "createstubs.py", - "github:josverl/micropython-stubber/src/stubber/board/createstubs_min.py" - ], - [ - "createstubs_db.py", - "github:Josverl/micropython-stubber/src/stubber/board/createstubs_db_min.py" - ], - [ - "createstubs_mem.py", - "github:Josverl/micropython-stubber/src/stubber/board/createstubs_mem_min.py" - ], - [ - "modules.txt", - "github:Josverl/micropython-stubber/src/stubber/board/modulelist.txt" - ], - [ - "board_info.csv", - "github:Josverl/micropython-stubber/src/stubber/board/board_info.csv" - ] + "urls": [ + [ + "createstubs.py", + "github:josverl/micropython-stubber/src/stubber/board/createstubs_min.py" ], - "deps": [], - "version": "1.16.2" -} \ No newline at end of file + [ + "createstubs_db.py", + "github:Josverl/micropython-stubber/src/stubber/board/createstubs_db_min.py" + ], + [ + "createstubs_mem.py", + "github:Josverl/micropython-stubber/src/stubber/board/createstubs_mem_min.py" + ], + [ + "modulelist.txt", + "github:Josverl/micropython-stubber/src/stubber/board/modulelist.txt" + ], + [ + "board_info.csv", + "github:Josverl/micropython-stubber/src/stubber/board/board_info.csv" + ] + ], + "deps": [], + "version": "1.16.2" +} diff --git a/mip/package.json b/mip/package.json deleted file mode 100644 index f52c054d0..000000000 --- a/mip/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "urls": [ - [ - "createstubs.py", - "github:josverl/micropython-stubber/src/stubber/board/createstubs.py" - ], - [ - "createstubs_db.py", - "github:Josverl/micropython-stubber/src/stubber/board/createstubs_db.py" - ], - [ - "createstubs_mem.py", - "github:Josverl/micropython-stubber/src/stubber/board/createstubs_mem.py" - ], - [ - "logging.py", - "github:Josverl/micropython-stubber/src/stubber/board/logging.py" - ], - [ - "modules.txt", - "github:Josverl/micropython-stubber/src/stubber/board/modulelist.txt" - ], - [ - "board_info.csv", - "github:Josverl/micropython-stubber/src/stubber/board/board_info.csv" - ] - ], - "deps": [], - "version": "1.11.2" -} \ No newline at end of file diff --git a/package.json b/package.json index c4ff276b6..b3f30d5e3 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,22 @@ { - "urls": [ - [ - "createstubs.py", - "github:josverl/micropython-stubber/src/stubber/board/createstubs_min.py" - ], - [ - "createstubs_db.py", - "github:Josverl/micropython-stubber/src/stubber/board/createstubs_db_min.py" - ], - [ - "createstubs_mem.py", - "github:Josverl/micropython-stubber/src/stubber/board/createstubs_mem_min.py" - ], - [ - "modules.txt", - "github:Josverl/micropython-stubber/src/stubber/board/modulelist.txt" - ] + "urls": [ + [ + "createstubs.py", + "github:josverl/micropython-stubber/src/stubber/board/createstubs_min.py" ], - "deps": [], - "version": "1.16.2" -} \ No newline at end of file + [ + "createstubs_db.py", + "github:Josverl/micropython-stubber/src/stubber/board/createstubs_db_min.py" + ], + [ + "createstubs_mem.py", + "github:Josverl/micropython-stubber/src/stubber/board/createstubs_mem_min.py" + ], + [ + "modulelist.txt", + "github:Josverl/micropython-stubber/src/stubber/board/modulelist.txt" + ] + ], + "deps": [], + "version": "1.16.2" +} From c412e8bf6dbf9d1a855b21c5b554234502e25c23 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Mon, 1 Jan 2024 17:52:25 +0100 Subject: [PATCH 02/68] chore: asdd some # type: ignores Signed-off-by: Jos Verlinde --- src/stubber/board/createstubs.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index eeaea1fb7..ec867a17d 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -32,11 +32,10 @@ class Stubber: def __init__(self, path: str = None, firmware_id: str = None): # type: ignore try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = None self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() @@ -477,7 +476,7 @@ def _info(): # type:() -> dict[str, str] machine = ( sys.implementation._machine if "_machine" in dir(sys.implementation) - else os.uname().machine + else os.uname().machine # type: ignore ) info["board"] = machine.strip() info["cpu"] = machine.split("with")[1].strip() @@ -508,10 +507,10 @@ def _info(): # type:() -> dict[str, str] try: # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) + info["build"] = _build(os.uname()[3]) # type: ignore if not info["build"]: # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) + info["build"] = _build(os.uname()[2]) # type: ignore if not info["build"] and ";" in sys.version: # extract build from uname().release if available info["build"] = _build(sys.version.split(";")[1]) @@ -523,7 +522,7 @@ def _info(): # type:() -> dict[str, str] if info["version"] == "" and sys.platform not in ("unix", "win32"): try: - u = os.uname() + u = os.uname() # type: ignore info["version"] = u.release except (IndexError, AttributeError, TypeError): pass From ce39284aab3ab4327cd1523042024078a16f9a9d Mon Sep 17 00:00:00 2001 From: Josverl Date: Mon, 1 Jan 2024 16:55:43 +0000 Subject: [PATCH 03/68] Update mip packages --- mip/v5/createstubs.py | 29 +++++--- mip/v5/createstubs_db.py | 24 +++--- mip/v5/createstubs_db_min.py | 45 ++++++------ mip/v5/createstubs_db_mpy.mpy | Bin 8521 -> 8585 bytes mip/v5/createstubs_lvgl.py | 24 +++--- mip/v5/createstubs_lvgl_min.py | 99 +++++++++++++------------ mip/v5/createstubs_lvgl_mpy.mpy | Bin 7977 -> 8040 bytes mip/v5/createstubs_mem.py | 24 +++--- mip/v5/createstubs_mem_min.py | 45 ++++++------ mip/v5/createstubs_mem_mpy.mpy | Bin 8014 -> 8078 bytes mip/v5/createstubs_min.py | 101 +++++++++++++------------- mip/v5/createstubs_mpy.mpy | Bin 10521 -> 10641 bytes mip/v5/modulelist.txt | 5 ++ mip/v6/createstubs.py | 29 +++++--- mip/v6/createstubs_db.py | 24 +++--- mip/v6/createstubs_db_min.py | 45 ++++++------ mip/v6/createstubs_db_mpy.mpy | Bin 8312 -> 8384 bytes mip/v6/createstubs_lvgl.py | 24 +++--- mip/v6/createstubs_lvgl_min.py | 99 +++++++++++++------------ mip/v6/createstubs_lvgl_mpy.mpy | Bin 7793 -> 7866 bytes mip/v6/createstubs_mem.py | 24 +++--- mip/v6/createstubs_mem_min.py | 45 ++++++------ mip/v6/createstubs_mem_mpy.mpy | Bin 7804 -> 7897 bytes mip/v6/createstubs_min.py | 101 +++++++++++++------------- mip/v6/createstubs_mpy.mpy | Bin 10758 -> 10909 bytes mip/v6/modulelist.txt | 5 ++ src/stubber/board/createstubs_db.py | 11 ++- src/stubber/board/createstubs_lvgl.py | 11 ++- src/stubber/board/createstubs_mem.py | 11 ++- 29 files changed, 455 insertions(+), 370 deletions(-) diff --git a/mip/v5/createstubs.py b/mip/v5/createstubs.py index 8e4714a8c..ec867a17d 100644 --- a/mip/v5/createstubs.py +++ b/mip/v5/createstubs.py @@ -20,7 +20,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.0" +__version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] @@ -32,11 +32,10 @@ class Stubber: def __init__(self, path: str = None, firmware_id: str = None): # type: ignore try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = None self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() @@ -455,15 +454,20 @@ def _info(): # type:() -> dict[str, str] "version": "", "build": "", "ver": "", - "port": "stm32" - if sys.platform.startswith("pyb") - else sys.platform, # port: esp32 / win32 / linux / stm32 + "port": sys.platform, # port: esp32 / win32 / linux / stm32 "board": "GENERIC", "cpu": "", "mpy": "", "arch": "", } ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" try: info["version"] = ".".join([str(n) for n in sys.implementation.version]) except AttributeError: @@ -472,7 +476,7 @@ def _info(): # type:() -> dict[str, str] machine = ( sys.implementation._machine if "_machine" in dir(sys.implementation) - else os.uname().machine + else os.uname().machine # type: ignore ) info["board"] = machine.strip() info["cpu"] = machine.split("with")[1].strip() @@ -503,10 +507,10 @@ def _info(): # type:() -> dict[str, str] try: # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) + info["build"] = _build(os.uname()[3]) # type: ignore if not info["build"]: # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) + info["build"] = _build(os.uname()[2]) # type: ignore if not info["build"] and ";" in sys.version: # extract build from uname().release if available info["build"] = _build(sys.version.split(";")[1]) @@ -518,7 +522,7 @@ def _info(): # type:() -> dict[str, str] if info["version"] == "" and sys.platform not in ("unix", "win32"): try: - u = os.uname() + u = os.uname() # type: ignore info["version"] = u.release except (IndexError, AttributeError, TypeError): pass @@ -715,6 +719,7 @@ def main(): "ak8963", "apa102", "apa106", + "argparse", "array", "asyncio/__init__", "asyncio/core", @@ -763,6 +768,7 @@ def main(): "esp32", "espidf", "espnow", + "ffi", "flashbdev", "framebuf", "freesans20", @@ -799,6 +805,7 @@ def main(): "micropython", "mip", "mip/__init__", + "mip/__main__", "motor", "mpu6500", "mpu9250", @@ -826,6 +833,7 @@ def main(): "queue", "random", "requests", + "requests/__init__", "rp2", "rtch", "samd", @@ -838,6 +846,7 @@ def main(): "stm", "struct", "sys", + "termios", "time", "tpcalib", "uarray", diff --git a/mip/v5/createstubs_db.py b/mip/v5/createstubs_db.py index 0c7225a05..c6c5ecb27 100644 --- a/mip/v5/createstubs_db.py +++ b/mip/v5/createstubs_db.py @@ -18,7 +18,7 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.0 +This variant was generated from createstubs.py by micropython-stubber v1.16.2 """ # Copyright (c) 2019-2023 Jos Verlinde @@ -39,7 +39,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.0" +__version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] @@ -51,11 +51,10 @@ class Stubber: def __init__(self, path: str = None, firmware_id: str = None): # type: ignore try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = None self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() @@ -448,19 +447,26 @@ def _info(): # type:() -> dict[str, str] "version": "", "build": "", "ver": "", - "port": "stm32" if sys.platform.startswith("pyb") else sys.platform, # port: esp32 / win32 / linux / stm32 + "port": sys.platform, # port: esp32 / win32 / linux / stm32 "board": "GENERIC", "cpu": "", "mpy": "", "arch": "", } ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" try: info["version"] = ".".join([str(n) for n in sys.implementation.version]) except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine + machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore info["board"] = machine.strip() info["cpu"] = machine.split("with")[1].strip() info["mpy"] = ( @@ -490,10 +496,10 @@ def _info(): # type:() -> dict[str, str] try: # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) + info["build"] = _build(os.uname()[3]) # type: ignore if not info["build"]: # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) + info["build"] = _build(os.uname()[2]) # type: ignore if not info["build"] and ";" in sys.version: # extract build from uname().release if available info["build"] = _build(sys.version.split(";")[1]) @@ -505,7 +511,7 @@ def _info(): # type:() -> dict[str, str] if info["version"] == "" and sys.platform not in ("unix", "win32"): try: - u = os.uname() + u = os.uname() # type: ignore info["version"] = u.release except (IndexError, AttributeError, TypeError): pass diff --git a/mip/v5/createstubs_db_min.py b/mip/v5/createstubs_db_min.py index 3e0a7370d..34ba0bee4 100644 --- a/mip/v5/createstubs_db_min.py +++ b/mip/v5/createstubs_db_min.py @@ -42,7 +42,7 @@ except P:pass try:from collections import OrderedDict as d except P:from ucollections import OrderedDict as d -__version__='v1.16.0' +__version__='v1.16.2' w=2 x=2 e=[J,'/lib','/sd/lib','/flash/lib','lib'] @@ -190,20 +190,23 @@ def U(s): if A in s:s=s.split(A,1)[0] return s.split('-')[1]if'-'in s else C def _info(): - k='ev3-pybricks';j='pycom';i='pycopy';f='GENERIC';c='arch';b='cpu';a='ver';V='with';G='mpy';F='build';A=d({O:sys.implementation.name,D:C,F:C,a:C,'port':'stm32'if sys.platform.startswith('pyb')else sys.platform,K:f,b:C,G:C,c:C}) + n='ev3-pybricks';m='pycom';l='pycopy';k='unix';j='win32';i='GENERIC';f='arch';c='cpu';b='ver';Y='with';I='mpy';G='port';F='build';A=d({O:sys.implementation.name,D:C,F:C,b:C,G:sys.platform,K:i,c:C,I:C,f:C}) + if A[G].startswith('pyb'):A[G]='stm32' + elif A[G]==j:A[G]='windows' + elif A[G]=='linux':A[G]=k try:A[D]=J.join([W(A)for A in sys.implementation.version]) except H:pass - try:Y=sys.implementation._machine if'_machine'in Q(sys.implementation)else os.uname().machine;A[K]=Y.strip();A[b]=Y.split(V)[1].strip();A[G]=sys.implementation._mpy if'_mpy'in Q(sys.implementation)else sys.implementation.mpy if G in Q(sys.implementation)else C + try:Z=sys.implementation._machine if'_machine'in Q(sys.implementation)else os.uname().machine;A[K]=Z.strip();A[c]=Z.split(Y)[1].strip();A[I]=sys.implementation._mpy if'_mpy'in Q(sys.implementation)else sys.implementation.mpy if I in Q(sys.implementation)else C except(H,R):pass B.collect() - for M in[A+'/board_info.csv'for A in e]: - if h(M): - I=A[K].strip() - if g(A,I,M):break - if V in I: - I=I.split(V)[0].strip() - if g(A,I,M):break - A[K]=f + for N in[A+'/board_info.csv'for A in e]: + if h(N): + M=A[K].strip() + if g(A,M,N):break + if Y in M: + M=M.split(Y)[0].strip() + if g(A,M,N):break + A[K]=i A[K]=A[K].replace(' ',T);B.collect() try: A[F]=U(os.uname()[3]) @@ -211,20 +214,20 @@ def _info(): if not A[F]and';'in sys.version:A[F]=U(sys.version.split(';')[1]) except(H,R):pass if A[F]and L(A[F])>5:A[F]=C - if A[D]==C and sys.platform not in('unix','win32'): - try:l=os.uname();A[D]=l.release + if A[D]==C and sys.platform not in(k,j): + try:o=os.uname();A[D]=o.release except(R,H,TypeError):pass - for(m,n,o)in[(i,i,'const'),(j,j,'FAT'),(k,'pybricks.hubs','EV3Brick')]: - try:p=__import__(n,E,E,o);A[O]=m;del p;break + for(p,q,r)in[(l,l,'const'),(m,m,'FAT'),(n,'pybricks.hubs','EV3Brick')]: + try:s=__import__(q,E,E,r);A[O]=p;del s;break except(P,S):pass - if A[O]==k:A['release']='2.0.0' + if A[O]==n:A['release']='2.0.0' if A[O]==X: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if G in A and A[G]: - N=int(A[G]);Z=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] - if Z:A[c]=Z - A[G]='v{}.{}'.format(N&255,N>>8&3) - A[a]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A + if I in A and A[I]: + V=int(A[I]);a=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] + if a:A[f]=a + A[I]='v{}.{}'.format(V&255,V>>8&3) + A[b]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A def g(info,board_descr,filename): with I(filename,'r')as B: while 1: diff --git a/mip/v5/createstubs_db_mpy.mpy b/mip/v5/createstubs_db_mpy.mpy index d6d2a4ee2e81fe808ba24b1eebbcd21f531357fc..753f589d002fa96e0b3628e4da1d43e4073f46b5 100644 GIT binary patch delta 1022 zcmY*YTWs4@81}K7%d)mR`Ryi6)5z^`+_l=$IJLZ0m5P?SS_xTr64s{_lL> zIsgCrKilayr`~!A4Sh8G2%%I%;g3qj&B8ka)j&31yinRpK9*(q$YD*BM-+x+O&dNq zd~j??8ylW{CUrzkYU2|Vx*V5P`d(=8n7>xcU-|?GR`bQN)C1goZ2I{0i_cAciv9DI zb4#CL@40gAbL_piQ27G;SM$}SZR}kxU;YyN%cV;7D;&tx@`dwX)89hz`Y`Zj4us7d zpu0KPE8=otzIvflS>DL41OI#ue0SJVlfAcdI{L=huq2LRZ~1c0K;|BT11r_#v6Qo6 zr}q=Kc&p`--7K^7rPURe4!SfB6!OK|rIzU<4VUD|OpF6QBlU7iDIS7iMC@kiuH;Ka z9T~`hFufMeoO*a);@&kl2L^41-o9s`HFmtq+_AAg%W8rkGY56FV|Ee{L_zeWWzqy6 z_(b1-SS>9Oh&xRh={;0G%RK^qX-h}uN#a1{>5eJ}e$i3zmM*X)=h&0h$vp+{mQuKf29>CA!t?>vJ}3XVaPj z0v_;49)o+;(ovhFzw{0)GL!-CWr#s+g#X#>AafbSon;PFB*4GGfR0}O!SoUsbWJd7 zfzUE13G5Rm8n;IHo$t(1G85(?EQJkD4JtvgyRuMNm|t0Npv%tmu)TvI(sD!_J<25o z6;x4`W(GNsvf2EyJ0{tzA_6}RNRjjowMPL5_!IVl9{MoSSKnlXdaMsyrk_nfDv?Yi z9UNwPcr4&gx6EhTeKilWkK2wDxFeBd<1)lz!NQ$dLSv4f%;>-Icw+oVb6-0?buGbL z%xE{A9rFxvnwDu1;9g-sM`{Rqu$M0O&7KL}cx zMU&`P`a$#t+NE0mb@V%3?;l4`=x)D){-jc@ggo@M*h%DXd>{J*A&Gt~kDw@hA|F7p JhB6RGe*v=9FP;DZ delta 992 zcmY*YO>7%Q6rP!le@NqW{C16-IL1!9b{m5o+g%ncqz0UcFfO7LyxWEfthh~yr6e{^ z(o$8$6Cxz&2{fvN#Hp8ZrFGLf+opghh4NPDL7b4PN+6+%1LFh=jI^5fzWv_M ze(&vDqc`(!KachErCS)MTRM3{GtLhDN$cI^>g>_l7XDF0o_HjockWDP=%Jwpv+?2V z(4HOHMZX{^b_ixXdIrpPThy=3!hT=vB|~_>OEea zpZbitXX+>hzJDLJ7v2JAkkXC@U4fmnyJDrS<8F`J=VQjD`et*H2VT%-o!I z&&|*5&gR`5JgSF!>$S#wr3GYf1$@ggv@M^D6$5`!2qPdx4NYZ$MhTb)i1AVr%-nnezMQamTwyC!)dj>!FRlkAP zSq}$ARa8$t!rS2Kbn_oHnO8W3owj&kTe5ioeFbFds)1RN%ha10zXtNMvwGD~n1_$c zlTY)@tLto#uWlCR|IqONSoiUk1B#tL*K`0&$|6NwKuRX*py1PdCK@jsl%H-vOpBRl z$udINS+SiJYZN%Rz@@oN^txqif?{W1v?*T~L8=jkaDvRp(vzDm1~S7&!;6J-56mgI#1f{+$6(KpxB-p1tg3AP3jj$cEJH5qWiV+DE%mX}Li=rLS1DCzHy^ zh#y(#Uq6@1{lKY{r=J+_4FMpuIU dict[str, str] "version": "", "build": "", "ver": "", - "port": "stm32" if sys.platform.startswith("pyb") else sys.platform, # port: esp32 / win32 / linux / stm32 + "port": sys.platform, # port: esp32 / win32 / linux / stm32 "board": "GENERIC", "cpu": "", "mpy": "", "arch": "", } ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" try: info["version"] = ".".join([str(n) for n in sys.implementation.version]) except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine + machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore info["board"] = machine.strip() info["cpu"] = machine.split("with")[1].strip() info["mpy"] = ( @@ -475,10 +481,10 @@ def _info(): # type:() -> dict[str, str] try: # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) + info["build"] = _build(os.uname()[3]) # type: ignore if not info["build"]: # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) + info["build"] = _build(os.uname()[2]) # type: ignore if not info["build"] and ";" in sys.version: # extract build from uname().release if available info["build"] = _build(sys.version.split(";")[1]) @@ -490,7 +496,7 @@ def _info(): # type:() -> dict[str, str] if info["version"] == "" and sys.platform not in ("unix", "win32"): try: - u = os.uname() + u = os.uname() # type: ignore info["version"] = u.release except (IndexError, AttributeError, TypeError): pass diff --git a/mip/v5/createstubs_lvgl_min.py b/mip/v5/createstubs_lvgl_min.py index eec6d93d1..69b505b09 100644 --- a/mip/v5/createstubs_lvgl_min.py +++ b/mip/v5/createstubs_lvgl_min.py @@ -22,10 +22,10 @@ Q=KeyError P=IndexError O=dir -N=print -M=ImportError -L=True -K='family' +M=print +N=ImportError +K=True +L='family' J='board' I='.' H=AttributeError @@ -38,10 +38,10 @@ import gc as C,os,sys from ujson import dumps as a try:from machine import reset -except M:pass +except N:pass try:from collections import OrderedDict as b -except M:from ucollections import OrderedDict as b -__version__='v1.16.0' +except N:from ucollections import OrderedDict as b +__version__='v1.16.2' u=2 v=2 w=[I,'/lib','/sd/lib','/flash/lib','lib'] @@ -54,7 +54,7 @@ def __init__(A,path=E,firmware_id=E): except H:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[K]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: @@ -62,7 +62,7 @@ def __init__(A,path=E,firmware_id=E): else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) try:c(path+G) - except F:N('error creating stub folder {}'.format(path)) + except F:M('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] @@ -97,29 +97,29 @@ def create_module_stub(J,module_name,file_name=E): if H is E:O=D.replace(I,S)+'.py';H=J.path+G+O else:O=H.split(G)[-1] if G in D:D=D.replace(G,I) - K=E - try:K=__import__(D,E,E,'*');T=C.mem_free() - except M:return A + L=E + try:L=__import__(D,E,E,'*');T=C.mem_free() + except N:return A c(H) - with V(H,'w')as N:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(N,K,D,B) + with V(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: - try:del K + try:del L except(F,Q):pass try:del sys.modules[D] except Q:pass - C.collect();return L + C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;N='Exception';H=fp;D=indent;C.collect() if O in K.problematic:return S,L=K.get_obj_attributes(O) - if L:N(L) + if L:M(L) for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',M]:continue + if E in['classmethod','staticmethod','BaseException',N]:continue if E[0].isdigit():continue if G==""and R(D)<=v*4: - U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=M + U=B;V=E.endswith(N)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=N A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) @@ -161,11 +161,11 @@ def report(B,filename='modules.json'): G=s.format(B.path,filename);C.collect() try: with V(G,'w')as D: - B.write_json_header(D);E=L + B.write_json_header(D);E=K for H in B._report:B.write_json_node(D,H,E);E=A B.write_json_end(D) I=B._start_free-C.mem_free() - except F:N('Failed to create the report.') + except F:M('Failed to create the report.') def write_json_header(B,f):A='firmware';f.write('{');f.write(a({A:B.info})[1:-1]);f.write(Z);f.write(a({t:{D:__version__},'stubtype':A})[1:-1]);f.write(Z);f.write('"modules" :[\n') def write_json_node(A,f,n,first): if not first:f.write(Z) @@ -181,7 +181,7 @@ def c(path): except F as D: if D.args[0]==u: try:os.mkdir(B) - except F as E:N('failed to create folder {}'.format(B));raise E + except F as E:M('failed to create folder {}'.format(B));raise E C=A+1 def T(s): A=' on ' @@ -189,20 +189,23 @@ def T(s): if A in s:s=s.split(A,1)[0] return s.split('-')[1]if'-'in s else B def _info(): - h='ev3-pybricks';g='pycom';f='pycopy';c='GENERIC';a='arch';Z='cpu';Y='ver';V='with';G='mpy';F='build';A=b({K:sys.implementation.name,D:B,F:B,Y:B,'port':'stm32'if sys.platform.startswith('pyb')else sys.platform,J:c,Z:B,G:B,a:B}) + k='ev3-pybricks';j='pycom';i='pycopy';h='unix';g='win32';f='GENERIC';c='arch';a='cpu';Z='ver';W='with';K='mpy';G='port';F='build';A=b({L:sys.implementation.name,D:B,F:B,Z:B,G:sys.platform,J:f,a:B,K:B,c:B}) + if A[G].startswith('pyb'):A[G]='stm32' + elif A[G]==g:A[G]='windows' + elif A[G]=='linux':A[G]=h try:A[D]=I.join([str(A)for A in sys.implementation.version]) except H:pass - try:W=sys.implementation._machine if'_machine'in O(sys.implementation)else os.uname().machine;A[J]=W.strip();A[Z]=W.split(V)[1].strip();A[G]=sys.implementation._mpy if'_mpy'in O(sys.implementation)else sys.implementation.mpy if G in O(sys.implementation)else B + try:X=sys.implementation._machine if'_machine'in O(sys.implementation)else os.uname().machine;A[J]=X.strip();A[a]=X.split(W)[1].strip();A[K]=sys.implementation._mpy if'_mpy'in O(sys.implementation)else sys.implementation.mpy if K in O(sys.implementation)else B except(H,P):pass C.collect() - for N in[A+'/board_info.csv'for A in w]: - if e(N): - L=A[J].strip() - if d(A,L,N):break - if V in L: - L=L.split(V)[0].strip() - if d(A,L,N):break - A[J]=c + for U in[A+'/board_info.csv'for A in w]: + if e(U): + M=A[J].strip() + if d(A,M,U):break + if W in M: + M=M.split(W)[0].strip() + if d(A,M,U):break + A[J]=f A[J]=A[J].replace(' ',S);C.collect() try: A[F]=T(os.uname()[3]) @@ -210,27 +213,27 @@ def _info(): if not A[F]and';'in sys.version:A[F]=T(sys.version.split(';')[1]) except(H,P):pass if A[F]and R(A[F])>5:A[F]=B - if A[D]==B and sys.platform not in('unix','win32'): - try:i=os.uname();A[D]=i.release + if A[D]==B and sys.platform not in(h,g): + try:m=os.uname();A[D]=m.release except(P,H,TypeError):pass - for(j,k,m)in[(f,f,'const'),(g,g,'FAT'),(h,'pybricks.hubs','EV3Brick')]: - try:n=__import__(k,E,E,m);A[K]=j;del n;break - except(M,Q):pass - if A[K]==h:A['release']='2.0.0' - if A[K]==l: + for(n,o,p)in[(i,i,'const'),(j,j,'FAT'),(k,'pybricks.hubs','EV3Brick')]: + try:q=__import__(o,E,E,p);A[L]=n;del q;break + except(N,Q):pass + if A[L]==k:A['release']='2.0.0' + if A[L]==l: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if G in A and A[G]: - U=int(A[G]);X=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][U>>10] - if X:A[a]=X - A[G]='v{}.{}'.format(U&255,U>>8&3) - A[Y]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A + if K in A and A[K]: + V=int(A[K]);Y=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] + if Y:A[c]=Y + A[K]='v{}.{}'.format(V&255,V>>8&3) + A[Z]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A def d(info,board_descr,filename): with V(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return L + if D==board_descr:info[J]=E;return K return A def get_root(): try:A=os.getcwd() @@ -242,7 +245,7 @@ def get_root(): return B def e(filename): try: - if os.stat(filename)[0]>>14:return L + if os.stat(filename)[0]>>14:return K return A except F:return A def f():sys.exit(1) @@ -256,7 +259,7 @@ def read_path(): return path def g(): try:B=bytes('abc',encoding='utf8');C=g.__module__;return A - except(h,H):return L + except(h,H):return K def main(): D='lvgl' try:import lvgl as A diff --git a/mip/v5/createstubs_lvgl_mpy.mpy b/mip/v5/createstubs_lvgl_mpy.mpy index 20303bcbed0f5a7e3e025d51494baf38f5ddaf54..e44d38a86ce42efb52a0cf26ccd59a4dc8009e40 100644 GIT binary patch delta 1107 zcmY*YO>7%Q6yBMQf9g2y_^o3naV$4svmsXN+Rkd*D3YP>M$Lao!n#ydvEs%dmh3ok zk|v=PPl%8Z5)#!QfjCt~9D1X1f1NBjltTDFzyX7z9*__R)T$Q_hy!C6m9o-kzxn2S zZ@zi+=4$-+_`8#+`_j}s@0eRqym)-li${oab~>NUt$Fb%3!^_!tnA0Hh-j2;SgxS4 zvSOXGpz-pnjqM1Hl;3yGAvCt>`pAO%*vC?l3tBwKuy!T)-hm}YDmy=0Xrw#AVDRXX zXfzm-ISNLjJqLRZ_I5{md*aW;js_#qzW#nS*cDXRJKl~H_T~BP>RsYk$r4ZejTgVm+TJ?h^Y-c4_WQV$CnCeMRgGh2qlJ#F1Xk=4QTO z_r0B^(KPe`*3%$vrvcqgL!(3%a??w*g<^gyeFN}t8f>@tQiYG3X%&5IZW$hd5$nQQ zT0{CiN*s$z`QDhhl}vO}zIeS_BVF9wOkriQM!Rb?apbb|%d1u0M$0u)po0Mc{CLPC z%*8OcrB=zs9WQ1J^D5Gi2|iZz4NrXcsYm!g6HMqxa&+mAhSvG^HRe{5*i-yi;O4<@ z747Lx3Zf)RwnUItzy>zS_7odUh!nca3TtXPlshYY4>+@J?G zfr14r9*ZWtVW_B1vL9OxlsFm&;S>ZQ5W@HM26}oJ31@kPE>Xaf9H{8cpL8pQj#>~L zHbAWEaSHpT{_^z@-upp6Ob2}e_&h#MP~5UxauqYV%=BW$gr?+hGtcb?2?Q-9K1sj1 zNrb_WcBzx2brCA0O@M!Yc=I2}K zdfhV~2R!kV>%=xMfyMZws@r*Q#KMtq#3Vj$+F}6CRrTlU71xjOU#(ClNkcfo8)=}M z6QV(!(QuT9{G$8+oA-tLe%ANb=M%4ovB4vg6?0ENL(Phz8x(|>IZ%<}WvAL+I^%u& zk)ilxpKhVD&%Bu=&hr;8hA&+72rtUs&h^qm+56U`jfebhDz#hTHLfcT)fFcA4Nht} z(M0(h`j-<8-jcVICUf}X=q?-b2hlFe`XlH!_Mv|Yjj#uP4Lx98?HlM%cD20^{l$K5 Wm(kzM9w?v&wi-BzY~|g+H2Md`1V-Ed delta 1070 zcmY*YTWlLe6y2Hii^NXHcQ-bvZQP`eApyI#yDV5jNpUu+<2eIBt9711(lIjbLZ^2 z_ntj-_s-CVLvPHWz{S}e*OXHTy71(T3r`UHLbg;WuDS3y3!~pqr0&5lh-jQ`nBPHD z^`K?ej3(~&XfwCm{T)acCE$j8K%t)5=|gjh~j zR(FWyOuqUlv7IffEPh5TrOMjpq$9UlD9(Su{&4lx#&d8Gu$BXHD+lO$4mu@LDP~s| z%GHuAFk-2!PoH-IF$p(HJ;kw&()lQzD)WAz+(Q?&@cC^!iKJRkg=6Ew)7F8UXnOHwfyW_+OtZ>~c?EZCHqi-vvp~nLHqXoXHeQ&1=nM z0tE0Vpny{`1>u$fcs%_W9O?C(XkN_s{Wg{6}qH>pcB(80$PU-7xmF zQ`BhanodD@o(BpFO6=19lc%KD?&(1}AZunCkd3QpVn1{4eE8gXSvVe$`qpcA1JZ?i z8+ZAAHJW$A9d0o~ErtOeor5Y)I4J*J?qj0P$Mt&JU}K&kbemo9_|Xpgz!O2guwBnA pnqVQXihgDD-VO9SyW@?cKUtqIfc|1fePx8$rtcUs)vb?Y(Lb;aGd=(S diff --git a/mip/v5/createstubs_mem.py b/mip/v5/createstubs_mem.py index edcf495ba..f0dc3b37d 100644 --- a/mip/v5/createstubs_mem.py +++ b/mip/v5/createstubs_mem.py @@ -9,7 +9,7 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.0 +This variant was generated from createstubs.py by micropython-stubber v1.16.2 """ # Copyright (c) 2019-2023 Jos Verlinde @@ -30,7 +30,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.0" +__version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] @@ -42,11 +42,10 @@ class Stubber: def __init__(self, path: str = None, firmware_id: str = None): # type: ignore try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = None self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() @@ -439,19 +438,26 @@ def _info(): # type:() -> dict[str, str] "version": "", "build": "", "ver": "", - "port": "stm32" if sys.platform.startswith("pyb") else sys.platform, # port: esp32 / win32 / linux / stm32 + "port": sys.platform, # port: esp32 / win32 / linux / stm32 "board": "GENERIC", "cpu": "", "mpy": "", "arch": "", } ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" try: info["version"] = ".".join([str(n) for n in sys.implementation.version]) except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine + machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore info["board"] = machine.strip() info["cpu"] = machine.split("with")[1].strip() info["mpy"] = ( @@ -481,10 +487,10 @@ def _info(): # type:() -> dict[str, str] try: # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) + info["build"] = _build(os.uname()[3]) # type: ignore if not info["build"]: # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) + info["build"] = _build(os.uname()[2]) # type: ignore if not info["build"] and ";" in sys.version: # extract build from uname().release if available info["build"] = _build(sys.version.split(";")[1]) @@ -496,7 +502,7 @@ def _info(): # type:() -> dict[str, str] if info["version"] == "" and sys.platform not in ("unix", "win32"): try: - u = os.uname() + u = os.uname() # type: ignore info["version"] = u.release except (IndexError, AttributeError, TypeError): pass diff --git a/mip/v5/createstubs_mem_min.py b/mip/v5/createstubs_mem_min.py index 03e5c7ade..53bc8a3ae 100644 --- a/mip/v5/createstubs_mem_min.py +++ b/mip/v5/createstubs_mem_min.py @@ -41,7 +41,7 @@ except O:pass try:from collections import OrderedDict as d except O:from ucollections import OrderedDict as d -__version__='v1.16.0' +__version__='v1.16.2' v=2 w=2 e=[I,'/lib','/sd/lib','/flash/lib','lib'] @@ -189,20 +189,23 @@ def U(s): if A in s:s=s.split(A,1)[0] return s.split('-')[1]if'-'in s else C def _info(): - k='ev3-pybricks';j='pycom';i='pycopy';f='GENERIC';c='arch';b='cpu';a='ver';V='with';G='mpy';F='build';A=d({M:sys.implementation.name,D:C,F:C,a:C,'port':'stm32'if sys.platform.startswith('pyb')else sys.platform,J:f,b:C,G:C,c:C}) + n='ev3-pybricks';m='pycom';l='pycopy';k='unix';j='win32';i='GENERIC';f='arch';c='cpu';b='ver';Y='with';K='mpy';G='port';F='build';A=d({M:sys.implementation.name,D:C,F:C,b:C,G:sys.platform,J:i,c:C,K:C,f:C}) + if A[G].startswith('pyb'):A[G]='stm32' + elif A[G]==j:A[G]='windows' + elif A[G]=='linux':A[G]=k try:A[D]=I.join([W(A)for A in sys.implementation.version]) except H:pass - try:Y=sys.implementation._machine if'_machine'in P(sys.implementation)else os.uname().machine;A[J]=Y.strip();A[b]=Y.split(V)[1].strip();A[G]=sys.implementation._mpy if'_mpy'in P(sys.implementation)else sys.implementation.mpy if G in P(sys.implementation)else C + try:Z=sys.implementation._machine if'_machine'in P(sys.implementation)else os.uname().machine;A[J]=Z.strip();A[c]=Z.split(Y)[1].strip();A[K]=sys.implementation._mpy if'_mpy'in P(sys.implementation)else sys.implementation.mpy if K in P(sys.implementation)else C except(H,Q):pass B.collect() - for N in[A+'/board_info.csv'for A in e]: - if h(N): - K=A[J].strip() - if g(A,K,N):break - if V in K: - K=K.split(V)[0].strip() - if g(A,K,N):break - A[J]=f + for R in[A+'/board_info.csv'for A in e]: + if h(R): + N=A[J].strip() + if g(A,N,R):break + if Y in N: + N=N.split(Y)[0].strip() + if g(A,N,R):break + A[J]=i A[J]=A[J].replace(' ',T);B.collect() try: A[F]=U(os.uname()[3]) @@ -210,20 +213,20 @@ def _info(): if not A[F]and';'in sys.version:A[F]=U(sys.version.split(';')[1]) except(H,Q):pass if A[F]and L(A[F])>5:A[F]=C - if A[D]==C and sys.platform not in('unix','win32'): - try:l=os.uname();A[D]=l.release + if A[D]==C and sys.platform not in(k,j): + try:o=os.uname();A[D]=o.release except(Q,H,TypeError):pass - for(m,n,o)in[(i,i,'const'),(j,j,'FAT'),(k,'pybricks.hubs','EV3Brick')]: - try:p=__import__(n,E,E,o);A[M]=m;del p;break + for(p,q,r)in[(l,l,'const'),(m,m,'FAT'),(n,'pybricks.hubs','EV3Brick')]: + try:s=__import__(q,E,E,r);A[M]=p;del s;break except(O,S):pass - if A[M]==k:A['release']='2.0.0' + if A[M]==n:A['release']='2.0.0' if A[M]==X: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if G in A and A[G]: - R=int(A[G]);Z=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][R>>10] - if Z:A[c]=Z - A[G]='v{}.{}'.format(R&255,R>>8&3) - A[a]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A + if K in A and A[K]: + V=int(A[K]);a=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] + if a:A[f]=a + A[K]='v{}.{}'.format(V&255,V>>8&3) + A[b]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A def g(info,board_descr,filename): with R(filename,'r')as C: while 1: diff --git a/mip/v5/createstubs_mem_mpy.mpy b/mip/v5/createstubs_mem_mpy.mpy index 16401c210dc2e3dd661dfeb13fadafe8b4f8c8c4..52eb3505c4a3dab35eda34ebdb9761b06eaab28c 100644 GIT binary patch delta 1012 zcmY*YO>7%Q6yDjjy^fQn$Rk7kU#g-h~ zI8M{5DxOdwP=yd^Ilu|Ti6bcebuvV#K+0b^aKRvh#DODKFB}jDX5EUPkw)|0H{bi6 zH+N>=IQZsqH2U$=y9lK=BjTfK`h(Kj57h&?V);y^o9<|uc3{6@XyZDUG{YF%H@0tT z)R-EZeK>VMOB&NNGp078#huqfvBUnga`D_P99S=wr&6Ec-otZG&K*B;=yU8}tSuG3 zz`mvG+Aj8;U9R26{`F$L@Fn)GRL_5f{nbjX{xuHd*NUan-#9;qMjB%vk~~P;c|bSv z(5>KVX|aB$Qd`-|Uj;Fn2l+a`YVv(8Z=!G6mZb^~_Epd4(};9Y99XTdOr_YCof)S5 z@=D7EdwFK3E96_V=UPOjn=UBO`KSQm5w%|^q(lfR14=JXcePk4n<$MK zgq;_|*<*J;QH6KX0)v>%rMGUT(FPCiBG+x~&+(cd$c=+0YLgxck|HT`Mx#xTL007d zphiZbFv6NnPya;el<*yhg&h--rznGg`yS&M#21*3cT9;Vd4jKuNpI@7O?0Z``@!iy zRP=vl7rn|rvNP{D7$8pCz=8+Fg|x_=_xcALY};nr)*+za1+VH&3olzHdH{}4EY3ho znP`)K3f)_pkgl4Zc%Kdo#3$@W`kYS(1{>SFVz2d4i}?8{q!P(Q zlHo8<#A|{0Y>OQ1G??t?hufE<*po=|xf$iUWZ@noVQ`C|NaSCAIx+nt+1t^Ny_66w zZfG}Io1CPqX%UNp@H`hx6c0fk_BqcDE}RTqzGub5dYE{r9%k2U+;jHA#l(e+s<5Dk zhBq2__0VhgF5Ts?(RAN|x30sO=r9;WEDol{%pS_W%mYla_z>Q(nbQ@SMYo*!h=y)E vg-87fK6rP#&A0ZCow`Ee`uwtP?|heUeB*Z<%vamjmDiy^=#>RD;?XK z?&;f{-VsfvGW{7dYDBxm`Hh{amfZvI4eTG>b)5!Asz=6tq`o7SnH$u1e6)I#22PZw z$8J&IMCIgd+Ekn=jUT-u{@U1G+YE#iL0K#UzFdU$Dy@u_FOESmUkE`opzYG^D?WU^MZMOL3Gl_yPX zVHd(qK8Owi$^FVad^nHM`{H_QX5YQo{%{29oH?$Q-gVSYX= zPd3RHmR49NUs@~7pVRRFSnK$_3yPEdy5<6wlv#>AK!z;RKq06FEi{}vBtPATZmruw zbGE5tchPYd?OnjZ3tr7@p-*gc4HWHdn`-iP9;6x(i1d;dg2)J_av<+Y!^EHdBE^T! zMkd&5gR;!t;jlq{n+9ekOCQmu6Q#**>0Yw(ki~f}j6m0P3*En}wp2&QM@ObcT?je( zuq+aWRzOy-@}kan;zC~RjGj2zOc*!aw*b@WFqO(R@t4`26AYb^{-0Jw#%!b(_ZRHB;^LZA$`TB&8b96 zMm%QvOFxsyJYpMG{e2%Nh%E!1y1T*-bGL3Yn*;hl8YYgZ5T-uyW&6-!_1sfCrWqRZ zazk@3I<)!tsndy5r!_QWs9m$QCx&|V>D&`JoqA&eQqNUJe3jvXZcET2*&vrc$A6e& z%l*9UxMEQ6!#{|#dKBLf-{?vFn^@M*;XlODjye3N_`M^8{}x>l13weHBV~-mLS!%Y K%==$IgZ~9a^cmCu diff --git a/mip/v5/createstubs_min.py b/mip/v5/createstubs_min.py index db0387e80..a74db7725 100644 --- a/mip/v5/createstubs_min.py +++ b/mip/v5/createstubs_min.py @@ -25,10 +25,10 @@ Q=KeyError P=IndexError O=dir -N=print -M=ImportError -L=True -K='family' +M=print +N=ImportError +K=True +L='family' J='board' I='.' H=AttributeError @@ -41,10 +41,10 @@ import gc as C,os,sys from ujson import dumps as c try:from machine import reset -except M:pass +except N:pass try:from collections import OrderedDict as d -except M:from ucollections import OrderedDict as d -__version__='v1.16.0' +except N:from ucollections import OrderedDict as d +__version__='v1.16.2' x=2 y=2 z=[I,'/lib','/sd/lib','/flash/lib','lib'] @@ -57,7 +57,7 @@ def __init__(A,path=E,firmware_id=E): except H:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[K]==W:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==W:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: @@ -65,7 +65,7 @@ def __init__(A,path=E,firmware_id=E): else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) try:e(path+G) - except F:N('error creating stub folder {}'.format(path)) + except F:M('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] @@ -100,29 +100,29 @@ def create_module_stub(J,module_name,file_name=E): if H is E:O=D.replace(I,S)+'.py';H=J.path+G+O else:O=H.split(G)[-1] if G in D:D=D.replace(G,I) - K=E - try:K=__import__(D,E,E,'*');T=C.mem_free() - except M:return A + L=E + try:L=__import__(D,E,E,'*');T=C.mem_free() + except N:return A e(H) - with V(H,'w')as N:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(N,K,D,B) + with V(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os',s,t,'gc'}: - try:del K + try:del L except(F,Q):pass try:del sys.modules[D] except Q:pass - C.collect();return L + C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;N='Exception';H=fp;D=indent;C.collect() if O in K.problematic:return S,L=K.get_obj_attributes(O) - if L:N(L) + if L:M(L) for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',M]:continue + if E in['classmethod','staticmethod','BaseException',N]:continue if E[0].isdigit():continue if G==""and R(D)<=y*4: - U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=M + U=B;V=E.endswith(N)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=N A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) @@ -164,11 +164,11 @@ def report(B,filename='modules.json'): G=u.format(B.path,filename);C.collect() try: with V(G,'w')as D: - B.write_json_header(D);E=L + B.write_json_header(D);E=K for H in B._report:B.write_json_node(D,H,E);E=A B.write_json_end(D) I=B._start_free-C.mem_free() - except F:N('Failed to create the report.') + except F:M('Failed to create the report.') def write_json_header(B,f):A='firmware';f.write('{');f.write(c({A:B.info})[1:-1]);f.write(a);f.write(c({v:{D:__version__},'stubtype':A})[1:-1]);f.write(a);f.write('"modules" :[\n') def write_json_node(A,f,n,first): if not first:f.write(a) @@ -184,7 +184,7 @@ def e(path): except F as D: if D.args[0]==x: try:os.mkdir(B) - except F as E:N('failed to create folder {}'.format(B));raise E + except F as E:M('failed to create folder {}'.format(B));raise E C=A+1 def T(s): A=' on ' @@ -192,20 +192,23 @@ def T(s): if A in s:s=s.split(A,1)[0] return s.split('-')[1]if'-'in s else B def _info(): - i='ev3-pybricks';h='pycopy';e='GENERIC';c='arch';a='cpu';Z='ver';V='with';G='mpy';F='build';A=d({K:sys.implementation.name,D:B,F:B,Z:B,'port':'stm32'if sys.platform.startswith(w)else sys.platform,J:e,a:B,G:B,c:B}) + l='ev3-pybricks';k='pycopy';j='unix';i='win32';h='GENERIC';e='arch';c='cpu';a='ver';X='with';K='mpy';G='port';F='build';A=d({L:sys.implementation.name,D:B,F:B,a:B,G:sys.platform,J:h,c:B,K:B,e:B}) + if A[G].startswith(w):A[G]='stm32' + elif A[G]==i:A[G]='windows' + elif A[G]=='linux':A[G]=j try:A[D]=I.join([str(A)for A in sys.implementation.version]) except H:pass - try:X=sys.implementation._machine if'_machine'in O(sys.implementation)else os.uname().machine;A[J]=X.strip();A[a]=X.split(V)[1].strip();A[G]=sys.implementation._mpy if'_mpy'in O(sys.implementation)else sys.implementation.mpy if G in O(sys.implementation)else B + try:Y=sys.implementation._machine if'_machine'in O(sys.implementation)else os.uname().machine;A[J]=Y.strip();A[c]=Y.split(X)[1].strip();A[K]=sys.implementation._mpy if'_mpy'in O(sys.implementation)else sys.implementation.mpy if K in O(sys.implementation)else B except(H,P):pass C.collect() - for N in[A+'/board_info.csv'for A in z]: - if g(N): - L=A[J].strip() - if f(A,L,N):break - if V in L: - L=L.split(V)[0].strip() - if f(A,L,N):break - A[J]=e + for U in[A+'/board_info.csv'for A in z]: + if g(U): + M=A[J].strip() + if f(A,M,U):break + if X in M: + M=M.split(X)[0].strip() + if f(A,M,U):break + A[J]=h A[J]=A[J].replace(' ',S);C.collect() try: A[F]=T(os.uname()[3]) @@ -213,27 +216,27 @@ def _info(): if not A[F]and';'in sys.version:A[F]=T(sys.version.split(';')[1]) except(H,P):pass if A[F]and R(A[F])>5:A[F]=B - if A[D]==B and sys.platform not in('unix','win32'): - try:j=os.uname();A[D]=j.release + if A[D]==B and sys.platform not in(j,i): + try:m=os.uname();A[D]=m.release except(P,H,TypeError):pass - for(k,l,m)in[(h,h,'const'),(b,b,'FAT'),(i,'pybricks.hubs','EV3Brick')]: - try:n=__import__(l,E,E,m);A[K]=k;del n;break - except(M,Q):pass - if A[K]==i:A['release']='2.0.0' - if A[K]==W: + for(n,o,p)in[(k,k,'const'),(b,b,'FAT'),(l,'pybricks.hubs','EV3Brick')]: + try:q=__import__(o,E,E,p);A[L]=n;del q;break + except(N,Q):pass + if A[L]==l:A['release']='2.0.0' + if A[L]==W: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if G in A and A[G]: - U=int(A[G]);Y=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][U>>10] - if Y:A[c]=Y - A[G]='v{}.{}'.format(U&255,U>>8&3) - A[Z]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A + if K in A and A[K]: + V=int(A[K]);Z=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] + if Z:A[e]=Z + A[K]='v{}.{}'.format(V&255,V>>8&3) + A[a]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A def f(info,board_descr,filename): with V(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return L + if D==board_descr:info[J]=E;return K return A def get_root(): try:A=os.getcwd() @@ -245,7 +248,7 @@ def get_root(): return B def g(filename): try: - if os.stat(filename)[0]>>14:return L + if os.stat(filename)[0]>>14:return K return A except F:return A def h():sys.exit(1) @@ -259,8 +262,8 @@ def read_path(): return path def i(): try:B=bytes('abc',encoding='utf8');C=i.__module__;return A - except(j,H):return L -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',W,'mip','mip/__init__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,b,'pye','qrcode','queue','random','requests','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() + except(j,H):return K +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',W,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,b,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() if __name__=='__main__'or i(): try:A0=logging.getLogger(v);logging.basicConfig(level=logging.INFO) except l:pass diff --git a/mip/v5/createstubs_mpy.mpy b/mip/v5/createstubs_mpy.mpy index 28374dcc116b9fcb6b6d541ea5388c25b45d6fa6..c80b70b1cffea2edfe89fe32829ee52753ceefd1 100644 GIT binary patch delta 1336 zcmY+DU2M}<6vut9n;Aq^qDA!U_F(-Ik#jsmH>w&@4Z)&Yb@l$3;8%NI^U zsSwm1+O(lf0^OJGVba7T_Q1mip+La{2{y*YzN9^jZYq1(!=_C_OqwlnJ(37s!=I-vO{~3RXo^yHnE!Bc@dQk85`&0kGl#4w)5=1c5of!*`zDELgjDmyre;j{>(1`S!umHfs|{c0lCqOqge zq5*A8+JWM9*}!%KBWq46RF5o5X6=FjIc>nlVL0ee$A#yqnB$##jiU{V|%MEgg{_JjEy@1WwESRHUNov$EFYrP~jMwlweSrp6 zwa8O)`eN7p1Li0$y3##2!ZbcA&a&gzZmXD+9cY8au)r zEaf}N`>)>>?)p|*x$N&c9)>c@Of2Y2(mqXJkR@5e+4l-f=KQ`DPJ3q??;hfJgLta~JrN{?Qx+kEzdB z1ZMiWuiqNI_jbg_9kQQlsNMHDK?6#u2TLinoT0z2`KGQun^kIe{1yPoX8P6IQNEiz zO9KIqeGBP9sHEhJYO$b@tz;V=3iLp-oxU0v-e9X_)VxwGBTGfeXOOK@noQ-CG-|A- zR5dk2Vx*Tyq>nsD`pE!&6qxQFByohQxm3D6o2`%`GE7DgUiM4H+{{z6TF$6sl*Q#! zlT%6|Lw1mzWEVZx(h0`s{g(A$oSI1on4n#x9lSslvIWSscgbVknpaBg$z(pI6zG}O Y-F7u|sG2EP%8V%mh3!)9_tqBh7vZs%`v3p{ delta 1224 zcmY*YT})e59KYvWS`Z35{BMDk(m^?e5e%h3sj>--auFyW1G?LRiz6+za+8*Jr5%!G za*>!A_X0T&x(5?KlKJApT*u0FI2Yyzem|H@(GXvZ55~AGF(w+Lo&qy^lAHVg|ML6& zKhIh7U!GW1kYg?IL-}Z_P+yKmCd%BwnO#Rr6EJE|pj2 zcXzm}k5)U_TjiFPlK#HYzKOx!Em9Cn&dlB+#+gL=ePTQxPJTcN7Sz=2hr}35EPg}^ zLuobo)HX9!)GiH$zz$drfw&O@v>t*Yi6o-IR3x5^nFR)T!GmO@MhfRsv9?yPQGXQeLP?j01ujl*;dR$RY)Z~{k$5Vb0ZJZp)BAl7ES{m z_+HM_rhG_XcPoxrKY7P2yzCKlumrfZcEf{~m3`zod-!lwWft;tS>0$?HfbPAqSWLS zHL&Sf7ChX%^eNz{Z@Q7}(|Ck^;b(v&`sPiyDCcWa{CHj3jm=%zu5Iqe*B;Q&|5y)c z*K`mA-YZKwAWm5(LLOkh2j@^IHWzz@sewt};3=px*Lj2$#f@~!MnKNdr8=4L5rJ8$M#N=S0w~fVd-{(BP2NP72a< z>NBKpL7i)BZN$4@$xYfonE+O^)gyfVu2hl?N5jGSunwgGUl~tQ1{EN98pVI}yv=S| z>XteMm-xk(^<#Up^n|5LH| zHXn*Xxw<14@Y~SpbU9r*vG9To3gFW_ayOs8RgoXzzuf3fl02u2U!9}e?-3PZYH_x3 z$#=4q0|$PGv*TO&(4Ig3tP?9-8OZ9p@)=FfDzc)1aF!cxR1fUU%E>eE;(euFa!9g4 zb4Yq7KuqT^Ty$QzXckU6pmurbo&#REzjBXnE1TO0pYI-{X^)XBj)NZTE!Oy(IKV`O z-^%rX&YrM#p*!rdwHj?R-ReR=vY)JeG|alHJm?peu3ACAvEQpY&>yVL=0Jb4Nn0G{ zv29y_p>Xw8SBY@0bk&%#94SNW(dxSysU{z>D*LE-j2>q(yQTCo+DS-4jm4AkIhA(N zZuXMBi+yb$b`+%4SeTTg5;MW58X~52FqsT4(i60YdTB3}X&-%@jnyt3@23NVq@%%5 zb0m_YgVaZd2<-WZcy#f=OwWgtbeQvE!I@cgE=))0C_TwAZAD|Ooi?Cxc9yoF3ARd` YQH0&5oyed0i~cRLq6UBFTtf}|2UGuN!2kdN diff --git a/mip/v5/modulelist.txt b/mip/v5/modulelist.txt index 16a92863c..d722c404c 100644 --- a/mip/v5/modulelist.txt +++ b/mip/v5/modulelist.txt @@ -45,6 +45,7 @@ aioespnow ak8963 apa102 apa106 +argparse array asyncio/__init__ asyncio/core @@ -93,6 +94,7 @@ esp esp32 espidf espnow +ffi flashbdev framebuf freesans20 @@ -129,6 +131,7 @@ microWebTemplate micropython mip mip/__init__ +mip/__main__ motor mpu6500 mpu9250 @@ -156,6 +159,7 @@ qrcode queue random requests +requests/__init__ rp2 rtch samd @@ -168,6 +172,7 @@ ssl stm struct sys +termios time tpcalib uarray diff --git a/mip/v6/createstubs.py b/mip/v6/createstubs.py index 8e4714a8c..ec867a17d 100644 --- a/mip/v6/createstubs.py +++ b/mip/v6/createstubs.py @@ -20,7 +20,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.0" +__version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] @@ -32,11 +32,10 @@ class Stubber: def __init__(self, path: str = None, firmware_id: str = None): # type: ignore try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = None self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() @@ -455,15 +454,20 @@ def _info(): # type:() -> dict[str, str] "version": "", "build": "", "ver": "", - "port": "stm32" - if sys.platform.startswith("pyb") - else sys.platform, # port: esp32 / win32 / linux / stm32 + "port": sys.platform, # port: esp32 / win32 / linux / stm32 "board": "GENERIC", "cpu": "", "mpy": "", "arch": "", } ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" try: info["version"] = ".".join([str(n) for n in sys.implementation.version]) except AttributeError: @@ -472,7 +476,7 @@ def _info(): # type:() -> dict[str, str] machine = ( sys.implementation._machine if "_machine" in dir(sys.implementation) - else os.uname().machine + else os.uname().machine # type: ignore ) info["board"] = machine.strip() info["cpu"] = machine.split("with")[1].strip() @@ -503,10 +507,10 @@ def _info(): # type:() -> dict[str, str] try: # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) + info["build"] = _build(os.uname()[3]) # type: ignore if not info["build"]: # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) + info["build"] = _build(os.uname()[2]) # type: ignore if not info["build"] and ";" in sys.version: # extract build from uname().release if available info["build"] = _build(sys.version.split(";")[1]) @@ -518,7 +522,7 @@ def _info(): # type:() -> dict[str, str] if info["version"] == "" and sys.platform not in ("unix", "win32"): try: - u = os.uname() + u = os.uname() # type: ignore info["version"] = u.release except (IndexError, AttributeError, TypeError): pass @@ -715,6 +719,7 @@ def main(): "ak8963", "apa102", "apa106", + "argparse", "array", "asyncio/__init__", "asyncio/core", @@ -763,6 +768,7 @@ def main(): "esp32", "espidf", "espnow", + "ffi", "flashbdev", "framebuf", "freesans20", @@ -799,6 +805,7 @@ def main(): "micropython", "mip", "mip/__init__", + "mip/__main__", "motor", "mpu6500", "mpu9250", @@ -826,6 +833,7 @@ def main(): "queue", "random", "requests", + "requests/__init__", "rp2", "rtch", "samd", @@ -838,6 +846,7 @@ def main(): "stm", "struct", "sys", + "termios", "time", "tpcalib", "uarray", diff --git a/mip/v6/createstubs_db.py b/mip/v6/createstubs_db.py index 0c7225a05..c6c5ecb27 100644 --- a/mip/v6/createstubs_db.py +++ b/mip/v6/createstubs_db.py @@ -18,7 +18,7 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.0 +This variant was generated from createstubs.py by micropython-stubber v1.16.2 """ # Copyright (c) 2019-2023 Jos Verlinde @@ -39,7 +39,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.0" +__version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] @@ -51,11 +51,10 @@ class Stubber: def __init__(self, path: str = None, firmware_id: str = None): # type: ignore try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = None self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() @@ -448,19 +447,26 @@ def _info(): # type:() -> dict[str, str] "version": "", "build": "", "ver": "", - "port": "stm32" if sys.platform.startswith("pyb") else sys.platform, # port: esp32 / win32 / linux / stm32 + "port": sys.platform, # port: esp32 / win32 / linux / stm32 "board": "GENERIC", "cpu": "", "mpy": "", "arch": "", } ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" try: info["version"] = ".".join([str(n) for n in sys.implementation.version]) except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine + machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore info["board"] = machine.strip() info["cpu"] = machine.split("with")[1].strip() info["mpy"] = ( @@ -490,10 +496,10 @@ def _info(): # type:() -> dict[str, str] try: # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) + info["build"] = _build(os.uname()[3]) # type: ignore if not info["build"]: # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) + info["build"] = _build(os.uname()[2]) # type: ignore if not info["build"] and ";" in sys.version: # extract build from uname().release if available info["build"] = _build(sys.version.split(";")[1]) @@ -505,7 +511,7 @@ def _info(): # type:() -> dict[str, str] if info["version"] == "" and sys.platform not in ("unix", "win32"): try: - u = os.uname() + u = os.uname() # type: ignore info["version"] = u.release except (IndexError, AttributeError, TypeError): pass diff --git a/mip/v6/createstubs_db_min.py b/mip/v6/createstubs_db_min.py index 3e0a7370d..34ba0bee4 100644 --- a/mip/v6/createstubs_db_min.py +++ b/mip/v6/createstubs_db_min.py @@ -42,7 +42,7 @@ except P:pass try:from collections import OrderedDict as d except P:from ucollections import OrderedDict as d -__version__='v1.16.0' +__version__='v1.16.2' w=2 x=2 e=[J,'/lib','/sd/lib','/flash/lib','lib'] @@ -190,20 +190,23 @@ def U(s): if A in s:s=s.split(A,1)[0] return s.split('-')[1]if'-'in s else C def _info(): - k='ev3-pybricks';j='pycom';i='pycopy';f='GENERIC';c='arch';b='cpu';a='ver';V='with';G='mpy';F='build';A=d({O:sys.implementation.name,D:C,F:C,a:C,'port':'stm32'if sys.platform.startswith('pyb')else sys.platform,K:f,b:C,G:C,c:C}) + n='ev3-pybricks';m='pycom';l='pycopy';k='unix';j='win32';i='GENERIC';f='arch';c='cpu';b='ver';Y='with';I='mpy';G='port';F='build';A=d({O:sys.implementation.name,D:C,F:C,b:C,G:sys.platform,K:i,c:C,I:C,f:C}) + if A[G].startswith('pyb'):A[G]='stm32' + elif A[G]==j:A[G]='windows' + elif A[G]=='linux':A[G]=k try:A[D]=J.join([W(A)for A in sys.implementation.version]) except H:pass - try:Y=sys.implementation._machine if'_machine'in Q(sys.implementation)else os.uname().machine;A[K]=Y.strip();A[b]=Y.split(V)[1].strip();A[G]=sys.implementation._mpy if'_mpy'in Q(sys.implementation)else sys.implementation.mpy if G in Q(sys.implementation)else C + try:Z=sys.implementation._machine if'_machine'in Q(sys.implementation)else os.uname().machine;A[K]=Z.strip();A[c]=Z.split(Y)[1].strip();A[I]=sys.implementation._mpy if'_mpy'in Q(sys.implementation)else sys.implementation.mpy if I in Q(sys.implementation)else C except(H,R):pass B.collect() - for M in[A+'/board_info.csv'for A in e]: - if h(M): - I=A[K].strip() - if g(A,I,M):break - if V in I: - I=I.split(V)[0].strip() - if g(A,I,M):break - A[K]=f + for N in[A+'/board_info.csv'for A in e]: + if h(N): + M=A[K].strip() + if g(A,M,N):break + if Y in M: + M=M.split(Y)[0].strip() + if g(A,M,N):break + A[K]=i A[K]=A[K].replace(' ',T);B.collect() try: A[F]=U(os.uname()[3]) @@ -211,20 +214,20 @@ def _info(): if not A[F]and';'in sys.version:A[F]=U(sys.version.split(';')[1]) except(H,R):pass if A[F]and L(A[F])>5:A[F]=C - if A[D]==C and sys.platform not in('unix','win32'): - try:l=os.uname();A[D]=l.release + if A[D]==C and sys.platform not in(k,j): + try:o=os.uname();A[D]=o.release except(R,H,TypeError):pass - for(m,n,o)in[(i,i,'const'),(j,j,'FAT'),(k,'pybricks.hubs','EV3Brick')]: - try:p=__import__(n,E,E,o);A[O]=m;del p;break + for(p,q,r)in[(l,l,'const'),(m,m,'FAT'),(n,'pybricks.hubs','EV3Brick')]: + try:s=__import__(q,E,E,r);A[O]=p;del s;break except(P,S):pass - if A[O]==k:A['release']='2.0.0' + if A[O]==n:A['release']='2.0.0' if A[O]==X: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if G in A and A[G]: - N=int(A[G]);Z=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] - if Z:A[c]=Z - A[G]='v{}.{}'.format(N&255,N>>8&3) - A[a]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A + if I in A and A[I]: + V=int(A[I]);a=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] + if a:A[f]=a + A[I]='v{}.{}'.format(V&255,V>>8&3) + A[b]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A def g(info,board_descr,filename): with I(filename,'r')as B: while 1: diff --git a/mip/v6/createstubs_db_mpy.mpy b/mip/v6/createstubs_db_mpy.mpy index b6fe6773ee0033f85004bf2a48c45611c5e1cda8..aad357f4ab29391407bd2ebb7f1e49f59893d1e5 100644 GIT binary patch delta 5153 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 o{^H$3jGMOe!i5uQ%Rs$9!R> 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 diff --git a/mip/v6/createstubs_lvgl.py b/mip/v6/createstubs_lvgl.py index 938a6ff61..68f8a5e7e 100644 --- a/mip/v6/createstubs_lvgl.py +++ b/mip/v6/createstubs_lvgl.py @@ -3,7 +3,7 @@ Note that the stubs can be very large, and it may be best to directly store them on an SD card if your device supports this. -This variant was generated from createstubs.py by micropython-stubber v1.16.0 +This variant was generated from createstubs.py by micropython-stubber v1.16.2 """ # Copyright (c) 2019-2023 Jos Verlinde @@ -24,7 +24,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.0" +__version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] @@ -36,11 +36,10 @@ class Stubber: def __init__(self, path: str = None, firmware_id: str = None): # type: ignore try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = None self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() @@ -433,19 +432,26 @@ def _info(): # type:() -> dict[str, str] "version": "", "build": "", "ver": "", - "port": "stm32" if sys.platform.startswith("pyb") else sys.platform, # port: esp32 / win32 / linux / stm32 + "port": sys.platform, # port: esp32 / win32 / linux / stm32 "board": "GENERIC", "cpu": "", "mpy": "", "arch": "", } ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" try: info["version"] = ".".join([str(n) for n in sys.implementation.version]) except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine + machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore info["board"] = machine.strip() info["cpu"] = machine.split("with")[1].strip() info["mpy"] = ( @@ -475,10 +481,10 @@ def _info(): # type:() -> dict[str, str] try: # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) + info["build"] = _build(os.uname()[3]) # type: ignore if not info["build"]: # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) + info["build"] = _build(os.uname()[2]) # type: ignore if not info["build"] and ";" in sys.version: # extract build from uname().release if available info["build"] = _build(sys.version.split(";")[1]) @@ -490,7 +496,7 @@ def _info(): # type:() -> dict[str, str] if info["version"] == "" and sys.platform not in ("unix", "win32"): try: - u = os.uname() + u = os.uname() # type: ignore info["version"] = u.release except (IndexError, AttributeError, TypeError): pass diff --git a/mip/v6/createstubs_lvgl_min.py b/mip/v6/createstubs_lvgl_min.py index eec6d93d1..69b505b09 100644 --- a/mip/v6/createstubs_lvgl_min.py +++ b/mip/v6/createstubs_lvgl_min.py @@ -22,10 +22,10 @@ Q=KeyError P=IndexError O=dir -N=print -M=ImportError -L=True -K='family' +M=print +N=ImportError +K=True +L='family' J='board' I='.' H=AttributeError @@ -38,10 +38,10 @@ import gc as C,os,sys from ujson import dumps as a try:from machine import reset -except M:pass +except N:pass try:from collections import OrderedDict as b -except M:from ucollections import OrderedDict as b -__version__='v1.16.0' +except N:from ucollections import OrderedDict as b +__version__='v1.16.2' u=2 v=2 w=[I,'/lib','/sd/lib','/flash/lib','lib'] @@ -54,7 +54,7 @@ def __init__(A,path=E,firmware_id=E): except H:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[K]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: @@ -62,7 +62,7 @@ def __init__(A,path=E,firmware_id=E): else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) try:c(path+G) - except F:N('error creating stub folder {}'.format(path)) + except F:M('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] @@ -97,29 +97,29 @@ def create_module_stub(J,module_name,file_name=E): if H is E:O=D.replace(I,S)+'.py';H=J.path+G+O else:O=H.split(G)[-1] if G in D:D=D.replace(G,I) - K=E - try:K=__import__(D,E,E,'*');T=C.mem_free() - except M:return A + L=E + try:L=__import__(D,E,E,'*');T=C.mem_free() + except N:return A c(H) - with V(H,'w')as N:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(N,K,D,B) + with V(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: - try:del K + try:del L except(F,Q):pass try:del sys.modules[D] except Q:pass - C.collect();return L + C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;N='Exception';H=fp;D=indent;C.collect() if O in K.problematic:return S,L=K.get_obj_attributes(O) - if L:N(L) + if L:M(L) for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',M]:continue + if E in['classmethod','staticmethod','BaseException',N]:continue if E[0].isdigit():continue if G==""and R(D)<=v*4: - U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=M + U=B;V=E.endswith(N)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=N A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) @@ -161,11 +161,11 @@ def report(B,filename='modules.json'): G=s.format(B.path,filename);C.collect() try: with V(G,'w')as D: - B.write_json_header(D);E=L + B.write_json_header(D);E=K for H in B._report:B.write_json_node(D,H,E);E=A B.write_json_end(D) I=B._start_free-C.mem_free() - except F:N('Failed to create the report.') + except F:M('Failed to create the report.') def write_json_header(B,f):A='firmware';f.write('{');f.write(a({A:B.info})[1:-1]);f.write(Z);f.write(a({t:{D:__version__},'stubtype':A})[1:-1]);f.write(Z);f.write('"modules" :[\n') def write_json_node(A,f,n,first): if not first:f.write(Z) @@ -181,7 +181,7 @@ def c(path): except F as D: if D.args[0]==u: try:os.mkdir(B) - except F as E:N('failed to create folder {}'.format(B));raise E + except F as E:M('failed to create folder {}'.format(B));raise E C=A+1 def T(s): A=' on ' @@ -189,20 +189,23 @@ def T(s): if A in s:s=s.split(A,1)[0] return s.split('-')[1]if'-'in s else B def _info(): - h='ev3-pybricks';g='pycom';f='pycopy';c='GENERIC';a='arch';Z='cpu';Y='ver';V='with';G='mpy';F='build';A=b({K:sys.implementation.name,D:B,F:B,Y:B,'port':'stm32'if sys.platform.startswith('pyb')else sys.platform,J:c,Z:B,G:B,a:B}) + k='ev3-pybricks';j='pycom';i='pycopy';h='unix';g='win32';f='GENERIC';c='arch';a='cpu';Z='ver';W='with';K='mpy';G='port';F='build';A=b({L:sys.implementation.name,D:B,F:B,Z:B,G:sys.platform,J:f,a:B,K:B,c:B}) + if A[G].startswith('pyb'):A[G]='stm32' + elif A[G]==g:A[G]='windows' + elif A[G]=='linux':A[G]=h try:A[D]=I.join([str(A)for A in sys.implementation.version]) except H:pass - try:W=sys.implementation._machine if'_machine'in O(sys.implementation)else os.uname().machine;A[J]=W.strip();A[Z]=W.split(V)[1].strip();A[G]=sys.implementation._mpy if'_mpy'in O(sys.implementation)else sys.implementation.mpy if G in O(sys.implementation)else B + try:X=sys.implementation._machine if'_machine'in O(sys.implementation)else os.uname().machine;A[J]=X.strip();A[a]=X.split(W)[1].strip();A[K]=sys.implementation._mpy if'_mpy'in O(sys.implementation)else sys.implementation.mpy if K in O(sys.implementation)else B except(H,P):pass C.collect() - for N in[A+'/board_info.csv'for A in w]: - if e(N): - L=A[J].strip() - if d(A,L,N):break - if V in L: - L=L.split(V)[0].strip() - if d(A,L,N):break - A[J]=c + for U in[A+'/board_info.csv'for A in w]: + if e(U): + M=A[J].strip() + if d(A,M,U):break + if W in M: + M=M.split(W)[0].strip() + if d(A,M,U):break + A[J]=f A[J]=A[J].replace(' ',S);C.collect() try: A[F]=T(os.uname()[3]) @@ -210,27 +213,27 @@ def _info(): if not A[F]and';'in sys.version:A[F]=T(sys.version.split(';')[1]) except(H,P):pass if A[F]and R(A[F])>5:A[F]=B - if A[D]==B and sys.platform not in('unix','win32'): - try:i=os.uname();A[D]=i.release + if A[D]==B and sys.platform not in(h,g): + try:m=os.uname();A[D]=m.release except(P,H,TypeError):pass - for(j,k,m)in[(f,f,'const'),(g,g,'FAT'),(h,'pybricks.hubs','EV3Brick')]: - try:n=__import__(k,E,E,m);A[K]=j;del n;break - except(M,Q):pass - if A[K]==h:A['release']='2.0.0' - if A[K]==l: + for(n,o,p)in[(i,i,'const'),(j,j,'FAT'),(k,'pybricks.hubs','EV3Brick')]: + try:q=__import__(o,E,E,p);A[L]=n;del q;break + except(N,Q):pass + if A[L]==k:A['release']='2.0.0' + if A[L]==l: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if G in A and A[G]: - U=int(A[G]);X=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][U>>10] - if X:A[a]=X - A[G]='v{}.{}'.format(U&255,U>>8&3) - A[Y]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A + if K in A and A[K]: + V=int(A[K]);Y=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] + if Y:A[c]=Y + A[K]='v{}.{}'.format(V&255,V>>8&3) + A[Z]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A def d(info,board_descr,filename): with V(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return L + if D==board_descr:info[J]=E;return K return A def get_root(): try:A=os.getcwd() @@ -242,7 +245,7 @@ def get_root(): return B def e(filename): try: - if os.stat(filename)[0]>>14:return L + if os.stat(filename)[0]>>14:return K return A except F:return A def f():sys.exit(1) @@ -256,7 +259,7 @@ def read_path(): return path def g(): try:B=bytes('abc',encoding='utf8');C=g.__module__;return A - except(h,H):return L + except(h,H):return K def main(): D='lvgl' try:import lvgl as A diff --git a/mip/v6/createstubs_lvgl_mpy.mpy b/mip/v6/createstubs_lvgl_mpy.mpy index 7e60951eff93d6af6290a3cbc9486935139513be..43060537acb028889d2046fcd16bbd2938ed2a91 100644 GIT binary patch delta 4671 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 KhYB20+5ZK6%|TZH diff --git a/mip/v6/createstubs_mem.py b/mip/v6/createstubs_mem.py index edcf495ba..f0dc3b37d 100644 --- a/mip/v6/createstubs_mem.py +++ b/mip/v6/createstubs_mem.py @@ -9,7 +9,7 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.0 +This variant was generated from createstubs.py by micropython-stubber v1.16.2 """ # Copyright (c) 2019-2023 Jos Verlinde @@ -30,7 +30,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.0" +__version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] @@ -42,11 +42,10 @@ class Stubber: def __init__(self, path: str = None, firmware_id: str = None): # type: ignore try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = None self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() @@ -439,19 +438,26 @@ def _info(): # type:() -> dict[str, str] "version": "", "build": "", "ver": "", - "port": "stm32" if sys.platform.startswith("pyb") else sys.platform, # port: esp32 / win32 / linux / stm32 + "port": sys.platform, # port: esp32 / win32 / linux / stm32 "board": "GENERIC", "cpu": "", "mpy": "", "arch": "", } ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" try: info["version"] = ".".join([str(n) for n in sys.implementation.version]) except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine + machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore info["board"] = machine.strip() info["cpu"] = machine.split("with")[1].strip() info["mpy"] = ( @@ -481,10 +487,10 @@ def _info(): # type:() -> dict[str, str] try: # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) + info["build"] = _build(os.uname()[3]) # type: ignore if not info["build"]: # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) + info["build"] = _build(os.uname()[2]) # type: ignore if not info["build"] and ";" in sys.version: # extract build from uname().release if available info["build"] = _build(sys.version.split(";")[1]) @@ -496,7 +502,7 @@ def _info(): # type:() -> dict[str, str] if info["version"] == "" and sys.platform not in ("unix", "win32"): try: - u = os.uname() + u = os.uname() # type: ignore info["version"] = u.release except (IndexError, AttributeError, TypeError): pass diff --git a/mip/v6/createstubs_mem_min.py b/mip/v6/createstubs_mem_min.py index 03e5c7ade..53bc8a3ae 100644 --- a/mip/v6/createstubs_mem_min.py +++ b/mip/v6/createstubs_mem_min.py @@ -41,7 +41,7 @@ except O:pass try:from collections import OrderedDict as d except O:from ucollections import OrderedDict as d -__version__='v1.16.0' +__version__='v1.16.2' v=2 w=2 e=[I,'/lib','/sd/lib','/flash/lib','lib'] @@ -189,20 +189,23 @@ def U(s): if A in s:s=s.split(A,1)[0] return s.split('-')[1]if'-'in s else C def _info(): - k='ev3-pybricks';j='pycom';i='pycopy';f='GENERIC';c='arch';b='cpu';a='ver';V='with';G='mpy';F='build';A=d({M:sys.implementation.name,D:C,F:C,a:C,'port':'stm32'if sys.platform.startswith('pyb')else sys.platform,J:f,b:C,G:C,c:C}) + n='ev3-pybricks';m='pycom';l='pycopy';k='unix';j='win32';i='GENERIC';f='arch';c='cpu';b='ver';Y='with';K='mpy';G='port';F='build';A=d({M:sys.implementation.name,D:C,F:C,b:C,G:sys.platform,J:i,c:C,K:C,f:C}) + if A[G].startswith('pyb'):A[G]='stm32' + elif A[G]==j:A[G]='windows' + elif A[G]=='linux':A[G]=k try:A[D]=I.join([W(A)for A in sys.implementation.version]) except H:pass - try:Y=sys.implementation._machine if'_machine'in P(sys.implementation)else os.uname().machine;A[J]=Y.strip();A[b]=Y.split(V)[1].strip();A[G]=sys.implementation._mpy if'_mpy'in P(sys.implementation)else sys.implementation.mpy if G in P(sys.implementation)else C + try:Z=sys.implementation._machine if'_machine'in P(sys.implementation)else os.uname().machine;A[J]=Z.strip();A[c]=Z.split(Y)[1].strip();A[K]=sys.implementation._mpy if'_mpy'in P(sys.implementation)else sys.implementation.mpy if K in P(sys.implementation)else C except(H,Q):pass B.collect() - for N in[A+'/board_info.csv'for A in e]: - if h(N): - K=A[J].strip() - if g(A,K,N):break - if V in K: - K=K.split(V)[0].strip() - if g(A,K,N):break - A[J]=f + for R in[A+'/board_info.csv'for A in e]: + if h(R): + N=A[J].strip() + if g(A,N,R):break + if Y in N: + N=N.split(Y)[0].strip() + if g(A,N,R):break + A[J]=i A[J]=A[J].replace(' ',T);B.collect() try: A[F]=U(os.uname()[3]) @@ -210,20 +213,20 @@ def _info(): if not A[F]and';'in sys.version:A[F]=U(sys.version.split(';')[1]) except(H,Q):pass if A[F]and L(A[F])>5:A[F]=C - if A[D]==C and sys.platform not in('unix','win32'): - try:l=os.uname();A[D]=l.release + if A[D]==C and sys.platform not in(k,j): + try:o=os.uname();A[D]=o.release except(Q,H,TypeError):pass - for(m,n,o)in[(i,i,'const'),(j,j,'FAT'),(k,'pybricks.hubs','EV3Brick')]: - try:p=__import__(n,E,E,o);A[M]=m;del p;break + for(p,q,r)in[(l,l,'const'),(m,m,'FAT'),(n,'pybricks.hubs','EV3Brick')]: + try:s=__import__(q,E,E,r);A[M]=p;del s;break except(O,S):pass - if A[M]==k:A['release']='2.0.0' + if A[M]==n:A['release']='2.0.0' if A[M]==X: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if G in A and A[G]: - R=int(A[G]);Z=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][R>>10] - if Z:A[c]=Z - A[G]='v{}.{}'.format(R&255,R>>8&3) - A[a]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A + if K in A and A[K]: + V=int(A[K]);a=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] + if a:A[f]=a + A[K]='v{}.{}'.format(V&255,V>>8&3) + A[b]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A def g(info,board_descr,filename): with R(filename,'r')as C: while 1: diff --git a/mip/v6/createstubs_mem_mpy.mpy b/mip/v6/createstubs_mem_mpy.mpy index 7720c2497622d41036140df8bc33a9ef3e810d8d..221be26ddffbddd54d3826c558da8fe10998623f 100644 GIT binary patch delta 4773 zcmZ`+Yj7Lab;jaBg73SF=bn4+x#yhwopXQx{OYdKJta1u>2Ljh=?WA1{wM!X>7JZ8e$iGw zb$p^Hk~_~dyWD5bym=w_SBz3qjm#rwrq0{SPaU6_yg2vIOpj|$DE-R8oXWW?cIqux z-B;a5`Xv0hRulHMiNSA)#4f-vaR`tiP65)yB}|YK0Y*rv0Iv|Y02xvyzyTIs6=0Nw zg9034VN8I-q+Ed4NQD67q*8z^sS@A_sTSZUiz{De;SB+fks1Mxvv5LylPsJ%B*1AF zCImRc!dU^%vGAq<=l2V6fe-;ES$Io;DHbjY@HSxuc!zKTTw>wd0$koFz%=m)peF^> zMtH$wSko?;4pJ+aP9xbM2&OC7R9TlT$;7G+($K~}uiZ6t&r zPrG8;iuR3e*vC$aHkpYYi`BBGi|_EiXH%FAB|DW3$*v7aoduh0%OtZE*I#mXw%q9c z9(#>6AHC-OF8iJBC;Glyext1UC|V-uq(v~RSQE{%wb_SyYyy-=7y-6KFz$^JjJrF6 zare<_W~j#{z;=TYm;yo8td5k*D9momVm8=ChED646J_+cgAvStcmy*bk<3>8(EYi= zC{Pa5z?dE*;`jT)qSEQ}cejf@&Ce=bvn#OxSI6&DY@QJU6{}i$W5g4v{9KE1a9Avp znWGps4lZvTHe{ReLKXL{Ouy9}`eR5(hs)_HM%$fF>Yet~lG@LmlWj|4B`@bu6|30!VFDZ# zvY*6FnOG$k&f{=hW@s*PrsGR(UxtIX#VTB)FqDnC1RessSS{9wL}W!SREleB2?zx0 z2zW)0$cJ3Ws<)2mNM>`Di(CY@z?8`w(O^i<`D(oSxmlSROZ=L7xWEr`a2(ByFQ8G5 zwWz8FV>cMitestu?T=!09310J;iin+^E(JMC=8@Nir1h&&wQ!v&TyvlBed!k2M0Jn zV_)F_r;c!t;&WCxmJ$sm~ zg#Bivk({}j%9_D80*#o24r4#6<{+w5Ur}?Td71flnL&S}r_JDt)!>F{V>r0EA(b0T zR4mQ#;KLAR)ShJa&zcT3g3olCUSq`H-tLonTk^}ZC|Qdx;b1yT>G}9|&pM&l2j_Eb)jWNmB z9O{vLftG;J_x$r+E#Y2qb|wE{jx%llsvVr)*zLGtC*WUyNG+hLxv;*X;x*BCP(v6! z^$@@FYuZbeyp9H<4XEK!tbsGhJW}|dfG9g3ZC;OJ?jVHz!Nf3z3hg~TM?jM8yZ1ci z;C0-v8Z&NK6fnbzSEZRiK(Rj&>v&n8$N8E&oat7aAK&JoWf6T#zoHij^hWUZP2An7 zI5Wx7gD6`?Q>UJn=jZ69Yo*rP@sG*OlRDxh&_;v~=i1M;iI_835+~G&9Gq;kZz6pK z=fz0Q551bUprqyG#>A$3Ik=F0U;Ci>Bm`m7++sGETg`1|W9~h!Rp0W6K`__4Fg6(9k&r6Irt zJQ5+$Ngzz1>u$)23)M!6VE#h4V#5L3+#oirYJU$LOciK`O3z&VuP?M80eU0AON1Z2 zt1$iblpqj6vYIOFAs`dz4LQ~VwNkAXy&K@gtvSQP>&p7C1HwJ@tR$eflG&#ub@Dxl zBd~*)=Om)o3k057zXR)vD^n1+tp@~2D2R=Jv|RnfH`&}2iy(%b}rXG4xd6k4<| zjN5@aYNPj#@e8e=z;glbt>y-OEjn;ZV%M}0(Z|aLg%R;O6eJ?mDGuC1-79V{j=jin zT6+@M`Nx}n4(JpAsuop0LyBJX=MnGz4(aRD2+VBpRPIg0T1CAB-B{f_&FrxEO? z3mD@^?MioZTWVL{y7K+Fj9H3#uz>2_6snMb0VI~=T=6Nj%tSs4^XmdEWtiRUVLt0UU49I`hnVk;{=r{ zq5#51Ov9@e=|sE$1;X1oof?N^xdMJA+$Q&yLFs z(5k*U0k3URC}MBN`swCO1`}s^9PNGi{}mTosBsv+8K)QGFdc>i=Jp}uA3Nrvacjq? zif1iB2>PobfpW(CMbq|L>>D7hP~`-?6)@Mw^rQ*ytm>#9i`i(*TdC`&U@4X;Vg z@AY>(vv;K*HXVD`_|WI`wM05QeWHj|cQ_adhPndbuGXFYuloGanx#g%5>hN^zCt+irpQ@hTt7KzD0i)>Ca7c;%9}s zv{J`uTSXFuyJ>Y4IrFPHdWnu+#u3@GstwH1QD4l96^Va2V&l9z?#Ih`*9y2>5yUt9 z!PrT%mxFWEB$-*mrjgpVSB;@xXk)qcryuZ1#a2Lr(jV|U?$8FvV%$m-YzO{i-G23z z#cwd9YE;J)6c*F8w7_NTot~DK&D@S)&Xm)pZ2!-=Nko3_kwLe#wh9pLG{VD&vO^ol z;6HWZjzre9F+_1{528OB_zj`K1N+)Eek zrJ{Q`dFCH@qa=-<;n%bwoJ0be2t0dd^kt z0&0oTjtuegm<2rO?f@&Xo{?gZ@QT72>Mpb9DH6`kl2_Us`8>(AIc7vBInd?^VTZM| z%R!4{fRFjG@sK>l&I19~i3N?L=buamYx`1Q8G8QfwOw`K^kixVvxdA{AR}nuX5T+$ z8LOSOK3FghV%}w~0Xg(9TBb;ieWC5Os3ff>lu9oa*0j%z!eUDM$l%KGD>Hfk8yOop zOkN}7BukEvqvUn+202EKhbkoD##gC8om8jwOLc{tX>x*>CBYB+ZzbXSS66)s439AOSX`90^6~jD|7rA#r9wxp9T~281=K88MiSg zUWWq@A1&lpwfM~$dQoUUq?RJ;(l+$k*(02O&iIe^9)I_aV5|(&?M=mYKh9IU!T8d< zK)b<9_pv0*EX|Pf5sg)3-HTJ9Tycy$q_1~PpTLrX|wK6|C9mrSDR z|LyPY#1{(+&rln`_Z97@FJ!3=`Zqe`WcDH{dCT}8&dX1Mg`(HIUhbmtd#NK7ZjmuX z?_>I6j=n83S5~#xD1}GG7b5!2wWbYHhMBsL@4C0}{h?xez9DTQ9u;|gGubO$n)}kb zPJJf@qZi1x$z?K)Pm=rGC6A8L!6qHu0EfTkh6}X7CbNIxz0OHsd$)8~P;3oF{DBu* zeZ7IOSaP4klEiQqWt(iGEm&jmWfQXH@eP6yGM30O%Q2kac#dL~K0Q0LuFK5s6Ax&u zE1g}RS;u-ePow%!J+VN+1N-=?1)0ItYk0v(5pexdOXRWRrB5^TO;L6siuVd%%eWm? z=R)z-`#YIgCs0Zi_YIpEc&ktD*eLbtzXhkMx+p$2kA|3{sYOj_zZ(_erwl*I G?EeAV_=M#E delta 4716 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 diff --git a/mip/v6/createstubs_min.py b/mip/v6/createstubs_min.py index db0387e80..a74db7725 100644 --- a/mip/v6/createstubs_min.py +++ b/mip/v6/createstubs_min.py @@ -25,10 +25,10 @@ Q=KeyError P=IndexError O=dir -N=print -M=ImportError -L=True -K='family' +M=print +N=ImportError +K=True +L='family' J='board' I='.' H=AttributeError @@ -41,10 +41,10 @@ import gc as C,os,sys from ujson import dumps as c try:from machine import reset -except M:pass +except N:pass try:from collections import OrderedDict as d -except M:from ucollections import OrderedDict as d -__version__='v1.16.0' +except N:from ucollections import OrderedDict as d +__version__='v1.16.2' x=2 y=2 z=[I,'/lib','/sd/lib','/flash/lib','lib'] @@ -57,7 +57,7 @@ def __init__(A,path=E,firmware_id=E): except H:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[K]==W:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==W:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: @@ -65,7 +65,7 @@ def __init__(A,path=E,firmware_id=E): else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) try:e(path+G) - except F:N('error creating stub folder {}'.format(path)) + except F:M('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] @@ -100,29 +100,29 @@ def create_module_stub(J,module_name,file_name=E): if H is E:O=D.replace(I,S)+'.py';H=J.path+G+O else:O=H.split(G)[-1] if G in D:D=D.replace(G,I) - K=E - try:K=__import__(D,E,E,'*');T=C.mem_free() - except M:return A + L=E + try:L=__import__(D,E,E,'*');T=C.mem_free() + except N:return A e(H) - with V(H,'w')as N:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(N,K,D,B) + with V(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os',s,t,'gc'}: - try:del K + try:del L except(F,Q):pass try:del sys.modules[D] except Q:pass - C.collect();return L + C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;N='Exception';H=fp;D=indent;C.collect() if O in K.problematic:return S,L=K.get_obj_attributes(O) - if L:N(L) + if L:M(L) for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',M]:continue + if E in['classmethod','staticmethod','BaseException',N]:continue if E[0].isdigit():continue if G==""and R(D)<=y*4: - U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=M + U=B;V=E.endswith(N)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=N A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) @@ -164,11 +164,11 @@ def report(B,filename='modules.json'): G=u.format(B.path,filename);C.collect() try: with V(G,'w')as D: - B.write_json_header(D);E=L + B.write_json_header(D);E=K for H in B._report:B.write_json_node(D,H,E);E=A B.write_json_end(D) I=B._start_free-C.mem_free() - except F:N('Failed to create the report.') + except F:M('Failed to create the report.') def write_json_header(B,f):A='firmware';f.write('{');f.write(c({A:B.info})[1:-1]);f.write(a);f.write(c({v:{D:__version__},'stubtype':A})[1:-1]);f.write(a);f.write('"modules" :[\n') def write_json_node(A,f,n,first): if not first:f.write(a) @@ -184,7 +184,7 @@ def e(path): except F as D: if D.args[0]==x: try:os.mkdir(B) - except F as E:N('failed to create folder {}'.format(B));raise E + except F as E:M('failed to create folder {}'.format(B));raise E C=A+1 def T(s): A=' on ' @@ -192,20 +192,23 @@ def T(s): if A in s:s=s.split(A,1)[0] return s.split('-')[1]if'-'in s else B def _info(): - i='ev3-pybricks';h='pycopy';e='GENERIC';c='arch';a='cpu';Z='ver';V='with';G='mpy';F='build';A=d({K:sys.implementation.name,D:B,F:B,Z:B,'port':'stm32'if sys.platform.startswith(w)else sys.platform,J:e,a:B,G:B,c:B}) + l='ev3-pybricks';k='pycopy';j='unix';i='win32';h='GENERIC';e='arch';c='cpu';a='ver';X='with';K='mpy';G='port';F='build';A=d({L:sys.implementation.name,D:B,F:B,a:B,G:sys.platform,J:h,c:B,K:B,e:B}) + if A[G].startswith(w):A[G]='stm32' + elif A[G]==i:A[G]='windows' + elif A[G]=='linux':A[G]=j try:A[D]=I.join([str(A)for A in sys.implementation.version]) except H:pass - try:X=sys.implementation._machine if'_machine'in O(sys.implementation)else os.uname().machine;A[J]=X.strip();A[a]=X.split(V)[1].strip();A[G]=sys.implementation._mpy if'_mpy'in O(sys.implementation)else sys.implementation.mpy if G in O(sys.implementation)else B + try:Y=sys.implementation._machine if'_machine'in O(sys.implementation)else os.uname().machine;A[J]=Y.strip();A[c]=Y.split(X)[1].strip();A[K]=sys.implementation._mpy if'_mpy'in O(sys.implementation)else sys.implementation.mpy if K in O(sys.implementation)else B except(H,P):pass C.collect() - for N in[A+'/board_info.csv'for A in z]: - if g(N): - L=A[J].strip() - if f(A,L,N):break - if V in L: - L=L.split(V)[0].strip() - if f(A,L,N):break - A[J]=e + for U in[A+'/board_info.csv'for A in z]: + if g(U): + M=A[J].strip() + if f(A,M,U):break + if X in M: + M=M.split(X)[0].strip() + if f(A,M,U):break + A[J]=h A[J]=A[J].replace(' ',S);C.collect() try: A[F]=T(os.uname()[3]) @@ -213,27 +216,27 @@ def _info(): if not A[F]and';'in sys.version:A[F]=T(sys.version.split(';')[1]) except(H,P):pass if A[F]and R(A[F])>5:A[F]=B - if A[D]==B and sys.platform not in('unix','win32'): - try:j=os.uname();A[D]=j.release + if A[D]==B and sys.platform not in(j,i): + try:m=os.uname();A[D]=m.release except(P,H,TypeError):pass - for(k,l,m)in[(h,h,'const'),(b,b,'FAT'),(i,'pybricks.hubs','EV3Brick')]: - try:n=__import__(l,E,E,m);A[K]=k;del n;break - except(M,Q):pass - if A[K]==i:A['release']='2.0.0' - if A[K]==W: + for(n,o,p)in[(k,k,'const'),(b,b,'FAT'),(l,'pybricks.hubs','EV3Brick')]: + try:q=__import__(o,E,E,p);A[L]=n;del q;break + except(N,Q):pass + if A[L]==l:A['release']='2.0.0' + if A[L]==W: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if G in A and A[G]: - U=int(A[G]);Y=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][U>>10] - if Y:A[c]=Y - A[G]='v{}.{}'.format(U&255,U>>8&3) - A[Z]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A + if K in A and A[K]: + V=int(A[K]);Z=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] + if Z:A[e]=Z + A[K]='v{}.{}'.format(V&255,V>>8&3) + A[a]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A def f(info,board_descr,filename): with V(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return L + if D==board_descr:info[J]=E;return K return A def get_root(): try:A=os.getcwd() @@ -245,7 +248,7 @@ def get_root(): return B def g(filename): try: - if os.stat(filename)[0]>>14:return L + if os.stat(filename)[0]>>14:return K return A except F:return A def h():sys.exit(1) @@ -259,8 +262,8 @@ def read_path(): return path def i(): try:B=bytes('abc',encoding='utf8');C=i.__module__;return A - except(j,H):return L -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',W,'mip','mip/__init__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,b,'pye','qrcode','queue','random','requests','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() + except(j,H):return K +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',W,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,b,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() if __name__=='__main__'or i(): try:A0=logging.getLogger(v);logging.basicConfig(level=logging.INFO) except l:pass diff --git a/mip/v6/createstubs_mpy.mpy b/mip/v6/createstubs_mpy.mpy index f1ada44782f2bf866a217913fd1b6db78e39448c..1794cec8e07c9371e6dfd3181f657f3a018efe2a 100644 GIT binary patch delta 5313 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 delta 5086 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 M dict[str, str] except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine + machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore info["board"] = machine.strip() info["cpu"] = machine.split("with")[1].strip() info["mpy"] = ( @@ -497,10 +496,10 @@ def _info(): # type:() -> dict[str, str] try: # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) + info["build"] = _build(os.uname()[3]) # type: ignore if not info["build"]: # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) + info["build"] = _build(os.uname()[2]) # type: ignore if not info["build"] and ";" in sys.version: # extract build from uname().release if available info["build"] = _build(sys.version.split(";")[1]) @@ -512,7 +511,7 @@ def _info(): # type:() -> dict[str, str] if info["version"] == "" and sys.platform not in ("unix", "win32"): try: - u = os.uname() + u = os.uname() # type: ignore info["version"] = u.release except (IndexError, AttributeError, TypeError): pass diff --git a/src/stubber/board/createstubs_lvgl.py b/src/stubber/board/createstubs_lvgl.py index dc9a0007c..68f8a5e7e 100644 --- a/src/stubber/board/createstubs_lvgl.py +++ b/src/stubber/board/createstubs_lvgl.py @@ -36,11 +36,10 @@ class Stubber: def __init__(self, path: str = None, firmware_id: str = None): # type: ignore try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = None self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() @@ -452,7 +451,7 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine + machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore info["board"] = machine.strip() info["cpu"] = machine.split("with")[1].strip() info["mpy"] = ( @@ -482,10 +481,10 @@ def _info(): # type:() -> dict[str, str] try: # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) + info["build"] = _build(os.uname()[3]) # type: ignore if not info["build"]: # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) + info["build"] = _build(os.uname()[2]) # type: ignore if not info["build"] and ";" in sys.version: # extract build from uname().release if available info["build"] = _build(sys.version.split(";")[1]) @@ -497,7 +496,7 @@ def _info(): # type:() -> dict[str, str] if info["version"] == "" and sys.platform not in ("unix", "win32"): try: - u = os.uname() + u = os.uname() # type: ignore info["version"] = u.release except (IndexError, AttributeError, TypeError): pass diff --git a/src/stubber/board/createstubs_mem.py b/src/stubber/board/createstubs_mem.py index 262d5d37c..f0dc3b37d 100644 --- a/src/stubber/board/createstubs_mem.py +++ b/src/stubber/board/createstubs_mem.py @@ -42,11 +42,10 @@ class Stubber: def __init__(self, path: str = None, firmware_id: str = None): # type: ignore try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = None self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() @@ -458,7 +457,7 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine + machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore info["board"] = machine.strip() info["cpu"] = machine.split("with")[1].strip() info["mpy"] = ( @@ -488,10 +487,10 @@ def _info(): # type:() -> dict[str, str] try: # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) + info["build"] = _build(os.uname()[3]) # type: ignore if not info["build"]: # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) + info["build"] = _build(os.uname()[2]) # type: ignore if not info["build"] and ";" in sys.version: # extract build from uname().release if available info["build"] = _build(sys.version.split(";")[1]) @@ -503,7 +502,7 @@ def _info(): # type:() -> dict[str, str] if info["version"] == "" and sys.platform not in ("unix", "win32"): try: - u = os.uname() + u = os.uname() # type: ignore info["version"] = u.release except (IndexError, AttributeError, TypeError): pass From 53a7098791c7aecaf834198b267c6737a6c807a4 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Mon, 1 Jan 2024 21:10:42 +0100 Subject: [PATCH 04/68] chore: add stubs as dependency Signed-off-by: Jos Verlinde --- requirements-stubs.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 requirements-stubs.txt diff --git a/requirements-stubs.txt b/requirements-stubs.txt new file mode 100644 index 000000000..15a0235dc --- /dev/null +++ b/requirements-stubs.txt @@ -0,0 +1,4 @@ +# install the stusbs using +# pip install -r requirements-stubs.txt -t typings --no-user + +micropython-esp32-stubs From aa806fd287d33e54c32a97f0ae7b6098ef59fe32 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Mon, 1 Jan 2024 21:28:34 +0100 Subject: [PATCH 05/68] update list of board names/Descriptions across versions Signed-off-by: Jos Verlinde --- scripts/get-boardnames.py | 166 ++- src/stubber/data/board_info.csv | 236 ++-- src/stubber/data/board_info.json | 2209 ++++++++++++++++++------------ 3 files changed, 1562 insertions(+), 1049 deletions(-) diff --git a/scripts/get-boardnames.py b/scripts/get-boardnames.py index 4675b5bd0..5edfb1f9a 100644 --- a/scripts/get-boardnames.py +++ b/scripts/get-boardnames.py @@ -1,10 +1,16 @@ -from dataclasses import dataclass, is_dataclass, asdict +""" +Collects board name and description information from MicroPython and writes it to JSON and CSV files. +""" -from pathlib import Path +import json import re +from dataclasses import asdict, dataclass, is_dataclass +from pathlib import Path from typing import List + from tabulate import tabulate -import json + +import stubber.basicgit as git @dataclass @@ -17,44 +23,11 @@ class Board: mcu_name: str description: str path: Path - - -# look for all mpconfigboard.h files and extract the board name -# from the #define MICROPY_HW_BOARD_NAME "PYBD_SF6" -# and the #define MICROPY_HW_MCU_NAME "STM32F767xx" - -mpy_path = Path("repos/micropython") -re_board_name = re.compile(r"#define MICROPY_HW_BOARD_NAME\s+\"(.+)\"") -re_mcu_name = re.compile(r"#define MICROPY_HW_MCU_NAME\s+\"(.+)\"") - - -board_list: List[Board] = [] - -for path in mpy_path.glob("**/mpconfigboard.h"): - board = path.parent.name - port = path.parent.parent.parent.name - with open(path, "r") as f: - board_name = mcu_name = "-" - found = 0 - for line in f: - if match := re_board_name.match(line): - board_name = match[1] - found += 1 - elif match := re_mcu_name.match(line): - mcu_name = match[1] - found += 1 - if found == 2: - break - description = f"{board_name} with {mcu_name}" if mcu_name != "-" else board_name - board_list.append(Board(port, board, board_name, mcu_name, description, path)) - -print(f"Found {len(board_list)} board definitions.") - -print(tabulate(board_list, headers="keys")) # type: ignore + version: str = "" class EnhancedJSONEncoder(json.JSONEncoder): - def default(self, o): + def default(self, o: object): if is_dataclass(o): return asdict(o) elif isinstance(o, Path): @@ -62,12 +35,113 @@ def default(self, o): return super().default(o) -# write the list to json file -with open("src/stubber/data/board_info.json", "w") as f: - json.dump(board_list, f, indent=4, cls=EnhancedJSONEncoder) +# look for all mpconfigboard.h files and extract the board name +# from the #define MICROPY_HW_BOARD_NAME "PYBD_SF6" +# and the #define MICROPY_HW_MCU_NAME "STM32F767xx" + -# create a csv with only the board and the description of the board_list -with open("src/stubber/data/board_info.csv", "w") as f: - f.write("board,description\n") - for board in board_list: - f.write(f"{board.description},{board.board}\n") +RE_BOARD_NAME = re.compile(r"#define MICROPY_HW_BOARD_NAME\s+\"(.+)\"") +RE_MCU_NAME = re.compile(r"#define MICROPY_HW_MCU_NAME\s+\"(.+)\"") + + +def collect_boardinfo(mpy_path: Path, version: str) -> List[Board]: + """Collects board information from mpconfigboard.h files. + + Args: + mpy_path (Path): The path to the MicroPython repository. + version (str): The version of MicroPython. + + Returns: + List[Board]: A list of Board objects containing the board information. + """ + board_list: List[Board] = [] + for path in mpy_path.glob("**/mpconfigboard.h"): + board = path.parent.name + port = path.parent.parent.parent.name + with open(path, "r") as f: + board_name = mcu_name = "-" + found = 0 + for line in f: + if match := RE_BOARD_NAME.match(line): + board_name = match[1] + found += 1 + elif match := RE_MCU_NAME.match(line): + mcu_name = match[1] + found += 1 + if found == 2: + break + description = f"{board_name} with {mcu_name}" if mcu_name != "-" else board_name + board_list.append(Board(port, board, board_name, mcu_name, description, path, version)) + return board_list + + +def write_files(board_list: List[Board], *, folder: Path = Path("src/stubber/data")): + """Writes the board information to JSON and CSV files. + + Args: + board_list (List[Board]): The list of Board objects. + """ + # write the list to json file + with open(folder / "board_info.json", "w") as f: + json.dump(board_list, f, indent=4, cls=EnhancedJSONEncoder) + + # create a csv with only the board and the description of the board_list + with open(folder / "board_info.csv", "w") as f: + f.write("board,description\n") + for board in board_list: + f.write(f"{board.description},{board.board}\n") + + +def get_board_list(versions: List[str], mpy_path: Path): + """Gets the list of boards for multiple versions of MicroPython. + + Args: + versions (List[str]): The list of MicroPython versions. + mpy_path (Path): The path to the MicroPython repository. + + Returns: + List[Board]: The list of Board objects. + """ + board_list: List[Board] = [] + for version in versions: + print(git.checkout_tag(tag=version, repo=mpy_path)) + new_ones = collect_boardinfo(mpy_path, version) + print(f"Found {len(new_ones)} board definitions for {version}.") + board_list += new_ones + + # sort the board_list by description and board + board_list.sort(key=lambda x: (x.description, x.board)) + print("Total number of boards found:", len(board_list)) + seen = set() + board_list = [x for x in board_list if not (x.description in seen or seen.add(x.description))] + print("Unique board descriptions found:", len(board_list)) + return board_list + + +def main(): + """Main function to collect and write board information.""" + mpy_path = Path("repos/micropython") + versions = [ + "v1.22.0", + "v1.21.0", + "v1.20.0", + "v1.19.1", + "v1.18", + "v1.17", + "v1.16", + "v1.15", + "v1.14", + "v1.13", + "v1.12", + "v1.11", + "v1.10", + ] + versions.reverse() + board_list = get_board_list(versions, mpy_path) + + print(tabulate(board_list, headers="keys")) # type: ignore + write_files(board_list) + + +if __name__ == "__main__": + main() diff --git a/src/stubber/data/board_info.csv b/src/stubber/data/board_info.csv index c4d8d6814..e637a33e2 100644 --- a/src/stubber/data/board_info.csv +++ b/src/stubber/data/board_info.csv @@ -1,113 +1,84 @@ board,description -LaunchPad with CC3200,LAUNCHXL -WiPy with CC3200,WIPY -Arduino Nano ESP32 with ESP32S3,ARDUINO_NANO_ESP32 -Generic ESP32 module with ESP32,ESP32_GENERIC -ESP32C3 module with ESP32C3,ESP32_GENERIC_C3 -Generic ESP32S2 module with ESP32S2,ESP32_GENERIC_S2 -Generic ESP32S3 module with ESP32S3,ESP32_GENERIC_S3 -LILYGO TTGO LoRa32 with ESP32,LILYGO_TTGO_LORA32 -LOLIN_C3_MINI with ESP32-C3FH4,LOLIN_C3_MINI -LOLIN_S2_MINI with ESP32-S2FN4R2,LOLIN_S2_MINI -LOLIN_S2_PICO with ESP32-S2FN4R2,LOLIN_S2_PICO -M5Stack ATOM with ESP32-PICO-D4,M5STACK_ATOM -Olimex ESP32 ETH with ESP32,OLIMEX_ESP32_POE -Silicognition wESP32 with ESP32,SIL_WESP32 -FeatherS2 with ESP32-S2,UM_FEATHERS2 -FeatherS2 Neo with ESP32-S2FN4R2,UM_FEATHERS2NEO -FeatherS3 with ESP32-S3,UM_FEATHERS3 -NanoS3 with ESP32-S3-FN8,UM_NANOS3 -ProS3 with ESP32-S3,UM_PROS3 -TinyPICO with ESP32-PICO-D4,UM_TINYPICO -TinyS2 with ESP32-S2FN4R2,UM_TINYS2 -TinyS3 with ESP32-S3-FN8,UM_TINYS3 -ESP module with ESP8266,ESP8266_GENERIC -Adafruit Metro M7 with MIMXRT1011DAE5A,ADAFRUIT_METRO_M7 -i.MX RT1010 EVK with MIMXRT1011DAE5A,MIMXRT1010_EVK -i.MX RT1015 EVK with MIMXRT1015DAF5A,MIMXRT1015_EVK -i.MX RT1020 EVK with MIMXRT1021DAG5A,MIMXRT1020_EVK -i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B,MIMXRT1050_EVK -i.MX RT1060 EVK with MIMXRT1062DVJ6A,MIMXRT1060_EVK -i.MX RT1064 EVK with MIMXRT1064DVL6A,MIMXRT1064_EVK -i.MX RT1170 EVK with MIMXRT1176DVMAA,MIMXRT1170_EVK -RT1010-Py-DevKIT with MIMXRT1011DAE5A,OLIMEX_RT1010 -Seeed ARCH MIX with MIMXRT1052DVL5B,SEEED_ARCH_MIX -Teensy 4.0 with MIMXRT1062DVJ6A,TEENSY40 -Teensy 4.1 with MIMXRT1062DVJ6A,TEENSY41 +4MB/OTA module with ESP32,GENERIC_OTA Actinius Icarus with NRF9160,ACTINIUS_ICARUS +Adafruit Feather RP2040,ADAFRUIT_FEATHER_RP2040 +Adafruit Feather STM32F405 with STM32F405RG,ADAFRUIT_F405_EXPRESS +Adafruit ItsyBitsy RP2040,ADAFRUIT_ITSYBITSY_RP2040 +Adafruit Metro M7 with MIMXRT1011DAE5A,ADAFRUIT_METRO_M7 +Adafruit QT Py RP2040,ADAFRUIT_QTPY_RP2040 +Arduino GIGA R1 WiFi with STM32H747,ARDUINO_GIGA Arduino Nano 33 BLE Sense with NRF52840,ARDUINO_NANO_33_BLE_SENSE +Arduino Nano ESP32 with ESP32S3,ARDUINO_NANO_ESP32 +Arduino Nano RP2040 Connect,ARDUINO_NANO_RP2040_CONNECT +Arduino Nicla Vision with STM32H747,ARDUINO_NICLA_VISION +Arduino Portenta C33 with RA6M5,ARDUINO_PORTENTA_C33 +Arduino Portenta H7 with STM32H747,ARDUINO_PORTENTA_H7 Arduino Primo with NRF52832,ARDUINO_PRIMO +B-L072Z-LRWAN1 with STM32L072CZ,B_L072Z_LRWAN1 +B-L475E-IOT01A with STM32L475,B_L475E_IOT01A BLUEIO-TAG-EVIM with NRF52832,BLUEIO_TAG_EVIM -DVK-BL652 with NRF52832,DVK_BL652 -EVK_NINA_B1 with NRF52832,EVK_NINA_B1 -EVK_NINA_B3 with NRF52840,EVK_NINA_B3 Bluefruit nRF52 Feather with NRF52832,FEATHER52 -IBK-BLYST-NANO with NRF52832,IBK_BLYST_NANO -IDK-BLYST-NANO with NRF52832,IDK_BLYST_NANO -micro:bit with NRF51822,MICROBIT -MDK-USB-DONGLE with NRF52840,NRF52840_MDK_USB_DONGLE -XENON with NRF52840,PARTICLE_XENON -PCA10000 with NRF51822,PCA10000 -PCA10001 with NRF51822,PCA10001 -PCA10028 with NRF51822,PCA10028 -PCA10031 with NRF51822,PCA10031 -PCA10040 with NRF52832,PCA10040 -PCA10056 with NRF52840,PCA10056 -PCA10059 with NRF52840,PCA10059 -PCA10090 with NRF9160,PCA10090 -XIAO nRF52840 Sense with NRF52840,SEEED_XIAO_NRF52 -WT51822-S4AT with NRF51822,WT51822_S4AT -PORTENTA C33 with RA6M5,ARDUINO_PORTENTA_C33 +Cerb40 with STM32F405RG,CERB40 +CustomPCB with STM32F439,STM32F439 +DVK-BL652 with NRF52832,DVK_BL652 EK-RA4M1 with RA4M1,EK_RA4M1 EK-RA4W1 with RA4W1,EK_RA4W1 EK-RA6M1 with RA6M1,EK_RA6M1 EK-RA6M2 with RA6M2,EK_RA6M2 -RA4M1 CLICKER with RA4M1,RA4M1_CLICKER -VK-RA6M5 with RA6M5,VK_RA6M5 -Adafruit Feather RP2040,ADAFRUIT_FEATHER_RP2040 -Adafruit ItsyBitsy RP2040,ADAFRUIT_ITSYBITSY_RP2040 -Adafruit QT Py RP2040,ADAFRUIT_QTPY_RP2040 -Arduino Nano RP2040 Connect,ARDUINO_NANO_RP2040_CONNECT -GARATRONIC_PYBSTICK26_RP2040,GARATRONIC_PYBSTICK26_RP2040 -nullbits Bit-C PRO,NULLBITS_BIT_C_PRO -Pimoroni Pico LiPo 16MB,PIMORONI_PICOLIPO_16MB -Pimoroni Pico LiPo 4MB,PIMORONI_PICOLIPO_4MB -Pimoroni Tiny 2040,PIMORONI_TINY2040 -Raspberry Pi Pico,RPI_PICO -Raspberry Pi Pico W,RPI_PICO_W -SparkFun Pro Micro RP2040,SPARKFUN_PROMICRO -SparkFun Thing Plus RP2040,SPARKFUN_THINGPLUS -W5100S-EVB-Pico,W5100S_EVB_PICO -W5500-EVB-Pico,W5500_EVB_PICO -WeAct Studio RP2040,WEACTSTUDIO +ESP module (1M) with ESP8266,GENERIC_1M +ESP module (512K) with ESP8266,GENERIC_512K +ESP module with ESP8266,ESP8266_GENERIC +ESP32 Unicore module with ESP32-UNICORE,GENERIC_UNICORE +ESP32 module (spiram) with ESP32,GENERIC_SPIRAM +ESP32 module with ESP32,GENERIC +ESP32-S2-WROVER with ESP32-S2,ESP32_S2_WROVER +ESP32C3 module with ESP32C3,ESP32_GENERIC_C3 +ESP32S2 module with ESP32S2,GENERIC_S2 +ESP32S3 module (spiram octal) with ESP32S3,GENERIC_S3_SPIRAM_OCT +ESP32S3 module (spiram) with ESP32S3,GENERIC_S3_SPIRAM +ESP32S3 module with ESP32S3,GENERIC_S3 +EVK_NINA_B1 with NRF52832,EVK_NINA_B1 +EVK_NINA_B3 with NRF52840,EVK_NINA_B3 +Espruino Pico with STM32F401CD,ESPRUINO_PICO +F411DISC with STM32F411,STM32F411DISC +F429I-DISCO with STM32F429,STM32F429DISC +F4DISC with STM32F407,STM32F4DISC +F769DISC with STM32F769,STM32F769DISC +F7DISC with STM32F746,STM32F7DISC Feather M0 Express with SAMD21G18A,ADAFRUIT_FEATHER_M0_EXPRESS Feather M4 Express with SAMD51J19A,ADAFRUIT_FEATHER_M4_EXPRESS -ItsyBitsy M0 Express with SAMD21G18A,ADAFRUIT_ITSYBITSY_M0_EXPRESS -ItsyBitsy M4 Express with SAMD51G19A,ADAFRUIT_ITSYBITSY_M4_EXPRESS -Metro M4 Express Airlift with SAMD51J19A,ADAFRUIT_METRO_M4_EXPRESS -Trinket M0 with SAMD21E18A,ADAFRUIT_TRINKET_M0 -Mini SAM M4 with SAMD51G19A,MINISAM_M4 -SAMD21-XPLAINED-PRO with SAMD21J18A,SAMD21_XPLAINED_PRO -Wio Terminal D51R with SAMD51P19A,SEEED_WIO_TERMINAL -Seeed Xiao with SAMD21G18A,SEEED_XIAO_SAMD21 -Sparkfun SAMD51 Thing Plus with SAMD51J20A,SPARKFUN_SAMD51_THING_PLUS -Adafruit Feather STM32F405 with STM32F405RG,ADAFRUIT_F405_EXPRESS +FeatherS2 Neo with ESP32-S2FN4R2,UM_FEATHERS2NEO +FeatherS2 with ESP32-S2,UM_FEATHERS2 +FeatherS3 with ESP32-S3,UM_FEATHERS3 +GARATRONIC_PYBSTICK26_RP2040,GARATRONIC_PYBSTICK26_RP2040 GIGA with STM32H747,ARDUINO_GIGA -NICLAVISION with STM32H747,ARDUINO_NICLA_VISION -PORTENTA with STM32H747,ARDUINO_PORTENTA_H7 -B-L072Z-LRWAN1 with STM32L072CZ,B_L072Z_LRWAN1 -B-L475E-IOT01A with STM32L475,B_L475E_IOT01A -Cerb40 with STM32F405RG,CERB40 -Espruino Pico with STM32F401CD,ESPRUINO_PICO -NADHAT_PYBF405 with STM32F405RG,GARATRONIC_NADHAT_F405 -PYBSTICK26_STD with STM32F411RE,GARATRONIC_PYBSTICK26_F411 +Generic ESP32 module with ESP32,ESP32_GENERIC +Generic ESP32-D2WD module with ESP32-D2WD,GENERIC_D2WD +Generic ESP32S2 module with ESP32S2,ESP32_GENERIC_S2 +Generic ESP32S3 module with ESP32S3,ESP32_GENERIC_S3 HydraBus1.0 with STM32F4,HYDRABUS +IBK-BLYST-NANO with NRF52832,IBK_BLYST_NANO +IDK-BLYST-NANO with NRF52832,IDK_BLYST_NANO +ItsyBitsy M0 Express with SAMD21G18A,ADAFRUIT_ITSYBITSY_M0_EXPRESS +ItsyBitsy M4 Express with SAMD51G19A,ADAFRUIT_ITSYBITSY_M4_EXPRESS +L476-DISCO with STM32L476,STM32L476DISC +L496G-DISCO with STM32L496,STM32L496GDISC LEGO Technic Hub No.6 with STM32F413,LEGO_HUB_NO6 LEGO Technic Hub No.7 with STM32F413,LEGO_HUB_NO7 +LILYGO TTGO LoRa32 with ESP32,LILYGO_TTGO_LORA32 LIMIFROG with STM32L476,LIMIFROG +LOLIN_C3_MINI with ESP32-C3FH4,LOLIN_C3_MINI +LOLIN_S2_MINI with ESP32-S2FN4R2,LOLIN_S2_MINI +LOLIN_S2_PICO with ESP32-S2FN4R2,LOLIN_S2_PICO +LaunchPad with CC3200,LAUNCHXL +M5Stack ATOM with ESP32-PICO-D4,M5STACK_ATOM +MDK-USB-DONGLE with NRF52840,NRF52840_MDK_USB_DONGLE MIKROE_CLICKER2_STM32 with STM32F407,MIKROE_CLICKER2_STM32 +Metro M4 Express Airlift with SAMD51J19A,ADAFRUIT_METRO_M4_EXPRESS MikroE Quail with STM32F427VI,MIKROE_QUAIL -NetduinoPlus2 with STM32F405RG,NETDUINO_PLUS_2 +Mini SAM M4 with SAMD51G19A,MINISAM_M4 +NADHAT_PYBF405 with STM32F405RG,GARATRONIC_NADHAT_F405 +NICLAVISION with STM32H747,ARDUINO_NICLA_VISION NUCLEO-F091RC with STM32F091RCT6,NUCLEO_F091RC NUCLEO-F401RE with STM32F401xE,NUCLEO_F401RE NUCLEO-F411RE with STM32F411xE,NUCLEO_F411RE @@ -121,10 +92,6 @@ NUCLEO-F746ZG with STM32F746,NUCLEO_F746ZG NUCLEO-F756ZG with STM32F756,NUCLEO_F756ZG NUCLEO-F767ZI with STM32F767,NUCLEO_F767ZI NUCLEO-G0B1RE with STM32G0B1xE,NUCLEO_G0B1RE -NUCLEO_G474RE with STM32G474,NUCLEO_G474RE -NUCLEO_H723ZG with STM32H723ZGT6,NUCLEO_H723ZG -NUCLEO_H743ZI with STM32H743,NUCLEO_H743ZI -NUCLEO_H743ZI2,NUCLEO_H743ZI2 NUCLEO-L073RZ with STM32L073RZT6,NUCLEO_L073RZ NUCLEO-L152RE with STM32L152xE,NUCLEO_L152RE NUCLEO-L432KC with STM32L432KC,NUCLEO_L432KC @@ -133,28 +100,89 @@ NUCLEO-L476RG with STM32L476RG,NUCLEO_L476RG NUCLEO-L4A6ZG with STM32L4A6ZG,NUCLEO_L4A6ZG NUCLEO-WB55 with STM32WB55RGV6,NUCLEO_WB55 NUCLEO-WL55 with STM32WL55JCI7,NUCLEO_WL55 +NUCLEO_G474RE with STM32G474,NUCLEO_G474RE +NUCLEO_H563ZI with STM32H563ZI,NUCLEO_H563ZI +NUCLEO_H723ZG with STM32H723ZGT6,NUCLEO_H723ZG +NUCLEO_H743ZI with STM32H743,NUCLEO_H743ZI +NUCLEO_H743ZI2,NUCLEO_H743ZI2 +NanoS3 with ESP32-S3-FN8,UM_NANOS3 +NetduinoPlus2 with STM32F405RG,NETDUINO_PLUS_2 OLIMEX STM32-E407 with STM32F407,OLIMEX_E407 OLIMEX STM32-H407 with STM32F407,OLIMEX_H407 +Olimex ESP32 ETH with ESP32,OLIMEX_ESP32_POE +PCA10000 with NRF51822,PCA10000 +PCA10001 with NRF51822,PCA10001 +PCA10028 with NRF51822,PCA10028 +PCA10031 with NRF51822,PCA10031 +PCA10040 with NRF52832,PCA10040 +PCA10056 with NRF52840,PCA10056 +PCA10059 with NRF52840,PCA10059 +PCA10090 with NRF9160,PCA10090 +PORTENTA C33 with RA6M5,ARDUINO_PORTENTA_C33 +PORTENTA with STM32H747,ARDUINO_PORTENTA_H7 PYBD-SF2W with STM32F722IEK,PYBD_SF2 PYBD-SF3W with STM32F733IEK,PYBD_SF3 PYBD-SF6W with STM32F767IIK,PYBD_SF6 PYBLITEv1.0 with STM32F411RE,PYBLITEV10 +PYBSTICK26_STD with STM32F411RE,GARATRONIC_PYBSTICK26_F411 PYBv1.0 with STM32F405RG,PYBV10 PYBv1.1 with STM32F405RG,PYBV11 PYBv3 with STM32F405RG,PYBV3 PYBv4 with STM32F405RG,PYBV4 -SparkFun STM32 MicroMod Processor with STM32F405RG,SPARKFUN_MICROMOD_STM32 -F411DISC with STM32F411,STM32F411DISC -F429I-DISCO with STM32F429,STM32F429DISC -CustomPCB with STM32F439,STM32F439 -F4DISC with STM32F407,STM32F4DISC -F769DISC with STM32F769,STM32F769DISC -F7DISC with STM32F746,STM32F7DISC +Pimoroni Pico LiPo 16MB,PIMORONI_PICOLIPO_16MB +Pimoroni Pico LiPo 4MB,PIMORONI_PICOLIPO_4MB +Pimoroni Tiny 2040,PIMORONI_TINY2040 +Pololu 3pi+ 2040 Robot,POLOLU_3PI_2040_ROBOT +Pololu Zumo 2040 Robot,POLOLU_ZUMO_2040_ROBOT +ProS3 with ESP32-S3,UM_PROS3 +RA4M1 CLICKER with RA4M1,RA4M1_CLICKER +RA4M1_CLICKER with RA4M1,RA4M1_CLICKER +RA4M1_EK with RA4M1,RA4M1_EK +RA4W1_EK with RA4W1,RA4W1_EK +RA6M1_EK with RA6M1,RA6M1_EK +RA6M2_EK with RA6M2,RA6M2_EK +RT1010-Py-DevKIT with MIMXRT1011DAE5A,OLIMEX_RT1010 +Raspberry Pi Pico,PICO +Raspberry Pi Pico W,PICO_W +SAMD21-XPLAINED-PRO with SAMD21J18A,SAMD21_XPLAINED_PRO STM32H573I-DK with STM32H573IIK3Q,STM32H573I_DK STM32H7B3I-DK with STM32H7B3LIH6Q,STM32H7B3I_DK -L476-DISCO with STM32L476,STM32L476DISC -L496G-DISCO with STM32L496,STM32L496GDISC +Seeed ARCH MIX with MIMXRT1052DVL5B,SEEED_ARCH_MIX +Seeed Xiao with SAMD21G18A,SEEED_XIAO +Silicognition RP2040-Shim,SIL_RP2040_SHIM +Silicognition wESP32 with ESP32,SIL_WESP32 +SparkFun Pro Micro RP2040,SPARKFUN_PROMICRO +SparkFun STM32 MicroMod Processor with STM32F405RG,SPARKFUN_MICROMOD_STM32 +SparkFun Thing Plus RP2040,SPARKFUN_THINGPLUS +Sparkfun SAMD51 Thing Plus with SAMD51J20A,SPARKFUN_SAMD51_THING_PLUS +Teensy 4.0 with MIMXRT1062DVJ6A,TEENSY40 +Teensy 4.1 with MIMXRT1062DVJ6A,TEENSY41 +TinyPICO with ESP32-PICO-D4,TINYPICO +TinyS2 with ESP32-S2FN4R2,UM_TINYS2 +TinyS3 with ESP32-S3-FN8,UM_TINYS3 +TinyWATCH S3 with ESP32-S3-PICO-1-N8R2,UM_TINYWATCHS3 +Trinket M0 with SAMD21E18A,ADAFRUIT_TRINKET_M0 USBDongle-WB55 with STM32WB55CGU6,USBDONGLE_WB55 VCC-GND STM32F407VE with STM32F407VE,VCC_GND_F407VE VCC-GND STM32F407ZG with STM32F407ZG,VCC_GND_F407ZG VCC-GND STM32H743VI with STM32H743VI,VCC_GND_H743VI +VK-RA6M5 with RA6M5,VK_RA6M5 +W5100S-EVB-Pico,W5100S_EVB_PICO +W5500-EVB-Pico,W5500_EVB_PICO +WT51822-S4AT with NRF51822,WT51822_S4AT +WeAct Studio RP2040,WEACTSTUDIO +WiPy with CC3200,WIPY +Wio Terminal D51R with SAMD51P19A,SEEED_WIO_TERMINAL +XENON with NRF52840,PARTICLE_XENON +XIAO nRF52840 Sense with NRF52840,SEEED_XIAO_NRF52 +i.MX RT1010 EVK with MIMXRT1011DAE5A,MIMXRT1010_EVK +i.MX RT1015 EVK with MIMXRT1015DAF5A,MIMXRT1015_EVK +i.MX RT1020 EVK with MIMXRT1021DAG5A,MIMXRT1020_EVK +i.MX RT1050 EVK with MIMXRT1052DVL6B,MIMXRT1050_EVK +i.MX RT1050 EVKB with MIMXRT1052DVL6B,MIMXRT1050_EVKB +i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B,MIMXRT1050_EVK +i.MX RT1060 EVK with MIMXRT1062DVJ6A,MIMXRT1060_EVK +i.MX RT1064 EVK with MIMXRT1064DVL6A,MIMXRT1064_EVK +i.MX RT1170 EVK with MIMXRT1176DVMAA,MIMXRT1170_EVK +micro:bit with NRF51822,MICROBIT +nullbits Bit-C PRO,NULLBITS_BIT_C_PRO diff --git a/src/stubber/data/board_info.json b/src/stubber/data/board_info.json index 640d848c3..7b2a24aab 100644 --- a/src/stubber/data/board_info.json +++ b/src/stubber/data/board_info.json @@ -1,19 +1,84 @@ [ { - "port": "cc3200", - "board": "LAUNCHXL", - "board_name": "LaunchPad", - "mcu_name": "CC3200", - "description": "LaunchPad with CC3200", - "path": "repos/micropython/ports/cc3200/boards/LAUNCHXL/mpconfigboard.h" + "port": "esp32", + "board": "GENERIC_OTA", + "board_name": "4MB/OTA module", + "mcu_name": "ESP32", + "description": "4MB/OTA module with ESP32", + "path": "repos/micropython/ports/esp32/boards/GENERIC_OTA/mpconfigboard.h", + "version": "v1.13" }, { - "port": "cc3200", - "board": "WIPY", - "board_name": "WiPy", - "mcu_name": "CC3200", - "description": "WiPy with CC3200", - "path": "repos/micropython/ports/cc3200/boards/WIPY/mpconfigboard.h" + "port": "nrf", + "board": "ACTINIUS_ICARUS", + "board_name": "Actinius Icarus", + "mcu_name": "NRF9160", + "description": "Actinius Icarus with NRF9160", + "path": "repos/micropython/ports/nrf/boards/ACTINIUS_ICARUS/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "rp2", + "board": "ADAFRUIT_FEATHER_RP2040", + "board_name": "Adafruit Feather RP2040", + "mcu_name": "-", + "description": "Adafruit Feather RP2040", + "path": "repos/micropython/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h", + "version": "v1.15" + }, + { + "port": "stm32", + "board": "ADAFRUIT_F405_EXPRESS", + "board_name": "Adafruit Feather STM32F405", + "mcu_name": "STM32F405RG", + "description": "Adafruit Feather STM32F405 with STM32F405RG", + "path": "repos/micropython/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h", + "version": "v1.12" + }, + { + "port": "rp2", + "board": "ADAFRUIT_ITSYBITSY_RP2040", + "board_name": "Adafruit ItsyBitsy RP2040", + "mcu_name": "-", + "description": "Adafruit ItsyBitsy RP2040", + "path": "repos/micropython/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h", + "version": "v1.17" + }, + { + "port": "mimxrt", + "board": "ADAFRUIT_METRO_M7", + "board_name": "Adafruit Metro M7", + "mcu_name": "MIMXRT1011DAE5A", + "description": "Adafruit Metro M7 with MIMXRT1011DAE5A", + "path": "repos/micropython/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "rp2", + "board": "ADAFRUIT_QTPY_RP2040", + "board_name": "Adafruit QT Py RP2040", + "mcu_name": "-", + "description": "Adafruit QT Py RP2040", + "path": "repos/micropython/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h", + "version": "v1.17" + }, + { + "port": "stm32", + "board": "ARDUINO_GIGA", + "board_name": "Arduino GIGA R1 WiFi", + "mcu_name": "STM32H747", + "description": "Arduino GIGA R1 WiFi with STM32H747", + "path": "repos/micropython/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h", + "version": "v1.22.0" + }, + { + "port": "nrf", + "board": "ARDUINO_NANO_33_BLE_SENSE", + "board_name": "Arduino Nano 33 BLE Sense", + "mcu_name": "NRF52840", + "description": "Arduino Nano 33 BLE Sense with NRF52840", + "path": "repos/micropython/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.h", + "version": "v1.21.0" }, { "port": "esp32", @@ -21,159 +86,170 @@ "board_name": "Arduino Nano ESP32", "mcu_name": "ESP32S3", "description": "Arduino Nano ESP32 with ESP32S3", - "path": "repos/micropython/ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.h" + "path": "repos/micropython/ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "esp32", - "board": "ESP32_GENERIC", - "board_name": "Generic ESP32 module", - "mcu_name": "ESP32", - "description": "Generic ESP32 module with ESP32", - "path": "repos/micropython/ports/esp32/boards/ESP32_GENERIC/mpconfigboard.h" - }, - { - "port": "esp32", - "board": "ESP32_GENERIC_C3", - "board_name": "ESP32C3 module", - "mcu_name": "ESP32C3", - "description": "ESP32C3 module with ESP32C3", - "path": "repos/micropython/ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.h" + "port": "rp2", + "board": "ARDUINO_NANO_RP2040_CONNECT", + "board_name": "Arduino Nano RP2040 Connect", + "mcu_name": "-", + "description": "Arduino Nano RP2040 Connect", + "path": "repos/micropython/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h", + "version": "v1.18" }, { - "port": "esp32", - "board": "ESP32_GENERIC_S2", - "board_name": "Generic ESP32S2 module", - "mcu_name": "ESP32S2", - "description": "Generic ESP32S2 module with ESP32S2", - "path": "repos/micropython/ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.h" + "port": "stm32", + "board": "ARDUINO_NICLA_VISION", + "board_name": "Arduino Nicla Vision", + "mcu_name": "STM32H747", + "description": "Arduino Nicla Vision with STM32H747", + "path": "repos/micropython/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h", + "version": "v1.22.0" }, { - "port": "esp32", - "board": "ESP32_GENERIC_S3", - "board_name": "Generic ESP32S3 module", - "mcu_name": "ESP32S3", - "description": "Generic ESP32S3 module with ESP32S3", - "path": "repos/micropython/ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.h" + "port": "renesas-ra", + "board": "ARDUINO_PORTENTA_C33", + "board_name": "Arduino Portenta C33", + "mcu_name": "RA6M5", + "description": "Arduino Portenta C33 with RA6M5", + "path": "repos/micropython/ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/mpconfigboard.h", + "version": "v1.22.0" }, { - "port": "esp32", - "board": "LILYGO_TTGO_LORA32", - "board_name": "LILYGO TTGO LoRa32", - "mcu_name": "ESP32", - "description": "LILYGO TTGO LoRa32 with ESP32", - "path": "repos/micropython/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.h" + "port": "stm32", + "board": "ARDUINO_PORTENTA_H7", + "board_name": "Arduino Portenta H7", + "mcu_name": "STM32H747", + "description": "Arduino Portenta H7 with STM32H747", + "path": "repos/micropython/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h", + "version": "v1.22.0" }, { - "port": "esp32", - "board": "LOLIN_C3_MINI", - "board_name": "LOLIN_C3_MINI", - "mcu_name": "ESP32-C3FH4", - "description": "LOLIN_C3_MINI with ESP32-C3FH4", - "path": "repos/micropython/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.h" + "port": "nrf", + "board": "ARDUINO_PRIMO", + "board_name": "Arduino Primo", + "mcu_name": "NRF52832", + "description": "Arduino Primo with NRF52832", + "path": "repos/micropython/ports/nrf/boards/ARDUINO_PRIMO/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "esp32", - "board": "LOLIN_S2_MINI", - "board_name": "LOLIN_S2_MINI", - "mcu_name": "ESP32-S2FN4R2", - "description": "LOLIN_S2_MINI with ESP32-S2FN4R2", - "path": "repos/micropython/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.h" + "port": "stm32", + "board": "B_L072Z_LRWAN1", + "board_name": "B-L072Z-LRWAN1", + "mcu_name": "STM32L072CZ", + "description": "B-L072Z-LRWAN1 with STM32L072CZ", + "path": "repos/micropython/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h", + "version": "v1.12" }, { - "port": "esp32", - "board": "LOLIN_S2_PICO", - "board_name": "LOLIN_S2_PICO", - "mcu_name": "ESP32-S2FN4R2", - "description": "LOLIN_S2_PICO with ESP32-S2FN4R2", - "path": "repos/micropython/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h" + "port": "stm32", + "board": "B_L475E_IOT01A", + "board_name": "B-L475E-IOT01A", + "mcu_name": "STM32L475", + "description": "B-L475E-IOT01A with STM32L475", + "path": "repos/micropython/ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.h", + "version": "v1.10" }, { - "port": "esp32", - "board": "M5STACK_ATOM", - "board_name": "M5Stack ATOM", - "mcu_name": "ESP32-PICO-D4", - "description": "M5Stack ATOM with ESP32-PICO-D4", - "path": "repos/micropython/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.h" + "port": "nrf", + "board": "BLUEIO_TAG_EVIM", + "board_name": "BLUEIO-TAG-EVIM", + "mcu_name": "NRF52832", + "description": "BLUEIO-TAG-EVIM with NRF52832", + "path": "repos/micropython/ports/nrf/boards/BLUEIO_TAG_EVIM/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "esp32", - "board": "OLIMEX_ESP32_POE", - "board_name": "Olimex ESP32 ETH", - "mcu_name": "ESP32", - "description": "Olimex ESP32 ETH with ESP32", - "path": "repos/micropython/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h" + "port": "nrf", + "board": "FEATHER52", + "board_name": "Bluefruit nRF52 Feather", + "mcu_name": "NRF52832", + "description": "Bluefruit nRF52 Feather with NRF52832", + "path": "repos/micropython/ports/nrf/boards/FEATHER52/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "esp32", - "board": "SIL_WESP32", - "board_name": "Silicognition wESP32", - "mcu_name": "ESP32", - "description": "Silicognition wESP32 with ESP32", - "path": "repos/micropython/ports/esp32/boards/SIL_WESP32/mpconfigboard.h" + "port": "stm32", + "board": "CERB40", + "board_name": "Cerb40", + "mcu_name": "STM32F405RG", + "description": "Cerb40 with STM32F405RG", + "path": "repos/micropython/ports/stm32/boards/CERB40/mpconfigboard.h", + "version": "v1.10" }, { - "port": "esp32", - "board": "UM_FEATHERS2", - "board_name": "FeatherS2", - "mcu_name": "ESP32-S2", - "description": "FeatherS2 with ESP32-S2", - "path": "repos/micropython/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.h" + "port": "stm32", + "board": "STM32F439", + "board_name": "CustomPCB", + "mcu_name": "STM32F439", + "description": "CustomPCB with STM32F439", + "path": "repos/micropython/ports/stm32/boards/STM32F439/mpconfigboard.h", + "version": "v1.10" }, { - "port": "esp32", - "board": "UM_FEATHERS2NEO", - "board_name": "FeatherS2 Neo", - "mcu_name": "ESP32-S2FN4R2", - "description": "FeatherS2 Neo with ESP32-S2FN4R2", - "path": "repos/micropython/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.h" + "port": "nrf", + "board": "DVK_BL652", + "board_name": "DVK-BL652", + "mcu_name": "NRF52832", + "description": "DVK-BL652 with NRF52832", + "path": "repos/micropython/ports/nrf/boards/DVK_BL652/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "esp32", - "board": "UM_FEATHERS3", - "board_name": "FeatherS3", - "mcu_name": "ESP32-S3", - "description": "FeatherS3 with ESP32-S3", - "path": "repos/micropython/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h" + "port": "renesas-ra", + "board": "EK_RA4M1", + "board_name": "EK-RA4M1", + "mcu_name": "RA4M1", + "description": "EK-RA4M1 with RA4M1", + "path": "repos/micropython/ports/renesas-ra/boards/EK_RA4M1/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "esp32", - "board": "UM_NANOS3", - "board_name": "NanoS3", - "mcu_name": "ESP32-S3-FN8", - "description": "NanoS3 with ESP32-S3-FN8", - "path": "repos/micropython/ports/esp32/boards/UM_NANOS3/mpconfigboard.h" + "port": "renesas-ra", + "board": "EK_RA4W1", + "board_name": "EK-RA4W1", + "mcu_name": "RA4W1", + "description": "EK-RA4W1 with RA4W1", + "path": "repos/micropython/ports/renesas-ra/boards/EK_RA4W1/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "esp32", - "board": "UM_PROS3", - "board_name": "ProS3", - "mcu_name": "ESP32-S3", - "description": "ProS3 with ESP32-S3", - "path": "repos/micropython/ports/esp32/boards/UM_PROS3/mpconfigboard.h" + "port": "renesas-ra", + "board": "EK_RA6M1", + "board_name": "EK-RA6M1", + "mcu_name": "RA6M1", + "description": "EK-RA6M1 with RA6M1", + "path": "repos/micropython/ports/renesas-ra/boards/EK_RA6M1/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "esp32", - "board": "UM_TINYPICO", - "board_name": "TinyPICO", - "mcu_name": "ESP32-PICO-D4", - "description": "TinyPICO with ESP32-PICO-D4", - "path": "repos/micropython/ports/esp32/boards/UM_TINYPICO/mpconfigboard.h" + "port": "renesas-ra", + "board": "EK_RA6M2", + "board_name": "EK-RA6M2", + "mcu_name": "RA6M2", + "description": "EK-RA6M2 with RA6M2", + "path": "repos/micropython/ports/renesas-ra/boards/EK_RA6M2/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "esp32", - "board": "UM_TINYS2", - "board_name": "TinyS2", - "mcu_name": "ESP32-S2FN4R2", - "description": "TinyS2 with ESP32-S2FN4R2", - "path": "repos/micropython/ports/esp32/boards/UM_TINYS2/mpconfigboard.h" + "port": "esp8266", + "board": "GENERIC_1M", + "board_name": "ESP module (1M)", + "mcu_name": "ESP8266", + "description": "ESP module (1M) with ESP8266", + "path": "repos/micropython/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h", + "version": "v1.13" }, { - "port": "esp32", - "board": "UM_TINYS3", - "board_name": "TinyS3", - "mcu_name": "ESP32-S3-FN8", - "description": "TinyS3 with ESP32-S3-FN8", - "path": "repos/micropython/ports/esp32/boards/UM_TINYS3/mpconfigboard.h" + "port": "esp8266", + "board": "GENERIC_512K", + "board_name": "ESP module (512K)", + "mcu_name": "ESP8266", + "description": "ESP module (512K) with ESP8266", + "path": "repos/micropython/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h", + "version": "v1.12" }, { "port": "esp8266", @@ -181,687 +257,710 @@ "board_name": "ESP module", "mcu_name": "ESP8266", "description": "ESP module with ESP8266", - "path": "repos/micropython/ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h" + "path": "repos/micropython/ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "mimxrt", - "board": "ADAFRUIT_METRO_M7", - "board_name": "Adafruit Metro M7", - "mcu_name": "MIMXRT1011DAE5A", - "description": "Adafruit Metro M7 with MIMXRT1011DAE5A", - "path": "repos/micropython/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.h" + "port": "esp32", + "board": "GENERIC_UNICORE", + "board_name": "ESP32 Unicore module", + "mcu_name": "ESP32-UNICORE", + "description": "ESP32 Unicore module with ESP32-UNICORE", + "path": "repos/micropython/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h", + "version": "v1.20.0" }, { - "port": "mimxrt", - "board": "MIMXRT1010_EVK", - "board_name": "i.MX RT1010 EVK", - "mcu_name": "MIMXRT1011DAE5A", - "description": "i.MX RT1010 EVK with MIMXRT1011DAE5A", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h" + "port": "esp32", + "board": "GENERIC_SPIRAM", + "board_name": "ESP32 module (spiram)", + "mcu_name": "ESP32", + "description": "ESP32 module (spiram) with ESP32", + "path": "repos/micropython/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.h", + "version": "v1.12" }, { - "port": "mimxrt", - "board": "MIMXRT1015_EVK", - "board_name": "i.MX RT1015 EVK", - "mcu_name": "MIMXRT1015DAF5A", - "description": "i.MX RT1015 EVK with MIMXRT1015DAF5A", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h" + "port": "esp32", + "board": "GENERIC", + "board_name": "ESP32 module", + "mcu_name": "ESP32", + "description": "ESP32 module with ESP32", + "path": "repos/micropython/ports/esp32/boards/GENERIC/mpconfigboard.h", + "version": "v1.12" }, { - "port": "mimxrt", - "board": "MIMXRT1020_EVK", - "board_name": "i.MX RT1020 EVK", - "mcu_name": "MIMXRT1021DAG5A", - "description": "i.MX RT1020 EVK with MIMXRT1021DAG5A", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h" + "port": "esp32", + "board": "ESP32_S2_WROVER", + "board_name": "ESP32-S2-WROVER", + "mcu_name": "ESP32-S2", + "description": "ESP32-S2-WROVER with ESP32-S2", + "path": "repos/micropython/ports/esp32/boards/ESP32_S2_WROVER/mpconfigboard.h", + "version": "v1.18" }, { - "port": "mimxrt", - "board": "MIMXRT1050_EVK", - "board_name": "i.MX RT1050 EVKB-A1", - "mcu_name": "MIMXRT1052DVL6B", - "description": "i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h" + "port": "esp32", + "board": "ESP32_GENERIC_C3", + "board_name": "ESP32C3 module", + "mcu_name": "ESP32C3", + "description": "ESP32C3 module with ESP32C3", + "path": "repos/micropython/ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "mimxrt", - "board": "MIMXRT1060_EVK", - "board_name": "i.MX RT1060 EVK", - "mcu_name": "MIMXRT1062DVJ6A", - "description": "i.MX RT1060 EVK with MIMXRT1062DVJ6A", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h" + "port": "esp32", + "board": "GENERIC_S2", + "board_name": "ESP32S2 module", + "mcu_name": "ESP32S2", + "description": "ESP32S2 module with ESP32S2", + "path": "repos/micropython/ports/esp32/boards/GENERIC_S2/mpconfigboard.h", + "version": "v1.15" }, { - "port": "mimxrt", - "board": "MIMXRT1064_EVK", - "board_name": "i.MX RT1064 EVK", - "mcu_name": "MIMXRT1064DVL6A", - "description": "i.MX RT1064 EVK with MIMXRT1064DVL6A", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h" + "port": "esp32", + "board": "GENERIC_S3_SPIRAM_OCT", + "board_name": "ESP32S3 module (spiram octal)", + "mcu_name": "ESP32S3", + "description": "ESP32S3 module (spiram octal) with ESP32S3", + "path": "repos/micropython/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.h", + "version": "v1.20.0" }, { - "port": "mimxrt", - "board": "MIMXRT1170_EVK", - "board_name": "i.MX RT1170 EVK", - "mcu_name": "MIMXRT1176DVMAA", - "description": "i.MX RT1170 EVK with MIMXRT1176DVMAA", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h" + "port": "esp32", + "board": "GENERIC_S3_SPIRAM", + "board_name": "ESP32S3 module (spiram)", + "mcu_name": "ESP32S3", + "description": "ESP32S3 module (spiram) with ESP32S3", + "path": "repos/micropython/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h", + "version": "v1.18" }, { - "port": "mimxrt", - "board": "OLIMEX_RT1010", - "board_name": "RT1010-Py-DevKIT", - "mcu_name": "MIMXRT1011DAE5A", - "description": "RT1010-Py-DevKIT with MIMXRT1011DAE5A", - "path": "repos/micropython/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h" + "port": "esp32", + "board": "GENERIC_S3", + "board_name": "ESP32S3 module", + "mcu_name": "ESP32S3", + "description": "ESP32S3 module with ESP32S3", + "path": "repos/micropython/ports/esp32/boards/GENERIC_S3/mpconfigboard.h", + "version": "v1.18" }, { - "port": "mimxrt", - "board": "SEEED_ARCH_MIX", - "board_name": "Seeed ARCH MIX", - "mcu_name": "MIMXRT1052DVL5B", - "description": "Seeed ARCH MIX with MIMXRT1052DVL5B", - "path": "repos/micropython/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h" + "port": "nrf", + "board": "EVK_NINA_B1", + "board_name": "EVK_NINA_B1", + "mcu_name": "NRF52832", + "description": "EVK_NINA_B1 with NRF52832", + "path": "repos/micropython/ports/nrf/boards/EVK_NINA_B1/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "mimxrt", - "board": "TEENSY40", - "board_name": "Teensy 4.0", - "mcu_name": "MIMXRT1062DVJ6A", - "description": "Teensy 4.0 with MIMXRT1062DVJ6A", - "path": "repos/micropython/ports/mimxrt/boards/TEENSY40/mpconfigboard.h" + "port": "nrf", + "board": "EVK_NINA_B3", + "board_name": "EVK_NINA_B3", + "mcu_name": "NRF52840", + "description": "EVK_NINA_B3 with NRF52840", + "path": "repos/micropython/ports/nrf/boards/EVK_NINA_B3/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "mimxrt", - "board": "TEENSY41", - "board_name": "Teensy 4.1", - "mcu_name": "MIMXRT1062DVJ6A", - "description": "Teensy 4.1 with MIMXRT1062DVJ6A", - "path": "repos/micropython/ports/mimxrt/boards/TEENSY41/mpconfigboard.h" + "port": "stm32", + "board": "ESPRUINO_PICO", + "board_name": "Espruino Pico", + "mcu_name": "STM32F401CD", + "description": "Espruino Pico with STM32F401CD", + "path": "repos/micropython/ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.h", + "version": "v1.10" }, { - "port": "nrf", - "board": "ACTINIUS_ICARUS", - "board_name": "Actinius Icarus", - "mcu_name": "NRF9160", - "description": "Actinius Icarus with NRF9160", - "path": "repos/micropython/ports/nrf/boards/ACTINIUS_ICARUS/mpconfigboard.h" + "port": "stm32", + "board": "STM32F411DISC", + "board_name": "F411DISC", + "mcu_name": "STM32F411", + "description": "F411DISC with STM32F411", + "path": "repos/micropython/ports/stm32/boards/STM32F411DISC/mpconfigboard.h", + "version": "v1.10" }, { - "port": "nrf", - "board": "ARDUINO_NANO_33_BLE_SENSE", - "board_name": "Arduino Nano 33 BLE Sense", - "mcu_name": "NRF52840", - "description": "Arduino Nano 33 BLE Sense with NRF52840", - "path": "repos/micropython/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.h" + "port": "stm32", + "board": "STM32F429DISC", + "board_name": "F429I-DISCO", + "mcu_name": "STM32F429", + "description": "F429I-DISCO with STM32F429", + "path": "repos/micropython/ports/stm32/boards/STM32F429DISC/mpconfigboard.h", + "version": "v1.10" }, { - "port": "nrf", - "board": "ARDUINO_PRIMO", - "board_name": "Arduino Primo", - "mcu_name": "NRF52832", - "description": "Arduino Primo with NRF52832", - "path": "repos/micropython/ports/nrf/boards/ARDUINO_PRIMO/mpconfigboard.h" + "port": "stm32", + "board": "STM32F4DISC", + "board_name": "F4DISC", + "mcu_name": "STM32F407", + "description": "F4DISC with STM32F407", + "path": "repos/micropython/ports/stm32/boards/STM32F4DISC/mpconfigboard.h", + "version": "v1.10" }, { - "port": "nrf", - "board": "BLUEIO_TAG_EVIM", - "board_name": "BLUEIO-TAG-EVIM", - "mcu_name": "NRF52832", - "description": "BLUEIO-TAG-EVIM with NRF52832", - "path": "repos/micropython/ports/nrf/boards/BLUEIO_TAG_EVIM/mpconfigboard.h" + "port": "stm32", + "board": "STM32F769DISC", + "board_name": "F769DISC", + "mcu_name": "STM32F769", + "description": "F769DISC with STM32F769", + "path": "repos/micropython/ports/stm32/boards/STM32F769DISC/mpconfigboard.h", + "version": "v1.10" }, { - "port": "nrf", - "board": "DVK_BL652", - "board_name": "DVK-BL652", - "mcu_name": "NRF52832", - "description": "DVK-BL652 with NRF52832", - "path": "repos/micropython/ports/nrf/boards/DVK_BL652/mpconfigboard.h" + "port": "stm32", + "board": "STM32F7DISC", + "board_name": "F7DISC", + "mcu_name": "STM32F746", + "description": "F7DISC with STM32F746", + "path": "repos/micropython/ports/stm32/boards/STM32F7DISC/mpconfigboard.h", + "version": "v1.10" }, { - "port": "nrf", - "board": "EVK_NINA_B1", - "board_name": "EVK_NINA_B1", - "mcu_name": "NRF52832", - "description": "EVK_NINA_B1 with NRF52832", - "path": "repos/micropython/ports/nrf/boards/EVK_NINA_B1/mpconfigboard.h" + "port": "samd", + "board": "ADAFRUIT_FEATHER_M0_EXPRESS", + "board_name": "Feather M0 Express", + "mcu_name": "SAMD21G18A", + "description": "Feather M0 Express with SAMD21G18A", + "path": "repos/micropython/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h", + "version": "v1.12" }, { - "port": "nrf", - "board": "EVK_NINA_B3", - "board_name": "EVK_NINA_B3", - "mcu_name": "NRF52840", - "description": "EVK_NINA_B3 with NRF52840", - "path": "repos/micropython/ports/nrf/boards/EVK_NINA_B3/mpconfigboard.h" + "port": "samd", + "board": "ADAFRUIT_FEATHER_M4_EXPRESS", + "board_name": "Feather M4 Express", + "mcu_name": "SAMD51J19A", + "description": "Feather M4 Express with SAMD51J19A", + "path": "repos/micropython/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h", + "version": "v1.20.0" }, { - "port": "nrf", - "board": "FEATHER52", - "board_name": "Bluefruit nRF52 Feather", - "mcu_name": "NRF52832", - "description": "Bluefruit nRF52 Feather with NRF52832", - "path": "repos/micropython/ports/nrf/boards/FEATHER52/mpconfigboard.h" + "port": "esp32", + "board": "UM_FEATHERS2NEO", + "board_name": "FeatherS2 Neo", + "mcu_name": "ESP32-S2FN4R2", + "description": "FeatherS2 Neo with ESP32-S2FN4R2", + "path": "repos/micropython/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.h", + "version": "v1.18" }, { - "port": "nrf", - "board": "IBK_BLYST_NANO", - "board_name": "IBK-BLYST-NANO", - "mcu_name": "NRF52832", - "description": "IBK-BLYST-NANO with NRF52832", - "path": "repos/micropython/ports/nrf/boards/IBK_BLYST_NANO/mpconfigboard.h" + "port": "esp32", + "board": "UM_FEATHERS2", + "board_name": "FeatherS2", + "mcu_name": "ESP32-S2", + "description": "FeatherS2 with ESP32-S2", + "path": "repos/micropython/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.h", + "version": "v1.16" }, { - "port": "nrf", - "board": "IDK_BLYST_NANO", - "board_name": "IDK-BLYST-NANO", - "mcu_name": "NRF52832", - "description": "IDK-BLYST-NANO with NRF52832", - "path": "repos/micropython/ports/nrf/boards/IDK_BLYST_NANO/mpconfigboard.h" + "port": "esp32", + "board": "UM_FEATHERS3", + "board_name": "FeatherS3", + "mcu_name": "ESP32-S3", + "description": "FeatherS3 with ESP32-S3", + "path": "repos/micropython/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h", + "version": "v1.19.1" }, { - "port": "nrf", - "board": "MICROBIT", - "board_name": "micro:bit", - "mcu_name": "NRF51822", - "description": "micro:bit with NRF51822", - "path": "repos/micropython/ports/nrf/boards/MICROBIT/mpconfigboard.h" + "port": "rp2", + "board": "GARATRONIC_PYBSTICK26_RP2040", + "board_name": "GARATRONIC_PYBSTICK26_RP2040", + "mcu_name": "-", + "description": "GARATRONIC_PYBSTICK26_RP2040", + "path": "repos/micropython/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.h", + "version": "v1.18" }, { - "port": "nrf", - "board": "NRF52840_MDK_USB_DONGLE", - "board_name": "MDK-USB-DONGLE", - "mcu_name": "NRF52840", - "description": "MDK-USB-DONGLE with NRF52840", - "path": "repos/micropython/ports/nrf/boards/NRF52840_MDK_USB_DONGLE/mpconfigboard.h" + "port": "stm32", + "board": "ARDUINO_GIGA", + "board_name": "GIGA", + "mcu_name": "STM32H747", + "description": "GIGA with STM32H747", + "path": "repos/micropython/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h", + "version": "v1.20.0" }, { - "port": "nrf", - "board": "PARTICLE_XENON", - "board_name": "XENON", - "mcu_name": "NRF52840", - "description": "XENON with NRF52840", - "path": "repos/micropython/ports/nrf/boards/PARTICLE_XENON/mpconfigboard.h" + "port": "esp32", + "board": "ESP32_GENERIC", + "board_name": "Generic ESP32 module", + "mcu_name": "ESP32", + "description": "Generic ESP32 module with ESP32", + "path": "repos/micropython/ports/esp32/boards/ESP32_GENERIC/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "nrf", - "board": "PCA10000", - "board_name": "PCA10000", - "mcu_name": "NRF51822", - "description": "PCA10000 with NRF51822", - "path": "repos/micropython/ports/nrf/boards/PCA10000/mpconfigboard.h" + "port": "esp32", + "board": "GENERIC_D2WD", + "board_name": "Generic ESP32-D2WD module", + "mcu_name": "ESP32-D2WD", + "description": "Generic ESP32-D2WD module with ESP32-D2WD", + "path": "repos/micropython/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.h", + "version": "v1.12" }, { - "port": "nrf", - "board": "PCA10001", - "board_name": "PCA10001", - "mcu_name": "NRF51822", - "description": "PCA10001 with NRF51822", - "path": "repos/micropython/ports/nrf/boards/PCA10001/mpconfigboard.h" + "port": "esp32", + "board": "ESP32_GENERIC_S2", + "board_name": "Generic ESP32S2 module", + "mcu_name": "ESP32S2", + "description": "Generic ESP32S2 module with ESP32S2", + "path": "repos/micropython/ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "nrf", - "board": "PCA10028", - "board_name": "PCA10028", - "mcu_name": "NRF51822", - "description": "PCA10028 with NRF51822", - "path": "repos/micropython/ports/nrf/boards/PCA10028/mpconfigboard.h" + "port": "esp32", + "board": "ESP32_GENERIC_S3", + "board_name": "Generic ESP32S3 module", + "mcu_name": "ESP32S3", + "description": "Generic ESP32S3 module with ESP32S3", + "path": "repos/micropython/ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "nrf", - "board": "PCA10031", - "board_name": "PCA10031", - "mcu_name": "NRF51822", - "description": "PCA10031 with NRF51822", - "path": "repos/micropython/ports/nrf/boards/PCA10031/mpconfigboard.h" + "port": "stm32", + "board": "HYDRABUS", + "board_name": "HydraBus1.0", + "mcu_name": "STM32F4", + "description": "HydraBus1.0 with STM32F4", + "path": "repos/micropython/ports/stm32/boards/HYDRABUS/mpconfigboard.h", + "version": "v1.10" }, { "port": "nrf", - "board": "PCA10040", - "board_name": "PCA10040", + "board": "IBK_BLYST_NANO", + "board_name": "IBK-BLYST-NANO", "mcu_name": "NRF52832", - "description": "PCA10040 with NRF52832", - "path": "repos/micropython/ports/nrf/boards/PCA10040/mpconfigboard.h" - }, - { - "port": "nrf", - "board": "PCA10056", - "board_name": "PCA10056", - "mcu_name": "NRF52840", - "description": "PCA10056 with NRF52840", - "path": "repos/micropython/ports/nrf/boards/PCA10056/mpconfigboard.h" + "description": "IBK-BLYST-NANO with NRF52832", + "path": "repos/micropython/ports/nrf/boards/IBK_BLYST_NANO/mpconfigboard.h", + "version": "v1.21.0" }, { "port": "nrf", - "board": "PCA10059", - "board_name": "PCA10059", - "mcu_name": "NRF52840", - "description": "PCA10059 with NRF52840", - "path": "repos/micropython/ports/nrf/boards/PCA10059/mpconfigboard.h" - }, - { - "port": "nrf", - "board": "PCA10090", - "board_name": "PCA10090", - "mcu_name": "NRF9160", - "description": "PCA10090 with NRF9160", - "path": "repos/micropython/ports/nrf/boards/PCA10090/mpconfigboard.h" - }, - { - "port": "nrf", - "board": "SEEED_XIAO_NRF52", - "board_name": "XIAO nRF52840 Sense", - "mcu_name": "NRF52840", - "description": "XIAO nRF52840 Sense with NRF52840", - "path": "repos/micropython/ports/nrf/boards/SEEED_XIAO_NRF52/mpconfigboard.h" - }, - { - "port": "nrf", - "board": "WT51822_S4AT", - "board_name": "WT51822-S4AT", - "mcu_name": "NRF51822", - "description": "WT51822-S4AT with NRF51822", - "path": "repos/micropython/ports/nrf/boards/WT51822_S4AT/mpconfigboard.h" - }, - { - "port": "renesas-ra", - "board": "ARDUINO_PORTENTA_C33", - "board_name": "PORTENTA C33", - "mcu_name": "RA6M5", - "description": "PORTENTA C33 with RA6M5", - "path": "repos/micropython/ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/mpconfigboard.h" - }, - { - "port": "renesas-ra", - "board": "EK_RA4M1", - "board_name": "EK-RA4M1", - "mcu_name": "RA4M1", - "description": "EK-RA4M1 with RA4M1", - "path": "repos/micropython/ports/renesas-ra/boards/EK_RA4M1/mpconfigboard.h" - }, - { - "port": "renesas-ra", - "board": "EK_RA4W1", - "board_name": "EK-RA4W1", - "mcu_name": "RA4W1", - "description": "EK-RA4W1 with RA4W1", - "path": "repos/micropython/ports/renesas-ra/boards/EK_RA4W1/mpconfigboard.h" + "board": "IDK_BLYST_NANO", + "board_name": "IDK-BLYST-NANO", + "mcu_name": "NRF52832", + "description": "IDK-BLYST-NANO with NRF52832", + "path": "repos/micropython/ports/nrf/boards/IDK_BLYST_NANO/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "renesas-ra", - "board": "EK_RA6M1", - "board_name": "EK-RA6M1", - "mcu_name": "RA6M1", - "description": "EK-RA6M1 with RA6M1", - "path": "repos/micropython/ports/renesas-ra/boards/EK_RA6M1/mpconfigboard.h" + "port": "samd", + "board": "ADAFRUIT_ITSYBITSY_M0_EXPRESS", + "board_name": "ItsyBitsy M0 Express", + "mcu_name": "SAMD21G18A", + "description": "ItsyBitsy M0 Express with SAMD21G18A", + "path": "repos/micropython/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h", + "version": "v1.20.0" }, { - "port": "renesas-ra", - "board": "EK_RA6M2", - "board_name": "EK-RA6M2", - "mcu_name": "RA6M2", - "description": "EK-RA6M2 with RA6M2", - "path": "repos/micropython/ports/renesas-ra/boards/EK_RA6M2/mpconfigboard.h" + "port": "samd", + "board": "ADAFRUIT_ITSYBITSY_M4_EXPRESS", + "board_name": "ItsyBitsy M4 Express", + "mcu_name": "SAMD51G19A", + "description": "ItsyBitsy M4 Express with SAMD51G19A", + "path": "repos/micropython/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h", + "version": "v1.12" }, { - "port": "renesas-ra", - "board": "RA4M1_CLICKER", - "board_name": "RA4M1 CLICKER", - "mcu_name": "RA4M1", - "description": "RA4M1 CLICKER with RA4M1", - "path": "repos/micropython/ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h" + "port": "stm32", + "board": "STM32L476DISC", + "board_name": "L476-DISCO", + "mcu_name": "STM32L476", + "description": "L476-DISCO with STM32L476", + "path": "repos/micropython/ports/stm32/boards/STM32L476DISC/mpconfigboard.h", + "version": "v1.10" }, { - "port": "renesas-ra", - "board": "VK_RA6M5", - "board_name": "VK-RA6M5", - "mcu_name": "RA6M5", - "description": "VK-RA6M5 with RA6M5", - "path": "repos/micropython/ports/renesas-ra/boards/VK_RA6M5/mpconfigboard.h" + "port": "stm32", + "board": "STM32L496GDISC", + "board_name": "L496G-DISCO", + "mcu_name": "STM32L496", + "description": "L496G-DISCO with STM32L496", + "path": "repos/micropython/ports/stm32/boards/STM32L496GDISC/mpconfigboard.h", + "version": "v1.10" }, { - "port": "rp2", - "board": "ADAFRUIT_FEATHER_RP2040", - "board_name": "Adafruit Feather RP2040", - "mcu_name": "-", - "description": "Adafruit Feather RP2040", - "path": "repos/micropython/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h" + "port": "stm32", + "board": "LEGO_HUB_NO6", + "board_name": "LEGO Technic Hub No.6", + "mcu_name": "STM32F413", + "description": "LEGO Technic Hub No.6 with STM32F413", + "path": "repos/micropython/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h", + "version": "v1.17" }, { - "port": "rp2", - "board": "ADAFRUIT_ITSYBITSY_RP2040", - "board_name": "Adafruit ItsyBitsy RP2040", - "mcu_name": "-", - "description": "Adafruit ItsyBitsy RP2040", - "path": "repos/micropython/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h" + "port": "stm32", + "board": "LEGO_HUB_NO7", + "board_name": "LEGO Technic Hub No.7", + "mcu_name": "STM32F413", + "description": "LEGO Technic Hub No.7 with STM32F413", + "path": "repos/micropython/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h", + "version": "v1.20.0" }, { - "port": "rp2", - "board": "ADAFRUIT_QTPY_RP2040", - "board_name": "Adafruit QT Py RP2040", - "mcu_name": "-", - "description": "Adafruit QT Py RP2040", - "path": "repos/micropython/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h" + "port": "esp32", + "board": "LILYGO_TTGO_LORA32", + "board_name": "LILYGO TTGO LoRa32", + "mcu_name": "ESP32", + "description": "LILYGO TTGO LoRa32 with ESP32", + "path": "repos/micropython/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.h", + "version": "v1.19.1" }, { - "port": "rp2", - "board": "ARDUINO_NANO_RP2040_CONNECT", - "board_name": "Arduino Nano RP2040 Connect", - "mcu_name": "-", - "description": "Arduino Nano RP2040 Connect", - "path": "repos/micropython/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h" + "port": "stm32", + "board": "LIMIFROG", + "board_name": "LIMIFROG", + "mcu_name": "STM32L476", + "description": "LIMIFROG with STM32L476", + "path": "repos/micropython/ports/stm32/boards/LIMIFROG/mpconfigboard.h", + "version": "v1.10" }, { - "port": "rp2", - "board": "GARATRONIC_PYBSTICK26_RP2040", - "board_name": "GARATRONIC_PYBSTICK26_RP2040", - "mcu_name": "-", - "description": "GARATRONIC_PYBSTICK26_RP2040", - "path": "repos/micropython/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.h" + "port": "esp32", + "board": "LOLIN_C3_MINI", + "board_name": "LOLIN_C3_MINI", + "mcu_name": "ESP32-C3FH4", + "description": "LOLIN_C3_MINI with ESP32-C3FH4", + "path": "repos/micropython/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.h", + "version": "v1.19.1" }, { - "port": "rp2", - "board": "NULLBITS_BIT_C_PRO", - "board_name": "nullbits Bit-C PRO", - "mcu_name": "-", - "description": "nullbits Bit-C PRO", - "path": "repos/micropython/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.h" + "port": "esp32", + "board": "LOLIN_S2_MINI", + "board_name": "LOLIN_S2_MINI", + "mcu_name": "ESP32-S2FN4R2", + "description": "LOLIN_S2_MINI with ESP32-S2FN4R2", + "path": "repos/micropython/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.h", + "version": "v1.18" }, { - "port": "rp2", - "board": "PIMORONI_PICOLIPO_16MB", - "board_name": "Pimoroni Pico LiPo 16MB", - "mcu_name": "-", - "description": "Pimoroni Pico LiPo 16MB", - "path": "repos/micropython/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h" + "port": "esp32", + "board": "LOLIN_S2_PICO", + "board_name": "LOLIN_S2_PICO", + "mcu_name": "ESP32-S2FN4R2", + "description": "LOLIN_S2_PICO with ESP32-S2FN4R2", + "path": "repos/micropython/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h", + "version": "v1.18" }, { - "port": "rp2", - "board": "PIMORONI_PICOLIPO_4MB", - "board_name": "Pimoroni Pico LiPo 4MB", - "mcu_name": "-", - "description": "Pimoroni Pico LiPo 4MB", - "path": "repos/micropython/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h" + "port": "cc3200", + "board": "LAUNCHXL", + "board_name": "LaunchPad", + "mcu_name": "CC3200", + "description": "LaunchPad with CC3200", + "path": "repos/micropython/ports/cc3200/boards/LAUNCHXL/mpconfigboard.h", + "version": "v1.10" }, { - "port": "rp2", - "board": "PIMORONI_TINY2040", - "board_name": "Pimoroni Tiny 2040", - "mcu_name": "-", - "description": "Pimoroni Tiny 2040", - "path": "repos/micropython/ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h" + "port": "esp32", + "board": "M5STACK_ATOM", + "board_name": "M5Stack ATOM", + "mcu_name": "ESP32-PICO-D4", + "description": "M5Stack ATOM with ESP32-PICO-D4", + "path": "repos/micropython/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.h", + "version": "v1.16" }, { - "port": "rp2", - "board": "RPI_PICO", - "board_name": "Raspberry Pi Pico", - "mcu_name": "-", - "description": "Raspberry Pi Pico", - "path": "repos/micropython/ports/rp2/boards/RPI_PICO/mpconfigboard.h" + "port": "nrf", + "board": "NRF52840_MDK_USB_DONGLE", + "board_name": "MDK-USB-DONGLE", + "mcu_name": "NRF52840", + "description": "MDK-USB-DONGLE with NRF52840", + "path": "repos/micropython/ports/nrf/boards/NRF52840_MDK_USB_DONGLE/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "rp2", - "board": "RPI_PICO_W", - "board_name": "Raspberry Pi Pico W", - "mcu_name": "-", - "description": "Raspberry Pi Pico W", - "path": "repos/micropython/ports/rp2/boards/RPI_PICO_W/mpconfigboard.h" + "port": "stm32", + "board": "MIKROE_CLICKER2_STM32", + "board_name": "MIKROE_CLICKER2_STM32", + "mcu_name": "STM32F407", + "description": "MIKROE_CLICKER2_STM32 with STM32F407", + "path": "repos/micropython/ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.h", + "version": "v1.12" }, { - "port": "rp2", - "board": "SPARKFUN_PROMICRO", - "board_name": "SparkFun Pro Micro RP2040", - "mcu_name": "-", - "description": "SparkFun Pro Micro RP2040", - "path": "repos/micropython/ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h" + "port": "samd", + "board": "ADAFRUIT_METRO_M4_EXPRESS", + "board_name": "Metro M4 Express Airlift", + "mcu_name": "SAMD51J19A", + "description": "Metro M4 Express Airlift with SAMD51J19A", + "path": "repos/micropython/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "rp2", - "board": "SPARKFUN_THINGPLUS", - "board_name": "SparkFun Thing Plus RP2040", - "mcu_name": "-", - "description": "SparkFun Thing Plus RP2040", - "path": "repos/micropython/ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h" + "port": "stm32", + "board": "MIKROE_QUAIL", + "board_name": "MikroE Quail", + "mcu_name": "STM32F427VI", + "description": "MikroE Quail with STM32F427VI", + "path": "repos/micropython/ports/stm32/boards/MIKROE_QUAIL/mpconfigboard.h", + "version": "v1.18" }, { - "port": "rp2", - "board": "W5100S_EVB_PICO", - "board_name": "W5100S-EVB-Pico", - "mcu_name": "-", - "description": "W5100S-EVB-Pico", - "path": "repos/micropython/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.h" + "port": "samd", + "board": "MINISAM_M4", + "board_name": "Mini SAM M4", + "mcu_name": "SAMD51G19A", + "description": "Mini SAM M4 with SAMD51G19A", + "path": "repos/micropython/ports/samd/boards/MINISAM_M4/mpconfigboard.h", + "version": "v1.12" }, { - "port": "rp2", - "board": "W5500_EVB_PICO", - "board_name": "W5500-EVB-Pico", - "mcu_name": "-", - "description": "W5500-EVB-Pico", - "path": "repos/micropython/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.h" + "port": "stm32", + "board": "GARATRONIC_NADHAT_F405", + "board_name": "NADHAT_PYBF405", + "mcu_name": "STM32F405RG", + "description": "NADHAT_PYBF405 with STM32F405RG", + "path": "repos/micropython/ports/stm32/boards/GARATRONIC_NADHAT_F405/mpconfigboard.h", + "version": "v1.18" }, { - "port": "rp2", - "board": "WEACTSTUDIO", - "board_name": "WeAct Studio RP2040", - "mcu_name": "-", - "description": "WeAct Studio RP2040", - "path": "repos/micropython/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.h" + "port": "stm32", + "board": "ARDUINO_NICLA_VISION", + "board_name": "NICLAVISION", + "mcu_name": "STM32H747", + "description": "NICLAVISION with STM32H747", + "path": "repos/micropython/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h", + "version": "v1.20.0" }, { - "port": "samd", - "board": "ADAFRUIT_FEATHER_M0_EXPRESS", - "board_name": "Feather M0 Express", - "mcu_name": "SAMD21G18A", - "description": "Feather M0 Express with SAMD21G18A", - "path": "repos/micropython/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h" + "port": "stm32", + "board": "NUCLEO_F091RC", + "board_name": "NUCLEO-F091RC", + "mcu_name": "STM32F091RCT6", + "description": "NUCLEO-F091RC with STM32F091RCT6", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h", + "version": "v1.10" }, { - "port": "samd", - "board": "ADAFRUIT_FEATHER_M4_EXPRESS", - "board_name": "Feather M4 Express", - "mcu_name": "SAMD51J19A", - "description": "Feather M4 Express with SAMD51J19A", - "path": "repos/micropython/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h" + "port": "stm32", + "board": "NUCLEO_F401RE", + "board_name": "NUCLEO-F401RE", + "mcu_name": "STM32F401xE", + "description": "NUCLEO-F401RE with STM32F401xE", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_F401RE/mpconfigboard.h", + "version": "v1.10" }, { - "port": "samd", - "board": "ADAFRUIT_ITSYBITSY_M0_EXPRESS", - "board_name": "ItsyBitsy M0 Express", - "mcu_name": "SAMD21G18A", - "description": "ItsyBitsy M0 Express with SAMD21G18A", - "path": "repos/micropython/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h" + "port": "stm32", + "board": "NUCLEO_F411RE", + "board_name": "NUCLEO-F411RE", + "mcu_name": "STM32F411xE", + "description": "NUCLEO-F411RE with STM32F411xE", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_F411RE/mpconfigboard.h", + "version": "v1.10" }, { - "port": "samd", - "board": "ADAFRUIT_ITSYBITSY_M4_EXPRESS", - "board_name": "ItsyBitsy M4 Express", - "mcu_name": "SAMD51G19A", - "description": "ItsyBitsy M4 Express with SAMD51G19A", - "path": "repos/micropython/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h" + "port": "stm32", + "board": "NUCLEO_F412ZG", + "board_name": "NUCLEO-F412ZG", + "mcu_name": "STM32F412Zx", + "description": "NUCLEO-F412ZG with STM32F412Zx", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_F412ZG/mpconfigboard.h", + "version": "v1.13" }, { - "port": "samd", - "board": "ADAFRUIT_METRO_M4_EXPRESS", - "board_name": "Metro M4 Express Airlift", - "mcu_name": "SAMD51J19A", - "description": "Metro M4 Express Airlift with SAMD51J19A", - "path": "repos/micropython/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.h" + "port": "stm32", + "board": "NUCLEO_F413ZH", + "board_name": "NUCLEO-F413ZH", + "mcu_name": "STM32F413", + "description": "NUCLEO-F413ZH with STM32F413", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.h", + "version": "v1.11" }, { - "port": "samd", - "board": "ADAFRUIT_TRINKET_M0", - "board_name": "Trinket M0", - "mcu_name": "SAMD21E18A", - "description": "Trinket M0 with SAMD21E18A", - "path": "repos/micropython/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h" + "port": "stm32", + "board": "NUCLEO_F429ZI", + "board_name": "NUCLEO-F429ZI", + "mcu_name": "STM32F429", + "description": "NUCLEO-F429ZI with STM32F429", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.h", + "version": "v1.10" }, { - "port": "samd", - "board": "MINISAM_M4", - "board_name": "Mini SAM M4", - "mcu_name": "SAMD51G19A", - "description": "Mini SAM M4 with SAMD51G19A", - "path": "repos/micropython/ports/samd/boards/MINISAM_M4/mpconfigboard.h" + "port": "stm32", + "board": "NUCLEO_F439ZI", + "board_name": "NUCLEO-F439ZI", + "mcu_name": "STM32F439ZIT6", + "description": "NUCLEO-F439ZI with STM32F439ZIT6", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_F439ZI/mpconfigboard.h", + "version": "v1.17" }, { - "port": "samd", - "board": "SAMD21_XPLAINED_PRO", - "board_name": "SAMD21-XPLAINED-PRO", - "mcu_name": "SAMD21J18A", - "description": "SAMD21-XPLAINED-PRO with SAMD21J18A", - "path": "repos/micropython/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h" + "port": "stm32", + "board": "NUCLEO_F446RE", + "board_name": "NUCLEO-F446RE", + "mcu_name": "STM32F446xx", + "description": "NUCLEO-F446RE with STM32F446xx", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.h", + "version": "v1.10" }, { - "port": "samd", - "board": "SEEED_WIO_TERMINAL", - "board_name": "Wio Terminal D51R", - "mcu_name": "SAMD51P19A", - "description": "Wio Terminal D51R with SAMD51P19A", - "path": "repos/micropython/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h" + "port": "stm32", + "board": "NUCLEO_F722ZE", + "board_name": "NUCLEO-F722ZE", + "mcu_name": "STM32F722", + "description": "NUCLEO-F722ZE with STM32F722", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.h", + "version": "v1.12" }, { - "port": "samd", - "board": "SEEED_XIAO_SAMD21", - "board_name": "Seeed Xiao", - "mcu_name": "SAMD21G18A", - "description": "Seeed Xiao with SAMD21G18A", - "path": "repos/micropython/ports/samd/boards/SEEED_XIAO_SAMD21/mpconfigboard.h" + "port": "stm32", + "board": "NUCLEO_F746ZG", + "board_name": "NUCLEO-F746ZG", + "mcu_name": "STM32F746", + "description": "NUCLEO-F746ZG with STM32F746", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.h", + "version": "v1.10" }, { - "port": "samd", - "board": "SPARKFUN_SAMD51_THING_PLUS", - "board_name": "Sparkfun SAMD51 Thing Plus", - "mcu_name": "SAMD51J20A", - "description": "Sparkfun SAMD51 Thing Plus with SAMD51J20A", - "path": "repos/micropython/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h" + "port": "stm32", + "board": "NUCLEO_F756ZG", + "board_name": "NUCLEO-F756ZG", + "mcu_name": "STM32F756", + "description": "NUCLEO-F756ZG with STM32F756", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_F756ZG/mpconfigboard.h", + "version": "v1.20.0" }, { "port": "stm32", - "board": "ADAFRUIT_F405_EXPRESS", - "board_name": "Adafruit Feather STM32F405", - "mcu_name": "STM32F405RG", - "description": "Adafruit Feather STM32F405 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h" + "board": "NUCLEO_F767ZI", + "board_name": "NUCLEO-F767ZI", + "mcu_name": "STM32F767", + "description": "NUCLEO-F767ZI with STM32F767", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h", + "version": "v1.10" }, { "port": "stm32", - "board": "ARDUINO_GIGA", - "board_name": "GIGA", - "mcu_name": "STM32H747", - "description": "GIGA with STM32H747", - "path": "repos/micropython/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h" + "board": "NUCLEO_G0B1RE", + "board_name": "NUCLEO-G0B1RE", + "mcu_name": "STM32G0B1xE", + "description": "NUCLEO-G0B1RE with STM32G0B1xE", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.h", + "version": "v1.19.1" }, { "port": "stm32", - "board": "ARDUINO_NICLA_VISION", - "board_name": "NICLAVISION", - "mcu_name": "STM32H747", - "description": "NICLAVISION with STM32H747", - "path": "repos/micropython/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h" + "board": "NUCLEO_L073RZ", + "board_name": "NUCLEO-L073RZ", + "mcu_name": "STM32L073RZT6", + "description": "NUCLEO-L073RZ with STM32L073RZT6", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h", + "version": "v1.12" }, { "port": "stm32", - "board": "ARDUINO_PORTENTA_H7", - "board_name": "PORTENTA", - "mcu_name": "STM32H747", - "description": "PORTENTA with STM32H747", - "path": "repos/micropython/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h" + "board": "NUCLEO_L152RE", + "board_name": "NUCLEO-L152RE", + "mcu_name": "STM32L152xE", + "description": "NUCLEO-L152RE with STM32L152xE", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.h", + "version": "v1.20.0" }, { "port": "stm32", - "board": "B_L072Z_LRWAN1", - "board_name": "B-L072Z-LRWAN1", - "mcu_name": "STM32L072CZ", - "description": "B-L072Z-LRWAN1 with STM32L072CZ", - "path": "repos/micropython/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h" + "board": "NUCLEO_L432KC", + "board_name": "NUCLEO-L432KC", + "mcu_name": "STM32L432KC", + "description": "NUCLEO-L432KC with STM32L432KC", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h", + "version": "v1.10" }, { "port": "stm32", - "board": "B_L475E_IOT01A", - "board_name": "B-L475E-IOT01A", - "mcu_name": "STM32L475", - "description": "B-L475E-IOT01A with STM32L475", - "path": "repos/micropython/ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.h" + "board": "NUCLEO_L452RE", + "board_name": "NUCLEO-L452RE", + "mcu_name": "STM32L452RE", + "description": "NUCLEO-L452RE with STM32L452RE", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.h", + "version": "v1.12" }, { "port": "stm32", - "board": "CERB40", - "board_name": "Cerb40", - "mcu_name": "STM32F405RG", - "description": "Cerb40 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/CERB40/mpconfigboard.h" + "board": "NUCLEO_L476RG", + "board_name": "NUCLEO-L476RG", + "mcu_name": "STM32L476RG", + "description": "NUCLEO-L476RG with STM32L476RG", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.h", + "version": "v1.10" }, { "port": "stm32", - "board": "ESPRUINO_PICO", - "board_name": "Espruino Pico", - "mcu_name": "STM32F401CD", - "description": "Espruino Pico with STM32F401CD", - "path": "repos/micropython/ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.h" + "board": "NUCLEO_L4A6ZG", + "board_name": "NUCLEO-L4A6ZG", + "mcu_name": "STM32L4A6ZG", + "description": "NUCLEO-L4A6ZG with STM32L4A6ZG", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_L4A6ZG/mpconfigboard.h", + "version": "v1.21.0" }, { "port": "stm32", - "board": "GARATRONIC_NADHAT_F405", - "board_name": "NADHAT_PYBF405", - "mcu_name": "STM32F405RG", - "description": "NADHAT_PYBF405 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/GARATRONIC_NADHAT_F405/mpconfigboard.h" + "board": "NUCLEO_WB55", + "board_name": "NUCLEO-WB55", + "mcu_name": "STM32WB55RGV6", + "description": "NUCLEO-WB55 with STM32WB55RGV6", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h", + "version": "v1.12" }, { "port": "stm32", - "board": "GARATRONIC_PYBSTICK26_F411", - "board_name": "PYBSTICK26_STD", - "mcu_name": "STM32F411RE", - "description": "PYBSTICK26_STD with STM32F411RE", - "path": "repos/micropython/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/mpconfigboard.h" + "board": "NUCLEO_WL55", + "board_name": "NUCLEO-WL55", + "mcu_name": "STM32WL55JCI7", + "description": "NUCLEO-WL55 with STM32WL55JCI7", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_WL55/mpconfigboard.h", + "version": "v1.19.1" }, { "port": "stm32", - "board": "HYDRABUS", - "board_name": "HydraBus1.0", - "mcu_name": "STM32F4", - "description": "HydraBus1.0 with STM32F4", - "path": "repos/micropython/ports/stm32/boards/HYDRABUS/mpconfigboard.h" + "board": "NUCLEO_G474RE", + "board_name": "NUCLEO_G474RE", + "mcu_name": "STM32G474", + "description": "NUCLEO_G474RE with STM32G474", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_G474RE/mpconfigboard.h", + "version": "v1.19.1" }, { "port": "stm32", - "board": "LEGO_HUB_NO6", - "board_name": "LEGO Technic Hub No.6", - "mcu_name": "STM32F413", - "description": "LEGO Technic Hub No.6 with STM32F413", - "path": "repos/micropython/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h" + "board": "NUCLEO_H563ZI", + "board_name": "NUCLEO_H563ZI", + "mcu_name": "STM32H563ZI", + "description": "NUCLEO_H563ZI with STM32H563ZI", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_H563ZI/mpconfigboard.h", + "version": "v1.22.0" }, { "port": "stm32", - "board": "LEGO_HUB_NO7", - "board_name": "LEGO Technic Hub No.7", - "mcu_name": "STM32F413", - "description": "LEGO Technic Hub No.7 with STM32F413", - "path": "repos/micropython/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h" + "board": "NUCLEO_H723ZG", + "board_name": "NUCLEO_H723ZG", + "mcu_name": "STM32H723ZGT6", + "description": "NUCLEO_H723ZG with STM32H723ZGT6", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_H723ZG/mpconfigboard.h", + "version": "v1.20.0" }, { "port": "stm32", - "board": "LIMIFROG", - "board_name": "LIMIFROG", - "mcu_name": "STM32L476", - "description": "LIMIFROG with STM32L476", - "path": "repos/micropython/ports/stm32/boards/LIMIFROG/mpconfigboard.h" + "board": "NUCLEO_H743ZI", + "board_name": "NUCLEO_H743ZI", + "mcu_name": "STM32H743", + "description": "NUCLEO_H743ZI with STM32H743", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h", + "version": "v1.10" }, { "port": "stm32", - "board": "MIKROE_CLICKER2_STM32", - "board_name": "MIKROE_CLICKER2_STM32", - "mcu_name": "STM32F407", - "description": "MIKROE_CLICKER2_STM32 with STM32F407", - "path": "repos/micropython/ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.h" + "board": "NUCLEO_H743ZI2", + "board_name": "NUCLEO_H743ZI2", + "mcu_name": "-", + "description": "NUCLEO_H743ZI2", + "path": "repos/micropython/ports/stm32/boards/NUCLEO_H743ZI2/mpconfigboard.h", + "version": "v1.17" }, { - "port": "stm32", - "board": "MIKROE_QUAIL", - "board_name": "MikroE Quail", - "mcu_name": "STM32F427VI", - "description": "MikroE Quail with STM32F427VI", - "path": "repos/micropython/ports/stm32/boards/MIKROE_QUAIL/mpconfigboard.h" + "port": "esp32", + "board": "UM_NANOS3", + "board_name": "NanoS3", + "mcu_name": "ESP32-S3-FN8", + "description": "NanoS3 with ESP32-S3-FN8", + "path": "repos/micropython/ports/esp32/boards/UM_NANOS3/mpconfigboard.h", + "version": "v1.21.0" }, { "port": "stm32", @@ -869,287 +968,413 @@ "board_name": "NetduinoPlus2", "mcu_name": "STM32F405RG", "description": "NetduinoPlus2 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/NETDUINO_PLUS_2/mpconfigboard.h" + "path": "repos/micropython/ports/stm32/boards/NETDUINO_PLUS_2/mpconfigboard.h", + "version": "v1.10" }, { "port": "stm32", - "board": "NUCLEO_F091RC", - "board_name": "NUCLEO-F091RC", - "mcu_name": "STM32F091RCT6", - "description": "NUCLEO-F091RC with STM32F091RCT6", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h" + "board": "OLIMEX_E407", + "board_name": "OLIMEX STM32-E407", + "mcu_name": "STM32F407", + "description": "OLIMEX STM32-E407 with STM32F407", + "path": "repos/micropython/ports/stm32/boards/OLIMEX_E407/mpconfigboard.h", + "version": "v1.10" }, { "port": "stm32", - "board": "NUCLEO_F401RE", - "board_name": "NUCLEO-F401RE", - "mcu_name": "STM32F401xE", - "description": "NUCLEO-F401RE with STM32F401xE", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F401RE/mpconfigboard.h" + "board": "OLIMEX_H407", + "board_name": "OLIMEX STM32-H407", + "mcu_name": "STM32F407", + "description": "OLIMEX STM32-H407 with STM32F407", + "path": "repos/micropython/ports/stm32/boards/OLIMEX_H407/mpconfigboard.h", + "version": "v1.18" + }, + { + "port": "esp32", + "board": "OLIMEX_ESP32_POE", + "board_name": "Olimex ESP32 ETH", + "mcu_name": "ESP32", + "description": "Olimex ESP32 ETH with ESP32", + "path": "repos/micropython/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h", + "version": "v1.20.0" + }, + { + "port": "nrf", + "board": "PCA10000", + "board_name": "PCA10000", + "mcu_name": "NRF51822", + "description": "PCA10000 with NRF51822", + "path": "repos/micropython/ports/nrf/boards/PCA10000/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "nrf", + "board": "PCA10001", + "board_name": "PCA10001", + "mcu_name": "NRF51822", + "description": "PCA10001 with NRF51822", + "path": "repos/micropython/ports/nrf/boards/PCA10001/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "nrf", + "board": "PCA10028", + "board_name": "PCA10028", + "mcu_name": "NRF51822", + "description": "PCA10028 with NRF51822", + "path": "repos/micropython/ports/nrf/boards/PCA10028/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "nrf", + "board": "PCA10031", + "board_name": "PCA10031", + "mcu_name": "NRF51822", + "description": "PCA10031 with NRF51822", + "path": "repos/micropython/ports/nrf/boards/PCA10031/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "nrf", + "board": "PCA10040", + "board_name": "PCA10040", + "mcu_name": "NRF52832", + "description": "PCA10040 with NRF52832", + "path": "repos/micropython/ports/nrf/boards/PCA10040/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "nrf", + "board": "PCA10056", + "board_name": "PCA10056", + "mcu_name": "NRF52840", + "description": "PCA10056 with NRF52840", + "path": "repos/micropython/ports/nrf/boards/PCA10056/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "nrf", + "board": "PCA10059", + "board_name": "PCA10059", + "mcu_name": "NRF52840", + "description": "PCA10059 with NRF52840", + "path": "repos/micropython/ports/nrf/boards/PCA10059/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "nrf", + "board": "PCA10090", + "board_name": "PCA10090", + "mcu_name": "NRF9160", + "description": "PCA10090 with NRF9160", + "path": "repos/micropython/ports/nrf/boards/PCA10090/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "stm32", - "board": "NUCLEO_F411RE", - "board_name": "NUCLEO-F411RE", - "mcu_name": "STM32F411xE", - "description": "NUCLEO-F411RE with STM32F411xE", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F411RE/mpconfigboard.h" + "port": "renesas-ra", + "board": "ARDUINO_PORTENTA_C33", + "board_name": "PORTENTA C33", + "mcu_name": "RA6M5", + "description": "PORTENTA C33 with RA6M5", + "path": "repos/micropython/ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/mpconfigboard.h", + "version": "v1.21.0" }, { "port": "stm32", - "board": "NUCLEO_F412ZG", - "board_name": "NUCLEO-F412ZG", - "mcu_name": "STM32F412Zx", - "description": "NUCLEO-F412ZG with STM32F412Zx", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F412ZG/mpconfigboard.h" + "board": "ARDUINO_PORTENTA_H7", + "board_name": "PORTENTA", + "mcu_name": "STM32H747", + "description": "PORTENTA with STM32H747", + "path": "repos/micropython/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h", + "version": "v1.19.1" }, { "port": "stm32", - "board": "NUCLEO_F413ZH", - "board_name": "NUCLEO-F413ZH", - "mcu_name": "STM32F413", - "description": "NUCLEO-F413ZH with STM32F413", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.h" + "board": "PYBD_SF2", + "board_name": "PYBD-SF2W", + "mcu_name": "STM32F722IEK", + "description": "PYBD-SF2W with STM32F722IEK", + "path": "repos/micropython/ports/stm32/boards/PYBD_SF2/mpconfigboard.h", + "version": "v1.12" }, { "port": "stm32", - "board": "NUCLEO_F429ZI", - "board_name": "NUCLEO-F429ZI", - "mcu_name": "STM32F429", - "description": "NUCLEO-F429ZI with STM32F429", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.h" + "board": "PYBD_SF3", + "board_name": "PYBD-SF3W", + "mcu_name": "STM32F733IEK", + "description": "PYBD-SF3W with STM32F733IEK", + "path": "repos/micropython/ports/stm32/boards/PYBD_SF3/mpconfigboard.h", + "version": "v1.12" }, { "port": "stm32", - "board": "NUCLEO_F439ZI", - "board_name": "NUCLEO-F439ZI", - "mcu_name": "STM32F439ZIT6", - "description": "NUCLEO-F439ZI with STM32F439ZIT6", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F439ZI/mpconfigboard.h" + "board": "PYBD_SF6", + "board_name": "PYBD-SF6W", + "mcu_name": "STM32F767IIK", + "description": "PYBD-SF6W with STM32F767IIK", + "path": "repos/micropython/ports/stm32/boards/PYBD_SF6/mpconfigboard.h", + "version": "v1.12" }, { "port": "stm32", - "board": "NUCLEO_F446RE", - "board_name": "NUCLEO-F446RE", - "mcu_name": "STM32F446xx", - "description": "NUCLEO-F446RE with STM32F446xx", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.h" + "board": "PYBLITEV10", + "board_name": "PYBLITEv1.0", + "mcu_name": "STM32F411RE", + "description": "PYBLITEv1.0 with STM32F411RE", + "path": "repos/micropython/ports/stm32/boards/PYBLITEV10/mpconfigboard.h", + "version": "v1.10" }, { "port": "stm32", - "board": "NUCLEO_F722ZE", - "board_name": "NUCLEO-F722ZE", - "mcu_name": "STM32F722", - "description": "NUCLEO-F722ZE with STM32F722", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.h" + "board": "GARATRONIC_PYBSTICK26_F411", + "board_name": "PYBSTICK26_STD", + "mcu_name": "STM32F411RE", + "description": "PYBSTICK26_STD with STM32F411RE", + "path": "repos/micropython/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/mpconfigboard.h", + "version": "v1.18" }, { "port": "stm32", - "board": "NUCLEO_F746ZG", - "board_name": "NUCLEO-F746ZG", - "mcu_name": "STM32F746", - "description": "NUCLEO-F746ZG with STM32F746", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.h" + "board": "PYBV10", + "board_name": "PYBv1.0", + "mcu_name": "STM32F405RG", + "description": "PYBv1.0 with STM32F405RG", + "path": "repos/micropython/ports/stm32/boards/PYBV10/mpconfigboard.h", + "version": "v1.10" }, { "port": "stm32", - "board": "NUCLEO_F756ZG", - "board_name": "NUCLEO-F756ZG", - "mcu_name": "STM32F756", - "description": "NUCLEO-F756ZG with STM32F756", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F756ZG/mpconfigboard.h" + "board": "PYBV11", + "board_name": "PYBv1.1", + "mcu_name": "STM32F405RG", + "description": "PYBv1.1 with STM32F405RG", + "path": "repos/micropython/ports/stm32/boards/PYBV11/mpconfigboard.h", + "version": "v1.10" }, { "port": "stm32", - "board": "NUCLEO_F767ZI", - "board_name": "NUCLEO-F767ZI", - "mcu_name": "STM32F767", - "description": "NUCLEO-F767ZI with STM32F767", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h" + "board": "PYBV3", + "board_name": "PYBv3", + "mcu_name": "STM32F405RG", + "description": "PYBv3 with STM32F405RG", + "path": "repos/micropython/ports/stm32/boards/PYBV3/mpconfigboard.h", + "version": "v1.10" }, { "port": "stm32", - "board": "NUCLEO_G0B1RE", - "board_name": "NUCLEO-G0B1RE", - "mcu_name": "STM32G0B1xE", - "description": "NUCLEO-G0B1RE with STM32G0B1xE", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.h" + "board": "PYBV4", + "board_name": "PYBv4", + "mcu_name": "STM32F405RG", + "description": "PYBv4 with STM32F405RG", + "path": "repos/micropython/ports/stm32/boards/PYBV4/mpconfigboard.h", + "version": "v1.10" }, { - "port": "stm32", - "board": "NUCLEO_G474RE", - "board_name": "NUCLEO_G474RE", - "mcu_name": "STM32G474", - "description": "NUCLEO_G474RE with STM32G474", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_G474RE/mpconfigboard.h" + "port": "rp2", + "board": "PIMORONI_PICOLIPO_16MB", + "board_name": "Pimoroni Pico LiPo 16MB", + "mcu_name": "-", + "description": "Pimoroni Pico LiPo 16MB", + "path": "repos/micropython/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h", + "version": "v1.17" }, { - "port": "stm32", - "board": "NUCLEO_H723ZG", - "board_name": "NUCLEO_H723ZG", - "mcu_name": "STM32H723ZGT6", - "description": "NUCLEO_H723ZG with STM32H723ZGT6", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_H723ZG/mpconfigboard.h" + "port": "rp2", + "board": "PIMORONI_PICOLIPO_4MB", + "board_name": "Pimoroni Pico LiPo 4MB", + "mcu_name": "-", + "description": "Pimoroni Pico LiPo 4MB", + "path": "repos/micropython/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h", + "version": "v1.17" }, { - "port": "stm32", - "board": "NUCLEO_H743ZI", - "board_name": "NUCLEO_H743ZI", - "mcu_name": "STM32H743", - "description": "NUCLEO_H743ZI with STM32H743", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h" + "port": "rp2", + "board": "PIMORONI_TINY2040", + "board_name": "Pimoroni Tiny 2040", + "mcu_name": "-", + "description": "Pimoroni Tiny 2040", + "path": "repos/micropython/ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h", + "version": "v1.17" }, { - "port": "stm32", - "board": "NUCLEO_H743ZI2", - "board_name": "NUCLEO_H743ZI2", + "port": "rp2", + "board": "POLOLU_3PI_2040_ROBOT", + "board_name": "Pololu 3pi+ 2040 Robot", "mcu_name": "-", - "description": "NUCLEO_H743ZI2", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_H743ZI2/mpconfigboard.h" + "description": "Pololu 3pi+ 2040 Robot", + "path": "repos/micropython/ports/rp2/boards/POLOLU_3PI_2040_ROBOT/mpconfigboard.h", + "version": "v1.22.0" }, { - "port": "stm32", - "board": "NUCLEO_L073RZ", - "board_name": "NUCLEO-L073RZ", - "mcu_name": "STM32L073RZT6", - "description": "NUCLEO-L073RZ with STM32L073RZT6", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h" + "port": "rp2", + "board": "POLOLU_ZUMO_2040_ROBOT", + "board_name": "Pololu Zumo 2040 Robot", + "mcu_name": "-", + "description": "Pololu Zumo 2040 Robot", + "path": "repos/micropython/ports/rp2/boards/POLOLU_ZUMO_2040_ROBOT/mpconfigboard.h", + "version": "v1.22.0" }, { - "port": "stm32", - "board": "NUCLEO_L152RE", - "board_name": "NUCLEO-L152RE", - "mcu_name": "STM32L152xE", - "description": "NUCLEO-L152RE with STM32L152xE", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.h" + "port": "esp32", + "board": "UM_PROS3", + "board_name": "ProS3", + "mcu_name": "ESP32-S3", + "description": "ProS3 with ESP32-S3", + "path": "repos/micropython/ports/esp32/boards/UM_PROS3/mpconfigboard.h", + "version": "v1.19.1" }, { - "port": "stm32", - "board": "NUCLEO_L432KC", - "board_name": "NUCLEO-L432KC", - "mcu_name": "STM32L432KC", - "description": "NUCLEO-L432KC with STM32L432KC", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h" + "port": "renesas-ra", + "board": "RA4M1_CLICKER", + "board_name": "RA4M1 CLICKER", + "mcu_name": "RA4M1", + "description": "RA4M1 CLICKER with RA4M1", + "path": "repos/micropython/ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h", + "version": "v1.21.0" }, { - "port": "stm32", - "board": "NUCLEO_L452RE", - "board_name": "NUCLEO-L452RE", - "mcu_name": "STM32L452RE", - "description": "NUCLEO-L452RE with STM32L452RE", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.h" + "port": "renesas-ra", + "board": "RA4M1_CLICKER", + "board_name": "RA4M1_CLICKER", + "mcu_name": "RA4M1", + "description": "RA4M1_CLICKER with RA4M1", + "path": "repos/micropython/ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h", + "version": "v1.19.1" }, { - "port": "stm32", - "board": "NUCLEO_L476RG", - "board_name": "NUCLEO-L476RG", - "mcu_name": "STM32L476RG", - "description": "NUCLEO-L476RG with STM32L476RG", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.h" + "port": "renesas-ra", + "board": "RA4M1_EK", + "board_name": "RA4M1_EK", + "mcu_name": "RA4M1", + "description": "RA4M1_EK with RA4M1", + "path": "repos/micropython/ports/renesas-ra/boards/RA4M1_EK/mpconfigboard.h", + "version": "v1.19.1" }, { - "port": "stm32", - "board": "NUCLEO_L4A6ZG", - "board_name": "NUCLEO-L4A6ZG", - "mcu_name": "STM32L4A6ZG", - "description": "NUCLEO-L4A6ZG with STM32L4A6ZG", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_L4A6ZG/mpconfigboard.h" + "port": "renesas-ra", + "board": "RA4W1_EK", + "board_name": "RA4W1_EK", + "mcu_name": "RA4W1", + "description": "RA4W1_EK with RA4W1", + "path": "repos/micropython/ports/renesas-ra/boards/RA4W1_EK/mpconfigboard.h", + "version": "v1.19.1" }, { - "port": "stm32", - "board": "NUCLEO_WB55", - "board_name": "NUCLEO-WB55", - "mcu_name": "STM32WB55RGV6", - "description": "NUCLEO-WB55 with STM32WB55RGV6", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h" + "port": "renesas-ra", + "board": "RA6M1_EK", + "board_name": "RA6M1_EK", + "mcu_name": "RA6M1", + "description": "RA6M1_EK with RA6M1", + "path": "repos/micropython/ports/renesas-ra/boards/RA6M1_EK/mpconfigboard.h", + "version": "v1.19.1" }, { - "port": "stm32", - "board": "NUCLEO_WL55", - "board_name": "NUCLEO-WL55", - "mcu_name": "STM32WL55JCI7", - "description": "NUCLEO-WL55 with STM32WL55JCI7", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_WL55/mpconfigboard.h" + "port": "renesas-ra", + "board": "RA6M2_EK", + "board_name": "RA6M2_EK", + "mcu_name": "RA6M2", + "description": "RA6M2_EK with RA6M2", + "path": "repos/micropython/ports/renesas-ra/boards/RA6M2_EK/mpconfigboard.h", + "version": "v1.19.1" }, { - "port": "stm32", - "board": "OLIMEX_E407", - "board_name": "OLIMEX STM32-E407", - "mcu_name": "STM32F407", - "description": "OLIMEX STM32-E407 with STM32F407", - "path": "repos/micropython/ports/stm32/boards/OLIMEX_E407/mpconfigboard.h" + "port": "mimxrt", + "board": "OLIMEX_RT1010", + "board_name": "RT1010-Py-DevKIT", + "mcu_name": "MIMXRT1011DAE5A", + "description": "RT1010-Py-DevKIT with MIMXRT1011DAE5A", + "path": "repos/micropython/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h", + "version": "v1.19.1" }, { - "port": "stm32", - "board": "OLIMEX_H407", - "board_name": "OLIMEX STM32-H407", - "mcu_name": "STM32F407", - "description": "OLIMEX STM32-H407 with STM32F407", - "path": "repos/micropython/ports/stm32/boards/OLIMEX_H407/mpconfigboard.h" + "port": "rp2", + "board": "PICO", + "board_name": "Raspberry Pi Pico", + "mcu_name": "-", + "description": "Raspberry Pi Pico", + "path": "repos/micropython/ports/rp2/boards/PICO/mpconfigboard.h", + "version": "v1.15" }, { - "port": "stm32", - "board": "PYBD_SF2", - "board_name": "PYBD-SF2W", - "mcu_name": "STM32F722IEK", - "description": "PYBD-SF2W with STM32F722IEK", - "path": "repos/micropython/ports/stm32/boards/PYBD_SF2/mpconfigboard.h" + "port": "rp2", + "board": "PICO_W", + "board_name": "Raspberry Pi Pico W", + "mcu_name": "-", + "description": "Raspberry Pi Pico W", + "path": "repos/micropython/ports/rp2/boards/PICO_W/mpconfigboard.h", + "version": "v1.20.0" }, { - "port": "stm32", - "board": "PYBD_SF3", - "board_name": "PYBD-SF3W", - "mcu_name": "STM32F733IEK", - "description": "PYBD-SF3W with STM32F733IEK", - "path": "repos/micropython/ports/stm32/boards/PYBD_SF3/mpconfigboard.h" + "port": "samd", + "board": "SAMD21_XPLAINED_PRO", + "board_name": "SAMD21-XPLAINED-PRO", + "mcu_name": "SAMD21J18A", + "description": "SAMD21-XPLAINED-PRO with SAMD21J18A", + "path": "repos/micropython/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h", + "version": "v1.12" }, { "port": "stm32", - "board": "PYBD_SF6", - "board_name": "PYBD-SF6W", - "mcu_name": "STM32F767IIK", - "description": "PYBD-SF6W with STM32F767IIK", - "path": "repos/micropython/ports/stm32/boards/PYBD_SF6/mpconfigboard.h" + "board": "STM32H573I_DK", + "board_name": "STM32H573I-DK", + "mcu_name": "STM32H573IIK3Q", + "description": "STM32H573I-DK with STM32H573IIK3Q", + "path": "repos/micropython/ports/stm32/boards/STM32H573I_DK/mpconfigboard.h", + "version": "v1.21.0" }, { "port": "stm32", - "board": "PYBLITEV10", - "board_name": "PYBLITEv1.0", - "mcu_name": "STM32F411RE", - "description": "PYBLITEv1.0 with STM32F411RE", - "path": "repos/micropython/ports/stm32/boards/PYBLITEV10/mpconfigboard.h" + "board": "STM32H7B3I_DK", + "board_name": "STM32H7B3I-DK", + "mcu_name": "STM32H7B3LIH6Q", + "description": "STM32H7B3I-DK with STM32H7B3LIH6Q", + "path": "repos/micropython/ports/stm32/boards/STM32H7B3I_DK/mpconfigboard.h", + "version": "v1.18" }, { - "port": "stm32", - "board": "PYBV10", - "board_name": "PYBv1.0", - "mcu_name": "STM32F405RG", - "description": "PYBv1.0 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/PYBV10/mpconfigboard.h" + "port": "mimxrt", + "board": "SEEED_ARCH_MIX", + "board_name": "Seeed ARCH MIX", + "mcu_name": "MIMXRT1052DVL5B", + "description": "Seeed ARCH MIX with MIMXRT1052DVL5B", + "path": "repos/micropython/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h", + "version": "v1.18" + }, + { + "port": "samd", + "board": "SEEED_XIAO", + "board_name": "Seeed Xiao", + "mcu_name": "SAMD21G18A", + "description": "Seeed Xiao with SAMD21G18A", + "path": "repos/micropython/ports/samd/boards/SEEED_XIAO/mpconfigboard.h", + "version": "v1.18" }, { - "port": "stm32", - "board": "PYBV11", - "board_name": "PYBv1.1", - "mcu_name": "STM32F405RG", - "description": "PYBv1.1 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/PYBV11/mpconfigboard.h" + "port": "rp2", + "board": "SIL_RP2040_SHIM", + "board_name": "Silicognition RP2040-Shim", + "mcu_name": "-", + "description": "Silicognition RP2040-Shim", + "path": "repos/micropython/ports/rp2/boards/SIL_RP2040_SHIM/mpconfigboard.h", + "version": "v1.22.0" }, { - "port": "stm32", - "board": "PYBV3", - "board_name": "PYBv3", - "mcu_name": "STM32F405RG", - "description": "PYBv3 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/PYBV3/mpconfigboard.h" + "port": "esp32", + "board": "SIL_WESP32", + "board_name": "Silicognition wESP32", + "mcu_name": "ESP32", + "description": "Silicognition wESP32 with ESP32", + "path": "repos/micropython/ports/esp32/boards/SIL_WESP32/mpconfigboard.h", + "version": "v1.17" }, { - "port": "stm32", - "board": "PYBV4", - "board_name": "PYBv4", - "mcu_name": "STM32F405RG", - "description": "PYBv4 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/PYBV4/mpconfigboard.h" + "port": "rp2", + "board": "SPARKFUN_PROMICRO", + "board_name": "SparkFun Pro Micro RP2040", + "mcu_name": "-", + "description": "SparkFun Pro Micro RP2040", + "path": "repos/micropython/ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h", + "version": "v1.16" }, { "port": "stm32", @@ -1157,87 +1382,89 @@ "board_name": "SparkFun STM32 MicroMod Processor", "mcu_name": "STM32F405RG", "description": "SparkFun STM32 MicroMod Processor with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/SPARKFUN_MICROMOD_STM32/mpconfigboard.h" - }, - { - "port": "stm32", - "board": "STM32F411DISC", - "board_name": "F411DISC", - "mcu_name": "STM32F411", - "description": "F411DISC with STM32F411", - "path": "repos/micropython/ports/stm32/boards/STM32F411DISC/mpconfigboard.h" + "path": "repos/micropython/ports/stm32/boards/SPARKFUN_MICROMOD_STM32/mpconfigboard.h", + "version": "v1.17" }, { - "port": "stm32", - "board": "STM32F429DISC", - "board_name": "F429I-DISCO", - "mcu_name": "STM32F429", - "description": "F429I-DISCO with STM32F429", - "path": "repos/micropython/ports/stm32/boards/STM32F429DISC/mpconfigboard.h" + "port": "rp2", + "board": "SPARKFUN_THINGPLUS", + "board_name": "SparkFun Thing Plus RP2040", + "mcu_name": "-", + "description": "SparkFun Thing Plus RP2040", + "path": "repos/micropython/ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h", + "version": "v1.16" }, { - "port": "stm32", - "board": "STM32F439", - "board_name": "CustomPCB", - "mcu_name": "STM32F439", - "description": "CustomPCB with STM32F439", - "path": "repos/micropython/ports/stm32/boards/STM32F439/mpconfigboard.h" + "port": "samd", + "board": "SPARKFUN_SAMD51_THING_PLUS", + "board_name": "Sparkfun SAMD51 Thing Plus", + "mcu_name": "SAMD51J20A", + "description": "Sparkfun SAMD51 Thing Plus with SAMD51J20A", + "path": "repos/micropython/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h", + "version": "v1.20.0" }, { - "port": "stm32", - "board": "STM32F4DISC", - "board_name": "F4DISC", - "mcu_name": "STM32F407", - "description": "F4DISC with STM32F407", - "path": "repos/micropython/ports/stm32/boards/STM32F4DISC/mpconfigboard.h" + "port": "mimxrt", + "board": "TEENSY40", + "board_name": "Teensy 4.0", + "mcu_name": "MIMXRT1062DVJ6A", + "description": "Teensy 4.0 with MIMXRT1062DVJ6A", + "path": "repos/micropython/ports/mimxrt/boards/TEENSY40/mpconfigboard.h", + "version": "v1.13" }, { - "port": "stm32", - "board": "STM32F769DISC", - "board_name": "F769DISC", - "mcu_name": "STM32F769", - "description": "F769DISC with STM32F769", - "path": "repos/micropython/ports/stm32/boards/STM32F769DISC/mpconfigboard.h" + "port": "mimxrt", + "board": "TEENSY41", + "board_name": "Teensy 4.1", + "mcu_name": "MIMXRT1062DVJ6A", + "description": "Teensy 4.1 with MIMXRT1062DVJ6A", + "path": "repos/micropython/ports/mimxrt/boards/TEENSY41/mpconfigboard.h", + "version": "v1.16" }, { - "port": "stm32", - "board": "STM32F7DISC", - "board_name": "F7DISC", - "mcu_name": "STM32F746", - "description": "F7DISC with STM32F746", - "path": "repos/micropython/ports/stm32/boards/STM32F7DISC/mpconfigboard.h" + "port": "esp32", + "board": "TINYPICO", + "board_name": "TinyPICO", + "mcu_name": "ESP32-PICO-D4", + "description": "TinyPICO with ESP32-PICO-D4", + "path": "repos/micropython/ports/esp32/boards/TINYPICO/mpconfigboard.h", + "version": "v1.12" }, { - "port": "stm32", - "board": "STM32H573I_DK", - "board_name": "STM32H573I-DK", - "mcu_name": "STM32H573IIK3Q", - "description": "STM32H573I-DK with STM32H573IIK3Q", - "path": "repos/micropython/ports/stm32/boards/STM32H573I_DK/mpconfigboard.h" + "port": "esp32", + "board": "UM_TINYS2", + "board_name": "TinyS2", + "mcu_name": "ESP32-S2FN4R2", + "description": "TinyS2 with ESP32-S2FN4R2", + "path": "repos/micropython/ports/esp32/boards/UM_TINYS2/mpconfigboard.h", + "version": "v1.16" }, { - "port": "stm32", - "board": "STM32H7B3I_DK", - "board_name": "STM32H7B3I-DK", - "mcu_name": "STM32H7B3LIH6Q", - "description": "STM32H7B3I-DK with STM32H7B3LIH6Q", - "path": "repos/micropython/ports/stm32/boards/STM32H7B3I_DK/mpconfigboard.h" + "port": "esp32", + "board": "UM_TINYS3", + "board_name": "TinyS3", + "mcu_name": "ESP32-S3-FN8", + "description": "TinyS3 with ESP32-S3-FN8", + "path": "repos/micropython/ports/esp32/boards/UM_TINYS3/mpconfigboard.h", + "version": "v1.19.1" }, { - "port": "stm32", - "board": "STM32L476DISC", - "board_name": "L476-DISCO", - "mcu_name": "STM32L476", - "description": "L476-DISCO with STM32L476", - "path": "repos/micropython/ports/stm32/boards/STM32L476DISC/mpconfigboard.h" + "port": "esp32", + "board": "UM_TINYWATCHS3", + "board_name": "TinyWATCH S3", + "mcu_name": "ESP32-S3-PICO-1-N8R2", + "description": "TinyWATCH S3 with ESP32-S3-PICO-1-N8R2", + "path": "repos/micropython/ports/esp32/boards/UM_TINYWATCHS3/mpconfigboard.h", + "version": "v1.22.0" }, { - "port": "stm32", - "board": "STM32L496GDISC", - "board_name": "L496G-DISCO", - "mcu_name": "STM32L496", - "description": "L496G-DISCO with STM32L496", - "path": "repos/micropython/ports/stm32/boards/STM32L496GDISC/mpconfigboard.h" + "port": "samd", + "board": "ADAFRUIT_TRINKET_M0", + "board_name": "Trinket M0", + "mcu_name": "SAMD21E18A", + "description": "Trinket M0 with SAMD21E18A", + "path": "repos/micropython/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h", + "version": "v1.12" }, { "port": "stm32", @@ -1245,7 +1472,8 @@ "board_name": "USBDongle-WB55", "mcu_name": "STM32WB55CGU6", "description": "USBDongle-WB55 with STM32WB55CGU6", - "path": "repos/micropython/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h" + "path": "repos/micropython/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h", + "version": "v1.12" }, { "port": "stm32", @@ -1253,7 +1481,8 @@ "board_name": "VCC-GND STM32F407VE", "mcu_name": "STM32F407VE", "description": "VCC-GND STM32F407VE with STM32F407VE", - "path": "repos/micropython/ports/stm32/boards/VCC_GND_F407VE/mpconfigboard.h" + "path": "repos/micropython/ports/stm32/boards/VCC_GND_F407VE/mpconfigboard.h", + "version": "v1.16" }, { "port": "stm32", @@ -1261,7 +1490,8 @@ "board_name": "VCC-GND STM32F407ZG", "mcu_name": "STM32F407ZG", "description": "VCC-GND STM32F407ZG with STM32F407ZG", - "path": "repos/micropython/ports/stm32/boards/VCC_GND_F407ZG/mpconfigboard.h" + "path": "repos/micropython/ports/stm32/boards/VCC_GND_F407ZG/mpconfigboard.h", + "version": "v1.16" }, { "port": "stm32", @@ -1269,6 +1499,187 @@ "board_name": "VCC-GND STM32H743VI", "mcu_name": "STM32H743VI", "description": "VCC-GND STM32H743VI with STM32H743VI", - "path": "repos/micropython/ports/stm32/boards/VCC_GND_H743VI/mpconfigboard.h" + "path": "repos/micropython/ports/stm32/boards/VCC_GND_H743VI/mpconfigboard.h", + "version": "v1.18" + }, + { + "port": "renesas-ra", + "board": "VK_RA6M5", + "board_name": "VK-RA6M5", + "mcu_name": "RA6M5", + "description": "VK-RA6M5 with RA6M5", + "path": "repos/micropython/ports/renesas-ra/boards/VK_RA6M5/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "rp2", + "board": "W5100S_EVB_PICO", + "board_name": "W5100S-EVB-Pico", + "mcu_name": "-", + "description": "W5100S-EVB-Pico", + "path": "repos/micropython/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.h", + "version": "v1.19.1" + }, + { + "port": "rp2", + "board": "W5500_EVB_PICO", + "board_name": "W5500-EVB-Pico", + "mcu_name": "-", + "description": "W5500-EVB-Pico", + "path": "repos/micropython/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.h", + "version": "v1.20.0" + }, + { + "port": "nrf", + "board": "WT51822_S4AT", + "board_name": "WT51822-S4AT", + "mcu_name": "NRF51822", + "description": "WT51822-S4AT with NRF51822", + "path": "repos/micropython/ports/nrf/boards/WT51822_S4AT/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "rp2", + "board": "WEACTSTUDIO", + "board_name": "WeAct Studio RP2040", + "mcu_name": "-", + "description": "WeAct Studio RP2040", + "path": "repos/micropython/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.h", + "version": "v1.20.0" + }, + { + "port": "cc3200", + "board": "WIPY", + "board_name": "WiPy", + "mcu_name": "CC3200", + "description": "WiPy with CC3200", + "path": "repos/micropython/ports/cc3200/boards/WIPY/mpconfigboard.h", + "version": "v1.10" + }, + { + "port": "samd", + "board": "SEEED_WIO_TERMINAL", + "board_name": "Wio Terminal D51R", + "mcu_name": "SAMD51P19A", + "description": "Wio Terminal D51R with SAMD51P19A", + "path": "repos/micropython/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h", + "version": "v1.18" + }, + { + "port": "nrf", + "board": "PARTICLE_XENON", + "board_name": "XENON", + "mcu_name": "NRF52840", + "description": "XENON with NRF52840", + "path": "repos/micropython/ports/nrf/boards/PARTICLE_XENON/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "nrf", + "board": "SEEED_XIAO_NRF52", + "board_name": "XIAO nRF52840 Sense", + "mcu_name": "NRF52840", + "description": "XIAO nRF52840 Sense with NRF52840", + "path": "repos/micropython/ports/nrf/boards/SEEED_XIAO_NRF52/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "mimxrt", + "board": "MIMXRT1010_EVK", + "board_name": "i.MX RT1010 EVK", + "mcu_name": "MIMXRT1011DAE5A", + "description": "i.MX RT1010 EVK with MIMXRT1011DAE5A", + "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h", + "version": "v1.13" + }, + { + "port": "mimxrt", + "board": "MIMXRT1015_EVK", + "board_name": "i.MX RT1015 EVK", + "mcu_name": "MIMXRT1015DAF5A", + "description": "i.MX RT1015 EVK with MIMXRT1015DAF5A", + "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h", + "version": "v1.19.1" + }, + { + "port": "mimxrt", + "board": "MIMXRT1020_EVK", + "board_name": "i.MX RT1020 EVK", + "mcu_name": "MIMXRT1021DAG5A", + "description": "i.MX RT1020 EVK with MIMXRT1021DAG5A", + "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h", + "version": "v1.13" + }, + { + "port": "mimxrt", + "board": "MIMXRT1050_EVK", + "board_name": "i.MX RT1050 EVK", + "mcu_name": "MIMXRT1052DVL6B", + "description": "i.MX RT1050 EVK with MIMXRT1052DVL6B", + "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h", + "version": "v1.15" + }, + { + "port": "mimxrt", + "board": "MIMXRT1050_EVKB", + "board_name": "i.MX RT1050 EVKB", + "mcu_name": "MIMXRT1052DVL6B", + "description": "i.MX RT1050 EVKB with MIMXRT1052DVL6B", + "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1050_EVKB/mpconfigboard.h", + "version": "v1.17" + }, + { + "port": "mimxrt", + "board": "MIMXRT1050_EVK", + "board_name": "i.MX RT1050 EVKB-A1", + "mcu_name": "MIMXRT1052DVL6B", + "description": "i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B", + "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h", + "version": "v1.18" + }, + { + "port": "mimxrt", + "board": "MIMXRT1060_EVK", + "board_name": "i.MX RT1060 EVK", + "mcu_name": "MIMXRT1062DVJ6A", + "description": "i.MX RT1060 EVK with MIMXRT1062DVJ6A", + "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h", + "version": "v1.13" + }, + { + "port": "mimxrt", + "board": "MIMXRT1064_EVK", + "board_name": "i.MX RT1064 EVK", + "mcu_name": "MIMXRT1064DVL6A", + "description": "i.MX RT1064 EVK with MIMXRT1064DVL6A", + "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h", + "version": "v1.14" + }, + { + "port": "mimxrt", + "board": "MIMXRT1170_EVK", + "board_name": "i.MX RT1170 EVK", + "mcu_name": "MIMXRT1176DVMAA", + "description": "i.MX RT1170 EVK with MIMXRT1176DVMAA", + "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h", + "version": "v1.20.0" + }, + { + "port": "nrf", + "board": "MICROBIT", + "board_name": "micro:bit", + "mcu_name": "NRF51822", + "description": "micro:bit with NRF51822", + "path": "repos/micropython/ports/nrf/boards/MICROBIT/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "port": "rp2", + "board": "NULLBITS_BIT_C_PRO", + "board_name": "nullbits Bit-C PRO", + "mcu_name": "-", + "description": "nullbits Bit-C PRO", + "path": "repos/micropython/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.h", + "version": "v1.20.0" } ] \ No newline at end of file From 4cfde8e8747abe2bd3d92f9e5e452d69109584ed Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Mon, 1 Jan 2024 23:44:52 +0100 Subject: [PATCH 06/68] boardnames: Add cmake variants. Signed-off-by: Jos Verlinde --- .../{get-boardnames.py => get_boardnames.py} | 72 +- src/stubber/data/board_info.csv | 77 +- src/stubber/data/board_info.json | 997 ++++++++---------- 3 files changed, 526 insertions(+), 620 deletions(-) rename scripts/{get-boardnames.py => get_boardnames.py} (59%) diff --git a/scripts/get-boardnames.py b/scripts/get_boardnames.py similarity index 59% rename from scripts/get-boardnames.py rename to scripts/get_boardnames.py index 5edfb1f9a..d9c6d5d79 100644 --- a/scripts/get-boardnames.py +++ b/scripts/get_boardnames.py @@ -13,15 +13,15 @@ import stubber.basicgit as git -@dataclass +@dataclass(kw_only=True) class Board: """MicroPython Board definition""" + description: str port: str board: str board_name: str mcu_name: str - description: str path: Path version: str = "" @@ -42,10 +42,13 @@ def default(self, o: object): RE_BOARD_NAME = re.compile(r"#define MICROPY_HW_BOARD_NAME\s+\"(.+)\"") RE_MCU_NAME = re.compile(r"#define MICROPY_HW_MCU_NAME\s+\"(.+)\"") +RE_CMAKE_BOARD_NAME = re.compile(r"MICROPY_HW_BOARD_NAME\s?=\s?\"(?P[\w\s\S]*)\"") +RE_CMAKE_MCU_NAME = re.compile(r"MICROPY_HW_MCU_NAME\s?=\s?\"(?P[\w\s\S]*)\"") +# TODO: normal make files def collect_boardinfo(mpy_path: Path, version: str) -> List[Board]: - """Collects board information from mpconfigboard.h files. + """Collects board name and decriptions from mpconfigboard.h files. Args: mpy_path (Path): The path to the MicroPython repository. @@ -55,7 +58,8 @@ def collect_boardinfo(mpy_path: Path, version: str) -> List[Board]: List[Board]: A list of Board objects containing the board information. """ board_list: List[Board] = [] - for path in mpy_path.glob("**/mpconfigboard.h"): + # look in boards + for path in mpy_path.glob("ports/**/mpconfigboard.h"): board = path.parent.name port = path.parent.parent.parent.name with open(path, "r") as f: @@ -69,9 +73,59 @@ def collect_boardinfo(mpy_path: Path, version: str) -> List[Board]: mcu_name = match[1] found += 1 if found == 2: - break - description = f"{board_name} with {mcu_name}" if mcu_name != "-" else board_name - board_list.append(Board(port, board, board_name, mcu_name, description, path, version)) + description = ( + f"{board_name} with {mcu_name}" if mcu_name != "-" else board_name + ) + board_list.append( + Board( + port=port, + board=board, + board_name=board_name, + mcu_name=mcu_name, + description=description, + path=path.relative_to(mpy_path), + version=version, + ) + ) + found = 0 + # look for variants in the .cmake files + for path in mpy_path.glob("ports/**/mpconfigboard.cmake"): + board = path.parent.name + port = path.parent.parent.parent.name + with open(path, "r") as f: + board_name = mcu_name = "-" + found = 0 + for line in f: + line = line.strip() + if match := RE_CMAKE_BOARD_NAME.match(line): + description = match["variant"] + board_list.append( + Board( + port=port, + board=board, + board_name=board_name, + mcu_name=mcu_name, + description=description, + path=path.relative_to(mpy_path), + version=version, + ) + ) + elif match := RE_CMAKE_MCU_NAME.match(line): + description = match["variant"] + board_list.append( + Board( + port=port, + board=board, + board_name=board_name, + mcu_name=mcu_name, + description=description, + path=path.relative_to(mpy_path), + version=version, + ) + ) + + # look for variants in the Makefile files + return board_list @@ -110,11 +164,13 @@ def get_board_list(versions: List[str], mpy_path: Path): board_list += new_ones # sort the board_list by description and board - board_list.sort(key=lambda x: (x.description, x.board)) print("Total number of boards found:", len(board_list)) seen = set() board_list = [x for x in board_list if not (x.description in seen or seen.add(x.description))] + board_list.sort(key=lambda x: x.description) print("Unique board descriptions found:", len(board_list)) + print(f" found OTA = {'Generic ESP32 module with OTA' in seen}") + print(f" found UNICORE = {'ESP32-UNICORE' in seen}") return board_list diff --git a/src/stubber/data/board_info.csv b/src/stubber/data/board_info.csv index e637a33e2..fe9cc4565 100644 --- a/src/stubber/data/board_info.csv +++ b/src/stubber/data/board_info.csv @@ -1,44 +1,42 @@ board,description 4MB/OTA module with ESP32,GENERIC_OTA -Actinius Icarus with NRF9160,ACTINIUS_ICARUS -Adafruit Feather RP2040,ADAFRUIT_FEATHER_RP2040 +Actinius Icarus with NRF9160,actinius_icarus Adafruit Feather STM32F405 with STM32F405RG,ADAFRUIT_F405_EXPRESS -Adafruit ItsyBitsy RP2040,ADAFRUIT_ITSYBITSY_RP2040 Adafruit Metro M7 with MIMXRT1011DAE5A,ADAFRUIT_METRO_M7 -Adafruit QT Py RP2040,ADAFRUIT_QTPY_RP2040 Arduino GIGA R1 WiFi with STM32H747,ARDUINO_GIGA -Arduino Nano 33 BLE Sense with NRF52840,ARDUINO_NANO_33_BLE_SENSE +Arduino Nano 33 BLE Sense with NRF52840,arduino_nano_33_ble_sense Arduino Nano ESP32 with ESP32S3,ARDUINO_NANO_ESP32 -Arduino Nano RP2040 Connect,ARDUINO_NANO_RP2040_CONNECT Arduino Nicla Vision with STM32H747,ARDUINO_NICLA_VISION Arduino Portenta C33 with RA6M5,ARDUINO_PORTENTA_C33 Arduino Portenta H7 with STM32H747,ARDUINO_PORTENTA_H7 -Arduino Primo with NRF52832,ARDUINO_PRIMO +Arduino Primo with NRF52832,arduino_primo B-L072Z-LRWAN1 with STM32L072CZ,B_L072Z_LRWAN1 B-L475E-IOT01A with STM32L475,B_L475E_IOT01A -BLUEIO-TAG-EVIM with NRF52832,BLUEIO_TAG_EVIM -Bluefruit nRF52 Feather with NRF52832,FEATHER52 +BLUEIO-TAG-EVIM with NRF52832,blueio_tag_evim +Bluefruit nRF52 Feather with NRF52832,feather52 Cerb40 with STM32F405RG,CERB40 CustomPCB with STM32F439,STM32F439 -DVK-BL652 with NRF52832,DVK_BL652 +DVK-BL652 with NRF52832,dvk_bl652 EK-RA4M1 with RA4M1,EK_RA4M1 EK-RA4W1 with RA4W1,EK_RA4W1 EK-RA6M1 with RA6M1,EK_RA6M1 EK-RA6M2 with RA6M2,EK_RA6M2 ESP module (1M) with ESP8266,GENERIC_1M ESP module (512K) with ESP8266,GENERIC_512K -ESP module with ESP8266,ESP8266_GENERIC +ESP module with ESP8266,GENERIC ESP32 Unicore module with ESP32-UNICORE,GENERIC_UNICORE ESP32 module (spiram) with ESP32,GENERIC_SPIRAM ESP32 module with ESP32,GENERIC +ESP32-D2WD,ESP32_GENERIC ESP32-S2-WROVER with ESP32-S2,ESP32_S2_WROVER -ESP32C3 module with ESP32C3,ESP32_GENERIC_C3 +ESP32-UNICORE,ESP32_GENERIC +ESP32C3 module with ESP32C3,GENERIC_C3 ESP32S2 module with ESP32S2,GENERIC_S2 ESP32S3 module (spiram octal) with ESP32S3,GENERIC_S3_SPIRAM_OCT ESP32S3 module (spiram) with ESP32S3,GENERIC_S3_SPIRAM ESP32S3 module with ESP32S3,GENERIC_S3 -EVK_NINA_B1 with NRF52832,EVK_NINA_B1 -EVK_NINA_B3 with NRF52840,EVK_NINA_B3 +EVK_NINA_B1 with NRF52832,evk_nina_b1 +EVK_NINA_B3 with NRF52840,evk_nina_b3 Espruino Pico with STM32F401CD,ESPRUINO_PICO F411DISC with STM32F411,STM32F411DISC F429I-DISCO with STM32F429,STM32F429DISC @@ -50,15 +48,17 @@ Feather M4 Express with SAMD51J19A,ADAFRUIT_FEATHER_M4_EXPRESS FeatherS2 Neo with ESP32-S2FN4R2,UM_FEATHERS2NEO FeatherS2 with ESP32-S2,UM_FEATHERS2 FeatherS3 with ESP32-S3,UM_FEATHERS3 -GARATRONIC_PYBSTICK26_RP2040,GARATRONIC_PYBSTICK26_RP2040 GIGA with STM32H747,ARDUINO_GIGA Generic ESP32 module with ESP32,ESP32_GENERIC +Generic ESP32 module with OTA,ESP32_GENERIC +Generic ESP32 module with SPIRAM,ESP32_GENERIC Generic ESP32-D2WD module with ESP32-D2WD,GENERIC_D2WD Generic ESP32S2 module with ESP32S2,ESP32_GENERIC_S2 Generic ESP32S3 module with ESP32S3,ESP32_GENERIC_S3 +Generic ESP32S3 module with Octal-SPIRAM,ESP32_GENERIC_S3 HydraBus1.0 with STM32F4,HYDRABUS -IBK-BLYST-NANO with NRF52832,IBK_BLYST_NANO -IDK-BLYST-NANO with NRF52832,IDK_BLYST_NANO +IBK-BLYST-NANO with NRF52832,ibk_blyst_nano +IDK-BLYST-NANO with NRF52832,idk_blyst_nano ItsyBitsy M0 Express with SAMD21G18A,ADAFRUIT_ITSYBITSY_M0_EXPRESS ItsyBitsy M4 Express with SAMD51G19A,ADAFRUIT_ITSYBITSY_M4_EXPRESS L476-DISCO with STM32L476,STM32L476DISC @@ -72,12 +72,12 @@ LOLIN_S2_MINI with ESP32-S2FN4R2,LOLIN_S2_MINI LOLIN_S2_PICO with ESP32-S2FN4R2,LOLIN_S2_PICO LaunchPad with CC3200,LAUNCHXL M5Stack ATOM with ESP32-PICO-D4,M5STACK_ATOM -MDK-USB-DONGLE with NRF52840,NRF52840_MDK_USB_DONGLE +MDK-USB-DONGLE with NRF52840,nrf52840-mdk-usb-dongle MIKROE_CLICKER2_STM32 with STM32F407,MIKROE_CLICKER2_STM32 Metro M4 Express Airlift with SAMD51J19A,ADAFRUIT_METRO_M4_EXPRESS MikroE Quail with STM32F427VI,MIKROE_QUAIL Mini SAM M4 with SAMD51G19A,MINISAM_M4 -NADHAT_PYBF405 with STM32F405RG,GARATRONIC_NADHAT_F405 +NADHAT_PYBF405 with STM32F405RG,NADHAT_PYBF405 NICLAVISION with STM32H747,ARDUINO_NICLA_VISION NUCLEO-F091RC with STM32F091RCT6,NUCLEO_F091RC NUCLEO-F401RE with STM32F401xE,NUCLEO_F401RE @@ -104,20 +104,19 @@ NUCLEO_G474RE with STM32G474,NUCLEO_G474RE NUCLEO_H563ZI with STM32H563ZI,NUCLEO_H563ZI NUCLEO_H723ZG with STM32H723ZGT6,NUCLEO_H723ZG NUCLEO_H743ZI with STM32H743,NUCLEO_H743ZI -NUCLEO_H743ZI2,NUCLEO_H743ZI2 NanoS3 with ESP32-S3-FN8,UM_NANOS3 NetduinoPlus2 with STM32F405RG,NETDUINO_PLUS_2 OLIMEX STM32-E407 with STM32F407,OLIMEX_E407 OLIMEX STM32-H407 with STM32F407,OLIMEX_H407 Olimex ESP32 ETH with ESP32,OLIMEX_ESP32_POE -PCA10000 with NRF51822,PCA10000 -PCA10001 with NRF51822,PCA10001 -PCA10028 with NRF51822,PCA10028 -PCA10031 with NRF51822,PCA10031 -PCA10040 with NRF52832,PCA10040 -PCA10056 with NRF52840,PCA10056 -PCA10059 with NRF52840,PCA10059 -PCA10090 with NRF9160,PCA10090 +PCA10000 with NRF51822,pca10000 +PCA10001 with NRF51822,pca10001 +PCA10028 with NRF51822,pca10028 +PCA10031 with NRF51822,pca10031 +PCA10040 with NRF52832,pca10040 +PCA10056 with NRF52840,pca10056 +PCA10059 with NRF52840,pca10059 +PCA10090 with NRF9160,pca10090 PORTENTA C33 with RA6M5,ARDUINO_PORTENTA_C33 PORTENTA with STM32H747,ARDUINO_PORTENTA_H7 PYBD-SF2W with STM32F722IEK,PYBD_SF2 @@ -129,11 +128,6 @@ PYBv1.0 with STM32F405RG,PYBV10 PYBv1.1 with STM32F405RG,PYBV11 PYBv3 with STM32F405RG,PYBV3 PYBv4 with STM32F405RG,PYBV4 -Pimoroni Pico LiPo 16MB,PIMORONI_PICOLIPO_16MB -Pimoroni Pico LiPo 4MB,PIMORONI_PICOLIPO_4MB -Pimoroni Tiny 2040,PIMORONI_TINY2040 -Pololu 3pi+ 2040 Robot,POLOLU_3PI_2040_ROBOT -Pololu Zumo 2040 Robot,POLOLU_ZUMO_2040_ROBOT ProS3 with ESP32-S3,UM_PROS3 RA4M1 CLICKER with RA4M1,RA4M1_CLICKER RA4M1_CLICKER with RA4M1,RA4M1_CLICKER @@ -142,18 +136,13 @@ RA4W1_EK with RA4W1,RA4W1_EK RA6M1_EK with RA6M1,RA6M1_EK RA6M2_EK with RA6M2,RA6M2_EK RT1010-Py-DevKIT with MIMXRT1011DAE5A,OLIMEX_RT1010 -Raspberry Pi Pico,PICO -Raspberry Pi Pico W,PICO_W SAMD21-XPLAINED-PRO with SAMD21J18A,SAMD21_XPLAINED_PRO STM32H573I-DK with STM32H573IIK3Q,STM32H573I_DK STM32H7B3I-DK with STM32H7B3LIH6Q,STM32H7B3I_DK Seeed ARCH MIX with MIMXRT1052DVL5B,SEEED_ARCH_MIX Seeed Xiao with SAMD21G18A,SEEED_XIAO -Silicognition RP2040-Shim,SIL_RP2040_SHIM Silicognition wESP32 with ESP32,SIL_WESP32 -SparkFun Pro Micro RP2040,SPARKFUN_PROMICRO SparkFun STM32 MicroMod Processor with STM32F405RG,SPARKFUN_MICROMOD_STM32 -SparkFun Thing Plus RP2040,SPARKFUN_THINGPLUS Sparkfun SAMD51 Thing Plus with SAMD51J20A,SPARKFUN_SAMD51_THING_PLUS Teensy 4.0 with MIMXRT1062DVJ6A,TEENSY40 Teensy 4.1 with MIMXRT1062DVJ6A,TEENSY41 @@ -167,14 +156,11 @@ VCC-GND STM32F407VE with STM32F407VE,VCC_GND_F407VE VCC-GND STM32F407ZG with STM32F407ZG,VCC_GND_F407ZG VCC-GND STM32H743VI with STM32H743VI,VCC_GND_H743VI VK-RA6M5 with RA6M5,VK_RA6M5 -W5100S-EVB-Pico,W5100S_EVB_PICO -W5500-EVB-Pico,W5500_EVB_PICO -WT51822-S4AT with NRF51822,WT51822_S4AT -WeAct Studio RP2040,WEACTSTUDIO +WT51822-S4AT with NRF51822,wt51822_s4at WiPy with CC3200,WIPY Wio Terminal D51R with SAMD51P19A,SEEED_WIO_TERMINAL -XENON with NRF52840,PARTICLE_XENON -XIAO nRF52840 Sense with NRF52840,SEEED_XIAO_NRF52 +XENON with NRF52840,particle_xenon +XIAO nRF52840 Sense with NRF52840,seeed_xiao_nrf52 i.MX RT1010 EVK with MIMXRT1011DAE5A,MIMXRT1010_EVK i.MX RT1015 EVK with MIMXRT1015DAF5A,MIMXRT1015_EVK i.MX RT1020 EVK with MIMXRT1021DAG5A,MIMXRT1020_EVK @@ -184,5 +170,4 @@ i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B,MIMXRT1050_EVK i.MX RT1060 EVK with MIMXRT1062DVJ6A,MIMXRT1060_EVK i.MX RT1064 EVK with MIMXRT1064DVL6A,MIMXRT1064_EVK i.MX RT1170 EVK with MIMXRT1176DVMAA,MIMXRT1170_EVK -micro:bit with NRF51822,MICROBIT -nullbits Bit-C PRO,NULLBITS_BIT_C_PRO +micro:bit with NRF51822,microbit diff --git a/src/stubber/data/board_info.json b/src/stubber/data/board_info.json index 7b2a24aab..41e858b54 100644 --- a/src/stubber/data/board_info.json +++ b/src/stubber/data/board_info.json @@ -1,1685 +1,1550 @@ [ { + "description": "4MB/OTA module with ESP32", "port": "esp32", "board": "GENERIC_OTA", "board_name": "4MB/OTA module", "mcu_name": "ESP32", - "description": "4MB/OTA module with ESP32", - "path": "repos/micropython/ports/esp32/boards/GENERIC_OTA/mpconfigboard.h", + "path": "ports/esp32/boards/GENERIC_OTA/mpconfigboard.h", "version": "v1.13" }, { + "description": "Actinius Icarus with NRF9160", "port": "nrf", - "board": "ACTINIUS_ICARUS", + "board": "actinius_icarus", "board_name": "Actinius Icarus", "mcu_name": "NRF9160", - "description": "Actinius Icarus with NRF9160", - "path": "repos/micropython/ports/nrf/boards/ACTINIUS_ICARUS/mpconfigboard.h", - "version": "v1.21.0" - }, - { - "port": "rp2", - "board": "ADAFRUIT_FEATHER_RP2040", - "board_name": "Adafruit Feather RP2040", - "mcu_name": "-", - "description": "Adafruit Feather RP2040", - "path": "repos/micropython/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h", - "version": "v1.15" + "path": "ports/nrf/boards/actinius_icarus/mpconfigboard.h", + "version": "v1.13" }, { + "description": "Adafruit Feather STM32F405 with STM32F405RG", "port": "stm32", "board": "ADAFRUIT_F405_EXPRESS", "board_name": "Adafruit Feather STM32F405", "mcu_name": "STM32F405RG", - "description": "Adafruit Feather STM32F405 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h", + "path": "ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h", "version": "v1.12" }, { - "port": "rp2", - "board": "ADAFRUIT_ITSYBITSY_RP2040", - "board_name": "Adafruit ItsyBitsy RP2040", - "mcu_name": "-", - "description": "Adafruit ItsyBitsy RP2040", - "path": "repos/micropython/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h", - "version": "v1.17" - }, - { + "description": "Adafruit Metro M7 with MIMXRT1011DAE5A", "port": "mimxrt", "board": "ADAFRUIT_METRO_M7", "board_name": "Adafruit Metro M7", "mcu_name": "MIMXRT1011DAE5A", - "description": "Adafruit Metro M7 with MIMXRT1011DAE5A", - "path": "repos/micropython/ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.h", + "path": "ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.h", "version": "v1.21.0" }, { - "port": "rp2", - "board": "ADAFRUIT_QTPY_RP2040", - "board_name": "Adafruit QT Py RP2040", - "mcu_name": "-", - "description": "Adafruit QT Py RP2040", - "path": "repos/micropython/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h", - "version": "v1.17" - }, - { + "description": "Arduino GIGA R1 WiFi with STM32H747", "port": "stm32", "board": "ARDUINO_GIGA", "board_name": "Arduino GIGA R1 WiFi", "mcu_name": "STM32H747", - "description": "Arduino GIGA R1 WiFi with STM32H747", - "path": "repos/micropython/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h", + "path": "ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h", "version": "v1.22.0" }, { + "description": "Arduino Nano 33 BLE Sense with NRF52840", "port": "nrf", - "board": "ARDUINO_NANO_33_BLE_SENSE", + "board": "arduino_nano_33_ble_sense", "board_name": "Arduino Nano 33 BLE Sense", "mcu_name": "NRF52840", - "description": "Arduino Nano 33 BLE Sense with NRF52840", - "path": "repos/micropython/ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.h", + "version": "v1.20.0" }, { + "description": "Arduino Nano ESP32 with ESP32S3", "port": "esp32", "board": "ARDUINO_NANO_ESP32", "board_name": "Arduino Nano ESP32", "mcu_name": "ESP32S3", - "description": "Arduino Nano ESP32 with ESP32S3", - "path": "repos/micropython/ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.h", + "path": "ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.h", "version": "v1.21.0" }, { - "port": "rp2", - "board": "ARDUINO_NANO_RP2040_CONNECT", - "board_name": "Arduino Nano RP2040 Connect", - "mcu_name": "-", - "description": "Arduino Nano RP2040 Connect", - "path": "repos/micropython/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h", - "version": "v1.18" - }, - { + "description": "Arduino Nicla Vision with STM32H747", "port": "stm32", "board": "ARDUINO_NICLA_VISION", "board_name": "Arduino Nicla Vision", "mcu_name": "STM32H747", - "description": "Arduino Nicla Vision with STM32H747", - "path": "repos/micropython/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h", + "path": "ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h", "version": "v1.22.0" }, { + "description": "Arduino Portenta C33 with RA6M5", "port": "renesas-ra", "board": "ARDUINO_PORTENTA_C33", "board_name": "Arduino Portenta C33", "mcu_name": "RA6M5", - "description": "Arduino Portenta C33 with RA6M5", - "path": "repos/micropython/ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/mpconfigboard.h", + "path": "ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/mpconfigboard.h", "version": "v1.22.0" }, { + "description": "Arduino Portenta H7 with STM32H747", "port": "stm32", "board": "ARDUINO_PORTENTA_H7", "board_name": "Arduino Portenta H7", "mcu_name": "STM32H747", - "description": "Arduino Portenta H7 with STM32H747", - "path": "repos/micropython/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h", + "path": "ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h", "version": "v1.22.0" }, { + "description": "Arduino Primo with NRF52832", "port": "nrf", - "board": "ARDUINO_PRIMO", + "board": "arduino_primo", "board_name": "Arduino Primo", "mcu_name": "NRF52832", - "description": "Arduino Primo with NRF52832", - "path": "repos/micropython/ports/nrf/boards/ARDUINO_PRIMO/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/arduino_primo/mpconfigboard.h", + "version": "v1.10" }, { + "description": "B-L072Z-LRWAN1 with STM32L072CZ", "port": "stm32", "board": "B_L072Z_LRWAN1", "board_name": "B-L072Z-LRWAN1", "mcu_name": "STM32L072CZ", - "description": "B-L072Z-LRWAN1 with STM32L072CZ", - "path": "repos/micropython/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h", + "path": "ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h", "version": "v1.12" }, { + "description": "B-L475E-IOT01A with STM32L475", "port": "stm32", "board": "B_L475E_IOT01A", "board_name": "B-L475E-IOT01A", "mcu_name": "STM32L475", - "description": "B-L475E-IOT01A with STM32L475", - "path": "repos/micropython/ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.h", + "path": "ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.h", "version": "v1.10" }, { + "description": "BLUEIO-TAG-EVIM with NRF52832", "port": "nrf", - "board": "BLUEIO_TAG_EVIM", + "board": "blueio_tag_evim", "board_name": "BLUEIO-TAG-EVIM", "mcu_name": "NRF52832", - "description": "BLUEIO-TAG-EVIM with NRF52832", - "path": "repos/micropython/ports/nrf/boards/BLUEIO_TAG_EVIM/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/blueio_tag_evim/mpconfigboard.h", + "version": "v1.11" }, { + "description": "Bluefruit nRF52 Feather with NRF52832", "port": "nrf", - "board": "FEATHER52", + "board": "feather52", "board_name": "Bluefruit nRF52 Feather", "mcu_name": "NRF52832", - "description": "Bluefruit nRF52 Feather with NRF52832", - "path": "repos/micropython/ports/nrf/boards/FEATHER52/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/feather52/mpconfigboard.h", + "version": "v1.10" }, { + "description": "Cerb40 with STM32F405RG", "port": "stm32", "board": "CERB40", "board_name": "Cerb40", "mcu_name": "STM32F405RG", - "description": "Cerb40 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/CERB40/mpconfigboard.h", + "path": "ports/stm32/boards/CERB40/mpconfigboard.h", "version": "v1.10" }, { + "description": "CustomPCB with STM32F439", "port": "stm32", "board": "STM32F439", "board_name": "CustomPCB", "mcu_name": "STM32F439", - "description": "CustomPCB with STM32F439", - "path": "repos/micropython/ports/stm32/boards/STM32F439/mpconfigboard.h", + "path": "ports/stm32/boards/STM32F439/mpconfigboard.h", "version": "v1.10" }, { + "description": "DVK-BL652 with NRF52832", "port": "nrf", - "board": "DVK_BL652", + "board": "dvk_bl652", "board_name": "DVK-BL652", "mcu_name": "NRF52832", - "description": "DVK-BL652 with NRF52832", - "path": "repos/micropython/ports/nrf/boards/DVK_BL652/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/dvk_bl652/mpconfigboard.h", + "version": "v1.10" }, { + "description": "EK-RA4M1 with RA4M1", "port": "renesas-ra", "board": "EK_RA4M1", "board_name": "EK-RA4M1", "mcu_name": "RA4M1", - "description": "EK-RA4M1 with RA4M1", - "path": "repos/micropython/ports/renesas-ra/boards/EK_RA4M1/mpconfigboard.h", + "path": "ports/renesas-ra/boards/EK_RA4M1/mpconfigboard.h", "version": "v1.21.0" }, { + "description": "EK-RA4W1 with RA4W1", "port": "renesas-ra", "board": "EK_RA4W1", "board_name": "EK-RA4W1", "mcu_name": "RA4W1", - "description": "EK-RA4W1 with RA4W1", - "path": "repos/micropython/ports/renesas-ra/boards/EK_RA4W1/mpconfigboard.h", + "path": "ports/renesas-ra/boards/EK_RA4W1/mpconfigboard.h", "version": "v1.21.0" }, { + "description": "EK-RA6M1 with RA6M1", "port": "renesas-ra", "board": "EK_RA6M1", "board_name": "EK-RA6M1", "mcu_name": "RA6M1", - "description": "EK-RA6M1 with RA6M1", - "path": "repos/micropython/ports/renesas-ra/boards/EK_RA6M1/mpconfigboard.h", + "path": "ports/renesas-ra/boards/EK_RA6M1/mpconfigboard.h", "version": "v1.21.0" }, { + "description": "EK-RA6M2 with RA6M2", "port": "renesas-ra", "board": "EK_RA6M2", "board_name": "EK-RA6M2", "mcu_name": "RA6M2", - "description": "EK-RA6M2 with RA6M2", - "path": "repos/micropython/ports/renesas-ra/boards/EK_RA6M2/mpconfigboard.h", + "path": "ports/renesas-ra/boards/EK_RA6M2/mpconfigboard.h", "version": "v1.21.0" }, { + "description": "ESP module (1M) with ESP8266", "port": "esp8266", "board": "GENERIC_1M", "board_name": "ESP module (1M)", "mcu_name": "ESP8266", - "description": "ESP module (1M) with ESP8266", - "path": "repos/micropython/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h", + "path": "ports/esp8266/boards/GENERIC_1M/mpconfigboard.h", "version": "v1.13" }, { + "description": "ESP module (512K) with ESP8266", "port": "esp8266", "board": "GENERIC_512K", "board_name": "ESP module (512K)", "mcu_name": "ESP8266", - "description": "ESP module (512K) with ESP8266", - "path": "repos/micropython/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h", + "path": "ports/esp8266/boards/GENERIC_512K/mpconfigboard.h", "version": "v1.12" }, { + "description": "ESP module with ESP8266", "port": "esp8266", - "board": "ESP8266_GENERIC", + "board": "GENERIC", "board_name": "ESP module", "mcu_name": "ESP8266", - "description": "ESP module with ESP8266", - "path": "repos/micropython/ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/esp8266/boards/GENERIC/mpconfigboard.h", + "version": "v1.12" }, { + "description": "ESP32 Unicore module with ESP32-UNICORE", "port": "esp32", "board": "GENERIC_UNICORE", "board_name": "ESP32 Unicore module", "mcu_name": "ESP32-UNICORE", - "description": "ESP32 Unicore module with ESP32-UNICORE", - "path": "repos/micropython/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h", + "path": "ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h", "version": "v1.20.0" }, { + "description": "ESP32 module (spiram) with ESP32", "port": "esp32", "board": "GENERIC_SPIRAM", "board_name": "ESP32 module (spiram)", "mcu_name": "ESP32", - "description": "ESP32 module (spiram) with ESP32", - "path": "repos/micropython/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.h", + "path": "ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.h", "version": "v1.12" }, { + "description": "ESP32 module with ESP32", "port": "esp32", "board": "GENERIC", "board_name": "ESP32 module", "mcu_name": "ESP32", - "description": "ESP32 module with ESP32", - "path": "repos/micropython/ports/esp32/boards/GENERIC/mpconfigboard.h", + "path": "ports/esp32/boards/GENERIC/mpconfigboard.h", "version": "v1.12" }, { + "description": "ESP32-D2WD", + "port": "esp32", + "board": "ESP32_GENERIC", + "board_name": "-", + "mcu_name": "-", + "path": "ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake", + "version": "v1.21.0" + }, + { + "description": "ESP32-S2-WROVER with ESP32-S2", "port": "esp32", "board": "ESP32_S2_WROVER", "board_name": "ESP32-S2-WROVER", "mcu_name": "ESP32-S2", - "description": "ESP32-S2-WROVER with ESP32-S2", - "path": "repos/micropython/ports/esp32/boards/ESP32_S2_WROVER/mpconfigboard.h", + "path": "ports/esp32/boards/ESP32_S2_WROVER/mpconfigboard.h", "version": "v1.18" }, { + "description": "ESP32-UNICORE", + "port": "esp32", + "board": "ESP32_GENERIC", + "board_name": "-", + "mcu_name": "-", + "path": "ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake", + "version": "v1.21.0" + }, + { + "description": "ESP32C3 module with ESP32C3", "port": "esp32", - "board": "ESP32_GENERIC_C3", + "board": "GENERIC_C3", "board_name": "ESP32C3 module", "mcu_name": "ESP32C3", - "description": "ESP32C3 module with ESP32C3", - "path": "repos/micropython/ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/esp32/boards/GENERIC_C3/mpconfigboard.h", + "version": "v1.17" }, { + "description": "ESP32S2 module with ESP32S2", "port": "esp32", "board": "GENERIC_S2", "board_name": "ESP32S2 module", "mcu_name": "ESP32S2", - "description": "ESP32S2 module with ESP32S2", - "path": "repos/micropython/ports/esp32/boards/GENERIC_S2/mpconfigboard.h", + "path": "ports/esp32/boards/GENERIC_S2/mpconfigboard.h", "version": "v1.15" }, { + "description": "ESP32S3 module (spiram octal) with ESP32S3", "port": "esp32", "board": "GENERIC_S3_SPIRAM_OCT", "board_name": "ESP32S3 module (spiram octal)", "mcu_name": "ESP32S3", - "description": "ESP32S3 module (spiram octal) with ESP32S3", - "path": "repos/micropython/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.h", + "path": "ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.h", "version": "v1.20.0" }, { + "description": "ESP32S3 module (spiram) with ESP32S3", "port": "esp32", "board": "GENERIC_S3_SPIRAM", "board_name": "ESP32S3 module (spiram)", "mcu_name": "ESP32S3", - "description": "ESP32S3 module (spiram) with ESP32S3", - "path": "repos/micropython/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h", + "path": "ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h", "version": "v1.18" }, { + "description": "ESP32S3 module with ESP32S3", "port": "esp32", "board": "GENERIC_S3", "board_name": "ESP32S3 module", "mcu_name": "ESP32S3", - "description": "ESP32S3 module with ESP32S3", - "path": "repos/micropython/ports/esp32/boards/GENERIC_S3/mpconfigboard.h", + "path": "ports/esp32/boards/GENERIC_S3/mpconfigboard.h", "version": "v1.18" }, { + "description": "EVK_NINA_B1 with NRF52832", "port": "nrf", - "board": "EVK_NINA_B1", + "board": "evk_nina_b1", "board_name": "EVK_NINA_B1", "mcu_name": "NRF52832", - "description": "EVK_NINA_B1 with NRF52832", - "path": "repos/micropython/ports/nrf/boards/EVK_NINA_B1/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/evk_nina_b1/mpconfigboard.h", + "version": "v1.12" }, { + "description": "EVK_NINA_B3 with NRF52840", "port": "nrf", - "board": "EVK_NINA_B3", + "board": "evk_nina_b3", "board_name": "EVK_NINA_B3", "mcu_name": "NRF52840", - "description": "EVK_NINA_B3 with NRF52840", - "path": "repos/micropython/ports/nrf/boards/EVK_NINA_B3/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/evk_nina_b3/mpconfigboard.h", + "version": "v1.16" }, { + "description": "Espruino Pico with STM32F401CD", "port": "stm32", "board": "ESPRUINO_PICO", "board_name": "Espruino Pico", "mcu_name": "STM32F401CD", - "description": "Espruino Pico with STM32F401CD", - "path": "repos/micropython/ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.h", + "path": "ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.h", "version": "v1.10" }, { + "description": "F411DISC with STM32F411", "port": "stm32", "board": "STM32F411DISC", "board_name": "F411DISC", "mcu_name": "STM32F411", - "description": "F411DISC with STM32F411", - "path": "repos/micropython/ports/stm32/boards/STM32F411DISC/mpconfigboard.h", + "path": "ports/stm32/boards/STM32F411DISC/mpconfigboard.h", "version": "v1.10" }, { + "description": "F429I-DISCO with STM32F429", "port": "stm32", "board": "STM32F429DISC", "board_name": "F429I-DISCO", "mcu_name": "STM32F429", - "description": "F429I-DISCO with STM32F429", - "path": "repos/micropython/ports/stm32/boards/STM32F429DISC/mpconfigboard.h", + "path": "ports/stm32/boards/STM32F429DISC/mpconfigboard.h", "version": "v1.10" }, { + "description": "F4DISC with STM32F407", "port": "stm32", "board": "STM32F4DISC", "board_name": "F4DISC", "mcu_name": "STM32F407", - "description": "F4DISC with STM32F407", - "path": "repos/micropython/ports/stm32/boards/STM32F4DISC/mpconfigboard.h", + "path": "ports/stm32/boards/STM32F4DISC/mpconfigboard.h", "version": "v1.10" }, { + "description": "F769DISC with STM32F769", "port": "stm32", "board": "STM32F769DISC", "board_name": "F769DISC", "mcu_name": "STM32F769", - "description": "F769DISC with STM32F769", - "path": "repos/micropython/ports/stm32/boards/STM32F769DISC/mpconfigboard.h", + "path": "ports/stm32/boards/STM32F769DISC/mpconfigboard.h", "version": "v1.10" }, { + "description": "F7DISC with STM32F746", "port": "stm32", "board": "STM32F7DISC", "board_name": "F7DISC", "mcu_name": "STM32F746", - "description": "F7DISC with STM32F746", - "path": "repos/micropython/ports/stm32/boards/STM32F7DISC/mpconfigboard.h", + "path": "ports/stm32/boards/STM32F7DISC/mpconfigboard.h", "version": "v1.10" }, { + "description": "Feather M0 Express with SAMD21G18A", "port": "samd", "board": "ADAFRUIT_FEATHER_M0_EXPRESS", "board_name": "Feather M0 Express", "mcu_name": "SAMD21G18A", - "description": "Feather M0 Express with SAMD21G18A", - "path": "repos/micropython/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h", + "path": "ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h", "version": "v1.12" }, { + "description": "Feather M4 Express with SAMD51J19A", "port": "samd", "board": "ADAFRUIT_FEATHER_M4_EXPRESS", "board_name": "Feather M4 Express", "mcu_name": "SAMD51J19A", - "description": "Feather M4 Express with SAMD51J19A", - "path": "repos/micropython/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h", + "path": "ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h", "version": "v1.20.0" }, { + "description": "FeatherS2 Neo with ESP32-S2FN4R2", "port": "esp32", "board": "UM_FEATHERS2NEO", "board_name": "FeatherS2 Neo", "mcu_name": "ESP32-S2FN4R2", - "description": "FeatherS2 Neo with ESP32-S2FN4R2", - "path": "repos/micropython/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.h", + "path": "ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.h", "version": "v1.18" }, { + "description": "FeatherS2 with ESP32-S2", "port": "esp32", "board": "UM_FEATHERS2", "board_name": "FeatherS2", "mcu_name": "ESP32-S2", - "description": "FeatherS2 with ESP32-S2", - "path": "repos/micropython/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.h", + "path": "ports/esp32/boards/UM_FEATHERS2/mpconfigboard.h", "version": "v1.16" }, { + "description": "FeatherS3 with ESP32-S3", "port": "esp32", "board": "UM_FEATHERS3", "board_name": "FeatherS3", "mcu_name": "ESP32-S3", - "description": "FeatherS3 with ESP32-S3", - "path": "repos/micropython/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h", + "path": "ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h", "version": "v1.19.1" }, { - "port": "rp2", - "board": "GARATRONIC_PYBSTICK26_RP2040", - "board_name": "GARATRONIC_PYBSTICK26_RP2040", - "mcu_name": "-", - "description": "GARATRONIC_PYBSTICK26_RP2040", - "path": "repos/micropython/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.h", - "version": "v1.18" - }, - { + "description": "GIGA with STM32H747", "port": "stm32", "board": "ARDUINO_GIGA", "board_name": "GIGA", "mcu_name": "STM32H747", - "description": "GIGA with STM32H747", - "path": "repos/micropython/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h", + "path": "ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h", "version": "v1.20.0" }, { + "description": "Generic ESP32 module with ESP32", "port": "esp32", "board": "ESP32_GENERIC", "board_name": "Generic ESP32 module", "mcu_name": "ESP32", - "description": "Generic ESP32 module with ESP32", - "path": "repos/micropython/ports/esp32/boards/ESP32_GENERIC/mpconfigboard.h", + "path": "ports/esp32/boards/ESP32_GENERIC/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "description": "Generic ESP32 module with OTA", + "port": "esp32", + "board": "ESP32_GENERIC", + "board_name": "-", + "mcu_name": "-", + "path": "ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake", + "version": "v1.21.0" + }, + { + "description": "Generic ESP32 module with SPIRAM", + "port": "esp32", + "board": "ESP32_GENERIC", + "board_name": "-", + "mcu_name": "-", + "path": "ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake", "version": "v1.21.0" }, { + "description": "Generic ESP32-D2WD module with ESP32-D2WD", "port": "esp32", "board": "GENERIC_D2WD", "board_name": "Generic ESP32-D2WD module", "mcu_name": "ESP32-D2WD", - "description": "Generic ESP32-D2WD module with ESP32-D2WD", - "path": "repos/micropython/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.h", + "path": "ports/esp32/boards/GENERIC_D2WD/mpconfigboard.h", "version": "v1.12" }, { + "description": "Generic ESP32S2 module with ESP32S2", "port": "esp32", "board": "ESP32_GENERIC_S2", "board_name": "Generic ESP32S2 module", "mcu_name": "ESP32S2", - "description": "Generic ESP32S2 module with ESP32S2", - "path": "repos/micropython/ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.h", + "path": "ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.h", "version": "v1.21.0" }, { + "description": "Generic ESP32S3 module with ESP32S3", "port": "esp32", "board": "ESP32_GENERIC_S3", "board_name": "Generic ESP32S3 module", "mcu_name": "ESP32S3", - "description": "Generic ESP32S3 module with ESP32S3", - "path": "repos/micropython/ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.h", + "path": "ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.h", "version": "v1.21.0" }, { + "description": "Generic ESP32S3 module with Octal-SPIRAM", + "port": "esp32", + "board": "ESP32_GENERIC_S3", + "board_name": "-", + "mcu_name": "-", + "path": "ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.cmake", + "version": "v1.21.0" + }, + { + "description": "HydraBus1.0 with STM32F4", "port": "stm32", "board": "HYDRABUS", "board_name": "HydraBus1.0", "mcu_name": "STM32F4", - "description": "HydraBus1.0 with STM32F4", - "path": "repos/micropython/ports/stm32/boards/HYDRABUS/mpconfigboard.h", + "path": "ports/stm32/boards/HYDRABUS/mpconfigboard.h", "version": "v1.10" }, { + "description": "IBK-BLYST-NANO with NRF52832", "port": "nrf", - "board": "IBK_BLYST_NANO", + "board": "ibk_blyst_nano", "board_name": "IBK-BLYST-NANO", "mcu_name": "NRF52832", - "description": "IBK-BLYST-NANO with NRF52832", - "path": "repos/micropython/ports/nrf/boards/IBK_BLYST_NANO/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/ibk_blyst_nano/mpconfigboard.h", + "version": "v1.11" }, { + "description": "IDK-BLYST-NANO with NRF52832", "port": "nrf", - "board": "IDK_BLYST_NANO", + "board": "idk_blyst_nano", "board_name": "IDK-BLYST-NANO", "mcu_name": "NRF52832", - "description": "IDK-BLYST-NANO with NRF52832", - "path": "repos/micropython/ports/nrf/boards/IDK_BLYST_NANO/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/idk_blyst_nano/mpconfigboard.h", + "version": "v1.11" }, { + "description": "ItsyBitsy M0 Express with SAMD21G18A", "port": "samd", "board": "ADAFRUIT_ITSYBITSY_M0_EXPRESS", "board_name": "ItsyBitsy M0 Express", "mcu_name": "SAMD21G18A", - "description": "ItsyBitsy M0 Express with SAMD21G18A", - "path": "repos/micropython/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h", + "path": "ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h", "version": "v1.20.0" }, { + "description": "ItsyBitsy M4 Express with SAMD51G19A", "port": "samd", "board": "ADAFRUIT_ITSYBITSY_M4_EXPRESS", "board_name": "ItsyBitsy M4 Express", "mcu_name": "SAMD51G19A", - "description": "ItsyBitsy M4 Express with SAMD51G19A", - "path": "repos/micropython/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h", + "path": "ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h", "version": "v1.12" }, { + "description": "L476-DISCO with STM32L476", "port": "stm32", "board": "STM32L476DISC", "board_name": "L476-DISCO", "mcu_name": "STM32L476", - "description": "L476-DISCO with STM32L476", - "path": "repos/micropython/ports/stm32/boards/STM32L476DISC/mpconfigboard.h", + "path": "ports/stm32/boards/STM32L476DISC/mpconfigboard.h", "version": "v1.10" }, { + "description": "L496G-DISCO with STM32L496", "port": "stm32", "board": "STM32L496GDISC", "board_name": "L496G-DISCO", "mcu_name": "STM32L496", - "description": "L496G-DISCO with STM32L496", - "path": "repos/micropython/ports/stm32/boards/STM32L496GDISC/mpconfigboard.h", + "path": "ports/stm32/boards/STM32L496GDISC/mpconfigboard.h", "version": "v1.10" }, { + "description": "LEGO Technic Hub No.6 with STM32F413", "port": "stm32", "board": "LEGO_HUB_NO6", "board_name": "LEGO Technic Hub No.6", "mcu_name": "STM32F413", - "description": "LEGO Technic Hub No.6 with STM32F413", - "path": "repos/micropython/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h", + "path": "ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h", "version": "v1.17" }, { + "description": "LEGO Technic Hub No.7 with STM32F413", "port": "stm32", "board": "LEGO_HUB_NO7", "board_name": "LEGO Technic Hub No.7", "mcu_name": "STM32F413", - "description": "LEGO Technic Hub No.7 with STM32F413", - "path": "repos/micropython/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h", + "path": "ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h", "version": "v1.20.0" }, { + "description": "LILYGO TTGO LoRa32 with ESP32", "port": "esp32", "board": "LILYGO_TTGO_LORA32", "board_name": "LILYGO TTGO LoRa32", "mcu_name": "ESP32", - "description": "LILYGO TTGO LoRa32 with ESP32", - "path": "repos/micropython/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.h", + "path": "ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "LIMIFROG with STM32L476", "port": "stm32", "board": "LIMIFROG", "board_name": "LIMIFROG", "mcu_name": "STM32L476", - "description": "LIMIFROG with STM32L476", - "path": "repos/micropython/ports/stm32/boards/LIMIFROG/mpconfigboard.h", + "path": "ports/stm32/boards/LIMIFROG/mpconfigboard.h", "version": "v1.10" }, { + "description": "LOLIN_C3_MINI with ESP32-C3FH4", "port": "esp32", "board": "LOLIN_C3_MINI", "board_name": "LOLIN_C3_MINI", "mcu_name": "ESP32-C3FH4", - "description": "LOLIN_C3_MINI with ESP32-C3FH4", - "path": "repos/micropython/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.h", + "path": "ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "LOLIN_S2_MINI with ESP32-S2FN4R2", "port": "esp32", "board": "LOLIN_S2_MINI", "board_name": "LOLIN_S2_MINI", "mcu_name": "ESP32-S2FN4R2", - "description": "LOLIN_S2_MINI with ESP32-S2FN4R2", - "path": "repos/micropython/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.h", + "path": "ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.h", "version": "v1.18" }, { + "description": "LOLIN_S2_PICO with ESP32-S2FN4R2", "port": "esp32", "board": "LOLIN_S2_PICO", "board_name": "LOLIN_S2_PICO", "mcu_name": "ESP32-S2FN4R2", - "description": "LOLIN_S2_PICO with ESP32-S2FN4R2", - "path": "repos/micropython/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h", + "path": "ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h", "version": "v1.18" }, { + "description": "LaunchPad with CC3200", "port": "cc3200", "board": "LAUNCHXL", "board_name": "LaunchPad", "mcu_name": "CC3200", - "description": "LaunchPad with CC3200", - "path": "repos/micropython/ports/cc3200/boards/LAUNCHXL/mpconfigboard.h", + "path": "ports/cc3200/boards/LAUNCHXL/mpconfigboard.h", "version": "v1.10" }, { + "description": "M5Stack ATOM with ESP32-PICO-D4", "port": "esp32", "board": "M5STACK_ATOM", "board_name": "M5Stack ATOM", "mcu_name": "ESP32-PICO-D4", - "description": "M5Stack ATOM with ESP32-PICO-D4", - "path": "repos/micropython/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.h", + "path": "ports/esp32/boards/M5STACK_ATOM/mpconfigboard.h", "version": "v1.16" }, { + "description": "MDK-USB-DONGLE with NRF52840", "port": "nrf", - "board": "NRF52840_MDK_USB_DONGLE", + "board": "nrf52840-mdk-usb-dongle", "board_name": "MDK-USB-DONGLE", "mcu_name": "NRF52840", - "description": "MDK-USB-DONGLE with NRF52840", - "path": "repos/micropython/ports/nrf/boards/NRF52840_MDK_USB_DONGLE/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/nrf52840-mdk-usb-dongle/mpconfigboard.h", + "version": "v1.13" }, { + "description": "MIKROE_CLICKER2_STM32 with STM32F407", "port": "stm32", "board": "MIKROE_CLICKER2_STM32", "board_name": "MIKROE_CLICKER2_STM32", "mcu_name": "STM32F407", - "description": "MIKROE_CLICKER2_STM32 with STM32F407", - "path": "repos/micropython/ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.h", + "path": "ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.h", "version": "v1.12" }, { + "description": "Metro M4 Express Airlift with SAMD51J19A", "port": "samd", "board": "ADAFRUIT_METRO_M4_EXPRESS", "board_name": "Metro M4 Express Airlift", "mcu_name": "SAMD51J19A", - "description": "Metro M4 Express Airlift with SAMD51J19A", - "path": "repos/micropython/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.h", + "path": "ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.h", "version": "v1.21.0" }, { + "description": "MikroE Quail with STM32F427VI", "port": "stm32", "board": "MIKROE_QUAIL", "board_name": "MikroE Quail", "mcu_name": "STM32F427VI", - "description": "MikroE Quail with STM32F427VI", - "path": "repos/micropython/ports/stm32/boards/MIKROE_QUAIL/mpconfigboard.h", + "path": "ports/stm32/boards/MIKROE_QUAIL/mpconfigboard.h", "version": "v1.18" }, { + "description": "Mini SAM M4 with SAMD51G19A", "port": "samd", "board": "MINISAM_M4", "board_name": "Mini SAM M4", "mcu_name": "SAMD51G19A", - "description": "Mini SAM M4 with SAMD51G19A", - "path": "repos/micropython/ports/samd/boards/MINISAM_M4/mpconfigboard.h", + "path": "ports/samd/boards/MINISAM_M4/mpconfigboard.h", "version": "v1.12" }, { + "description": "NADHAT_PYBF405 with STM32F405RG", "port": "stm32", - "board": "GARATRONIC_NADHAT_F405", + "board": "NADHAT_PYBF405", "board_name": "NADHAT_PYBF405", "mcu_name": "STM32F405RG", - "description": "NADHAT_PYBF405 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/GARATRONIC_NADHAT_F405/mpconfigboard.h", - "version": "v1.18" + "path": "ports/stm32/boards/NADHAT_PYBF405/mpconfigboard.h", + "version": "v1.12" }, { + "description": "NICLAVISION with STM32H747", "port": "stm32", "board": "ARDUINO_NICLA_VISION", "board_name": "NICLAVISION", "mcu_name": "STM32H747", - "description": "NICLAVISION with STM32H747", - "path": "repos/micropython/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h", + "path": "ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h", "version": "v1.20.0" }, { + "description": "NUCLEO-F091RC with STM32F091RCT6", "port": "stm32", "board": "NUCLEO_F091RC", "board_name": "NUCLEO-F091RC", "mcu_name": "STM32F091RCT6", - "description": "NUCLEO-F091RC with STM32F091RCT6", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h", "version": "v1.10" }, { + "description": "NUCLEO-F401RE with STM32F401xE", "port": "stm32", "board": "NUCLEO_F401RE", "board_name": "NUCLEO-F401RE", "mcu_name": "STM32F401xE", - "description": "NUCLEO-F401RE with STM32F401xE", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F401RE/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_F401RE/mpconfigboard.h", "version": "v1.10" }, { + "description": "NUCLEO-F411RE with STM32F411xE", "port": "stm32", "board": "NUCLEO_F411RE", "board_name": "NUCLEO-F411RE", "mcu_name": "STM32F411xE", - "description": "NUCLEO-F411RE with STM32F411xE", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F411RE/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_F411RE/mpconfigboard.h", "version": "v1.10" }, { + "description": "NUCLEO-F412ZG with STM32F412Zx", "port": "stm32", "board": "NUCLEO_F412ZG", "board_name": "NUCLEO-F412ZG", "mcu_name": "STM32F412Zx", - "description": "NUCLEO-F412ZG with STM32F412Zx", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F412ZG/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_F412ZG/mpconfigboard.h", "version": "v1.13" }, { + "description": "NUCLEO-F413ZH with STM32F413", "port": "stm32", "board": "NUCLEO_F413ZH", "board_name": "NUCLEO-F413ZH", "mcu_name": "STM32F413", - "description": "NUCLEO-F413ZH with STM32F413", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.h", "version": "v1.11" }, { + "description": "NUCLEO-F429ZI with STM32F429", "port": "stm32", "board": "NUCLEO_F429ZI", "board_name": "NUCLEO-F429ZI", "mcu_name": "STM32F429", - "description": "NUCLEO-F429ZI with STM32F429", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.h", "version": "v1.10" }, { + "description": "NUCLEO-F439ZI with STM32F439ZIT6", "port": "stm32", "board": "NUCLEO_F439ZI", "board_name": "NUCLEO-F439ZI", "mcu_name": "STM32F439ZIT6", - "description": "NUCLEO-F439ZI with STM32F439ZIT6", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F439ZI/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_F439ZI/mpconfigboard.h", "version": "v1.17" }, { + "description": "NUCLEO-F446RE with STM32F446xx", "port": "stm32", "board": "NUCLEO_F446RE", "board_name": "NUCLEO-F446RE", "mcu_name": "STM32F446xx", - "description": "NUCLEO-F446RE with STM32F446xx", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.h", "version": "v1.10" }, { + "description": "NUCLEO-F722ZE with STM32F722", "port": "stm32", "board": "NUCLEO_F722ZE", "board_name": "NUCLEO-F722ZE", "mcu_name": "STM32F722", - "description": "NUCLEO-F722ZE with STM32F722", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.h", "version": "v1.12" }, { + "description": "NUCLEO-F746ZG with STM32F746", "port": "stm32", "board": "NUCLEO_F746ZG", "board_name": "NUCLEO-F746ZG", "mcu_name": "STM32F746", - "description": "NUCLEO-F746ZG with STM32F746", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.h", "version": "v1.10" }, { + "description": "NUCLEO-F756ZG with STM32F756", "port": "stm32", "board": "NUCLEO_F756ZG", "board_name": "NUCLEO-F756ZG", "mcu_name": "STM32F756", - "description": "NUCLEO-F756ZG with STM32F756", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F756ZG/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_F756ZG/mpconfigboard.h", "version": "v1.20.0" }, { + "description": "NUCLEO-F767ZI with STM32F767", "port": "stm32", "board": "NUCLEO_F767ZI", "board_name": "NUCLEO-F767ZI", "mcu_name": "STM32F767", - "description": "NUCLEO-F767ZI with STM32F767", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h", "version": "v1.10" }, { + "description": "NUCLEO-G0B1RE with STM32G0B1xE", "port": "stm32", "board": "NUCLEO_G0B1RE", "board_name": "NUCLEO-G0B1RE", "mcu_name": "STM32G0B1xE", - "description": "NUCLEO-G0B1RE with STM32G0B1xE", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "NUCLEO-L073RZ with STM32L073RZT6", "port": "stm32", "board": "NUCLEO_L073RZ", "board_name": "NUCLEO-L073RZ", "mcu_name": "STM32L073RZT6", - "description": "NUCLEO-L073RZ with STM32L073RZT6", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h", "version": "v1.12" }, { + "description": "NUCLEO-L152RE with STM32L152xE", "port": "stm32", "board": "NUCLEO_L152RE", "board_name": "NUCLEO-L152RE", "mcu_name": "STM32L152xE", - "description": "NUCLEO-L152RE with STM32L152xE", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.h", "version": "v1.20.0" }, { + "description": "NUCLEO-L432KC with STM32L432KC", "port": "stm32", "board": "NUCLEO_L432KC", "board_name": "NUCLEO-L432KC", "mcu_name": "STM32L432KC", - "description": "NUCLEO-L432KC with STM32L432KC", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h", "version": "v1.10" }, { + "description": "NUCLEO-L452RE with STM32L452RE", "port": "stm32", "board": "NUCLEO_L452RE", "board_name": "NUCLEO-L452RE", "mcu_name": "STM32L452RE", - "description": "NUCLEO-L452RE with STM32L452RE", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.h", "version": "v1.12" }, { + "description": "NUCLEO-L476RG with STM32L476RG", "port": "stm32", "board": "NUCLEO_L476RG", "board_name": "NUCLEO-L476RG", "mcu_name": "STM32L476RG", - "description": "NUCLEO-L476RG with STM32L476RG", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.h", "version": "v1.10" }, { + "description": "NUCLEO-L4A6ZG with STM32L4A6ZG", "port": "stm32", "board": "NUCLEO_L4A6ZG", "board_name": "NUCLEO-L4A6ZG", "mcu_name": "STM32L4A6ZG", - "description": "NUCLEO-L4A6ZG with STM32L4A6ZG", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_L4A6ZG/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_L4A6ZG/mpconfigboard.h", "version": "v1.21.0" }, { + "description": "NUCLEO-WB55 with STM32WB55RGV6", "port": "stm32", "board": "NUCLEO_WB55", "board_name": "NUCLEO-WB55", "mcu_name": "STM32WB55RGV6", - "description": "NUCLEO-WB55 with STM32WB55RGV6", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h", "version": "v1.12" }, { + "description": "NUCLEO-WL55 with STM32WL55JCI7", "port": "stm32", "board": "NUCLEO_WL55", "board_name": "NUCLEO-WL55", "mcu_name": "STM32WL55JCI7", - "description": "NUCLEO-WL55 with STM32WL55JCI7", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_WL55/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_WL55/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "NUCLEO_G474RE with STM32G474", "port": "stm32", "board": "NUCLEO_G474RE", "board_name": "NUCLEO_G474RE", "mcu_name": "STM32G474", - "description": "NUCLEO_G474RE with STM32G474", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_G474RE/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_G474RE/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "NUCLEO_H563ZI with STM32H563ZI", "port": "stm32", "board": "NUCLEO_H563ZI", "board_name": "NUCLEO_H563ZI", "mcu_name": "STM32H563ZI", - "description": "NUCLEO_H563ZI with STM32H563ZI", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_H563ZI/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_H563ZI/mpconfigboard.h", "version": "v1.22.0" }, { + "description": "NUCLEO_H723ZG with STM32H723ZGT6", "port": "stm32", "board": "NUCLEO_H723ZG", "board_name": "NUCLEO_H723ZG", "mcu_name": "STM32H723ZGT6", - "description": "NUCLEO_H723ZG with STM32H723ZGT6", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_H723ZG/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_H723ZG/mpconfigboard.h", "version": "v1.20.0" }, { + "description": "NUCLEO_H743ZI with STM32H743", "port": "stm32", "board": "NUCLEO_H743ZI", "board_name": "NUCLEO_H743ZI", "mcu_name": "STM32H743", - "description": "NUCLEO_H743ZI with STM32H743", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h", + "path": "ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h", "version": "v1.10" }, { - "port": "stm32", - "board": "NUCLEO_H743ZI2", - "board_name": "NUCLEO_H743ZI2", - "mcu_name": "-", - "description": "NUCLEO_H743ZI2", - "path": "repos/micropython/ports/stm32/boards/NUCLEO_H743ZI2/mpconfigboard.h", - "version": "v1.17" - }, - { + "description": "NanoS3 with ESP32-S3-FN8", "port": "esp32", "board": "UM_NANOS3", "board_name": "NanoS3", "mcu_name": "ESP32-S3-FN8", - "description": "NanoS3 with ESP32-S3-FN8", - "path": "repos/micropython/ports/esp32/boards/UM_NANOS3/mpconfigboard.h", + "path": "ports/esp32/boards/UM_NANOS3/mpconfigboard.h", "version": "v1.21.0" }, { + "description": "NetduinoPlus2 with STM32F405RG", "port": "stm32", "board": "NETDUINO_PLUS_2", "board_name": "NetduinoPlus2", "mcu_name": "STM32F405RG", - "description": "NetduinoPlus2 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/NETDUINO_PLUS_2/mpconfigboard.h", + "path": "ports/stm32/boards/NETDUINO_PLUS_2/mpconfigboard.h", "version": "v1.10" }, { + "description": "OLIMEX STM32-E407 with STM32F407", "port": "stm32", "board": "OLIMEX_E407", "board_name": "OLIMEX STM32-E407", "mcu_name": "STM32F407", - "description": "OLIMEX STM32-E407 with STM32F407", - "path": "repos/micropython/ports/stm32/boards/OLIMEX_E407/mpconfigboard.h", + "path": "ports/stm32/boards/OLIMEX_E407/mpconfigboard.h", "version": "v1.10" }, { + "description": "OLIMEX STM32-H407 with STM32F407", "port": "stm32", "board": "OLIMEX_H407", "board_name": "OLIMEX STM32-H407", "mcu_name": "STM32F407", - "description": "OLIMEX STM32-H407 with STM32F407", - "path": "repos/micropython/ports/stm32/boards/OLIMEX_H407/mpconfigboard.h", + "path": "ports/stm32/boards/OLIMEX_H407/mpconfigboard.h", "version": "v1.18" }, { + "description": "Olimex ESP32 ETH with ESP32", "port": "esp32", "board": "OLIMEX_ESP32_POE", "board_name": "Olimex ESP32 ETH", "mcu_name": "ESP32", - "description": "Olimex ESP32 ETH with ESP32", - "path": "repos/micropython/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h", + "path": "ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h", "version": "v1.20.0" }, { + "description": "PCA10000 with NRF51822", "port": "nrf", - "board": "PCA10000", + "board": "pca10000", "board_name": "PCA10000", "mcu_name": "NRF51822", - "description": "PCA10000 with NRF51822", - "path": "repos/micropython/ports/nrf/boards/PCA10000/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/pca10000/mpconfigboard.h", + "version": "v1.10" }, { + "description": "PCA10001 with NRF51822", "port": "nrf", - "board": "PCA10001", + "board": "pca10001", "board_name": "PCA10001", "mcu_name": "NRF51822", - "description": "PCA10001 with NRF51822", - "path": "repos/micropython/ports/nrf/boards/PCA10001/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/pca10001/mpconfigboard.h", + "version": "v1.10" }, { + "description": "PCA10028 with NRF51822", "port": "nrf", - "board": "PCA10028", + "board": "pca10028", "board_name": "PCA10028", "mcu_name": "NRF51822", - "description": "PCA10028 with NRF51822", - "path": "repos/micropython/ports/nrf/boards/PCA10028/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/pca10028/mpconfigboard.h", + "version": "v1.10" }, { + "description": "PCA10031 with NRF51822", "port": "nrf", - "board": "PCA10031", + "board": "pca10031", "board_name": "PCA10031", "mcu_name": "NRF51822", - "description": "PCA10031 with NRF51822", - "path": "repos/micropython/ports/nrf/boards/PCA10031/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/pca10031/mpconfigboard.h", + "version": "v1.10" }, { + "description": "PCA10040 with NRF52832", "port": "nrf", - "board": "PCA10040", + "board": "pca10040", "board_name": "PCA10040", "mcu_name": "NRF52832", - "description": "PCA10040 with NRF52832", - "path": "repos/micropython/ports/nrf/boards/PCA10040/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/pca10040/mpconfigboard.h", + "version": "v1.10" }, { + "description": "PCA10056 with NRF52840", "port": "nrf", - "board": "PCA10056", + "board": "pca10056", "board_name": "PCA10056", "mcu_name": "NRF52840", - "description": "PCA10056 with NRF52840", - "path": "repos/micropython/ports/nrf/boards/PCA10056/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/pca10056/mpconfigboard.h", + "version": "v1.10" }, { + "description": "PCA10059 with NRF52840", "port": "nrf", - "board": "PCA10059", + "board": "pca10059", "board_name": "PCA10059", "mcu_name": "NRF52840", - "description": "PCA10059 with NRF52840", - "path": "repos/micropython/ports/nrf/boards/PCA10059/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/pca10059/mpconfigboard.h", + "version": "v1.12" }, { + "description": "PCA10090 with NRF9160", "port": "nrf", - "board": "PCA10090", + "board": "pca10090", "board_name": "PCA10090", "mcu_name": "NRF9160", - "description": "PCA10090 with NRF9160", - "path": "repos/micropython/ports/nrf/boards/PCA10090/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/pca10090/mpconfigboard.h", + "version": "v1.12" }, { + "description": "PORTENTA C33 with RA6M5", "port": "renesas-ra", "board": "ARDUINO_PORTENTA_C33", "board_name": "PORTENTA C33", "mcu_name": "RA6M5", - "description": "PORTENTA C33 with RA6M5", - "path": "repos/micropython/ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/mpconfigboard.h", + "path": "ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/mpconfigboard.h", "version": "v1.21.0" }, { + "description": "PORTENTA with STM32H747", "port": "stm32", "board": "ARDUINO_PORTENTA_H7", "board_name": "PORTENTA", "mcu_name": "STM32H747", - "description": "PORTENTA with STM32H747", - "path": "repos/micropython/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h", + "path": "ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "PYBD-SF2W with STM32F722IEK", "port": "stm32", "board": "PYBD_SF2", "board_name": "PYBD-SF2W", "mcu_name": "STM32F722IEK", - "description": "PYBD-SF2W with STM32F722IEK", - "path": "repos/micropython/ports/stm32/boards/PYBD_SF2/mpconfigboard.h", + "path": "ports/stm32/boards/PYBD_SF2/mpconfigboard.h", "version": "v1.12" }, { + "description": "PYBD-SF3W with STM32F733IEK", "port": "stm32", "board": "PYBD_SF3", "board_name": "PYBD-SF3W", "mcu_name": "STM32F733IEK", - "description": "PYBD-SF3W with STM32F733IEK", - "path": "repos/micropython/ports/stm32/boards/PYBD_SF3/mpconfigboard.h", + "path": "ports/stm32/boards/PYBD_SF3/mpconfigboard.h", "version": "v1.12" }, { + "description": "PYBD-SF6W with STM32F767IIK", "port": "stm32", "board": "PYBD_SF6", "board_name": "PYBD-SF6W", "mcu_name": "STM32F767IIK", - "description": "PYBD-SF6W with STM32F767IIK", - "path": "repos/micropython/ports/stm32/boards/PYBD_SF6/mpconfigboard.h", + "path": "ports/stm32/boards/PYBD_SF6/mpconfigboard.h", "version": "v1.12" }, { + "description": "PYBLITEv1.0 with STM32F411RE", "port": "stm32", "board": "PYBLITEV10", "board_name": "PYBLITEv1.0", "mcu_name": "STM32F411RE", - "description": "PYBLITEv1.0 with STM32F411RE", - "path": "repos/micropython/ports/stm32/boards/PYBLITEV10/mpconfigboard.h", + "path": "ports/stm32/boards/PYBLITEV10/mpconfigboard.h", "version": "v1.10" }, { + "description": "PYBSTICK26_STD with STM32F411RE", "port": "stm32", "board": "GARATRONIC_PYBSTICK26_F411", "board_name": "PYBSTICK26_STD", "mcu_name": "STM32F411RE", - "description": "PYBSTICK26_STD with STM32F411RE", - "path": "repos/micropython/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/mpconfigboard.h", + "path": "ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/mpconfigboard.h", "version": "v1.18" }, { + "description": "PYBv1.0 with STM32F405RG", "port": "stm32", "board": "PYBV10", "board_name": "PYBv1.0", "mcu_name": "STM32F405RG", - "description": "PYBv1.0 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/PYBV10/mpconfigboard.h", + "path": "ports/stm32/boards/PYBV10/mpconfigboard.h", "version": "v1.10" }, { + "description": "PYBv1.1 with STM32F405RG", "port": "stm32", "board": "PYBV11", "board_name": "PYBv1.1", "mcu_name": "STM32F405RG", - "description": "PYBv1.1 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/PYBV11/mpconfigboard.h", + "path": "ports/stm32/boards/PYBV11/mpconfigboard.h", "version": "v1.10" }, { + "description": "PYBv3 with STM32F405RG", "port": "stm32", "board": "PYBV3", "board_name": "PYBv3", "mcu_name": "STM32F405RG", - "description": "PYBv3 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/PYBV3/mpconfigboard.h", + "path": "ports/stm32/boards/PYBV3/mpconfigboard.h", "version": "v1.10" }, { + "description": "PYBv4 with STM32F405RG", "port": "stm32", "board": "PYBV4", "board_name": "PYBv4", "mcu_name": "STM32F405RG", - "description": "PYBv4 with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/PYBV4/mpconfigboard.h", + "path": "ports/stm32/boards/PYBV4/mpconfigboard.h", "version": "v1.10" }, { - "port": "rp2", - "board": "PIMORONI_PICOLIPO_16MB", - "board_name": "Pimoroni Pico LiPo 16MB", - "mcu_name": "-", - "description": "Pimoroni Pico LiPo 16MB", - "path": "repos/micropython/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h", - "version": "v1.17" - }, - { - "port": "rp2", - "board": "PIMORONI_PICOLIPO_4MB", - "board_name": "Pimoroni Pico LiPo 4MB", - "mcu_name": "-", - "description": "Pimoroni Pico LiPo 4MB", - "path": "repos/micropython/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h", - "version": "v1.17" - }, - { - "port": "rp2", - "board": "PIMORONI_TINY2040", - "board_name": "Pimoroni Tiny 2040", - "mcu_name": "-", - "description": "Pimoroni Tiny 2040", - "path": "repos/micropython/ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h", - "version": "v1.17" - }, - { - "port": "rp2", - "board": "POLOLU_3PI_2040_ROBOT", - "board_name": "Pololu 3pi+ 2040 Robot", - "mcu_name": "-", - "description": "Pololu 3pi+ 2040 Robot", - "path": "repos/micropython/ports/rp2/boards/POLOLU_3PI_2040_ROBOT/mpconfigboard.h", - "version": "v1.22.0" - }, - { - "port": "rp2", - "board": "POLOLU_ZUMO_2040_ROBOT", - "board_name": "Pololu Zumo 2040 Robot", - "mcu_name": "-", - "description": "Pololu Zumo 2040 Robot", - "path": "repos/micropython/ports/rp2/boards/POLOLU_ZUMO_2040_ROBOT/mpconfigboard.h", - "version": "v1.22.0" - }, - { + "description": "ProS3 with ESP32-S3", "port": "esp32", "board": "UM_PROS3", "board_name": "ProS3", "mcu_name": "ESP32-S3", - "description": "ProS3 with ESP32-S3", - "path": "repos/micropython/ports/esp32/boards/UM_PROS3/mpconfigboard.h", + "path": "ports/esp32/boards/UM_PROS3/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "RA4M1 CLICKER with RA4M1", "port": "renesas-ra", "board": "RA4M1_CLICKER", "board_name": "RA4M1 CLICKER", "mcu_name": "RA4M1", - "description": "RA4M1 CLICKER with RA4M1", - "path": "repos/micropython/ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h", + "path": "ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h", "version": "v1.21.0" }, { + "description": "RA4M1_CLICKER with RA4M1", "port": "renesas-ra", "board": "RA4M1_CLICKER", "board_name": "RA4M1_CLICKER", "mcu_name": "RA4M1", - "description": "RA4M1_CLICKER with RA4M1", - "path": "repos/micropython/ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h", + "path": "ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "RA4M1_EK with RA4M1", "port": "renesas-ra", "board": "RA4M1_EK", "board_name": "RA4M1_EK", "mcu_name": "RA4M1", - "description": "RA4M1_EK with RA4M1", - "path": "repos/micropython/ports/renesas-ra/boards/RA4M1_EK/mpconfigboard.h", + "path": "ports/renesas-ra/boards/RA4M1_EK/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "RA4W1_EK with RA4W1", "port": "renesas-ra", "board": "RA4W1_EK", "board_name": "RA4W1_EK", "mcu_name": "RA4W1", - "description": "RA4W1_EK with RA4W1", - "path": "repos/micropython/ports/renesas-ra/boards/RA4W1_EK/mpconfigboard.h", + "path": "ports/renesas-ra/boards/RA4W1_EK/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "RA6M1_EK with RA6M1", "port": "renesas-ra", "board": "RA6M1_EK", "board_name": "RA6M1_EK", "mcu_name": "RA6M1", - "description": "RA6M1_EK with RA6M1", - "path": "repos/micropython/ports/renesas-ra/boards/RA6M1_EK/mpconfigboard.h", + "path": "ports/renesas-ra/boards/RA6M1_EK/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "RA6M2_EK with RA6M2", "port": "renesas-ra", "board": "RA6M2_EK", "board_name": "RA6M2_EK", "mcu_name": "RA6M2", - "description": "RA6M2_EK with RA6M2", - "path": "repos/micropython/ports/renesas-ra/boards/RA6M2_EK/mpconfigboard.h", + "path": "ports/renesas-ra/boards/RA6M2_EK/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "RT1010-Py-DevKIT with MIMXRT1011DAE5A", "port": "mimxrt", "board": "OLIMEX_RT1010", "board_name": "RT1010-Py-DevKIT", "mcu_name": "MIMXRT1011DAE5A", - "description": "RT1010-Py-DevKIT with MIMXRT1011DAE5A", - "path": "repos/micropython/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h", + "path": "ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h", "version": "v1.19.1" }, { - "port": "rp2", - "board": "PICO", - "board_name": "Raspberry Pi Pico", - "mcu_name": "-", - "description": "Raspberry Pi Pico", - "path": "repos/micropython/ports/rp2/boards/PICO/mpconfigboard.h", - "version": "v1.15" - }, - { - "port": "rp2", - "board": "PICO_W", - "board_name": "Raspberry Pi Pico W", - "mcu_name": "-", - "description": "Raspberry Pi Pico W", - "path": "repos/micropython/ports/rp2/boards/PICO_W/mpconfigboard.h", - "version": "v1.20.0" - }, - { + "description": "SAMD21-XPLAINED-PRO with SAMD21J18A", "port": "samd", "board": "SAMD21_XPLAINED_PRO", "board_name": "SAMD21-XPLAINED-PRO", "mcu_name": "SAMD21J18A", - "description": "SAMD21-XPLAINED-PRO with SAMD21J18A", - "path": "repos/micropython/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h", + "path": "ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h", "version": "v1.12" }, { + "description": "STM32H573I-DK with STM32H573IIK3Q", "port": "stm32", "board": "STM32H573I_DK", "board_name": "STM32H573I-DK", "mcu_name": "STM32H573IIK3Q", - "description": "STM32H573I-DK with STM32H573IIK3Q", - "path": "repos/micropython/ports/stm32/boards/STM32H573I_DK/mpconfigboard.h", + "path": "ports/stm32/boards/STM32H573I_DK/mpconfigboard.h", "version": "v1.21.0" }, { + "description": "STM32H7B3I-DK with STM32H7B3LIH6Q", "port": "stm32", "board": "STM32H7B3I_DK", "board_name": "STM32H7B3I-DK", "mcu_name": "STM32H7B3LIH6Q", - "description": "STM32H7B3I-DK with STM32H7B3LIH6Q", - "path": "repos/micropython/ports/stm32/boards/STM32H7B3I_DK/mpconfigboard.h", + "path": "ports/stm32/boards/STM32H7B3I_DK/mpconfigboard.h", "version": "v1.18" }, { + "description": "Seeed ARCH MIX with MIMXRT1052DVL5B", "port": "mimxrt", "board": "SEEED_ARCH_MIX", "board_name": "Seeed ARCH MIX", "mcu_name": "MIMXRT1052DVL5B", - "description": "Seeed ARCH MIX with MIMXRT1052DVL5B", - "path": "repos/micropython/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h", + "path": "ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h", "version": "v1.18" }, { + "description": "Seeed Xiao with SAMD21G18A", "port": "samd", "board": "SEEED_XIAO", "board_name": "Seeed Xiao", "mcu_name": "SAMD21G18A", - "description": "Seeed Xiao with SAMD21G18A", - "path": "repos/micropython/ports/samd/boards/SEEED_XIAO/mpconfigboard.h", + "path": "ports/samd/boards/SEEED_XIAO/mpconfigboard.h", "version": "v1.18" }, { - "port": "rp2", - "board": "SIL_RP2040_SHIM", - "board_name": "Silicognition RP2040-Shim", - "mcu_name": "-", - "description": "Silicognition RP2040-Shim", - "path": "repos/micropython/ports/rp2/boards/SIL_RP2040_SHIM/mpconfigboard.h", - "version": "v1.22.0" - }, - { + "description": "Silicognition wESP32 with ESP32", "port": "esp32", "board": "SIL_WESP32", "board_name": "Silicognition wESP32", "mcu_name": "ESP32", - "description": "Silicognition wESP32 with ESP32", - "path": "repos/micropython/ports/esp32/boards/SIL_WESP32/mpconfigboard.h", + "path": "ports/esp32/boards/SIL_WESP32/mpconfigboard.h", "version": "v1.17" }, { - "port": "rp2", - "board": "SPARKFUN_PROMICRO", - "board_name": "SparkFun Pro Micro RP2040", - "mcu_name": "-", - "description": "SparkFun Pro Micro RP2040", - "path": "repos/micropython/ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h", - "version": "v1.16" - }, - { + "description": "SparkFun STM32 MicroMod Processor with STM32F405RG", "port": "stm32", "board": "SPARKFUN_MICROMOD_STM32", "board_name": "SparkFun STM32 MicroMod Processor", "mcu_name": "STM32F405RG", - "description": "SparkFun STM32 MicroMod Processor with STM32F405RG", - "path": "repos/micropython/ports/stm32/boards/SPARKFUN_MICROMOD_STM32/mpconfigboard.h", + "path": "ports/stm32/boards/SPARKFUN_MICROMOD_STM32/mpconfigboard.h", "version": "v1.17" }, { - "port": "rp2", - "board": "SPARKFUN_THINGPLUS", - "board_name": "SparkFun Thing Plus RP2040", - "mcu_name": "-", - "description": "SparkFun Thing Plus RP2040", - "path": "repos/micropython/ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h", - "version": "v1.16" - }, - { + "description": "Sparkfun SAMD51 Thing Plus with SAMD51J20A", "port": "samd", "board": "SPARKFUN_SAMD51_THING_PLUS", "board_name": "Sparkfun SAMD51 Thing Plus", "mcu_name": "SAMD51J20A", - "description": "Sparkfun SAMD51 Thing Plus with SAMD51J20A", - "path": "repos/micropython/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h", + "path": "ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h", "version": "v1.20.0" }, { + "description": "Teensy 4.0 with MIMXRT1062DVJ6A", "port": "mimxrt", "board": "TEENSY40", "board_name": "Teensy 4.0", "mcu_name": "MIMXRT1062DVJ6A", - "description": "Teensy 4.0 with MIMXRT1062DVJ6A", - "path": "repos/micropython/ports/mimxrt/boards/TEENSY40/mpconfigboard.h", + "path": "ports/mimxrt/boards/TEENSY40/mpconfigboard.h", "version": "v1.13" }, { + "description": "Teensy 4.1 with MIMXRT1062DVJ6A", "port": "mimxrt", "board": "TEENSY41", "board_name": "Teensy 4.1", "mcu_name": "MIMXRT1062DVJ6A", - "description": "Teensy 4.1 with MIMXRT1062DVJ6A", - "path": "repos/micropython/ports/mimxrt/boards/TEENSY41/mpconfigboard.h", + "path": "ports/mimxrt/boards/TEENSY41/mpconfigboard.h", "version": "v1.16" }, { + "description": "TinyPICO with ESP32-PICO-D4", "port": "esp32", "board": "TINYPICO", "board_name": "TinyPICO", "mcu_name": "ESP32-PICO-D4", - "description": "TinyPICO with ESP32-PICO-D4", - "path": "repos/micropython/ports/esp32/boards/TINYPICO/mpconfigboard.h", + "path": "ports/esp32/boards/TINYPICO/mpconfigboard.h", "version": "v1.12" }, { + "description": "TinyS2 with ESP32-S2FN4R2", "port": "esp32", "board": "UM_TINYS2", "board_name": "TinyS2", "mcu_name": "ESP32-S2FN4R2", - "description": "TinyS2 with ESP32-S2FN4R2", - "path": "repos/micropython/ports/esp32/boards/UM_TINYS2/mpconfigboard.h", + "path": "ports/esp32/boards/UM_TINYS2/mpconfigboard.h", "version": "v1.16" }, { + "description": "TinyS3 with ESP32-S3-FN8", "port": "esp32", "board": "UM_TINYS3", "board_name": "TinyS3", "mcu_name": "ESP32-S3-FN8", - "description": "TinyS3 with ESP32-S3-FN8", - "path": "repos/micropython/ports/esp32/boards/UM_TINYS3/mpconfigboard.h", + "path": "ports/esp32/boards/UM_TINYS3/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "TinyWATCH S3 with ESP32-S3-PICO-1-N8R2", "port": "esp32", "board": "UM_TINYWATCHS3", "board_name": "TinyWATCH S3", "mcu_name": "ESP32-S3-PICO-1-N8R2", - "description": "TinyWATCH S3 with ESP32-S3-PICO-1-N8R2", - "path": "repos/micropython/ports/esp32/boards/UM_TINYWATCHS3/mpconfigboard.h", + "path": "ports/esp32/boards/UM_TINYWATCHS3/mpconfigboard.h", "version": "v1.22.0" }, { + "description": "Trinket M0 with SAMD21E18A", "port": "samd", "board": "ADAFRUIT_TRINKET_M0", "board_name": "Trinket M0", "mcu_name": "SAMD21E18A", - "description": "Trinket M0 with SAMD21E18A", - "path": "repos/micropython/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h", + "path": "ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h", "version": "v1.12" }, { + "description": "USBDongle-WB55 with STM32WB55CGU6", "port": "stm32", "board": "USBDONGLE_WB55", "board_name": "USBDongle-WB55", "mcu_name": "STM32WB55CGU6", - "description": "USBDongle-WB55 with STM32WB55CGU6", - "path": "repos/micropython/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h", + "path": "ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h", "version": "v1.12" }, { + "description": "VCC-GND STM32F407VE with STM32F407VE", "port": "stm32", "board": "VCC_GND_F407VE", "board_name": "VCC-GND STM32F407VE", "mcu_name": "STM32F407VE", - "description": "VCC-GND STM32F407VE with STM32F407VE", - "path": "repos/micropython/ports/stm32/boards/VCC_GND_F407VE/mpconfigboard.h", + "path": "ports/stm32/boards/VCC_GND_F407VE/mpconfigboard.h", "version": "v1.16" }, { + "description": "VCC-GND STM32F407ZG with STM32F407ZG", "port": "stm32", "board": "VCC_GND_F407ZG", "board_name": "VCC-GND STM32F407ZG", "mcu_name": "STM32F407ZG", - "description": "VCC-GND STM32F407ZG with STM32F407ZG", - "path": "repos/micropython/ports/stm32/boards/VCC_GND_F407ZG/mpconfigboard.h", + "path": "ports/stm32/boards/VCC_GND_F407ZG/mpconfigboard.h", "version": "v1.16" }, { + "description": "VCC-GND STM32H743VI with STM32H743VI", "port": "stm32", "board": "VCC_GND_H743VI", "board_name": "VCC-GND STM32H743VI", "mcu_name": "STM32H743VI", - "description": "VCC-GND STM32H743VI with STM32H743VI", - "path": "repos/micropython/ports/stm32/boards/VCC_GND_H743VI/mpconfigboard.h", + "path": "ports/stm32/boards/VCC_GND_H743VI/mpconfigboard.h", "version": "v1.18" }, { + "description": "VK-RA6M5 with RA6M5", "port": "renesas-ra", "board": "VK_RA6M5", "board_name": "VK-RA6M5", "mcu_name": "RA6M5", - "description": "VK-RA6M5 with RA6M5", - "path": "repos/micropython/ports/renesas-ra/boards/VK_RA6M5/mpconfigboard.h", + "path": "ports/renesas-ra/boards/VK_RA6M5/mpconfigboard.h", "version": "v1.21.0" }, { - "port": "rp2", - "board": "W5100S_EVB_PICO", - "board_name": "W5100S-EVB-Pico", - "mcu_name": "-", - "description": "W5100S-EVB-Pico", - "path": "repos/micropython/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.h", - "version": "v1.19.1" - }, - { - "port": "rp2", - "board": "W5500_EVB_PICO", - "board_name": "W5500-EVB-Pico", - "mcu_name": "-", - "description": "W5500-EVB-Pico", - "path": "repos/micropython/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.h", - "version": "v1.20.0" - }, - { + "description": "WT51822-S4AT with NRF51822", "port": "nrf", - "board": "WT51822_S4AT", + "board": "wt51822_s4at", "board_name": "WT51822-S4AT", "mcu_name": "NRF51822", - "description": "WT51822-S4AT with NRF51822", - "path": "repos/micropython/ports/nrf/boards/WT51822_S4AT/mpconfigboard.h", - "version": "v1.21.0" - }, - { - "port": "rp2", - "board": "WEACTSTUDIO", - "board_name": "WeAct Studio RP2040", - "mcu_name": "-", - "description": "WeAct Studio RP2040", - "path": "repos/micropython/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.h", - "version": "v1.20.0" + "path": "ports/nrf/boards/wt51822_s4at/mpconfigboard.h", + "version": "v1.10" }, { + "description": "WiPy with CC3200", "port": "cc3200", "board": "WIPY", "board_name": "WiPy", "mcu_name": "CC3200", - "description": "WiPy with CC3200", - "path": "repos/micropython/ports/cc3200/boards/WIPY/mpconfigboard.h", + "path": "ports/cc3200/boards/WIPY/mpconfigboard.h", "version": "v1.10" }, { + "description": "Wio Terminal D51R with SAMD51P19A", "port": "samd", "board": "SEEED_WIO_TERMINAL", "board_name": "Wio Terminal D51R", "mcu_name": "SAMD51P19A", - "description": "Wio Terminal D51R with SAMD51P19A", - "path": "repos/micropython/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h", + "path": "ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h", "version": "v1.18" }, { + "description": "XENON with NRF52840", "port": "nrf", - "board": "PARTICLE_XENON", + "board": "particle_xenon", "board_name": "XENON", "mcu_name": "NRF52840", - "description": "XENON with NRF52840", - "path": "repos/micropython/ports/nrf/boards/PARTICLE_XENON/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/particle_xenon/mpconfigboard.h", + "version": "v1.12" }, { + "description": "XIAO nRF52840 Sense with NRF52840", "port": "nrf", - "board": "SEEED_XIAO_NRF52", + "board": "seeed_xiao_nrf52", "board_name": "XIAO nRF52840 Sense", "mcu_name": "NRF52840", - "description": "XIAO nRF52840 Sense with NRF52840", - "path": "repos/micropython/ports/nrf/boards/SEEED_XIAO_NRF52/mpconfigboard.h", - "version": "v1.21.0" + "path": "ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.h", + "version": "v1.20.0" }, { + "description": "i.MX RT1010 EVK with MIMXRT1011DAE5A", "port": "mimxrt", "board": "MIMXRT1010_EVK", "board_name": "i.MX RT1010 EVK", "mcu_name": "MIMXRT1011DAE5A", - "description": "i.MX RT1010 EVK with MIMXRT1011DAE5A", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h", + "path": "ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h", "version": "v1.13" }, { + "description": "i.MX RT1015 EVK with MIMXRT1015DAF5A", "port": "mimxrt", "board": "MIMXRT1015_EVK", "board_name": "i.MX RT1015 EVK", "mcu_name": "MIMXRT1015DAF5A", - "description": "i.MX RT1015 EVK with MIMXRT1015DAF5A", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h", + "path": "ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h", "version": "v1.19.1" }, { + "description": "i.MX RT1020 EVK with MIMXRT1021DAG5A", "port": "mimxrt", "board": "MIMXRT1020_EVK", "board_name": "i.MX RT1020 EVK", "mcu_name": "MIMXRT1021DAG5A", - "description": "i.MX RT1020 EVK with MIMXRT1021DAG5A", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h", + "path": "ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h", "version": "v1.13" }, { + "description": "i.MX RT1050 EVK with MIMXRT1052DVL6B", "port": "mimxrt", "board": "MIMXRT1050_EVK", "board_name": "i.MX RT1050 EVK", "mcu_name": "MIMXRT1052DVL6B", - "description": "i.MX RT1050 EVK with MIMXRT1052DVL6B", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h", + "path": "ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h", "version": "v1.15" }, { + "description": "i.MX RT1050 EVKB with MIMXRT1052DVL6B", "port": "mimxrt", "board": "MIMXRT1050_EVKB", "board_name": "i.MX RT1050 EVKB", "mcu_name": "MIMXRT1052DVL6B", - "description": "i.MX RT1050 EVKB with MIMXRT1052DVL6B", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1050_EVKB/mpconfigboard.h", + "path": "ports/mimxrt/boards/MIMXRT1050_EVKB/mpconfigboard.h", "version": "v1.17" }, { + "description": "i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B", "port": "mimxrt", "board": "MIMXRT1050_EVK", "board_name": "i.MX RT1050 EVKB-A1", "mcu_name": "MIMXRT1052DVL6B", - "description": "i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h", + "path": "ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h", "version": "v1.18" }, { + "description": "i.MX RT1060 EVK with MIMXRT1062DVJ6A", "port": "mimxrt", "board": "MIMXRT1060_EVK", "board_name": "i.MX RT1060 EVK", "mcu_name": "MIMXRT1062DVJ6A", - "description": "i.MX RT1060 EVK with MIMXRT1062DVJ6A", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h", + "path": "ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h", "version": "v1.13" }, { + "description": "i.MX RT1064 EVK with MIMXRT1064DVL6A", "port": "mimxrt", "board": "MIMXRT1064_EVK", "board_name": "i.MX RT1064 EVK", "mcu_name": "MIMXRT1064DVL6A", - "description": "i.MX RT1064 EVK with MIMXRT1064DVL6A", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h", + "path": "ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h", "version": "v1.14" }, { + "description": "i.MX RT1170 EVK with MIMXRT1176DVMAA", "port": "mimxrt", "board": "MIMXRT1170_EVK", "board_name": "i.MX RT1170 EVK", "mcu_name": "MIMXRT1176DVMAA", - "description": "i.MX RT1170 EVK with MIMXRT1176DVMAA", - "path": "repos/micropython/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h", + "path": "ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h", "version": "v1.20.0" }, { + "description": "micro:bit with NRF51822", "port": "nrf", - "board": "MICROBIT", + "board": "microbit", "board_name": "micro:bit", "mcu_name": "NRF51822", - "description": "micro:bit with NRF51822", - "path": "repos/micropython/ports/nrf/boards/MICROBIT/mpconfigboard.h", - "version": "v1.21.0" - }, - { - "port": "rp2", - "board": "NULLBITS_BIT_C_PRO", - "board_name": "nullbits Bit-C PRO", - "mcu_name": "-", - "description": "nullbits Bit-C PRO", - "path": "repos/micropython/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.h", - "version": "v1.20.0" + "path": "ports/nrf/boards/microbit/mpconfigboard.h", + "version": "v1.10" } ] \ No newline at end of file From 2e3106bc806ad413a61cbb94466cb5558b3f0bda Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 2 Jan 2024 00:01:44 +0100 Subject: [PATCH 07/68] Refactor write_files function and sort board_list by description (case insensitive) Signed-off-by: Jos Verlinde --- scripts/get_boardnames.py | 8 +- src/stubber/data/board_info.csv | 50 ++-- src/stubber/data/board_info.json | 432 +++++++++++++++---------------- 3 files changed, 244 insertions(+), 246 deletions(-) diff --git a/scripts/get_boardnames.py b/scripts/get_boardnames.py index d9c6d5d79..2ff8bdb8a 100644 --- a/scripts/get_boardnames.py +++ b/scripts/get_boardnames.py @@ -129,7 +129,7 @@ def collect_boardinfo(mpy_path: Path, version: str) -> List[Board]: return board_list -def write_files(board_list: List[Board], *, folder: Path = Path("src/stubber/data")): +def write_files(board_list: List[Board], *, folder: Path): """Writes the board information to JSON and CSV files. Args: @@ -167,10 +167,8 @@ def get_board_list(versions: List[str], mpy_path: Path): print("Total number of boards found:", len(board_list)) seen = set() board_list = [x for x in board_list if not (x.description in seen or seen.add(x.description))] - board_list.sort(key=lambda x: x.description) + board_list.sort(key=lambda x: x.description.lower()) print("Unique board descriptions found:", len(board_list)) - print(f" found OTA = {'Generic ESP32 module with OTA' in seen}") - print(f" found UNICORE = {'ESP32-UNICORE' in seen}") return board_list @@ -196,7 +194,7 @@ def main(): board_list = get_board_list(versions, mpy_path) print(tabulate(board_list, headers="keys")) # type: ignore - write_files(board_list) + write_files(board_list, folder=Path("src/stubber/data")) if __name__ == "__main__": diff --git a/src/stubber/data/board_info.csv b/src/stubber/data/board_info.csv index fe9cc4565..86c740e01 100644 --- a/src/stubber/data/board_info.csv +++ b/src/stubber/data/board_info.csv @@ -12,8 +12,8 @@ Arduino Portenta H7 with STM32H747,ARDUINO_PORTENTA_H7 Arduino Primo with NRF52832,arduino_primo B-L072Z-LRWAN1 with STM32L072CZ,B_L072Z_LRWAN1 B-L475E-IOT01A with STM32L475,B_L475E_IOT01A -BLUEIO-TAG-EVIM with NRF52832,blueio_tag_evim Bluefruit nRF52 Feather with NRF52832,feather52 +BLUEIO-TAG-EVIM with NRF52832,blueio_tag_evim Cerb40 with STM32F405RG,CERB40 CustomPCB with STM32F439,STM32F439 DVK-BL652 with NRF52832,dvk_bl652 @@ -24,9 +24,9 @@ EK-RA6M2 with RA6M2,EK_RA6M2 ESP module (1M) with ESP8266,GENERIC_1M ESP module (512K) with ESP8266,GENERIC_512K ESP module with ESP8266,GENERIC -ESP32 Unicore module with ESP32-UNICORE,GENERIC_UNICORE ESP32 module (spiram) with ESP32,GENERIC_SPIRAM ESP32 module with ESP32,GENERIC +ESP32 Unicore module with ESP32-UNICORE,GENERIC_UNICORE ESP32-D2WD,ESP32_GENERIC ESP32-S2-WROVER with ESP32-S2,ESP32_S2_WROVER ESP32-UNICORE,ESP32_GENERIC @@ -35,9 +35,9 @@ ESP32S2 module with ESP32S2,GENERIC_S2 ESP32S3 module (spiram octal) with ESP32S3,GENERIC_S3_SPIRAM_OCT ESP32S3 module (spiram) with ESP32S3,GENERIC_S3_SPIRAM ESP32S3 module with ESP32S3,GENERIC_S3 +Espruino Pico with STM32F401CD,ESPRUINO_PICO EVK_NINA_B1 with NRF52832,evk_nina_b1 EVK_NINA_B3 with NRF52840,evk_nina_b3 -Espruino Pico with STM32F401CD,ESPRUINO_PICO F411DISC with STM32F411,STM32F411DISC F429I-DISCO with STM32F429,STM32F429DISC F4DISC with STM32F407,STM32F4DISC @@ -48,7 +48,6 @@ Feather M4 Express with SAMD51J19A,ADAFRUIT_FEATHER_M4_EXPRESS FeatherS2 Neo with ESP32-S2FN4R2,UM_FEATHERS2NEO FeatherS2 with ESP32-S2,UM_FEATHERS2 FeatherS3 with ESP32-S3,UM_FEATHERS3 -GIGA with STM32H747,ARDUINO_GIGA Generic ESP32 module with ESP32,ESP32_GENERIC Generic ESP32 module with OTA,ESP32_GENERIC Generic ESP32 module with SPIRAM,ESP32_GENERIC @@ -56,13 +55,24 @@ Generic ESP32-D2WD module with ESP32-D2WD,GENERIC_D2WD Generic ESP32S2 module with ESP32S2,ESP32_GENERIC_S2 Generic ESP32S3 module with ESP32S3,ESP32_GENERIC_S3 Generic ESP32S3 module with Octal-SPIRAM,ESP32_GENERIC_S3 +GIGA with STM32H747,ARDUINO_GIGA HydraBus1.0 with STM32F4,HYDRABUS +i.MX RT1010 EVK with MIMXRT1011DAE5A,MIMXRT1010_EVK +i.MX RT1015 EVK with MIMXRT1015DAF5A,MIMXRT1015_EVK +i.MX RT1020 EVK with MIMXRT1021DAG5A,MIMXRT1020_EVK +i.MX RT1050 EVK with MIMXRT1052DVL6B,MIMXRT1050_EVK +i.MX RT1050 EVKB with MIMXRT1052DVL6B,MIMXRT1050_EVKB +i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B,MIMXRT1050_EVK +i.MX RT1060 EVK with MIMXRT1062DVJ6A,MIMXRT1060_EVK +i.MX RT1064 EVK with MIMXRT1064DVL6A,MIMXRT1064_EVK +i.MX RT1170 EVK with MIMXRT1176DVMAA,MIMXRT1170_EVK IBK-BLYST-NANO with NRF52832,ibk_blyst_nano IDK-BLYST-NANO with NRF52832,idk_blyst_nano ItsyBitsy M0 Express with SAMD21G18A,ADAFRUIT_ITSYBITSY_M0_EXPRESS ItsyBitsy M4 Express with SAMD51G19A,ADAFRUIT_ITSYBITSY_M4_EXPRESS L476-DISCO with STM32L476,STM32L476DISC L496G-DISCO with STM32L496,STM32L496GDISC +LaunchPad with CC3200,LAUNCHXL LEGO Technic Hub No.6 with STM32F413,LEGO_HUB_NO6 LEGO Technic Hub No.7 with STM32F413,LEGO_HUB_NO7 LILYGO TTGO LoRa32 with ESP32,LILYGO_TTGO_LORA32 @@ -70,14 +80,16 @@ LIMIFROG with STM32L476,LIMIFROG LOLIN_C3_MINI with ESP32-C3FH4,LOLIN_C3_MINI LOLIN_S2_MINI with ESP32-S2FN4R2,LOLIN_S2_MINI LOLIN_S2_PICO with ESP32-S2FN4R2,LOLIN_S2_PICO -LaunchPad with CC3200,LAUNCHXL M5Stack ATOM with ESP32-PICO-D4,M5STACK_ATOM MDK-USB-DONGLE with NRF52840,nrf52840-mdk-usb-dongle -MIKROE_CLICKER2_STM32 with STM32F407,MIKROE_CLICKER2_STM32 Metro M4 Express Airlift with SAMD51J19A,ADAFRUIT_METRO_M4_EXPRESS +micro:bit with NRF51822,microbit MikroE Quail with STM32F427VI,MIKROE_QUAIL +MIKROE_CLICKER2_STM32 with STM32F407,MIKROE_CLICKER2_STM32 Mini SAM M4 with SAMD51G19A,MINISAM_M4 NADHAT_PYBF405 with STM32F405RG,NADHAT_PYBF405 +NanoS3 with ESP32-S3-FN8,UM_NANOS3 +NetduinoPlus2 with STM32F405RG,NETDUINO_PLUS_2 NICLAVISION with STM32H747,ARDUINO_NICLA_VISION NUCLEO-F091RC with STM32F091RCT6,NUCLEO_F091RC NUCLEO-F401RE with STM32F401xE,NUCLEO_F401RE @@ -104,11 +116,9 @@ NUCLEO_G474RE with STM32G474,NUCLEO_G474RE NUCLEO_H563ZI with STM32H563ZI,NUCLEO_H563ZI NUCLEO_H723ZG with STM32H723ZGT6,NUCLEO_H723ZG NUCLEO_H743ZI with STM32H743,NUCLEO_H743ZI -NanoS3 with ESP32-S3-FN8,UM_NANOS3 -NetduinoPlus2 with STM32F405RG,NETDUINO_PLUS_2 +Olimex ESP32 ETH with ESP32,OLIMEX_ESP32_POE OLIMEX STM32-E407 with STM32F407,OLIMEX_E407 OLIMEX STM32-H407 with STM32F407,OLIMEX_H407 -Olimex ESP32 ETH with ESP32,OLIMEX_ESP32_POE PCA10000 with NRF51822,pca10000 PCA10001 with NRF51822,pca10001 PCA10028 with NRF51822,pca10028 @@ -119,6 +129,7 @@ PCA10059 with NRF52840,pca10059 PCA10090 with NRF9160,pca10090 PORTENTA C33 with RA6M5,ARDUINO_PORTENTA_C33 PORTENTA with STM32H747,ARDUINO_PORTENTA_H7 +ProS3 with ESP32-S3,UM_PROS3 PYBD-SF2W with STM32F722IEK,PYBD_SF2 PYBD-SF3W with STM32F733IEK,PYBD_SF3 PYBD-SF6W with STM32F767IIK,PYBD_SF6 @@ -128,7 +139,6 @@ PYBv1.0 with STM32F405RG,PYBV10 PYBv1.1 with STM32F405RG,PYBV11 PYBv3 with STM32F405RG,PYBV3 PYBv4 with STM32F405RG,PYBV4 -ProS3 with ESP32-S3,UM_PROS3 RA4M1 CLICKER with RA4M1,RA4M1_CLICKER RA4M1_CLICKER with RA4M1,RA4M1_CLICKER RA4M1_EK with RA4M1,RA4M1_EK @@ -137,13 +147,13 @@ RA6M1_EK with RA6M1,RA6M1_EK RA6M2_EK with RA6M2,RA6M2_EK RT1010-Py-DevKIT with MIMXRT1011DAE5A,OLIMEX_RT1010 SAMD21-XPLAINED-PRO with SAMD21J18A,SAMD21_XPLAINED_PRO -STM32H573I-DK with STM32H573IIK3Q,STM32H573I_DK -STM32H7B3I-DK with STM32H7B3LIH6Q,STM32H7B3I_DK Seeed ARCH MIX with MIMXRT1052DVL5B,SEEED_ARCH_MIX Seeed Xiao with SAMD21G18A,SEEED_XIAO Silicognition wESP32 with ESP32,SIL_WESP32 -SparkFun STM32 MicroMod Processor with STM32F405RG,SPARKFUN_MICROMOD_STM32 Sparkfun SAMD51 Thing Plus with SAMD51J20A,SPARKFUN_SAMD51_THING_PLUS +SparkFun STM32 MicroMod Processor with STM32F405RG,SPARKFUN_MICROMOD_STM32 +STM32H573I-DK with STM32H573IIK3Q,STM32H573I_DK +STM32H7B3I-DK with STM32H7B3LIH6Q,STM32H7B3I_DK Teensy 4.0 with MIMXRT1062DVJ6A,TEENSY40 Teensy 4.1 with MIMXRT1062DVJ6A,TEENSY41 TinyPICO with ESP32-PICO-D4,TINYPICO @@ -156,18 +166,8 @@ VCC-GND STM32F407VE with STM32F407VE,VCC_GND_F407VE VCC-GND STM32F407ZG with STM32F407ZG,VCC_GND_F407ZG VCC-GND STM32H743VI with STM32H743VI,VCC_GND_H743VI VK-RA6M5 with RA6M5,VK_RA6M5 -WT51822-S4AT with NRF51822,wt51822_s4at -WiPy with CC3200,WIPY Wio Terminal D51R with SAMD51P19A,SEEED_WIO_TERMINAL +WiPy with CC3200,WIPY +WT51822-S4AT with NRF51822,wt51822_s4at XENON with NRF52840,particle_xenon XIAO nRF52840 Sense with NRF52840,seeed_xiao_nrf52 -i.MX RT1010 EVK with MIMXRT1011DAE5A,MIMXRT1010_EVK -i.MX RT1015 EVK with MIMXRT1015DAF5A,MIMXRT1015_EVK -i.MX RT1020 EVK with MIMXRT1021DAG5A,MIMXRT1020_EVK -i.MX RT1050 EVK with MIMXRT1052DVL6B,MIMXRT1050_EVK -i.MX RT1050 EVKB with MIMXRT1052DVL6B,MIMXRT1050_EVKB -i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B,MIMXRT1050_EVK -i.MX RT1060 EVK with MIMXRT1062DVJ6A,MIMXRT1060_EVK -i.MX RT1064 EVK with MIMXRT1064DVL6A,MIMXRT1064_EVK -i.MX RT1170 EVK with MIMXRT1176DVMAA,MIMXRT1170_EVK -micro:bit with NRF51822,microbit diff --git a/src/stubber/data/board_info.json b/src/stubber/data/board_info.json index 41e858b54..a47fdee8b 100644 --- a/src/stubber/data/board_info.json +++ b/src/stubber/data/board_info.json @@ -116,15 +116,6 @@ "path": "ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.h", "version": "v1.10" }, - { - "description": "BLUEIO-TAG-EVIM with NRF52832", - "port": "nrf", - "board": "blueio_tag_evim", - "board_name": "BLUEIO-TAG-EVIM", - "mcu_name": "NRF52832", - "path": "ports/nrf/boards/blueio_tag_evim/mpconfigboard.h", - "version": "v1.11" - }, { "description": "Bluefruit nRF52 Feather with NRF52832", "port": "nrf", @@ -134,6 +125,15 @@ "path": "ports/nrf/boards/feather52/mpconfigboard.h", "version": "v1.10" }, + { + "description": "BLUEIO-TAG-EVIM with NRF52832", + "port": "nrf", + "board": "blueio_tag_evim", + "board_name": "BLUEIO-TAG-EVIM", + "mcu_name": "NRF52832", + "path": "ports/nrf/boards/blueio_tag_evim/mpconfigboard.h", + "version": "v1.11" + }, { "description": "Cerb40 with STM32F405RG", "port": "stm32", @@ -224,15 +224,6 @@ "path": "ports/esp8266/boards/GENERIC/mpconfigboard.h", "version": "v1.12" }, - { - "description": "ESP32 Unicore module with ESP32-UNICORE", - "port": "esp32", - "board": "GENERIC_UNICORE", - "board_name": "ESP32 Unicore module", - "mcu_name": "ESP32-UNICORE", - "path": "ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h", - "version": "v1.20.0" - }, { "description": "ESP32 module (spiram) with ESP32", "port": "esp32", @@ -251,6 +242,15 @@ "path": "ports/esp32/boards/GENERIC/mpconfigboard.h", "version": "v1.12" }, + { + "description": "ESP32 Unicore module with ESP32-UNICORE", + "port": "esp32", + "board": "GENERIC_UNICORE", + "board_name": "ESP32 Unicore module", + "mcu_name": "ESP32-UNICORE", + "path": "ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h", + "version": "v1.20.0" + }, { "description": "ESP32-D2WD", "port": "esp32", @@ -323,6 +323,15 @@ "path": "ports/esp32/boards/GENERIC_S3/mpconfigboard.h", "version": "v1.18" }, + { + "description": "Espruino Pico with STM32F401CD", + "port": "stm32", + "board": "ESPRUINO_PICO", + "board_name": "Espruino Pico", + "mcu_name": "STM32F401CD", + "path": "ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.h", + "version": "v1.10" + }, { "description": "EVK_NINA_B1 with NRF52832", "port": "nrf", @@ -341,15 +350,6 @@ "path": "ports/nrf/boards/evk_nina_b3/mpconfigboard.h", "version": "v1.16" }, - { - "description": "Espruino Pico with STM32F401CD", - "port": "stm32", - "board": "ESPRUINO_PICO", - "board_name": "Espruino Pico", - "mcu_name": "STM32F401CD", - "path": "ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.h", - "version": "v1.10" - }, { "description": "F411DISC with STM32F411", "port": "stm32", @@ -440,15 +440,6 @@ "path": "ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h", "version": "v1.19.1" }, - { - "description": "GIGA with STM32H747", - "port": "stm32", - "board": "ARDUINO_GIGA", - "board_name": "GIGA", - "mcu_name": "STM32H747", - "path": "ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h", - "version": "v1.20.0" - }, { "description": "Generic ESP32 module with ESP32", "port": "esp32", @@ -512,6 +503,15 @@ "path": "ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.cmake", "version": "v1.21.0" }, + { + "description": "GIGA with STM32H747", + "port": "stm32", + "board": "ARDUINO_GIGA", + "board_name": "GIGA", + "mcu_name": "STM32H747", + "path": "ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h", + "version": "v1.20.0" + }, { "description": "HydraBus1.0 with STM32F4", "port": "stm32", @@ -521,6 +521,87 @@ "path": "ports/stm32/boards/HYDRABUS/mpconfigboard.h", "version": "v1.10" }, + { + "description": "i.MX RT1010 EVK with MIMXRT1011DAE5A", + "port": "mimxrt", + "board": "MIMXRT1010_EVK", + "board_name": "i.MX RT1010 EVK", + "mcu_name": "MIMXRT1011DAE5A", + "path": "ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h", + "version": "v1.13" + }, + { + "description": "i.MX RT1015 EVK with MIMXRT1015DAF5A", + "port": "mimxrt", + "board": "MIMXRT1015_EVK", + "board_name": "i.MX RT1015 EVK", + "mcu_name": "MIMXRT1015DAF5A", + "path": "ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h", + "version": "v1.19.1" + }, + { + "description": "i.MX RT1020 EVK with MIMXRT1021DAG5A", + "port": "mimxrt", + "board": "MIMXRT1020_EVK", + "board_name": "i.MX RT1020 EVK", + "mcu_name": "MIMXRT1021DAG5A", + "path": "ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h", + "version": "v1.13" + }, + { + "description": "i.MX RT1050 EVK with MIMXRT1052DVL6B", + "port": "mimxrt", + "board": "MIMXRT1050_EVK", + "board_name": "i.MX RT1050 EVK", + "mcu_name": "MIMXRT1052DVL6B", + "path": "ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h", + "version": "v1.15" + }, + { + "description": "i.MX RT1050 EVKB with MIMXRT1052DVL6B", + "port": "mimxrt", + "board": "MIMXRT1050_EVKB", + "board_name": "i.MX RT1050 EVKB", + "mcu_name": "MIMXRT1052DVL6B", + "path": "ports/mimxrt/boards/MIMXRT1050_EVKB/mpconfigboard.h", + "version": "v1.17" + }, + { + "description": "i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B", + "port": "mimxrt", + "board": "MIMXRT1050_EVK", + "board_name": "i.MX RT1050 EVKB-A1", + "mcu_name": "MIMXRT1052DVL6B", + "path": "ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h", + "version": "v1.18" + }, + { + "description": "i.MX RT1060 EVK with MIMXRT1062DVJ6A", + "port": "mimxrt", + "board": "MIMXRT1060_EVK", + "board_name": "i.MX RT1060 EVK", + "mcu_name": "MIMXRT1062DVJ6A", + "path": "ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h", + "version": "v1.13" + }, + { + "description": "i.MX RT1064 EVK with MIMXRT1064DVL6A", + "port": "mimxrt", + "board": "MIMXRT1064_EVK", + "board_name": "i.MX RT1064 EVK", + "mcu_name": "MIMXRT1064DVL6A", + "path": "ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h", + "version": "v1.14" + }, + { + "description": "i.MX RT1170 EVK with MIMXRT1176DVMAA", + "port": "mimxrt", + "board": "MIMXRT1170_EVK", + "board_name": "i.MX RT1170 EVK", + "mcu_name": "MIMXRT1176DVMAA", + "path": "ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h", + "version": "v1.20.0" + }, { "description": "IBK-BLYST-NANO with NRF52832", "port": "nrf", @@ -575,6 +656,15 @@ "path": "ports/stm32/boards/STM32L496GDISC/mpconfigboard.h", "version": "v1.10" }, + { + "description": "LaunchPad with CC3200", + "port": "cc3200", + "board": "LAUNCHXL", + "board_name": "LaunchPad", + "mcu_name": "CC3200", + "path": "ports/cc3200/boards/LAUNCHXL/mpconfigboard.h", + "version": "v1.10" + }, { "description": "LEGO Technic Hub No.6 with STM32F413", "port": "stm32", @@ -638,15 +728,6 @@ "path": "ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h", "version": "v1.18" }, - { - "description": "LaunchPad with CC3200", - "port": "cc3200", - "board": "LAUNCHXL", - "board_name": "LaunchPad", - "mcu_name": "CC3200", - "path": "ports/cc3200/boards/LAUNCHXL/mpconfigboard.h", - "version": "v1.10" - }, { "description": "M5Stack ATOM with ESP32-PICO-D4", "port": "esp32", @@ -665,15 +746,6 @@ "path": "ports/nrf/boards/nrf52840-mdk-usb-dongle/mpconfigboard.h", "version": "v1.13" }, - { - "description": "MIKROE_CLICKER2_STM32 with STM32F407", - "port": "stm32", - "board": "MIKROE_CLICKER2_STM32", - "board_name": "MIKROE_CLICKER2_STM32", - "mcu_name": "STM32F407", - "path": "ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.h", - "version": "v1.12" - }, { "description": "Metro M4 Express Airlift with SAMD51J19A", "port": "samd", @@ -683,6 +755,15 @@ "path": "ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.h", "version": "v1.21.0" }, + { + "description": "micro:bit with NRF51822", + "port": "nrf", + "board": "microbit", + "board_name": "micro:bit", + "mcu_name": "NRF51822", + "path": "ports/nrf/boards/microbit/mpconfigboard.h", + "version": "v1.10" + }, { "description": "MikroE Quail with STM32F427VI", "port": "stm32", @@ -692,6 +773,15 @@ "path": "ports/stm32/boards/MIKROE_QUAIL/mpconfigboard.h", "version": "v1.18" }, + { + "description": "MIKROE_CLICKER2_STM32 with STM32F407", + "port": "stm32", + "board": "MIKROE_CLICKER2_STM32", + "board_name": "MIKROE_CLICKER2_STM32", + "mcu_name": "STM32F407", + "path": "ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.h", + "version": "v1.12" + }, { "description": "Mini SAM M4 with SAMD51G19A", "port": "samd", @@ -710,6 +800,24 @@ "path": "ports/stm32/boards/NADHAT_PYBF405/mpconfigboard.h", "version": "v1.12" }, + { + "description": "NanoS3 with ESP32-S3-FN8", + "port": "esp32", + "board": "UM_NANOS3", + "board_name": "NanoS3", + "mcu_name": "ESP32-S3-FN8", + "path": "ports/esp32/boards/UM_NANOS3/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "description": "NetduinoPlus2 with STM32F405RG", + "port": "stm32", + "board": "NETDUINO_PLUS_2", + "board_name": "NetduinoPlus2", + "mcu_name": "STM32F405RG", + "path": "ports/stm32/boards/NETDUINO_PLUS_2/mpconfigboard.h", + "version": "v1.10" + }, { "description": "NICLAVISION with STM32H747", "port": "stm32", @@ -945,22 +1053,13 @@ "version": "v1.10" }, { - "description": "NanoS3 with ESP32-S3-FN8", + "description": "Olimex ESP32 ETH with ESP32", "port": "esp32", - "board": "UM_NANOS3", - "board_name": "NanoS3", - "mcu_name": "ESP32-S3-FN8", - "path": "ports/esp32/boards/UM_NANOS3/mpconfigboard.h", - "version": "v1.21.0" - }, - { - "description": "NetduinoPlus2 with STM32F405RG", - "port": "stm32", - "board": "NETDUINO_PLUS_2", - "board_name": "NetduinoPlus2", - "mcu_name": "STM32F405RG", - "path": "ports/stm32/boards/NETDUINO_PLUS_2/mpconfigboard.h", - "version": "v1.10" + "board": "OLIMEX_ESP32_POE", + "board_name": "Olimex ESP32 ETH", + "mcu_name": "ESP32", + "path": "ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h", + "version": "v1.20.0" }, { "description": "OLIMEX STM32-E407 with STM32F407", @@ -980,15 +1079,6 @@ "path": "ports/stm32/boards/OLIMEX_H407/mpconfigboard.h", "version": "v1.18" }, - { - "description": "Olimex ESP32 ETH with ESP32", - "port": "esp32", - "board": "OLIMEX_ESP32_POE", - "board_name": "Olimex ESP32 ETH", - "mcu_name": "ESP32", - "path": "ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h", - "version": "v1.20.0" - }, { "description": "PCA10000 with NRF51822", "port": "nrf", @@ -1079,6 +1169,15 @@ "path": "ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h", "version": "v1.19.1" }, + { + "description": "ProS3 with ESP32-S3", + "port": "esp32", + "board": "UM_PROS3", + "board_name": "ProS3", + "mcu_name": "ESP32-S3", + "path": "ports/esp32/boards/UM_PROS3/mpconfigboard.h", + "version": "v1.19.1" + }, { "description": "PYBD-SF2W with STM32F722IEK", "port": "stm32", @@ -1160,15 +1259,6 @@ "path": "ports/stm32/boards/PYBV4/mpconfigboard.h", "version": "v1.10" }, - { - "description": "ProS3 with ESP32-S3", - "port": "esp32", - "board": "UM_PROS3", - "board_name": "ProS3", - "mcu_name": "ESP32-S3", - "path": "ports/esp32/boards/UM_PROS3/mpconfigboard.h", - "version": "v1.19.1" - }, { "description": "RA4M1 CLICKER with RA4M1", "port": "renesas-ra", @@ -1241,24 +1331,6 @@ "path": "ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h", "version": "v1.12" }, - { - "description": "STM32H573I-DK with STM32H573IIK3Q", - "port": "stm32", - "board": "STM32H573I_DK", - "board_name": "STM32H573I-DK", - "mcu_name": "STM32H573IIK3Q", - "path": "ports/stm32/boards/STM32H573I_DK/mpconfigboard.h", - "version": "v1.21.0" - }, - { - "description": "STM32H7B3I-DK with STM32H7B3LIH6Q", - "port": "stm32", - "board": "STM32H7B3I_DK", - "board_name": "STM32H7B3I-DK", - "mcu_name": "STM32H7B3LIH6Q", - "path": "ports/stm32/boards/STM32H7B3I_DK/mpconfigboard.h", - "version": "v1.18" - }, { "description": "Seeed ARCH MIX with MIMXRT1052DVL5B", "port": "mimxrt", @@ -1286,6 +1358,15 @@ "path": "ports/esp32/boards/SIL_WESP32/mpconfigboard.h", "version": "v1.17" }, + { + "description": "Sparkfun SAMD51 Thing Plus with SAMD51J20A", + "port": "samd", + "board": "SPARKFUN_SAMD51_THING_PLUS", + "board_name": "Sparkfun SAMD51 Thing Plus", + "mcu_name": "SAMD51J20A", + "path": "ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h", + "version": "v1.20.0" + }, { "description": "SparkFun STM32 MicroMod Processor with STM32F405RG", "port": "stm32", @@ -1296,13 +1377,22 @@ "version": "v1.17" }, { - "description": "Sparkfun SAMD51 Thing Plus with SAMD51J20A", - "port": "samd", - "board": "SPARKFUN_SAMD51_THING_PLUS", - "board_name": "Sparkfun SAMD51 Thing Plus", - "mcu_name": "SAMD51J20A", - "path": "ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h", - "version": "v1.20.0" + "description": "STM32H573I-DK with STM32H573IIK3Q", + "port": "stm32", + "board": "STM32H573I_DK", + "board_name": "STM32H573I-DK", + "mcu_name": "STM32H573IIK3Q", + "path": "ports/stm32/boards/STM32H573I_DK/mpconfigboard.h", + "version": "v1.21.0" + }, + { + "description": "STM32H7B3I-DK with STM32H7B3LIH6Q", + "port": "stm32", + "board": "STM32H7B3I_DK", + "board_name": "STM32H7B3I-DK", + "mcu_name": "STM32H7B3LIH6Q", + "path": "ports/stm32/boards/STM32H7B3I_DK/mpconfigboard.h", + "version": "v1.18" }, { "description": "Teensy 4.0 with MIMXRT1062DVJ6A", @@ -1413,13 +1503,13 @@ "version": "v1.21.0" }, { - "description": "WT51822-S4AT with NRF51822", - "port": "nrf", - "board": "wt51822_s4at", - "board_name": "WT51822-S4AT", - "mcu_name": "NRF51822", - "path": "ports/nrf/boards/wt51822_s4at/mpconfigboard.h", - "version": "v1.10" + "description": "Wio Terminal D51R with SAMD51P19A", + "port": "samd", + "board": "SEEED_WIO_TERMINAL", + "board_name": "Wio Terminal D51R", + "mcu_name": "SAMD51P19A", + "path": "ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h", + "version": "v1.18" }, { "description": "WiPy with CC3200", @@ -1431,13 +1521,13 @@ "version": "v1.10" }, { - "description": "Wio Terminal D51R with SAMD51P19A", - "port": "samd", - "board": "SEEED_WIO_TERMINAL", - "board_name": "Wio Terminal D51R", - "mcu_name": "SAMD51P19A", - "path": "ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h", - "version": "v1.18" + "description": "WT51822-S4AT with NRF51822", + "port": "nrf", + "board": "wt51822_s4at", + "board_name": "WT51822-S4AT", + "mcu_name": "NRF51822", + "path": "ports/nrf/boards/wt51822_s4at/mpconfigboard.h", + "version": "v1.10" }, { "description": "XENON with NRF52840", @@ -1456,95 +1546,5 @@ "mcu_name": "NRF52840", "path": "ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.h", "version": "v1.20.0" - }, - { - "description": "i.MX RT1010 EVK with MIMXRT1011DAE5A", - "port": "mimxrt", - "board": "MIMXRT1010_EVK", - "board_name": "i.MX RT1010 EVK", - "mcu_name": "MIMXRT1011DAE5A", - "path": "ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h", - "version": "v1.13" - }, - { - "description": "i.MX RT1015 EVK with MIMXRT1015DAF5A", - "port": "mimxrt", - "board": "MIMXRT1015_EVK", - "board_name": "i.MX RT1015 EVK", - "mcu_name": "MIMXRT1015DAF5A", - "path": "ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h", - "version": "v1.19.1" - }, - { - "description": "i.MX RT1020 EVK with MIMXRT1021DAG5A", - "port": "mimxrt", - "board": "MIMXRT1020_EVK", - "board_name": "i.MX RT1020 EVK", - "mcu_name": "MIMXRT1021DAG5A", - "path": "ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h", - "version": "v1.13" - }, - { - "description": "i.MX RT1050 EVK with MIMXRT1052DVL6B", - "port": "mimxrt", - "board": "MIMXRT1050_EVK", - "board_name": "i.MX RT1050 EVK", - "mcu_name": "MIMXRT1052DVL6B", - "path": "ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h", - "version": "v1.15" - }, - { - "description": "i.MX RT1050 EVKB with MIMXRT1052DVL6B", - "port": "mimxrt", - "board": "MIMXRT1050_EVKB", - "board_name": "i.MX RT1050 EVKB", - "mcu_name": "MIMXRT1052DVL6B", - "path": "ports/mimxrt/boards/MIMXRT1050_EVKB/mpconfigboard.h", - "version": "v1.17" - }, - { - "description": "i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B", - "port": "mimxrt", - "board": "MIMXRT1050_EVK", - "board_name": "i.MX RT1050 EVKB-A1", - "mcu_name": "MIMXRT1052DVL6B", - "path": "ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h", - "version": "v1.18" - }, - { - "description": "i.MX RT1060 EVK with MIMXRT1062DVJ6A", - "port": "mimxrt", - "board": "MIMXRT1060_EVK", - "board_name": "i.MX RT1060 EVK", - "mcu_name": "MIMXRT1062DVJ6A", - "path": "ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h", - "version": "v1.13" - }, - { - "description": "i.MX RT1064 EVK with MIMXRT1064DVL6A", - "port": "mimxrt", - "board": "MIMXRT1064_EVK", - "board_name": "i.MX RT1064 EVK", - "mcu_name": "MIMXRT1064DVL6A", - "path": "ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h", - "version": "v1.14" - }, - { - "description": "i.MX RT1170 EVK with MIMXRT1176DVMAA", - "port": "mimxrt", - "board": "MIMXRT1170_EVK", - "board_name": "i.MX RT1170 EVK", - "mcu_name": "MIMXRT1176DVMAA", - "path": "ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h", - "version": "v1.20.0" - }, - { - "description": "micro:bit with NRF51822", - "port": "nrf", - "board": "microbit", - "board_name": "micro:bit", - "mcu_name": "NRF51822", - "path": "ports/nrf/boards/microbit/mpconfigboard.h", - "version": "v1.10" } ] \ No newline at end of file From 219d72c460c6ef0343c8e32b23bb7d86c99703b7 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 2 Jan 2024 00:18:09 +0100 Subject: [PATCH 08/68] Fix board_stubber script and update dependencies Signed-off-by: Jos Verlinde --- scripts/board_stubber.py | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/scripts/board_stubber.py b/scripts/board_stubber.py index cb3f95433..960d0ea50 100644 --- a/scripts/board_stubber.py +++ b/scripts/board_stubber.py @@ -1,11 +1,5 @@ """ This script creates stubs for a connected micropython MCU board. - -# MPRemote is not working properly with ESP32 boards :-( at least on Windows) -# this was fixed in the latest version of mpremote, not published yet on pypi - -Workaround -pip install git+https://github.com/josverl/mpremote.git#subdirectory=tools/mpremote """ import json @@ -33,9 +27,11 @@ ERROR = -1 RETRIES = 3 TESTING = False -LOCAL_FILES = True +LOCAL_FILES = False ############################################################################################### +reset_before = False +############################################################################################### @dataclass @@ -327,7 +323,8 @@ def copy_createstubs(board: MPRemoteBoard, variant: Variant, form: Form) -> bool @retry(stop=stop_after_attempt(4), wait=wait_fixed(2)) def hard_reset(board: MPRemoteBoard) -> bool: """Reset the board""" - rc, _ = board.run_command(["soft-reset", "exec", "import machine;machine.reset()"], timeout=5) + # do not run "exec", "import machine;machine.reset()" as it will hang an esp32 + rc, _ = board.run_command(["reset"], timeout=5) board.connected = False return rc == OK @@ -346,10 +343,10 @@ def run_createstubs(dest: Path, board: MPRemoteBoard, variant: Variant = Variant ] board.run_command(cmd_path, timeout=5) - log.info(f"Resetting {board.port} {board.uname[4] if board.uname else ''}") - board.run_command("reset", timeout=5) - - time.sleep(2) + if reset_before: + log.info(f"Resetting {board.port} {board.uname[4] if board.uname else ''}") + board.run_command("reset", timeout=5) + time.sleep(2) log.info( f"Running createstubs {variant} on {board.port} {board.uname[4] if board.uname else ''}" @@ -408,8 +405,15 @@ def generate_board_stubs( if LOCAL_FILES: ok = copy_createstubs(mcu, variant, form) else: - # TODO: Add Branch to install from - ok = mcu.mip_install("github:josverl/micropython-stubber") + if form == Form.min: + location = "github:josverl/micropython-stubber/mip/minified.json" + elif form == Form.mpy: + location = "github:josverl/micropython-stubber/mip/mpy_v6.json" + else: + location = "github:josverl/micropython-stubber/mip/full.json" + + ok = mcu.mip_install(location) + if not ok and not TESTING: log.warning("Error copying createstubs to board") return ERROR, None @@ -530,8 +534,8 @@ def copy_to_repo(source: Path, fw: dict) -> Optional[Path]: if __name__ == "__main__": set_loglevel(0) - variant = Variant.db - form = Form.mpy + variant = Variant.mem + form = Form.min tempdir = mkdtemp(prefix="board_stubber") dest = Path(tempdir) From 96c7fb7dfa09c3073e48f04e952928f7c66eeee2 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 2 Jan 2024 00:18:19 +0100 Subject: [PATCH 09/68] Update board name in createstubs.py Signed-off-by: Jos Verlinde --- src/stubber/board/createstubs.py | 49 +++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index ec867a17d..af07c6418 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -455,7 +455,7 @@ def _info(): # type:() -> dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -473,13 +473,13 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = ( + _machine = ( sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore ) - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -490,19 +490,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -581,6 +569,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: From 5a498b1916ad818a3e99b49c06b7bf9f94b2ebdb Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 2 Jan 2024 00:18:28 +0100 Subject: [PATCH 10/68] Update switch_tag function signature Signed-off-by: Jos Verlinde --- src/stubber/basicgit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stubber/basicgit.py b/src/stubber/basicgit.py index f8802caaf..3d327dc35 100644 --- a/src/stubber/basicgit.py +++ b/src/stubber/basicgit.py @@ -196,7 +196,7 @@ def checkout_commit(commit_hash: str, repo: Optional[Union[Path, str]] = None) - return True -def switch_tag(tag: str, repo: Optional[Union[Path, str]] = None) -> bool: +def switch_tag(tag: Union[str, Path], repo: Optional[Union[Path, str]] = None) -> bool: """ switch to the specified version tag of a local repo repo should be in the form of : path/.git From c895a494128ac418da27bad5a578dfef497c11b3 Mon Sep 17 00:00:00 2001 From: Josverl Date: Mon, 1 Jan 2024 23:19:47 +0000 Subject: [PATCH 11/68] Update mip packages --- mip/v5/createstubs.py | 49 ++- mip/v5/createstubs_db.py | 49 ++- mip/v5/createstubs_db_min.py | 363 +++++++++++---------- mip/v5/createstubs_db_mpy.mpy | Bin 8585 -> 8748 bytes mip/v5/createstubs_lvgl.py | 49 ++- mip/v5/createstubs_lvgl_min.py | 283 ++++++++-------- mip/v5/createstubs_lvgl_mpy.mpy | Bin 8040 -> 8198 bytes mip/v5/createstubs_mem.py | 49 ++- mip/v5/createstubs_mem_min.py | 307 ++++++++--------- mip/v5/createstubs_mem_mpy.mpy | Bin 8078 -> 8236 bytes mip/v5/createstubs_min.py | 291 +++++++++-------- mip/v5/createstubs_mpy.mpy | Bin 10641 -> 10809 bytes mip/v6/createstubs.py | 49 ++- mip/v6/createstubs_db.py | 49 ++- mip/v6/createstubs_db_min.py | 363 +++++++++++---------- mip/v6/createstubs_db_mpy.mpy | Bin 8384 -> 8556 bytes mip/v6/createstubs_lvgl.py | 49 ++- mip/v6/createstubs_lvgl_min.py | 283 ++++++++-------- mip/v6/createstubs_lvgl_mpy.mpy | Bin 7866 -> 8033 bytes mip/v6/createstubs_mem.py | 49 ++- mip/v6/createstubs_mem_min.py | 307 ++++++++--------- mip/v6/createstubs_mem_mpy.mpy | Bin 7897 -> 8067 bytes mip/v6/createstubs_min.py | 291 +++++++++-------- mip/v6/createstubs_mpy.mpy | Bin 10909 -> 11085 bytes src/stubber/board/createstubs_db.py | 49 ++- src/stubber/board/createstubs_db_min.py | 363 +++++++++++---------- src/stubber/board/createstubs_db_mpy.mpy | Bin 8362 -> 8534 bytes src/stubber/board/createstubs_lvgl.py | 49 ++- src/stubber/board/createstubs_lvgl_min.py | 283 ++++++++-------- src/stubber/board/createstubs_lvgl_mpy.mpy | Bin 7843 -> 8010 bytes src/stubber/board/createstubs_mem.py | 49 ++- src/stubber/board/createstubs_mem_min.py | 307 ++++++++--------- src/stubber/board/createstubs_mem_mpy.mpy | Bin 7875 -> 8045 bytes src/stubber/board/createstubs_min.py | 291 +++++++++-------- src/stubber/board/createstubs_mpy.mpy | Bin 10888 -> 11064 bytes 35 files changed, 2260 insertions(+), 2011 deletions(-) diff --git a/mip/v5/createstubs.py b/mip/v5/createstubs.py index ec867a17d..af07c6418 100644 --- a/mip/v5/createstubs.py +++ b/mip/v5/createstubs.py @@ -455,7 +455,7 @@ def _info(): # type:() -> dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -473,13 +473,13 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = ( + _machine = ( sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore ) - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -490,19 +490,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -581,6 +569,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/mip/v5/createstubs_db.py b/mip/v5/createstubs_db.py index c6c5ecb27..ecb9ffe19 100644 --- a/mip/v5/createstubs_db.py +++ b/mip/v5/createstubs_db.py @@ -448,7 +448,7 @@ def _info(): # type:() -> dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -466,9 +466,9 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -479,19 +479,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -569,6 +557,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/mip/v5/createstubs_db_min.py b/mip/v5/createstubs_db_min.py index 34ba0bee4..8f5a7e7f8 100644 --- a/mip/v5/createstubs_db_min.py +++ b/mip/v5/createstubs_db_min.py @@ -1,178 +1,180 @@ -v='stubber' -u='{}/{}' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n=NameError -m=sorted -l=MemoryError -k=NotImplementedError -b=',\n' -a='dict' -Z='list' -Y='tuple' -X='micropython' -W=str -V=repr -T='_' -S=KeyError -R=IndexError -Q=dir -P=ImportError +x='stubber' +w='{}/{}' +v='method' +u='function' +t='bool' +s='str' +r='float' +q='int' +p=NameError +o=sorted +n=MemoryError +m=NotImplementedError +d=',\n' +c='dict' +b='list' +a='tuple' +Z='micropython' +Y=str +X=repr +V='cpu' +U='_' +T=KeyError +S=IndexError +R=dir +Q=ImportError +P='with' O='family' N=print -M=True -L=len +M=len +L='.' K='board' -J='.' +J=True I=open H=AttributeError G='/' -F=False -E=None -D='version' +F=None +E='version' +D=False A=OSError C='' import gc as B,os,sys -from ujson import dumps as c +from ujson import dumps as e try:from machine import reset -except P:pass -try:from collections import OrderedDict as d -except P:from ucollections import OrderedDict as d +except Q:pass +try:from collections import OrderedDict as f +except Q:from ucollections import OrderedDict as f __version__='v1.16.2' -w=2 -x=2 -e=[J,'/lib','/sd/lib','/flash/lib','lib'] +y=2 +z=2 +g=[L,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: - def __init__(C,path=E,firmware_id=E): + def __init__(C,path=F,firmware_id=F): D=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') except H:pass C._report=[];C.info=_info();B.collect() if D:C._fwid=D.lower() - elif C.info[O]==X:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) + elif C.info[O]==Z:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) else:C._fwid='{family}-{ver}-{port}'.format(**C.info) C._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) - try:f(path+G) + try:h(path+G) except A:N('error creating stub folder {}'.format(path)) C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in Q(I): - if A.startswith(T)and not A in L.modules:continue + for A in R(I): + if A.startswith(U)and not A in L.modules:continue try: E=getattr(I,A) - try:F=V(type(E)).split("'")[1] - except R:F=C - if F in{o,p,q,r,Y,Z,a}:G=1 - elif F in{s,t}:G=2 + try:F=X(type(E)).split("'")[1] + except S:F=C + if F in{q,r,s,t,a,b,c}:G=1 + elif F in{u,v}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,V(E),V(type(E)),E,G)) + D.append((A,X(E),X(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) - except l as K:sleep(1);reset() - D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) + except n as K:sleep(1);reset() + D=o([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J + def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) def create_one_stub(C,module_name): - D=module_name - if D in C.problematic:return F - if D in C.excluded:return F - H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=F - try:E=C.create_module_stub(D,H) - except A:return F - B.collect();return E - def create_module_stub(K,module_name,file_name=E): - H=file_name;D=module_name - if H is E:O=D.replace(J,T)+'.py';H=K.path+G+O + E=module_name + if E in C.problematic:return D + if E in C.excluded:return D + H='{}/{}.py'.format(C.path,E.replace(L,G));B.collect();F=D + try:F=C.create_module_stub(E,H) + except A:return D + B.collect();return F + def create_module_stub(K,module_name,file_name=F): + H=file_name;E=module_name + if H is F:O=E.replace(L,U)+'.py';H=K.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,J) - L=E - try:L=__import__(D,E,E,'*');U=B.mem_free() - except P:return F - f(H) - with I(H,'w')as N:Q=W(K.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,K._fwid,Q,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,L,D,C) - K._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: - try:del L - except(A,S):pass - try:del sys.modules[D] - except S:pass - B.collect();return M + if G in E:E=E.replace(G,L) + M=F + try:M=__import__(E,F,F,'*');S=B.mem_free() + except Q:return D + h(H) + with I(H,'w')as N:P=Y(K.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(E,K._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,M,E,C) + K._report.append('{{"module": "{}", "file": "{}"}}'.format(E,H.replace('\\',G))) + if E not in{'os','sys','logging','gc'}: + try:del M + except(A,T):pass + try:del sys.modules[E] + except T:pass + B.collect();return J def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() + d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() if P in K.problematic:return - R,M=K.get_obj_attributes(P) - if M:N(M) - for(F,J,G,T,f)in R: + R,L=K.get_obj_attributes(P) + if L:N(L) + for(F,J,G,S,f)in R: if F in['classmethod','staticmethod','BaseException',O]:continue if F[0].isdigit():continue - if G==""and L(E)<=x*4: + if G==""and M(E)<=z*4: U=C;V=F.endswith(O)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O D='\n{}class {}({}):\n'.format(E,F,U) if V:D+=E+' ...\n';H.write(D);return - H.write(D);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) - elif any(A in G for A in[t,s,'closure']): - W=b;X=C + H.write(D);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) + elif any(A in G for A in[v,u,'closure']): + W=Y;X=C if Q>0:X='self, ' - if c in G or c in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) + if Z in G or Z in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,X,W) D+=E+' ...\n\n';H.write(D) elif G=="":0 elif G.startswith("5:A[F]=C - if A[D]==C and sys.platform not in(k,j): - try:o=os.uname();A[D]=o.release - except(R,H,TypeError):pass - for(p,q,r)in[(l,l,'const'),(m,m,'FAT'),(n,'pybricks.hubs','EV3Brick')]: - try:s=__import__(q,E,E,r);A[O]=p;del s;break - except(P,S):pass - if A[O]==n:A['release']='2.0.0' - if A[O]==X: - if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] + A[D]=W(os.uname()[3]) + if not A[D]:A[D]=W(os.uname()[2]) + if not A[D]and';'in sys.version:A[D]=W(sys.version.split(';')[1]) + except(H,S):pass + if A[D]and M(A[D])>5:A[D]=C + if A[E]==C and sys.platform not in(c,b): + try:h=os.uname();A[E]=h.release + except(S,H,TypeError):pass + for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: + try:l=__import__(j,F,F,k);A[O]=i;del l;break + except(Q,T):pass + if A[O]==g:A['release']='2.0.0' + if A[O]==Z: + if A[E]and A[E].endswith('.0')and A[E]>='1.10.0'and A[E]<='1.19.9':A[E]=A[E][:-2] if I in A and A[I]: - V=int(A[I]);a=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if a:A[f]=a - A[I]='v{}.{}'.format(V&255,V>>8&3) - A[b]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def g(info,board_descr,filename): + J=int(A[I]);U=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][J>>10] + if U:A[a]=U + A[I]='v{}.{}'.format(J&255,J>>8&3) + A[X]=f"v{A[E]}-{A[D]}"if A[D]else f"v{A[E]}";return A +def A0(info,desc=C): + G='with ';C=info;E=D + for F in[A+'/board_info.csv'for A in g]: + if j(F): + A=desc or C[K].strip() + if i(C,A,F):E=J;break + if P in A: + A=A.split(P)[0].strip() + if i(C,A,F):E=J;break + if not E: + A=desc or C[K].strip() + if G+C[V].upper()in A:A=A.split(G+C[V].upper())[0].strip() + C[K]=A + C[K]=C[K].replace(' ',U);B.collect() +def i(info,board_descr,filename): with I(filename,'r')as B: while 1: A=B.readline() if not A:break - C,D=A.split(',')[0].strip(),A.split(',')[1].strip() - if C==board_descr:info[K]=D;return M - return F + C,E=A.split(',')[0].strip(),A.split(',')[1].strip() + if C==board_descr:info[K]=E;return J + return D def get_root(): try:B=os.getcwd() - except(A,H):B=J + except(A,H):B=L C=B - for C in[B,'/sd','/flash',G,J]: + for C in[B,'/sd','/flash',G,L]: try:D=os.stat(C);break except A:continue return C -def h(filename): +def j(filename): try: - if os.stat(filename)[0]>>14:return M - return F - except A:return F -def i():sys.exit(1) + if os.stat(filename)[0]>>14:return J + return D + except A:return D +def k():sys.exit(1) def read_path(): path=C - if L(sys.argv)==3: + if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:i() - elif L(sys.argv)==2:i() + else:k() + elif M(sys.argv)==2:k() return path -def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return F - except(k,H):return M +def l(): + try:A=bytes('abc',encoding='utf8');B=l.__module__;return D + except(m,H):return J def main(): - K='failed';G='modulelist.done';import machine as O - try:C=I(G,'r+b');N=M - except A:C=I(G,'w+b');N=F + L='failed';G='modulelist.done';import machine as O + try:C=I(G,'r+b');N=J + except A:C=I(G,'w+b');N=D stubber=Stubber(path=read_path()) if not N:stubber.clean() - y(stubber);D={} + A1(stubber);E={} try: with I(G)as C: - for E in C.read().split('\n'): - E=E.strip();B.collect() - if L(E)>0:P,Q=E.split('=',1);D[P]=Q + for F in C.read().split('\n'): + F=F.strip();B.collect() + if M(F)>0:P,Q=F.split('=',1);E[P]=Q except(A,SyntaxError):pass - B.collect();R=[A for A in stubber.modules if A not in D.keys()];B.collect() + B.collect();R=[A for A in stubber.modules if A not in E.keys()];B.collect() for H in R: - J=F - try:J=stubber.create_one_stub(H) - except l:O.reset() - B.collect();D[H]=W(stubber._report[-1]if J else K) - with I(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if J else K)) - if D:stubber._report=[A for(B,A)in D.items()if A!=K];stubber.report() -def y(stubber): + K=D + try:K=stubber.create_one_stub(H) + except n:O.reset() + B.collect();E[H]=Y(stubber._report[-1]if K else L) + with I(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if K else L)) + if E:stubber._report=[A for(B,A)in E.items()if A!=L];stubber.report() +def A1(stubber): E='/modulelist.txt';stubber.modules=[] - for D in e: + for D in g: try: with I(D+E)as F: N('DEBUG: list of modules: '+D+E) for C in F.read().split('\n'): C=C.strip() - if L(C)>0 and C[0]!='#':stubber.modules.append(C) + if M(C)>0 and C[0]!='#':stubber.modules.append(C) B.collect();break except A:pass - if not stubber.modules:stubber.modules=[X];_log.warn('Could not find modulelist.txt, using default modules') + if not stubber.modules:stubber.modules=[Z];_log.warn('Could not find modulelist.txt, using default modules') B.collect() -if __name__=='__main__'or j(): - try:z=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except n:pass - if not h('no_auto_stubber.txt'): +if __name__=='__main__'or l(): + try:A2=logging.getLogger(x);logging.basicConfig(level=logging.INFO) + except p:pass + if not j('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_db_mpy.mpy b/mip/v5/createstubs_db_mpy.mpy index 753f589d002fa96e0b3628e4da1d43e4073f46b5..c57a213d3cb43455e77fbeb3717fb5bb3a0073a0 100644 GIT binary patch delta 2452 zcmYjSZBUch6~6Z*As+;|?@jU|@)1n3$VUiCjBy!s)$oc4h=3%BTTPP?Of(Qo0?4v9 zFK(UMwLfI;xNWD~Zl|_0o!U-uBdFP>Raag6>5oo#N;|B(fBLJ_9kXNYe8Y}@=<5oU>gBASUM$3&PRWPExul8GlLMVKb&6%jH7eOrVy(TyjP zp^OMAf{u%DT0pHLObO_c2uT6iMVJ&&n+Ov`Y1fG`Mo_N^5rPsTgbDh-2qA*fA{-S8 z!A1piE-S(jQWBY(79l{8Mg+frnnV~DP@@Qk1=J_PkboLQ7$ln6cqS&o0MUEqmQapv;ArX26G$X`ZMM${yB0B9Z z?t(jDb}bsWG_n_CX>O?bS4>0XQsp9Xv&c}lll5ijkm2P!h>a^ z1vu@Pn){ZAT~SzYSMGsA#CSVfSB~NdwnKFcA7z(S7jP_BS8^NUF7{YmONQR{;9&1l zbbr~17zIDmYwGb4)~c!6e)zGZkw>ZN!yb%|-Jo!qLW)9~LWV+!LYP9NRlP2$R}IhQV-8B1(j*NV5Y z%epWQv;XL7%DX<6%<^?3TA-!^9ZTt$ZE%B#IZ_}(A(r#tQ3?lg1ZF+3e*itCFv@;b zy2?+9>38BD_7nY|ahlDSeWX6P>cJFVV@JwwD`z-ER#UO0<0)+9l3^cJSk#eXE+O`` z;-|`C3RAhOFli>D@LL#gQ9Yew{A0`ojX!J-glvauSEvA2yis(ri&XV|K7KmG+% znOg8KnafnAf|ypm#`;ZtwCu4oAm2YAp=ATwCHpDNv8yI4-oYN3{H76uylQK7A)={I zPS)R9>Qu^f7i$;oj(0ZwgN$tmx>UYvHk+M0TrP97jaz1Oi>ux0e%b7FwRg08%oeki zeNS{+HK9}_cAu2+CVD_hCZ^^-B$}yYD)W%{-gG=M_8Yp5l~h`?RtlW7;#QdAl`t(e zkf}r{GoDOM+zgX)e}8ZPp^<(HyE{Y1B~x=@FP5}2(WNsJ z+uZq^0iQ+Ye_mfJfaSCC$+6^Yx&R9WnCKGm$>}p|l3LDju+xX+?pj2l&xm4fpe94D z;d$eGuovfPb)csVjZo-*EGgw;Wx9XF%MqLiMPl*ED1{;RNo7;^cN7MAi1&tgNP=`uZ64HWH5Q~I(VBfmQs~L#WNymFJ9PiDxS|dzi>PcChalE z6b^FBgU|m(Dv@bb;S}2Hr;0Ucr%Wph9l7hxu>L2hRqi$+T4}8GqTj!7C{INb(NH>? zXIH9rW;>8m@rOS?>aIi77!1ZI3W5m+f5p3t;$M4|4P-S>;ZUHF?5UC$icDaT!te`R ze0Q^Xs`4+b@u!OD+zzM1nJ1N;iHeK;=$f=!&eJNtw1fX(UW!9R>2PxSY~^c(e>c&) z94@})Z&Gy;D6ZQb?SGXjitE9z@v8EjfgAaC=~X#@!!P+|ijH%`gBt{PW%H5a!kbV0 z4b(>YJ7}Z%1c0i=grf3n~R%;YmX}v!X-VsSL@;f^o!a$T)|9r7Zimd z{Z8F`e9XOSuEnEl&iodxW~9CuTUbYZW0kF`(Q3DE+iJG$+}eSx_zo}MrY*b#?DhI{ KeDFQ3fAfFZ2cYx- delta 2313 zcmY*aTX0jy8Q%RRSr;3#XLY>7wPi{6v9OISEFnZZ1`^B1U~De7LBdW7iX_WeAWKG) zZCsb=m^2+=+8LNlLLQo#G}DK4+DxJ57K0jSOG28Yold5mIvt0{_MubCQywx+x)NA2?hm1CTBB=LMoeKkSAy-gB(GZ7@Q=Q$#gbWU@$|_Q3hEFbu!3E=mLXj z33(W#CA68r38ME{7{m!0Vh|%J&EQ#rUS}{)P@chvQ|Sc;2PCw}VE-tCeG)psU@x)6v$34uJ4C?CU{FGH4E9LK z$zXt>Dh9iU8SENi&`)aTlDT|Ejw+!p2E7Df27MYohrKw#Z({`7E^Wn)K@!g#CJEiKa4>S-*k7F@F^!$C8C;E}Jd*jSQyzLP*MQW;BNsmprdLoC|rMsyL4?h!v}Q-JT-Z1CL4{-7P8TNVKyF5 z=DdYdh3{=Q1vfP!o58P0oW7JlI8_jJv;fBEk^hVd5um3|zb;NylPc#PjLoW+yN z&s5#PSmoGcCnLWM;ONj-=-xFMaSDgH*W|ol&Z25sqn$fXH`JcR;(-IT;>t}}b^H19Hh7mxC{%|7w}z}$cj@-NI= zahUroLBVCp;=sH3SxYCtAir*j|Gc3{qbNR_rjLAV?GXYon`A$0B~ z`MkBsl1L|G8MAh&vuBHY)3~DF8S*#GWrRDMX^PBMIpi8kQ;EE-s_lPN$OH92-suDA^?~^LgZug04K2@0dfK*M-Ec}j`X0o}$hoWU?Q|XD1 zD2PV0H5c0{2uZrzaf)xoX|aupOsT(v}O$}Cqpg@e} zNL9Y92)0xE6MDsFs#T+~S1bbfrN5|E8g-SO(9L10TUB>zbiK7_`D%w9);>`;YXde! zZL%$h+>#<$Yja7_zWHQ{AFSVA>_uHVH+5Ux@_-9bIT}q(m+LSZRji_?DOTiw-d(5A z5`_biwz_BPwWSIp7^ZOW2~MHgA|i(HE z2v#gQD;6c%5Eft%LhCfqod3miVNvThBc%iY*ERIGev3At%h914bXN@BD*?P&4m~QC z=b|CqTWc_AAMocJJq9?Y)BeUUH16L3LlH6L5+XJu-xjlbmoPPz4@ds6QNa(nZ1>~Ilp8N>Qn2rFZdtrEkygb(&g=L?-sSxcSq!!>zj`1k4qN}e6q zny`uAXgUkx)C@UpiG$}$haDg0jm}rG%$J=VxPgD>Y^%4ox3zf0fO06?H};?wd{=1L R;1Vsu9j-ItD0 dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -451,9 +451,9 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -464,19 +464,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -554,6 +542,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/mip/v5/createstubs_lvgl_min.py b/mip/v5/createstubs_lvgl_min.py index 69b505b09..9ccf49b17 100644 --- a/mip/v5/createstubs_lvgl_min.py +++ b/mip/v5/createstubs_lvgl_min.py @@ -1,33 +1,35 @@ -t='stubber' -s='{}/{}' -r='method' -q='function' -p='bool' -o='str' -n='float' -m='int' -l='micropython' -k=Exception -j=NameError -i=sorted -h=NotImplementedError -Z=',\n' -Y='dict' -X='list' -W='tuple' -V=open -U=repr -S='_' -R=len -Q=KeyError -P=IndexError -O=dir -M=print +v='stubber' +u='{}/{}' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n='micropython' +m=Exception +l=NameError +k=sorted +j=NotImplementedError +b=',\n' +a='dict' +Z='list' +Y='tuple' +X=open +W=repr +U='cpu' +T='_' +S=len +R=KeyError +Q=IndexError +P=dir +O=print N=ImportError -K=True +M='with' L='family' -J='board' -I='.' +K=True +J='.' +I='board' H=AttributeError A=False G='/' @@ -36,51 +38,51 @@ F=OSError B='' import gc as C,os,sys -from ujson import dumps as a +from ujson import dumps as c try:from machine import reset except N:pass -try:from collections import OrderedDict as b -except N:from ucollections import OrderedDict as b +try:from collections import OrderedDict as d +except N:from ucollections import OrderedDict as d __version__='v1.16.2' -u=2 -v=2 -w=[I,'/lib','/sd/lib','/flash/lib','lib'] +w=2 +x=2 +y=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise h('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') except H:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[L]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==n:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:c(path+G) - except F:M('error creating stub folder {}'.format(path)) + try:e(path+G) + except F:O('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in O(I): - if A.startswith(S)and not A in L.modules:continue + for A in P(I): + if A.startswith(T)and not A in L.modules:continue try: E=getattr(I,A) - try:F=U(type(E)).split("'")[1] - except P:F=B - if F in{m,n,o,p,W,X,Y}:G=1 - elif F in{q,r}:G=2 + try:F=W(type(E)).split("'")[1] + except Q:F=B + if F in{o,p,q,r,Y,Z,a}:G=1 + elif F in{s,t}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,U(E),U(type(E)),E,G)) + D.append((A,W(E),W(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) except MemoryError as K:sleep(1);reset() - D=i([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J - def add_modules(A,modules):A.modules=i(set(A.modules)|set(modules)) + D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) def create_all_stubs(A): C.collect() for B in A.modules:A.create_one_stub(B) @@ -88,90 +90,90 @@ def create_one_stub(B,module_name): D=module_name if D in B.problematic:return A if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(I,G));C.collect();E=A + H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A try:E=B.create_module_stub(D,H) except F:return A C.collect();return E - def create_module_stub(J,module_name,file_name=E): + def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:O=D.replace(I,S)+'.py';H=J.path+G+O + if H is E:O=D.replace(J,T)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,I) + if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');T=C.mem_free() + try:L=__import__(D,E,E,'*');S=C.mem_free() except N:return A - c(H) - with V(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) - J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) + e(H) + with X(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del L - except(F,Q):pass + except(F,R):pass try:del sys.modules[D] - except Q:pass + except R:pass C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;N='Exception';H=fp;D=indent;C.collect() - if O in K.problematic:return - S,L=K.get_obj_attributes(O) - if L:M(L) - for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',N]:continue + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;D=indent;C.collect() + if N in K.problematic:return + Q,L=K.get_obj_attributes(N) + if L:O(L) + for(E,J,G,T,f)in Q: + if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and R(D)<=v*4: - U=B;V=E.endswith(N)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=N + if G==""and S(D)<=x*4: + U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): - Z=b;a=B - if P>0:a='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,Z) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,Z) + elif any(A in G for A in[t,s,'closure']): + W=b;X=B + if P>0:X='self, ' + if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(h,g): - try:m=os.uname();A[D]=m.release - except(P,H,TypeError):pass - for(n,o,p)in[(i,i,'const'),(j,j,'FAT'),(k,'pybricks.hubs','EV3Brick')]: - try:q=__import__(o,E,E,p);A[L]=n;del q;break - except(N,Q):pass - if A[L]==k:A['release']='2.0.0' - if A[L]==l: + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=V(sys.version.split(';')[1]) + except(H,Q):pass + if A[F]and S(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(a,Z): + try:f=os.uname();A[D]=f.release + except(Q,H,TypeError):pass + for(g,h,i)in[(b,b,'const'),(c,c,'FAT'),(e,'pybricks.hubs','EV3Brick')]: + try:j=__import__(h,E,E,i);A[L]=g;del j;break + except(N,R):pass + if A[L]==e:A['release']='2.0.0' + if A[L]==n: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - V=int(A[K]);Y=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if Y:A[c]=Y - A[K]='v{}.{}'.format(V&255,V>>8&3) - A[Z]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def d(info,board_descr,filename): - with V(filename,'r')as C: + O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] + if W:A[Y]=W + A[K]='v{}.{}'.format(O&255,O>>8&3) + A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def z(info,desc=B): + G='with ';D=info;E=A + for F in[A+'/board_info.csv'for A in y]: + if g(F): + B=desc or D[I].strip() + if f(D,B,F):E=K;break + if M in B: + B=B.split(M)[0].strip() + if f(D,B,F):E=K;break + if not E: + B=desc or D[I].strip() + if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() + D[I]=B + D[I]=D[I].replace(' ',T);C.collect() +def f(info,board_descr,filename): + with X(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return K + if D==board_descr:info[I]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=I + except(F,H):A=J B=A - for B in[A,'/sd','/flash',G,I]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def e(filename): +def g(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def f():sys.exit(1) +def h():sys.exit(1) def read_path(): path=B - if R(sys.argv)==3: + if S(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:f() - elif R(sys.argv)==2:f() + else:h() + elif S(sys.argv)==2:h() return path -def g(): - try:B=bytes('abc',encoding='utf8');C=g.__module__;return A - except(h,H):return K +def i(): + try:B=bytes('abc',encoding='utf8');C=i.__module__;return A + except(j,H):return K def main(): D='lvgl' try:import lvgl as A - except k:return + except m:return B=D try:B='lvgl-{0}_{1}_{2}-{3}-{4}'.format(A.version_major(),A.version_minor(),A.version_patch(),A.version_info(),sys.platform) - except k:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) + except m:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) finally:stubber=Stubber(firmware_id=B) stubber.clean();stubber.modules=['io','lodepng','rtch',D];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or g(): - try:x=logging.getLogger(t);logging.basicConfig(level=logging.INFO) - except j:pass - if not e('no_auto_stubber.txt'): +if __name__=='__main__'or i(): + try:A0=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + except l:pass + if not g('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_lvgl_mpy.mpy b/mip/v5/createstubs_lvgl_mpy.mpy index e44d38a86ce42efb52a0cf26ccd59a4dc8009e40..e59be1e35eda71ffb194cd820f2aeee89d7802a9 100644 GIT binary patch delta 2259 zcmYjSTTq+F72Z9P&;?nnR?<3H2H7CXfI$|r@;e%w0OI$AfNcy$0^AslB!p3{3zh^n zrbItUsMDm)U~lbYI&s^{^daNvWN@&-R-H6<rawJ)0%bPKw8#}3gf=)I0sXOm-x6A@D`KNXF}vkaz*VRml!>>PtBVob&J6PYmv zc|yjg(y@FZlV*@3=m`c{f?j2Ck{HI5nMj_&BtfIB02zXE4AN%gWRNnW76wT(T4Zp- zjCM14hNznj459?}GKdhAWN?(AOAJQLXqv&W89m2fh*ZQTrx*kY(lHn`qZ15{m{B8x z0W)e~&~HWu7#udESq6P(3eDk?a_6 z!=pIHzmK=$NBK?Mg2(t@aHsZ^h z51;`j`4&}QvoU8$XTp)Gd?viH?e6^P{0sYZQp?tu@R5&~;GBDM<~w_qFR1(&`}im7 z5&R5q)EvWUepd4$j&o9B!+p!Hipv=9=fBm~ki&2LaJcus=*~4O;uHq?f3(~15O?UR zrT+V}P8p#P_^=0~W2+Q06ecO0q>!Z`@S_wWE!s6%qs-q8Y*z#!Mc09;G)<23v91Id3;eNwG+{4crVmQM8YG@Rrw#u9?zU;%o?=WAi{0I;5 zqsC7B6o1|L8=U2-P3Ljnc~h76$U8nv;WY0ty{FELh}=}QWDqH>=a%JntLn6oa&9C1 zLDie;0Sd|GOXLE^1-^$i;qUQL>a-6^a4YbS!j%|8=-Ug{mn^l0STY_->y_8|B|3zs z_?I+--{3=*20Y9a%SGJBH(U4BUPeOGiEQdrBpbhd#fpARU{pH4bZaEwd&)(KnN0U=n4#%!mf4%oHho{xw=Jz@39QFJa=5gvG+1SJ# zQZXIRen2WxlQSO@-DD=4zbkY+l}L_#L}85oi`5nCDacW(x)G&#B}ywTWHK4ak7u%} z>rr9~9_l^RH*|=?Q&Fm?5ER5!LA)0A;a?Q52ZcsR#pFy>!m?f=hFm_i$6LG}3e+iL z@anx1XgZZhk7Z8fO0c;E6GJkQo;rO`)+);a>Iy9QC{v7!ktP@AR3ViHN`M49km z2^Xn7)UycE_15FDV=pE`Dl7=ct(1UvNWE z!dCQ}go<=WsEn&5To6fbKtvZ7`$BCZrp<@fWTQe=7L`RCa0u~gsn()>2;Cb{DYUV; z8tS1U89RmkCiprb3S9-ODV9kl=)#$7X;&y55ta`x z{7$Y=Xmu$HZ3$A-UW-?W&raUt|vyvQ$B?<=$+ zkLp*y{-nDWQENDyNRZcmYH7MW;*6w>$PcBM$GgYsVS!Qv$Ph}!KD>e(s!s$e@Ywz^xzlt0M! zGEnaO-TvRpRpoyFv*J+2%+P9aP5y>bTn)-Wg`!bm_^`{&FK!tgHNW&A=%P+4>X4Hb zuZ4(ldUnn|J7-0MPIKLS;d7_?#Rt!SE`d19^3Ew`MoXC?)D{$=1c6P8xH}t|N(iaA z5-P?3^8@y_!X2~=ErolH=oUqzV5Uq!zR delta 2054 zcmY*adrVu`89(Rq+q}*_HpivJ80f`>3=DQ0r!FZi=4JsB!qX;n1A-+U!cc z{_gL7=lg!&^FI6dM?IDy1GpMrm~DS)!_p42dm~tnTQ?>f*Gj~?vf8<_%AiOpGs)6? zZk9oTkhz6yqLj*I89YT$4}&~G-(ip=*12>pR$`DPXof+Cpdy2`gk%P1CDg&-jD#*R zNJ*%Z!93BoTNyk-&~XM+1f?0ABItVzCMC4UAR?jj0}R3hnHh{r=q!UV3AHg8mC$|$ zBN95nU|2#c42C4+W^i(h!EsVK7t5s5%M4BsYdjY#2)=^^JbVPt;28fYZo*#vN8Ewq z{8QX(S~$;OQ98trfsB`U8rpgiJ{^MzpPpHxsq9?NXJ9bvGcs~IS&9~NxsuPsAn6m7 z=6n`L3(44QG#@L?`$QzCeHDBcI*g?NW^j&6y8ZYJe?&LjUQx7VbJ5sBDHko47UJ<_ z!BaX{`q~k5plx45m?$O7aM6=r{)Tt+nl6a3kKfTx;dwq_n8s=Tvf(+L;9bUAJhb^m zc!D=u z19*~8S%>fdf7zPAQC?BehR6A#ilRBO>BqufgkPSJpX3ZWjw?i ztNTo2njceG&FA|cIe}^*AfV!=P%eV+8V5hbTXE;s4sGjPU0f3wZ-rizGT~vBm9c(MdAIh z{Yb+rNc3&0kXecqlD~M(j($L3C4i^O5``Gwu-D@!_>b+4xWwPLAH%P5R{I6lkIzAMz5*GC*{L8gZ0xWQ?c3D4RQ@8jd?9sqW=@%MH_u8jIz3Fnf z9zN{#x(>)fa(TUN?QQJ`TfGO{dLHsU?CSCcySx3a7MGjpNwzdMTBi%`FwnuvCVLHJ!>XoZC@M>Sh^4YQGav7_bM?ybq{ktFu)L z#znCp{5XI$>WBkAGqJ>cDx0J*%y%7aYw!Quj=mc}8f}UQ zY2&Q`UKjkz$n^*@M@8IJ64oU@-c>49s6>c3A zMh?Jdt||1{s}s3&I+-X1(3DR{VW~Vw(`)Dt6p}anSQ$|@T6fR2n^2h5WOCE56X8yY zE96(-lF6qgW`d6Qmb|8h|oNtL#<6fBz|wx(V81 zZ&?eVXTpB0ZAY~2a358vfg0?F06PCU*rF2XrcJhvUF89lR#1b@ASe)1Ia7Nl_X2iO z=Y8=CV~S0sFeU^)zVK(osM4mg6WST3x*erQr8Tzh&DRe&VfRl;r`qp8)M0l7kXw=^ zTXi8RhO3y=cwgO-wO-Vvb5pm?ZSQYF)E(uoGE`G#33jd!W7aw%42&4P!5Z~a^8lC-qR&I z^k}O9bYW8I^?1dRzbf^gKLCSpGeYoVH{*{! zcxr}Syc>2qWQSORvO{|#LMj(mRy`}Lb~GWg=JmBZGJEdsGj~L(w#wxY8Qjz8*wfHx zeOQ122vwg*g_?Nu1zRr~Ht=8$(+kALmJAql9`uC2;)>fAs z5LJ)xi~IT>fWZib;|Y dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -457,9 +457,9 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -470,19 +470,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -560,6 +548,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/mip/v5/createstubs_mem_min.py b/mip/v5/createstubs_mem_min.py index 53bc8a3ae..b80e20c14 100644 --- a/mip/v5/createstubs_mem_min.py +++ b/mip/v5/createstubs_mem_min.py @@ -1,33 +1,35 @@ -u='stubber' -t='{}/{}' -s='method' -r='function' -q='bool' -p='str' -o='float' -n='int' -m=NameError -l=sorted -k=NotImplementedError -b=',\n' -a='dict' -Z='list' -Y='tuple' -X='micropython' -W=str -V=repr -T='_' -S=KeyError -R=open -Q=IndexError -P=dir -O=ImportError -N=True -M='family' -L=len -K=print -J='board' -I='.' +w='stubber' +v='{}/{}' +u='method' +t='function' +s='bool' +r='str' +q='float' +p='int' +o=NameError +n=sorted +m=NotImplementedError +d=',\n' +c='dict' +b='list' +a='tuple' +Z='micropython' +Y=str +X=repr +V='cpu' +U='_' +T=KeyError +S=open +R=IndexError +Q=dir +P=ImportError +O='with' +N='family' +M=len +L=print +K=True +J='.' +I='board' H=AttributeError A=False G='/' @@ -36,51 +38,51 @@ F=OSError C='' import gc as B,os,sys -from ujson import dumps as c +from ujson import dumps as e try:from machine import reset -except O:pass -try:from collections import OrderedDict as d -except O:from ucollections import OrderedDict as d +except P:pass +try:from collections import OrderedDict as f +except P:from ucollections import OrderedDict as f __version__='v1.16.2' -v=2 -w=2 -e=[I,'/lib','/sd/lib','/flash/lib','lib'] +x=2 +y=2 +g=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): C=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') except H:pass A._report=[];A.info=_info();B.collect() if C:A._fwid=C.lower() - elif A.info[M]==X:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[N]==Z:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:f(path+G) - except F:K('error creating stub folder {}'.format(path)) + try:h(path+G) + except F:L('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in P(I): - if A.startswith(T)and not A in L.modules:continue + for A in Q(I): + if A.startswith(U)and not A in L.modules:continue try: E=getattr(I,A) - try:F=V(type(E)).split("'")[1] - except Q:F=C - if F in{n,o,p,q,Y,Z,a}:G=1 - elif F in{r,s}:G=2 + try:F=X(type(E)).split("'")[1] + except R:F=C + if F in{p,q,r,s,a,b,c}:G=1 + elif F in{t,u}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,V(E),V(type(E)),E,G)) + D.append((A,X(E),X(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) except MemoryError as K:sleep(1);reset() - D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) + D=n([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J + def add_modules(A,modules):A.modules=n(set(A.modules)|set(modules)) def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) @@ -88,90 +90,90 @@ def create_one_stub(C,module_name): D=module_name if D in C.problematic:return A if D in C.excluded:return A - H='{}/{}.py'.format(C.path,D.replace(I,G));B.collect();E=A + H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=A try:E=C.create_module_stub(D,H) except F:return A B.collect();return E - def create_module_stub(J,module_name,file_name=E): + def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:M=D.replace(I,T)+'.py';H=J.path+G+M - else:M=H.split(G)[-1] - if G in D:D=D.replace(G,I) - K=E - try:K=__import__(D,E,E,'*');U=B.mem_free() - except O:return A - f(H) - with R(H,'w')as L:P=W(J.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);L.write(Q);L.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(L,K,D,C) - J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) + if H is E:N=D.replace(J,U)+'.py';H=I.path+G+N + else:N=H.split(G)[-1] + if G in D:D=D.replace(G,J) + L=E + try:L=__import__(D,E,E,'*');R=B.mem_free() + except P:return A + h(H) + with S(H,'w')as M:O=Y(I.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,O,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,C) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: - try:del K - except(F,S):pass + try:del L + except(F,T):pass try:del sys.modules[D] - except S:pass - B.collect();return N - def write_object_stub(M,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() - if P in M.problematic:return - R,N=M.get_obj_attributes(P) - if N:K(N) - for(E,J,G,T,f)in R: + except T:pass + B.collect();return K + def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): + d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() + if P in K.problematic:return + R,N=K.get_obj_attributes(P) + if N:L(N) + for(E,J,G,S,f)in R: if E in['classmethod','staticmethod','BaseException',O]:continue if E[0].isdigit():continue - if G==""and L(D)<=w*4: + if G==""and M(D)<=y*4: U=C;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return - H.write(A);M.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[s,r,'closure']): - W=b;X=C + H.write(A);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) + elif any(A in G for A in[u,t,'closure']): + W=Y;X=C if Q>0:X='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) + if Z in G or Z in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=C - if A[D]==C and sys.platform not in(k,j): - try:o=os.uname();A[D]=o.release - except(Q,H,TypeError):pass - for(p,q,r)in[(l,l,'const'),(m,m,'FAT'),(n,'pybricks.hubs','EV3Brick')]: - try:s=__import__(q,E,E,r);A[M]=p;del s;break - except(O,S):pass - if A[M]==n:A['release']='2.0.0' - if A[M]==X: + A[F]=W(os.uname()[3]) + if not A[F]:A[F]=W(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=W(sys.version.split(';')[1]) + except(H,R):pass + if A[F]and M(A[F])>5:A[F]=C + if A[D]==C and sys.platform not in(c,b): + try:h=os.uname();A[D]=h.release + except(R,H,TypeError):pass + for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: + try:l=__import__(j,E,E,k);A[N]=i;del l;break + except(P,T):pass + if A[N]==g:A['release']='2.0.0' + if A[N]==Z: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - V=int(A[K]);a=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if a:A[f]=a - A[K]='v{}.{}'.format(V&255,V>>8&3) - A[b]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def g(info,board_descr,filename): - with R(filename,'r')as C: + L=int(A[K]);U=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][L>>10] + if U:A[a]=U + A[K]='v{}.{}'.format(L&255,L>>8&3) + A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def z(info,desc=C): + G='with ';D=info;E=A + for F in[A+'/board_info.csv'for A in g]: + if j(F): + C=desc or D[I].strip() + if i(D,C,F):E=K;break + if O in C: + C=C.split(O)[0].strip() + if i(D,C,F):E=K;break + if not E: + C=desc or D[I].strip() + if G+D[V].upper()in C:C=C.split(G+D[V].upper())[0].strip() + D[I]=C + D[I]=D[I].replace(' ',U);B.collect() +def i(info,board_descr,filename): + with S(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return N + if D==board_descr:info[I]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=I + except(F,H):A=J B=A - for B in[A,'/sd','/flash',G,I]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def h(filename): +def j(filename): try: - if os.stat(filename)[0]>>14:return N + if os.stat(filename)[0]>>14:return K return A except F:return A -def i():sys.exit(1) +def k():sys.exit(1) def read_path(): path=C - if L(sys.argv)==3: + if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:i() - elif L(sys.argv)==2:i() + else:k() + elif M(sys.argv)==2:k() return path -def j(): - try:B=bytes('abc',encoding='utf8');C=j.__module__;return A - except(k,H):return N +def l(): + try:B=bytes('abc',encoding='utf8');C=l.__module__;return A + except(m,H):return K def main(): E='/modulelist.txt';stubber=Stubber(path=read_path());stubber.clean();stubber.modules=[] - for C in e: + for C in g: try: F=B.mem_free() - with R(C+E)as D: - K('Debug: List of modules: '+C+E);A=D.readline() + with S(C+E)as D: + L('Debug: List of modules: '+C+E);A=D.readline() while A: A=A.strip() - if L(A)>0 and A[0]!='#':stubber.modules.append(A) + if M(A)>0 and A[0]!='#':stubber.modules.append(A) A=D.readline() - B.collect();K('Debug: Used memory to load modulelist.txt: '+W(F-B.mem_free())+' bytes');break + B.collect();L('Debug: Used memory to load modulelist.txt: '+Y(F-B.mem_free())+' bytes');break except Exception:pass - if not stubber.modules:stubber.modules=[X] + if not stubber.modules:stubber.modules=[Z] B.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or j(): - try:x=logging.getLogger(u);logging.basicConfig(level=logging.INFO) - except m:pass - if not h('no_auto_stubber.txt'): +if __name__=='__main__'or l(): + try:A0=logging.getLogger(w);logging.basicConfig(level=logging.INFO) + except o:pass + if not j('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_mem_mpy.mpy b/mip/v5/createstubs_mem_mpy.mpy index 52eb3505c4a3dab35eda34ebdb9761b06eaab28c..f88cb945ec36e00c587b4d47a15400aa6ef7cd4e 100644 GIT binary patch delta 2409 zcmYjSU2s#!72Z9PtRKtrY9(D_jC~zT2;0~~5{igwsEvFn#y0-JmW)ZUMt{Z%vgAlI z#<-5IlXyr-hk_nhyXJ=^wvyY`?8#Jbn}n=hW%Hl259^ESK9Znr<}Y_qj_>^7Un`Rd$) zKHk1i`>J6j;JjOYac4wJIzG5VMrZ1@-(hQ`iuw?cqnw^GoB5~;DYaZeK- z+^G`al)FrTgj+3;WAR)llTPQ{oaeJ{tpLZ}I)P^5;aF%goEvwS3y^f{*@w`gp7vrv zx!1`aKm$&*&5FKeeb$sphr(02bZ8^(j@-%IOS?7RmMu~4BNs2iS;yqecXuwmuJB>( zVV^5U@C0jAji`D96ppads+aLNBV`ucvt%#3i19x58+8pCxa`59?*F1Y%VxwV1lWJn zb@(t7HC5h2_a%)yLZRc6E{u+@QkbOh9EA*pEQK(I2!&{idQDQv^LPDE%G@AFVTz?R zui+HK+V9{&_Po}`pNraRJj6cJK81q}bY48de7b|Ui=Ea*ahUy8*N6kmQXaGQuLl&P z#ds9Pmpqt((CNA>~3YfI$B~MW)CXgvkXy4H!1E*N_nIhcOa_A(7p5l zc?sh@+ew@7_t+@4RR_Fq)BlhBr6@w^l?C$|Q>`wVjE7TN`Av3#4&xK-D;mb{uwm0S z{>gch74Ks2nlhZ!Ci9+eTtvJf5}AqVa3+51k{P{AV3sGMxS|km#)~FRQ8V+v~V@R#YxI0XChuKX=S3z<|cN!3s-~wdYQkxa<2#)rW2`H zdOBN#jYXK~l8MyR$$OGoUiwxMMRI2iqR?eV<8Gi9Q;o^MX=nM2@?bA6(CT1U1sbN% z`A7_%@9?^XCc@G2L@G{UfPJy4G5-q+ecZ)Q%;-Gj=LXj6Wkzp$QGsp^mT-j^=Q-&O zh-gAQGt|OkT0D47(#up~Qkc|!k#~)ns!i(0&|Q9oOdAWU!7j?lR8u(A1dj+&@aN5j zXgZmUM{{1p+v8NB*d;2nitjoP^UoWmR>r;s4-PnLsP8 zGHqXzo{(udRhd-$gNWLT=hux&;W_2UqH|}GsZFMEkgq&=;kQzmOsk4fXiI=9?n%34 zT4`!sy3zz|Uq~%-rv=eX=1pGo*>#g46X)%cjThJ(RlD=8$f@|{uRiarMbsP$B_@iJ z357nSu#e)OdX#o@qd=iI*g)E=2MavCeB1v z9C!DmHn~8n0@5!2hj}IXh|=NY>emV-opVs_3kJ7-2iHe>yK z{!5$j=ZPQs(56MN7$ot1ZAmFZe5D-aQ+bf;WC)C0K|8W-3E_v_{v;RT9IDu5BrH8lyPO0SkP0fuvybUg&ZHL%wM?_b=w ztT^Dq=njQvmpxb-k}vJk$xFP^*7f-@g~ZazvPU76^TKxD9^pT~n=kuT*77`ED;qMG zzcyDrvR17dD`fxM`70gm8;;c*hL?GaAYcE;iyp45Nt;WaI9RMk5%c1&U9K!qMR5Ja zJV8o+3wfakQ7iZ#7dxMIxHKj;v3NF`+-tCk@*miH)yqo>O3o>4 zPKU42$DMS1#AVI`HKWR;@mx7ut#R?|^v^Xl*ud1a9sJ(!uH9TQczN-m2k+0K+Z1|O SrgoU$ZJ*Zq@DZjI&-@R9@tP(8 delta 2225 zcmY*adu&tJ89(RqGtPr^&vj0kg5v}(&ZCJF8)KS=M{zDAPx2skNH^lyjze7h2)2`e zvdlMa=~`4F;8ffG*@V!xR#nvnQc4@RJle9dSKDd-ESoZ<{V{3MRKzMx+BB&Gnv9CeV$d(4;|%&FG|!-y*rJ(8R`Bg1;O2vP9LM<2aUI^t ze}`M}1pf-}x6Fz_bJ9+J5ELBeNod?V=`}D2dX3B$PNXL@UK4|3UNa-d;`wkklgWE6 z45qwR1_^HoquF?5B0L?*PkBXF&wESx8nl>a{FuQ>E*Tndia%o*XfDmk=}b5>lh1^6 z`I%@mo^|I>=3m-v^*3&b2^aZz5ze`%Prc?@zG`U4*vlUn$MA99Z5lK62PqukZNH`HrI6!itru{T*Ohz+5Ah$Dc*O7LC7bau z|9i)%G&@A@sH)KAhpZB=b1N= znE6CDH5bXoKfG*5KOr#h$7976g;+CQlC8yQxf1o^#ey4xkM^Sc9lH}?hJR{5h~MI@ z@~N7)(Ygb(?dXCq8xoAl%TJFio`bE}qP@evUD-!>+*b#+yWJ|fDx*D`=>IIgS-B1G z;(w_ORt9BlMQQLLVy(@jYws*|8a29y_pxUGrR3|i`Hi_P)owYR&Zl>IJkBOXtehTC zV{>Ekj(X3I#=YCTPdnQ@?HwIH=XR%y|BSVDR2)2T=)iDy=UrlrWMfmmAm-Tg%qPS= z8_(V&*11G}>X*cvnm+X_Vx7)p^S>6CYbKGL_zi^#{x9Y%^haqU1vN?yH=-23AEl)- znNCLXlbLMldh{xVo+!0k6I(0d`<^J%Z}sazF|x!weJbk5YKcZ{xqNDeSHB(#Y}Lf( zyQ@X8VlI)M$js%6uvCPJEtyEqoLp5c+Hw&@T9*US-Oz1EQ(mBwTrF1!(m5ecKJ3Rj ztqS#&qfrW7k7lInRng6GDiWJYq~jC@`C3(D;nSOT^g}<=Xw|8uY`K22wO#As0kj0rVy}K#4^cb zJeK#PF|UC_ym*0+7SLxDrf&JLXuM9VH$uAzg=4xxZutx%-7)bA__PlcvZgAULN-`x zk4*9ZTb5{7b!rF&E*5l(h0!8GMj;S>D5A97UM}Ky9YGX=bh~|f!H-@H`mlZ@q~8d3 zQjMCZ$!_wa7rq9!YXmxIo!qjfKB3W4YLZQY0B`K0zk&TNxnv3havwC-7 zKWa0$s7rR)yXp|Nhr@|faTLR0MW%3oV#V$=x+)c_Q|J#hR6bj+Ev_?y0Sbp7;}p0d zDq;#QtqOT0Hm|$Q-KLW&LCI7U+EsPmdIQv5;;&e@0b+Ewi3vSWF91W3lzH49apX_x z=C7aI-R*x=H?2PpeOFw6aWb@`uc_bE^p&6*)F>Jk3mFlQ8R7CPM=6rdjh<(jyk|HBMI za`g8@dJKSn`D91kN9ZZE6z(lUcZBF(_Tg50;9;RCex~I93X@5@#|O4F6F6qj{@PMo zU++}>ViJb=nJt}9Ku?Imp_nMs(6@w)?-!@m#f|@Yi-N!421m2d{x-+338pHwfAW_d zeq&;j_HTaMv5jc|QQF+?jqSo&=WWq;{-tBw_`Gz^$b&T=@jm-rjRRZwPis0G;^E$l y=)Qk(MN*Dm8F09@WCAVm_jcn&QbBknR2${Bm9!{%zps^+GP3w diff --git a/mip/v5/createstubs_min.py b/mip/v5/createstubs_min.py index a74db7725..75a060686 100644 --- a/mip/v5/createstubs_min.py +++ b/mip/v5/createstubs_min.py @@ -1,36 +1,38 @@ -w='pyb' -v='stubber' -u='{}/{}' -t='logging' -s='sys' -r='method' -q='function' -p='bool' -o='str' -n='float' -m='int' -l=NameError -k=sorted -j=NotImplementedError -b='pycom' -a=',\n' -Z='dict' -Y='list' -X='tuple' -W='micropython' -V=open -U=repr -S='_' -R=len -Q=KeyError -P=IndexError -O=dir -M=print +y='pyb' +x='stubber' +w='{}/{}' +v='logging' +u='sys' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n=NameError +m=sorted +l=NotImplementedError +d='pycom' +c=',\n' +b='dict' +a='list' +Z='tuple' +Y='micropython' +X=open +W=repr +U='cpu' +T='_' +S=len +R=KeyError +Q=IndexError +P=dir +O=print N=ImportError -K=True +M='with' L='family' -J='board' -I='.' +K=True +J='.' +I='board' H=AttributeError A=False G='/' @@ -39,51 +41,51 @@ D='version' B='' import gc as C,os,sys -from ujson import dumps as c +from ujson import dumps as e try:from machine import reset except N:pass -try:from collections import OrderedDict as d -except N:from ucollections import OrderedDict as d +try:from collections import OrderedDict as f +except N:from ucollections import OrderedDict as f __version__='v1.16.2' -x=2 -y=2 -z=[I,'/lib','/sd/lib','/flash/lib','lib'] +z=2 +A0=2 +A1=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise l('MicroPython 1.13.0 cannot be stubbed') except H:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[L]==W:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==Y:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:e(path+G) - except F:M('error creating stub folder {}'.format(path)) + try:g(path+G) + except F:O('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in O(I): - if A.startswith(S)and not A in L.modules:continue + for A in P(I): + if A.startswith(T)and not A in L.modules:continue try: E=getattr(I,A) - try:F=U(type(E)).split("'")[1] - except P:F=B - if F in{m,n,o,p,X,Y,Z}:G=1 - elif F in{q,r}:G=2 + try:F=W(type(E)).split("'")[1] + except Q:F=B + if F in{o,p,q,r,Z,a,b}:G=1 + elif F in{s,t}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,U(E),U(type(E)),E,G)) + D.append((A,W(E),W(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) except MemoryError as K:sleep(1);reset() - D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J - def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) + D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) def create_all_stubs(A): C.collect() for B in A.modules:A.create_one_stub(B) @@ -91,90 +93,90 @@ def create_one_stub(B,module_name): D=module_name if D in B.problematic:return A if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(I,G));C.collect();E=A + H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A try:E=B.create_module_stub(D,H) except F:return A C.collect();return E - def create_module_stub(J,module_name,file_name=E): + def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:O=D.replace(I,S)+'.py';H=J.path+G+O + if H is E:O=D.replace(J,T)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,I) + if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');T=C.mem_free() + try:L=__import__(D,E,E,'*');S=C.mem_free() except N:return A - e(H) - with V(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) - J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os',s,t,'gc'}: + g(H) + with X(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) + if D not in{'os',u,v,'gc'}: try:del L - except(F,Q):pass + except(F,R):pass try:del sys.modules[D] - except Q:pass + except R:pass C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;N='Exception';H=fp;D=indent;C.collect() - if O in K.problematic:return - S,L=K.get_obj_attributes(O) - if L:M(L) - for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',N]:continue + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;D=indent;C.collect() + if N in K.problematic:return + Q,L=K.get_obj_attributes(N) + if L:O(L) + for(E,J,G,T,f)in Q: + if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and R(D)<=y*4: - U=B;V=E.endswith(N)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=N + if G==""and S(D)<=A0*4: + U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): - W=b;a=B - if P>0:a='self, ' + elif any(A in G for A in[t,s,'closure']): + W=Y;X=B + if P>0:X='self, ' if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(j,i): - try:m=os.uname();A[D]=m.release - except(P,H,TypeError):pass - for(n,o,p)in[(k,k,'const'),(b,b,'FAT'),(l,'pybricks.hubs','EV3Brick')]: - try:q=__import__(o,E,E,p);A[L]=n;del q;break - except(N,Q):pass - if A[L]==l:A['release']='2.0.0' - if A[L]==W: + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=V(sys.version.split(';')[1]) + except(H,Q):pass + if A[F]and S(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(b,a): + try:g=os.uname();A[D]=g.release + except(Q,H,TypeError):pass + for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(e,'pybricks.hubs','EV3Brick')]: + try:k=__import__(i,E,E,j);A[L]=h;del k;break + except(N,R):pass + if A[L]==e:A['release']='2.0.0' + if A[L]==Y: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - V=int(A[K]);Z=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if Z:A[e]=Z - A[K]='v{}.{}'.format(V&255,V>>8&3) - A[a]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def f(info,board_descr,filename): - with V(filename,'r')as C: + O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] + if W:A[Z]=W + A[K]='v{}.{}'.format(O&255,O>>8&3) + A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def A2(info,desc=B): + G='with ';D=info;E=A + for F in[A+'/board_info.csv'for A in A1]: + if i(F): + B=desc or D[I].strip() + if h(D,B,F):E=K;break + if M in B: + B=B.split(M)[0].strip() + if h(D,B,F):E=K;break + if not E: + B=desc or D[I].strip() + if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() + D[I]=B + D[I]=D[I].replace(' ',T);C.collect() +def h(info,board_descr,filename): + with X(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return K + if D==board_descr:info[I]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=I + except(F,H):A=J B=A - for B in[A,'/sd','/flash',G,I]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def g(filename): +def i(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def h():sys.exit(1) +def j():sys.exit(1) def read_path(): path=B - if R(sys.argv)==3: + if S(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:h() - elif R(sys.argv)==2:h() + else:j() + elif S(sys.argv)==2:j() return path -def i(): - try:B=bytes('abc',encoding='utf8');C=i.__module__;return A - except(j,H):return K -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',W,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,b,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or i(): - try:A0=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except l:pass - if not g('no_auto_stubber.txt'): +def k(): + try:B=bytes('abc',encoding='utf8');C=k.__module__;return A + except(l,H):return K +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',y,d,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or k(): + try:A3=logging.getLogger(x);logging.basicConfig(level=logging.INFO) + except n:pass + if not i('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_mpy.mpy b/mip/v5/createstubs_mpy.mpy index c80b70b1cffea2edfe89fe32829ee52753ceefd1..7d0b02dbef6ab6346dda4f6614e643c0c7a8fff1 100644 GIT binary patch delta 2404 zcmYjSYj9J?72Z8pvSeAvtCe((F-Eo}8^0u5LJyBQPkCHsuj$o3@$hpVE#?r|q;qDa>@H?VolflLY;^ z+CBH|Ip00sclMk=S{kc9qy%%*H=4SCa=yAp(bm>xJ-@r5u?KS9-R?koK%J9b0YW%Qj0LA zM<+!%sz)6njOtOl2qSuQP=q6Tv?Ri?9<_;Zn5Y+H**Os!4-xH5FcFLAML0Mr!Vm$w z2!liuN(IvqHif5gl-UcHBnfkjaCIanS#4$L|Q5&TYt zs0qZ9Gb#PvPJDESk~=z`RU*teRU(;Dx`^!q?OnSp?dG<2bBoi~Vz!yL z??$UPyU?vJbeqDFOD-H3`X9P;#fTV%G1jbZIx|yOnz~9MMPZ)8^Ayq)j!_6w2-#HYl2Ts2=WUj`Lxw_@omanx6UdOgeR9FcJwQQjuIdno-K*>|ymY{KHx`ZhV{_*Bruw?4l-&BTQG* zfydacnv8n3$iJ4t1S{6OqsUQMV8^wa@hHn_C47Lrr~Me`*ejb}!^3Qwu3vrheHW&j zMK-7VK#}E;Sa7~bYd}>j^11~qPGbw@w4R>g(!Q~*nq?A zhsGv+ihX2!4!_HcrY^k7_L;UQW~=2Qn>J117uXF`Ug0;$KVu$oul>8mzmdp>Mr-8T zX0y3_r^8|HwDOhN+~x3CoV(1u4$mHs%iLyeVLuYvE$U!8Ja?N^Ekx6INL6A!{~=M& zr_$NGyiIbkc;p^+u-dwoLNf&^M1^Z1im!xdje*R^gV~u>I&n2bbiTtwhlj@xQ#cT! z)f9Z(ag94(4!Q6zN>_aqrRCjNs+Nf+lTGY!mah7}Ei!*qyk9oz7GudsYB5tb>&s@M ziN}(;Q}-p6e5q_ieeysfqA+Mgb55WpL!&{*5oh={IpZ&c{s*-7aISaMe;@rPGQA@3EA)8;Z4WFCp(2MAuzNX z^$H*T`Zr~kjDbKbQPxl(@IHn86#vwv`0b4ng@gX~+I{u%as?%Dxr{!A(|fB>qDtS& zeSYB(jnm$1?=6vfj#BBPFnM44!WU&uvrpQ||1jrgm?-SMTvOZmUhomE!|vcm{wOtk zw)faQe~@Y``;jkkrujktT4`P4k=A^YPo`*^FI>2duPwgX zM7ywb+P-w!h{mj>Wx4RsN?v~S(nB|Jf;XyK@vv1q%GkKk4c<*M@1`dXD&3inVKS_uqk(a$Nmu zuahqi71q{yz1E(nU;e~h`Kh;Z!M-zr@0-}fZ2>WSkep2Nr2-*cnKJkpj*ByKFz zQMS49Cn490RPb-SSSCop=ZqV;snyS$z^DtS;_+xW%f&wuMp#`Qsp?2H6OQ-kn$7ZG zS*fAB)+EUPv^8ztZnnC4e@w7{HT3IEe%cWB-YAS5pQ09CH4{6s)r$Yka$CFk%y?_- zsKR49huD9%x)mpC&neiBMhiJtW$m?lIy^jx_XFMqY^HHqaZ-Oy$L=*c_)z_C<2Fo+ h_1o3}FR+iBynGNDn%_|5DMZ-2&1sw~wzQ;F{|Ba~k;DK1 delta 2286 zcmY*aT~J%c72Z9P5E3BoU5Uj6V<8~~m_JFqmP2WsAj>ue|ACP(xVA8_*p*98y37unbQbHXJCW$dK8%-w}M2NQ4SYQw)sE@%2K?w%K1pSo3 zQG$fOAqh=02ukQ#1_6Rf861(&Nd^NFYG%+cp(X~0CA6QxAqmYfI3OV>gM$MM`bha$ zI2ljOGT2Xyk#smKIQJ50XRuE~bqsnAGw3F$gaLmZ@5fR87i`0B{v~e1qud7F`qRSa zthAj^LOsAU{2VmzjCnK+20dD448>DpX^)P@Qa?FPS&3?b0Z|&k8*k z5Jf|mF3WJYry5ZRQ1r7aGM2FgEfQ$-;)TGyUP*O(_>sR(k(ZB{Vihc+!41?3I$ z8EznU{m44^qufJ&tL>+dSb0d!W32Ez-GA! zW}d97e#`UYCJEHNIR7qT-8>b;;Id ztCQblO!0a z@mgR#iDyI-8x&&9<&)p>6t4w+c129BJWxT?OguH3p2?}Oq{76Qh^MAbKk)07ODc$z zo?4OT`z&Z;hX<%+t~Q$l-<)V_GWOyktqS&5sQKRW$gfq_Rq1(AND)egqZ9E|Oq3M= zva0#mM>j0!q8AmZEht8dZ>g2Cfm{ia(vUbcmBj9njMs$9RAbhd^**bzO7&E4)_)6i z`!ot|D6R&3MIq8EQE2?fo1Z9nG!&juYj+6!k;3@fGWPc>MOwY#w#TVp*pIw=)CCJZ@>nHKo_-{+t&P>62%LLmpGu$y9sS=Kr& z4yj0Cf3V5&bhWau&I=Aw=>HZoUs1$G7g%~AIvp{3+Fk9gBB>U{bO8!O5ByIF0cryN z9pa-#?-0?pyF@PTZWMqfK+4_iZn5N3f6X`lo$Z~U_&2Tp_n&EpfLIw^Ew1^GDaF-* zKcG-_LJVZ=tmMHbj-IG|>2bix985G(2P<9Xyr#=`7qy_JP+vK^MbU+28FyHG zj|*yJ(loUprjwoz0zMGv7Nxd~Vu$ zLK~OP>3L?WyKa(hS9MS?n8xTvCq(GH{P8bbCUi*2cXqIQNt Pgb&%XIJfeFJ+1#YCysaw diff --git a/mip/v6/createstubs.py b/mip/v6/createstubs.py index ec867a17d..af07c6418 100644 --- a/mip/v6/createstubs.py +++ b/mip/v6/createstubs.py @@ -455,7 +455,7 @@ def _info(): # type:() -> dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -473,13 +473,13 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = ( + _machine = ( sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore ) - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -490,19 +490,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -581,6 +569,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/mip/v6/createstubs_db.py b/mip/v6/createstubs_db.py index c6c5ecb27..ecb9ffe19 100644 --- a/mip/v6/createstubs_db.py +++ b/mip/v6/createstubs_db.py @@ -448,7 +448,7 @@ def _info(): # type:() -> dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -466,9 +466,9 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -479,19 +479,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -569,6 +557,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/mip/v6/createstubs_db_min.py b/mip/v6/createstubs_db_min.py index 34ba0bee4..8f5a7e7f8 100644 --- a/mip/v6/createstubs_db_min.py +++ b/mip/v6/createstubs_db_min.py @@ -1,178 +1,180 @@ -v='stubber' -u='{}/{}' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n=NameError -m=sorted -l=MemoryError -k=NotImplementedError -b=',\n' -a='dict' -Z='list' -Y='tuple' -X='micropython' -W=str -V=repr -T='_' -S=KeyError -R=IndexError -Q=dir -P=ImportError +x='stubber' +w='{}/{}' +v='method' +u='function' +t='bool' +s='str' +r='float' +q='int' +p=NameError +o=sorted +n=MemoryError +m=NotImplementedError +d=',\n' +c='dict' +b='list' +a='tuple' +Z='micropython' +Y=str +X=repr +V='cpu' +U='_' +T=KeyError +S=IndexError +R=dir +Q=ImportError +P='with' O='family' N=print -M=True -L=len +M=len +L='.' K='board' -J='.' +J=True I=open H=AttributeError G='/' -F=False -E=None -D='version' +F=None +E='version' +D=False A=OSError C='' import gc as B,os,sys -from ujson import dumps as c +from ujson import dumps as e try:from machine import reset -except P:pass -try:from collections import OrderedDict as d -except P:from ucollections import OrderedDict as d +except Q:pass +try:from collections import OrderedDict as f +except Q:from ucollections import OrderedDict as f __version__='v1.16.2' -w=2 -x=2 -e=[J,'/lib','/sd/lib','/flash/lib','lib'] +y=2 +z=2 +g=[L,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: - def __init__(C,path=E,firmware_id=E): + def __init__(C,path=F,firmware_id=F): D=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') except H:pass C._report=[];C.info=_info();B.collect() if D:C._fwid=D.lower() - elif C.info[O]==X:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) + elif C.info[O]==Z:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) else:C._fwid='{family}-{ver}-{port}'.format(**C.info) C._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) - try:f(path+G) + try:h(path+G) except A:N('error creating stub folder {}'.format(path)) C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in Q(I): - if A.startswith(T)and not A in L.modules:continue + for A in R(I): + if A.startswith(U)and not A in L.modules:continue try: E=getattr(I,A) - try:F=V(type(E)).split("'")[1] - except R:F=C - if F in{o,p,q,r,Y,Z,a}:G=1 - elif F in{s,t}:G=2 + try:F=X(type(E)).split("'")[1] + except S:F=C + if F in{q,r,s,t,a,b,c}:G=1 + elif F in{u,v}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,V(E),V(type(E)),E,G)) + D.append((A,X(E),X(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) - except l as K:sleep(1);reset() - D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) + except n as K:sleep(1);reset() + D=o([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J + def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) def create_one_stub(C,module_name): - D=module_name - if D in C.problematic:return F - if D in C.excluded:return F - H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=F - try:E=C.create_module_stub(D,H) - except A:return F - B.collect();return E - def create_module_stub(K,module_name,file_name=E): - H=file_name;D=module_name - if H is E:O=D.replace(J,T)+'.py';H=K.path+G+O + E=module_name + if E in C.problematic:return D + if E in C.excluded:return D + H='{}/{}.py'.format(C.path,E.replace(L,G));B.collect();F=D + try:F=C.create_module_stub(E,H) + except A:return D + B.collect();return F + def create_module_stub(K,module_name,file_name=F): + H=file_name;E=module_name + if H is F:O=E.replace(L,U)+'.py';H=K.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,J) - L=E - try:L=__import__(D,E,E,'*');U=B.mem_free() - except P:return F - f(H) - with I(H,'w')as N:Q=W(K.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,K._fwid,Q,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,L,D,C) - K._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: - try:del L - except(A,S):pass - try:del sys.modules[D] - except S:pass - B.collect();return M + if G in E:E=E.replace(G,L) + M=F + try:M=__import__(E,F,F,'*');S=B.mem_free() + except Q:return D + h(H) + with I(H,'w')as N:P=Y(K.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(E,K._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,M,E,C) + K._report.append('{{"module": "{}", "file": "{}"}}'.format(E,H.replace('\\',G))) + if E not in{'os','sys','logging','gc'}: + try:del M + except(A,T):pass + try:del sys.modules[E] + except T:pass + B.collect();return J def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() + d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() if P in K.problematic:return - R,M=K.get_obj_attributes(P) - if M:N(M) - for(F,J,G,T,f)in R: + R,L=K.get_obj_attributes(P) + if L:N(L) + for(F,J,G,S,f)in R: if F in['classmethod','staticmethod','BaseException',O]:continue if F[0].isdigit():continue - if G==""and L(E)<=x*4: + if G==""and M(E)<=z*4: U=C;V=F.endswith(O)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O D='\n{}class {}({}):\n'.format(E,F,U) if V:D+=E+' ...\n';H.write(D);return - H.write(D);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) - elif any(A in G for A in[t,s,'closure']): - W=b;X=C + H.write(D);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) + elif any(A in G for A in[v,u,'closure']): + W=Y;X=C if Q>0:X='self, ' - if c in G or c in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) + if Z in G or Z in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,X,W) D+=E+' ...\n\n';H.write(D) elif G=="":0 elif G.startswith("5:A[F]=C - if A[D]==C and sys.platform not in(k,j): - try:o=os.uname();A[D]=o.release - except(R,H,TypeError):pass - for(p,q,r)in[(l,l,'const'),(m,m,'FAT'),(n,'pybricks.hubs','EV3Brick')]: - try:s=__import__(q,E,E,r);A[O]=p;del s;break - except(P,S):pass - if A[O]==n:A['release']='2.0.0' - if A[O]==X: - if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] + A[D]=W(os.uname()[3]) + if not A[D]:A[D]=W(os.uname()[2]) + if not A[D]and';'in sys.version:A[D]=W(sys.version.split(';')[1]) + except(H,S):pass + if A[D]and M(A[D])>5:A[D]=C + if A[E]==C and sys.platform not in(c,b): + try:h=os.uname();A[E]=h.release + except(S,H,TypeError):pass + for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: + try:l=__import__(j,F,F,k);A[O]=i;del l;break + except(Q,T):pass + if A[O]==g:A['release']='2.0.0' + if A[O]==Z: + if A[E]and A[E].endswith('.0')and A[E]>='1.10.0'and A[E]<='1.19.9':A[E]=A[E][:-2] if I in A and A[I]: - V=int(A[I]);a=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if a:A[f]=a - A[I]='v{}.{}'.format(V&255,V>>8&3) - A[b]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def g(info,board_descr,filename): + J=int(A[I]);U=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][J>>10] + if U:A[a]=U + A[I]='v{}.{}'.format(J&255,J>>8&3) + A[X]=f"v{A[E]}-{A[D]}"if A[D]else f"v{A[E]}";return A +def A0(info,desc=C): + G='with ';C=info;E=D + for F in[A+'/board_info.csv'for A in g]: + if j(F): + A=desc or C[K].strip() + if i(C,A,F):E=J;break + if P in A: + A=A.split(P)[0].strip() + if i(C,A,F):E=J;break + if not E: + A=desc or C[K].strip() + if G+C[V].upper()in A:A=A.split(G+C[V].upper())[0].strip() + C[K]=A + C[K]=C[K].replace(' ',U);B.collect() +def i(info,board_descr,filename): with I(filename,'r')as B: while 1: A=B.readline() if not A:break - C,D=A.split(',')[0].strip(),A.split(',')[1].strip() - if C==board_descr:info[K]=D;return M - return F + C,E=A.split(',')[0].strip(),A.split(',')[1].strip() + if C==board_descr:info[K]=E;return J + return D def get_root(): try:B=os.getcwd() - except(A,H):B=J + except(A,H):B=L C=B - for C in[B,'/sd','/flash',G,J]: + for C in[B,'/sd','/flash',G,L]: try:D=os.stat(C);break except A:continue return C -def h(filename): +def j(filename): try: - if os.stat(filename)[0]>>14:return M - return F - except A:return F -def i():sys.exit(1) + if os.stat(filename)[0]>>14:return J + return D + except A:return D +def k():sys.exit(1) def read_path(): path=C - if L(sys.argv)==3: + if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:i() - elif L(sys.argv)==2:i() + else:k() + elif M(sys.argv)==2:k() return path -def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return F - except(k,H):return M +def l(): + try:A=bytes('abc',encoding='utf8');B=l.__module__;return D + except(m,H):return J def main(): - K='failed';G='modulelist.done';import machine as O - try:C=I(G,'r+b');N=M - except A:C=I(G,'w+b');N=F + L='failed';G='modulelist.done';import machine as O + try:C=I(G,'r+b');N=J + except A:C=I(G,'w+b');N=D stubber=Stubber(path=read_path()) if not N:stubber.clean() - y(stubber);D={} + A1(stubber);E={} try: with I(G)as C: - for E in C.read().split('\n'): - E=E.strip();B.collect() - if L(E)>0:P,Q=E.split('=',1);D[P]=Q + for F in C.read().split('\n'): + F=F.strip();B.collect() + if M(F)>0:P,Q=F.split('=',1);E[P]=Q except(A,SyntaxError):pass - B.collect();R=[A for A in stubber.modules if A not in D.keys()];B.collect() + B.collect();R=[A for A in stubber.modules if A not in E.keys()];B.collect() for H in R: - J=F - try:J=stubber.create_one_stub(H) - except l:O.reset() - B.collect();D[H]=W(stubber._report[-1]if J else K) - with I(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if J else K)) - if D:stubber._report=[A for(B,A)in D.items()if A!=K];stubber.report() -def y(stubber): + K=D + try:K=stubber.create_one_stub(H) + except n:O.reset() + B.collect();E[H]=Y(stubber._report[-1]if K else L) + with I(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if K else L)) + if E:stubber._report=[A for(B,A)in E.items()if A!=L];stubber.report() +def A1(stubber): E='/modulelist.txt';stubber.modules=[] - for D in e: + for D in g: try: with I(D+E)as F: N('DEBUG: list of modules: '+D+E) for C in F.read().split('\n'): C=C.strip() - if L(C)>0 and C[0]!='#':stubber.modules.append(C) + if M(C)>0 and C[0]!='#':stubber.modules.append(C) B.collect();break except A:pass - if not stubber.modules:stubber.modules=[X];_log.warn('Could not find modulelist.txt, using default modules') + if not stubber.modules:stubber.modules=[Z];_log.warn('Could not find modulelist.txt, using default modules') B.collect() -if __name__=='__main__'or j(): - try:z=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except n:pass - if not h('no_auto_stubber.txt'): +if __name__=='__main__'or l(): + try:A2=logging.getLogger(x);logging.basicConfig(level=logging.INFO) + except p:pass + if not j('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_db_mpy.mpy b/mip/v6/createstubs_db_mpy.mpy index aad357f4ab29391407bd2ebb7f1e49f59893d1e5..e1e5d09b8bc7f7df04626c838f32f68dbd2f3186 100644 GIT binary patch delta 5810 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 delta 5533 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 diff --git a/mip/v6/createstubs_lvgl.py b/mip/v6/createstubs_lvgl.py index 68f8a5e7e..4f881cc48 100644 --- a/mip/v6/createstubs_lvgl.py +++ b/mip/v6/createstubs_lvgl.py @@ -433,7 +433,7 @@ def _info(): # type:() -> dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -451,9 +451,9 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -464,19 +464,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -554,6 +542,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/mip/v6/createstubs_lvgl_min.py b/mip/v6/createstubs_lvgl_min.py index 69b505b09..9ccf49b17 100644 --- a/mip/v6/createstubs_lvgl_min.py +++ b/mip/v6/createstubs_lvgl_min.py @@ -1,33 +1,35 @@ -t='stubber' -s='{}/{}' -r='method' -q='function' -p='bool' -o='str' -n='float' -m='int' -l='micropython' -k=Exception -j=NameError -i=sorted -h=NotImplementedError -Z=',\n' -Y='dict' -X='list' -W='tuple' -V=open -U=repr -S='_' -R=len -Q=KeyError -P=IndexError -O=dir -M=print +v='stubber' +u='{}/{}' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n='micropython' +m=Exception +l=NameError +k=sorted +j=NotImplementedError +b=',\n' +a='dict' +Z='list' +Y='tuple' +X=open +W=repr +U='cpu' +T='_' +S=len +R=KeyError +Q=IndexError +P=dir +O=print N=ImportError -K=True +M='with' L='family' -J='board' -I='.' +K=True +J='.' +I='board' H=AttributeError A=False G='/' @@ -36,51 +38,51 @@ F=OSError B='' import gc as C,os,sys -from ujson import dumps as a +from ujson import dumps as c try:from machine import reset except N:pass -try:from collections import OrderedDict as b -except N:from ucollections import OrderedDict as b +try:from collections import OrderedDict as d +except N:from ucollections import OrderedDict as d __version__='v1.16.2' -u=2 -v=2 -w=[I,'/lib','/sd/lib','/flash/lib','lib'] +w=2 +x=2 +y=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise h('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') except H:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[L]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==n:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:c(path+G) - except F:M('error creating stub folder {}'.format(path)) + try:e(path+G) + except F:O('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in O(I): - if A.startswith(S)and not A in L.modules:continue + for A in P(I): + if A.startswith(T)and not A in L.modules:continue try: E=getattr(I,A) - try:F=U(type(E)).split("'")[1] - except P:F=B - if F in{m,n,o,p,W,X,Y}:G=1 - elif F in{q,r}:G=2 + try:F=W(type(E)).split("'")[1] + except Q:F=B + if F in{o,p,q,r,Y,Z,a}:G=1 + elif F in{s,t}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,U(E),U(type(E)),E,G)) + D.append((A,W(E),W(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) except MemoryError as K:sleep(1);reset() - D=i([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J - def add_modules(A,modules):A.modules=i(set(A.modules)|set(modules)) + D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) def create_all_stubs(A): C.collect() for B in A.modules:A.create_one_stub(B) @@ -88,90 +90,90 @@ def create_one_stub(B,module_name): D=module_name if D in B.problematic:return A if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(I,G));C.collect();E=A + H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A try:E=B.create_module_stub(D,H) except F:return A C.collect();return E - def create_module_stub(J,module_name,file_name=E): + def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:O=D.replace(I,S)+'.py';H=J.path+G+O + if H is E:O=D.replace(J,T)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,I) + if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');T=C.mem_free() + try:L=__import__(D,E,E,'*');S=C.mem_free() except N:return A - c(H) - with V(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) - J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) + e(H) + with X(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del L - except(F,Q):pass + except(F,R):pass try:del sys.modules[D] - except Q:pass + except R:pass C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;N='Exception';H=fp;D=indent;C.collect() - if O in K.problematic:return - S,L=K.get_obj_attributes(O) - if L:M(L) - for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',N]:continue + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;D=indent;C.collect() + if N in K.problematic:return + Q,L=K.get_obj_attributes(N) + if L:O(L) + for(E,J,G,T,f)in Q: + if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and R(D)<=v*4: - U=B;V=E.endswith(N)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=N + if G==""and S(D)<=x*4: + U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): - Z=b;a=B - if P>0:a='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,Z) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,Z) + elif any(A in G for A in[t,s,'closure']): + W=b;X=B + if P>0:X='self, ' + if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(h,g): - try:m=os.uname();A[D]=m.release - except(P,H,TypeError):pass - for(n,o,p)in[(i,i,'const'),(j,j,'FAT'),(k,'pybricks.hubs','EV3Brick')]: - try:q=__import__(o,E,E,p);A[L]=n;del q;break - except(N,Q):pass - if A[L]==k:A['release']='2.0.0' - if A[L]==l: + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=V(sys.version.split(';')[1]) + except(H,Q):pass + if A[F]and S(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(a,Z): + try:f=os.uname();A[D]=f.release + except(Q,H,TypeError):pass + for(g,h,i)in[(b,b,'const'),(c,c,'FAT'),(e,'pybricks.hubs','EV3Brick')]: + try:j=__import__(h,E,E,i);A[L]=g;del j;break + except(N,R):pass + if A[L]==e:A['release']='2.0.0' + if A[L]==n: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - V=int(A[K]);Y=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if Y:A[c]=Y - A[K]='v{}.{}'.format(V&255,V>>8&3) - A[Z]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def d(info,board_descr,filename): - with V(filename,'r')as C: + O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] + if W:A[Y]=W + A[K]='v{}.{}'.format(O&255,O>>8&3) + A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def z(info,desc=B): + G='with ';D=info;E=A + for F in[A+'/board_info.csv'for A in y]: + if g(F): + B=desc or D[I].strip() + if f(D,B,F):E=K;break + if M in B: + B=B.split(M)[0].strip() + if f(D,B,F):E=K;break + if not E: + B=desc or D[I].strip() + if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() + D[I]=B + D[I]=D[I].replace(' ',T);C.collect() +def f(info,board_descr,filename): + with X(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return K + if D==board_descr:info[I]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=I + except(F,H):A=J B=A - for B in[A,'/sd','/flash',G,I]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def e(filename): +def g(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def f():sys.exit(1) +def h():sys.exit(1) def read_path(): path=B - if R(sys.argv)==3: + if S(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:f() - elif R(sys.argv)==2:f() + else:h() + elif S(sys.argv)==2:h() return path -def g(): - try:B=bytes('abc',encoding='utf8');C=g.__module__;return A - except(h,H):return K +def i(): + try:B=bytes('abc',encoding='utf8');C=i.__module__;return A + except(j,H):return K def main(): D='lvgl' try:import lvgl as A - except k:return + except m:return B=D try:B='lvgl-{0}_{1}_{2}-{3}-{4}'.format(A.version_major(),A.version_minor(),A.version_patch(),A.version_info(),sys.platform) - except k:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) + except m:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) finally:stubber=Stubber(firmware_id=B) stubber.clean();stubber.modules=['io','lodepng','rtch',D];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or g(): - try:x=logging.getLogger(t);logging.basicConfig(level=logging.INFO) - except j:pass - if not e('no_auto_stubber.txt'): +if __name__=='__main__'or i(): + try:A0=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + except l:pass + if not g('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_lvgl_mpy.mpy b/mip/v6/createstubs_lvgl_mpy.mpy index 43060537acb028889d2046fcd16bbd2938ed2a91..ba80b338d66088ec097403f074c74b62165e5c7d 100644 GIT binary patch delta 5355 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 fIqZE&f_Bpq~S@fElhQ@BiU83z%Ec# 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 kKfW0q_>L!#Phbs!g7HAkB)-2^VFRZNaT=Q dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -457,9 +457,9 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -470,19 +470,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -560,6 +548,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/mip/v6/createstubs_mem_min.py b/mip/v6/createstubs_mem_min.py index 53bc8a3ae..b80e20c14 100644 --- a/mip/v6/createstubs_mem_min.py +++ b/mip/v6/createstubs_mem_min.py @@ -1,33 +1,35 @@ -u='stubber' -t='{}/{}' -s='method' -r='function' -q='bool' -p='str' -o='float' -n='int' -m=NameError -l=sorted -k=NotImplementedError -b=',\n' -a='dict' -Z='list' -Y='tuple' -X='micropython' -W=str -V=repr -T='_' -S=KeyError -R=open -Q=IndexError -P=dir -O=ImportError -N=True -M='family' -L=len -K=print -J='board' -I='.' +w='stubber' +v='{}/{}' +u='method' +t='function' +s='bool' +r='str' +q='float' +p='int' +o=NameError +n=sorted +m=NotImplementedError +d=',\n' +c='dict' +b='list' +a='tuple' +Z='micropython' +Y=str +X=repr +V='cpu' +U='_' +T=KeyError +S=open +R=IndexError +Q=dir +P=ImportError +O='with' +N='family' +M=len +L=print +K=True +J='.' +I='board' H=AttributeError A=False G='/' @@ -36,51 +38,51 @@ F=OSError C='' import gc as B,os,sys -from ujson import dumps as c +from ujson import dumps as e try:from machine import reset -except O:pass -try:from collections import OrderedDict as d -except O:from ucollections import OrderedDict as d +except P:pass +try:from collections import OrderedDict as f +except P:from ucollections import OrderedDict as f __version__='v1.16.2' -v=2 -w=2 -e=[I,'/lib','/sd/lib','/flash/lib','lib'] +x=2 +y=2 +g=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): C=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') except H:pass A._report=[];A.info=_info();B.collect() if C:A._fwid=C.lower() - elif A.info[M]==X:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[N]==Z:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:f(path+G) - except F:K('error creating stub folder {}'.format(path)) + try:h(path+G) + except F:L('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in P(I): - if A.startswith(T)and not A in L.modules:continue + for A in Q(I): + if A.startswith(U)and not A in L.modules:continue try: E=getattr(I,A) - try:F=V(type(E)).split("'")[1] - except Q:F=C - if F in{n,o,p,q,Y,Z,a}:G=1 - elif F in{r,s}:G=2 + try:F=X(type(E)).split("'")[1] + except R:F=C + if F in{p,q,r,s,a,b,c}:G=1 + elif F in{t,u}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,V(E),V(type(E)),E,G)) + D.append((A,X(E),X(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) except MemoryError as K:sleep(1);reset() - D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) + D=n([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J + def add_modules(A,modules):A.modules=n(set(A.modules)|set(modules)) def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) @@ -88,90 +90,90 @@ def create_one_stub(C,module_name): D=module_name if D in C.problematic:return A if D in C.excluded:return A - H='{}/{}.py'.format(C.path,D.replace(I,G));B.collect();E=A + H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=A try:E=C.create_module_stub(D,H) except F:return A B.collect();return E - def create_module_stub(J,module_name,file_name=E): + def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:M=D.replace(I,T)+'.py';H=J.path+G+M - else:M=H.split(G)[-1] - if G in D:D=D.replace(G,I) - K=E - try:K=__import__(D,E,E,'*');U=B.mem_free() - except O:return A - f(H) - with R(H,'w')as L:P=W(J.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);L.write(Q);L.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(L,K,D,C) - J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) + if H is E:N=D.replace(J,U)+'.py';H=I.path+G+N + else:N=H.split(G)[-1] + if G in D:D=D.replace(G,J) + L=E + try:L=__import__(D,E,E,'*');R=B.mem_free() + except P:return A + h(H) + with S(H,'w')as M:O=Y(I.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,O,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,C) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: - try:del K - except(F,S):pass + try:del L + except(F,T):pass try:del sys.modules[D] - except S:pass - B.collect();return N - def write_object_stub(M,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() - if P in M.problematic:return - R,N=M.get_obj_attributes(P) - if N:K(N) - for(E,J,G,T,f)in R: + except T:pass + B.collect();return K + def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): + d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() + if P in K.problematic:return + R,N=K.get_obj_attributes(P) + if N:L(N) + for(E,J,G,S,f)in R: if E in['classmethod','staticmethod','BaseException',O]:continue if E[0].isdigit():continue - if G==""and L(D)<=w*4: + if G==""and M(D)<=y*4: U=C;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return - H.write(A);M.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[s,r,'closure']): - W=b;X=C + H.write(A);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) + elif any(A in G for A in[u,t,'closure']): + W=Y;X=C if Q>0:X='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) + if Z in G or Z in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=C - if A[D]==C and sys.platform not in(k,j): - try:o=os.uname();A[D]=o.release - except(Q,H,TypeError):pass - for(p,q,r)in[(l,l,'const'),(m,m,'FAT'),(n,'pybricks.hubs','EV3Brick')]: - try:s=__import__(q,E,E,r);A[M]=p;del s;break - except(O,S):pass - if A[M]==n:A['release']='2.0.0' - if A[M]==X: + A[F]=W(os.uname()[3]) + if not A[F]:A[F]=W(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=W(sys.version.split(';')[1]) + except(H,R):pass + if A[F]and M(A[F])>5:A[F]=C + if A[D]==C and sys.platform not in(c,b): + try:h=os.uname();A[D]=h.release + except(R,H,TypeError):pass + for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: + try:l=__import__(j,E,E,k);A[N]=i;del l;break + except(P,T):pass + if A[N]==g:A['release']='2.0.0' + if A[N]==Z: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - V=int(A[K]);a=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if a:A[f]=a - A[K]='v{}.{}'.format(V&255,V>>8&3) - A[b]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def g(info,board_descr,filename): - with R(filename,'r')as C: + L=int(A[K]);U=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][L>>10] + if U:A[a]=U + A[K]='v{}.{}'.format(L&255,L>>8&3) + A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def z(info,desc=C): + G='with ';D=info;E=A + for F in[A+'/board_info.csv'for A in g]: + if j(F): + C=desc or D[I].strip() + if i(D,C,F):E=K;break + if O in C: + C=C.split(O)[0].strip() + if i(D,C,F):E=K;break + if not E: + C=desc or D[I].strip() + if G+D[V].upper()in C:C=C.split(G+D[V].upper())[0].strip() + D[I]=C + D[I]=D[I].replace(' ',U);B.collect() +def i(info,board_descr,filename): + with S(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return N + if D==board_descr:info[I]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=I + except(F,H):A=J B=A - for B in[A,'/sd','/flash',G,I]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def h(filename): +def j(filename): try: - if os.stat(filename)[0]>>14:return N + if os.stat(filename)[0]>>14:return K return A except F:return A -def i():sys.exit(1) +def k():sys.exit(1) def read_path(): path=C - if L(sys.argv)==3: + if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:i() - elif L(sys.argv)==2:i() + else:k() + elif M(sys.argv)==2:k() return path -def j(): - try:B=bytes('abc',encoding='utf8');C=j.__module__;return A - except(k,H):return N +def l(): + try:B=bytes('abc',encoding='utf8');C=l.__module__;return A + except(m,H):return K def main(): E='/modulelist.txt';stubber=Stubber(path=read_path());stubber.clean();stubber.modules=[] - for C in e: + for C in g: try: F=B.mem_free() - with R(C+E)as D: - K('Debug: List of modules: '+C+E);A=D.readline() + with S(C+E)as D: + L('Debug: List of modules: '+C+E);A=D.readline() while A: A=A.strip() - if L(A)>0 and A[0]!='#':stubber.modules.append(A) + if M(A)>0 and A[0]!='#':stubber.modules.append(A) A=D.readline() - B.collect();K('Debug: Used memory to load modulelist.txt: '+W(F-B.mem_free())+' bytes');break + B.collect();L('Debug: Used memory to load modulelist.txt: '+Y(F-B.mem_free())+' bytes');break except Exception:pass - if not stubber.modules:stubber.modules=[X] + if not stubber.modules:stubber.modules=[Z] B.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or j(): - try:x=logging.getLogger(u);logging.basicConfig(level=logging.INFO) - except m:pass - if not h('no_auto_stubber.txt'): +if __name__=='__main__'or l(): + try:A0=logging.getLogger(w);logging.basicConfig(level=logging.INFO) + except o:pass + if not j('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_mem_mpy.mpy b/mip/v6/createstubs_mem_mpy.mpy index 221be26ddffbddd54d3826c558da8fe10998623f..32ba3d10d95c08775940a9637f1aec1520a946b0 100644 GIT binary patch delta 5408 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 d?WPddhOg|CeklVr^E(K{pN|4@D8M0__+P3R5 zbt)ZACL_)EEHkb7HzUoiv|6=Rm`5HYbO%CS-P1GD&W~<-n`!Nj*&ieAjyk*AAFI`B z&$V&7wY>>&&pr3lx#ygF?sv|;wSRqI_MvRXZdU&+`=G!Vp6weMzIdIi zpN)MXon@dV_wr=lBy%Hw4^B*8XGX+$e0XGhY+^DVpYP9pWv%|r#oAwTti$0@ z@YmsVI_ZD}C7n(MhnXV<Xsg1;n);Jiy;j8SN`0Waq&x?%<)z&q`(?ow$hyhvHhl$)p`Pwdnvq zB{M1;914~2W|ml2{cFb0#wc0u-;~^$kpxC%Vv$6_orAgcHFq0+%HJlA!P~h%;q@O^ zop1R`{@pysAX*~nq((Bg@Fs&lZmzSDksu#^foGIi|&A(F0-ADSrSwkl)$WU z@n(@PM@3N0nEy8Y`Fx_Cb)b`cP$5Qm$xp+do%#Mx_=rI{s|many=F#)d2Tks1% zOWBxNP)tCSi{z~`k$GA0fDFK^YEQ_8jWR<1dv_uj!g-e1Dw!u|XG=eUV zD!c5}HT%7uYP;JmHz!v;%u^4uCcvdRm5q1&iG8*xwhJ(fmWLP7PRm9x5O9U=vVvJM zx2ST@L!|-?38r*UMU%v4qC>f#h3Jd$R*do3*V=)YU|L_GsrLmqApm-CTmW1e5FjBy ze_hUoroqd=sr$mH0Nr&QPR*BrL-z@6NAlLoK;XTX^CDy~;x@R)cQ(8Cz@3E&8*V{u zc$g<&wet%i=-G0Ks4mVu^jmN-5_#py>kU_6{7S#px?i;y3J$=~3FS1O(~E3x;Fr?^ zoc1yEDofxkAFG<|(>IB*;N}vXncH3nM?p3s7{_>ru#z;QVmpC|pA9x7y<(s?afUC1 zV`ialL}uTMCQO%`Km{hI#W;q#1qjmMQTu~QmHk(h#WTUvFkSByK`u-iU9QZAR4(38 zure!x9nU!yXpAI&RC&4r?55SU89mjtwRWYcCb>F?k|h`;0j3j_E=$oTrV|7zMHLzB zoY*D6jZ{kcxi=o6{9330)mP2U`?)oGP&B#lpimJWRK}2n#4pbLir)iO@UCey%Z&KU zU4EO+{88&&*wj1h=Ll54en$7Ask-?3X#lTHGu@HZqt9?$*w7B9#C5a;cN0wJd8k}4 z$pTXNLqJxo&oh@Loizxs-x}k^LqW?%<_Rb&cR)Y%Qh>9#VG(9qmn>m&rEiXdfYZ;t zl1oK(0hhNv6wF+|^^*r8)GT2X=_uQfK)+oN?&0oMzcm&))r+!QFumk5{BE9J!5!3k z4*#>U1yV|E1l&Zbvu^xB8x2`qdUlx5cnNU9&1DKffndW!Tj)I5okErioBT{51(-~H zsD0$P04|s^x0&VUcJnQ>!WiH0_P84w>zeKEn!4R~d-Wcd+pc*1?%I00$KIGcG>1a?01SWzfYp%6@6Xz(*Q;T`32`MUPEAi&jSnw-je|M8{v0bq2TqC&(|kNj+F z86^n#kStONfkpxXGnSoj}?JHv#8E1#LuDhu9+gSOizmjJ~ai?u9R0YXj8W^N?^Cga+)HH_NDQ_ zSxW7*Jv6@1S_$lN+U`5bH-c^V6@EkOk?m-TpOx_nP>V|ame)=xa73<3&uz%DqK(wP zy(#-LHU&NhN4YLnuWP};XGqfP{R4!(zd`!WG(xtsjBYC_Whn?tV_6S@eFWb2WN&DZ zd+8l`rHt+n_-BJk_NQQO0E4AnthEr>kF0(IEy%{<9RUXVo!d6Q+@_QrjBb8CsFV>1 z5C{^`@Z&#d!3WMVSx#?J<|tQqe-;M!jq$ydloe5RApBym>2&5&No6I?Q~^%8@rI|m zmPmqyGpj8GIzdJ}yE&6Ak+6xVH2!)=1HCsZ1X@?;;vHL_CdICKiu~M4pdp#~aqivX z3gFBvV2uxI{S6LxbYBuL@E^5S{ES@*6=SV!pn!!Vv>~w?7ScE6CcP=Gc>V}3sJZQ_ z08y-A6nsJjR9ZibK#wHugs4qL>p z>m~%oU7lSj-PEF_pIgmbkx&OB$Xpsh>Yt+W_IautCf87MOI+{ZpCL0mzqsJHAbWZ( zP>1slDwKu@l0m3{e;zJQThf7o*JWqA4pWE@7eTw3@kF<5~Nj#bTck70kSK zL`*8tNaGl;PD`A4-cD%XIK26(F6Q1~WTw?tr8hyhu_V`ciGO7_sNq#hBxg6Y@T}OJ z1V3j)pO9UfbFzze7zrx!Ncnl?&~D>nyWL*ntFO1qGExm*m&fJV>Gba0vA5c*+8y5J zX1~u~WtSVg9{a9ZyL(5IYjWaVhkuADfeR>HI$Zvqb;g!-M;5`4Mdr!nErn z9m|ip1E-L)u#U5XbaohL{a%>*7-9LjLAOk8Bh*28(JqWB7vQ0H;qN=qwo8*{8*1_7@w=CPi1d^p|#Nnpn8lyrm}Tin?x<4 zd29v|i-%HRhv9be3SZolJ|u(%7^C4bx4r?}xjAy&ZAm6c%x#&Kt>lE;;=$%_?@o(T za27kokR3ZArI@xty2&7VTd|}H=st8UEWIeSLDK^{2=%lDzCAu5Tr&Qxwz0aQ*%iveber%qPr@R_FFap* z7ifEW;|Z3b*_ByxnM@)~BEypv@2Fe}ZNV>SAzW?ggm6(B_1a=B3QNmYMKW=#vWZNg z>Hk^XP>-)C6rM#J_2^H(p}qWMBGrcf-=;j0xJI(C82=^M#H)~k?%Ot-aLxE{rOxB6 zQ87iIVD@5;URT*$>slYB&{cfFV%)Mew06ocqfhYJc?F+70el#2N}GsB$kUP8GMl)y zQ_H>azI89fqPNKp$xSkiuc0Txjba@S2j2%61~~JbFig^_9!dO_?T(-T^M1}gm%PK{ zt9HJque;PM?Vwo3!j=5bss` zF;5lcVrtF5sp2a8nm`U!+|p&@xrYmy(6749{vz<_X{s)W58pu#n>IDA3GL5C`*Fy_ HA(HrCA%yAc diff --git a/mip/v6/createstubs_min.py b/mip/v6/createstubs_min.py index a74db7725..75a060686 100644 --- a/mip/v6/createstubs_min.py +++ b/mip/v6/createstubs_min.py @@ -1,36 +1,38 @@ -w='pyb' -v='stubber' -u='{}/{}' -t='logging' -s='sys' -r='method' -q='function' -p='bool' -o='str' -n='float' -m='int' -l=NameError -k=sorted -j=NotImplementedError -b='pycom' -a=',\n' -Z='dict' -Y='list' -X='tuple' -W='micropython' -V=open -U=repr -S='_' -R=len -Q=KeyError -P=IndexError -O=dir -M=print +y='pyb' +x='stubber' +w='{}/{}' +v='logging' +u='sys' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n=NameError +m=sorted +l=NotImplementedError +d='pycom' +c=',\n' +b='dict' +a='list' +Z='tuple' +Y='micropython' +X=open +W=repr +U='cpu' +T='_' +S=len +R=KeyError +Q=IndexError +P=dir +O=print N=ImportError -K=True +M='with' L='family' -J='board' -I='.' +K=True +J='.' +I='board' H=AttributeError A=False G='/' @@ -39,51 +41,51 @@ D='version' B='' import gc as C,os,sys -from ujson import dumps as c +from ujson import dumps as e try:from machine import reset except N:pass -try:from collections import OrderedDict as d -except N:from ucollections import OrderedDict as d +try:from collections import OrderedDict as f +except N:from ucollections import OrderedDict as f __version__='v1.16.2' -x=2 -y=2 -z=[I,'/lib','/sd/lib','/flash/lib','lib'] +z=2 +A0=2 +A1=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise l('MicroPython 1.13.0 cannot be stubbed') except H:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[L]==W:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==Y:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:e(path+G) - except F:M('error creating stub folder {}'.format(path)) + try:g(path+G) + except F:O('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in O(I): - if A.startswith(S)and not A in L.modules:continue + for A in P(I): + if A.startswith(T)and not A in L.modules:continue try: E=getattr(I,A) - try:F=U(type(E)).split("'")[1] - except P:F=B - if F in{m,n,o,p,X,Y,Z}:G=1 - elif F in{q,r}:G=2 + try:F=W(type(E)).split("'")[1] + except Q:F=B + if F in{o,p,q,r,Z,a,b}:G=1 + elif F in{s,t}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,U(E),U(type(E)),E,G)) + D.append((A,W(E),W(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) except MemoryError as K:sleep(1);reset() - D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J - def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) + D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) def create_all_stubs(A): C.collect() for B in A.modules:A.create_one_stub(B) @@ -91,90 +93,90 @@ def create_one_stub(B,module_name): D=module_name if D in B.problematic:return A if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(I,G));C.collect();E=A + H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A try:E=B.create_module_stub(D,H) except F:return A C.collect();return E - def create_module_stub(J,module_name,file_name=E): + def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:O=D.replace(I,S)+'.py';H=J.path+G+O + if H is E:O=D.replace(J,T)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,I) + if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');T=C.mem_free() + try:L=__import__(D,E,E,'*');S=C.mem_free() except N:return A - e(H) - with V(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) - J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os',s,t,'gc'}: + g(H) + with X(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) + if D not in{'os',u,v,'gc'}: try:del L - except(F,Q):pass + except(F,R):pass try:del sys.modules[D] - except Q:pass + except R:pass C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;N='Exception';H=fp;D=indent;C.collect() - if O in K.problematic:return - S,L=K.get_obj_attributes(O) - if L:M(L) - for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',N]:continue + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;D=indent;C.collect() + if N in K.problematic:return + Q,L=K.get_obj_attributes(N) + if L:O(L) + for(E,J,G,T,f)in Q: + if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and R(D)<=y*4: - U=B;V=E.endswith(N)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=N + if G==""and S(D)<=A0*4: + U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): - W=b;a=B - if P>0:a='self, ' + elif any(A in G for A in[t,s,'closure']): + W=Y;X=B + if P>0:X='self, ' if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(j,i): - try:m=os.uname();A[D]=m.release - except(P,H,TypeError):pass - for(n,o,p)in[(k,k,'const'),(b,b,'FAT'),(l,'pybricks.hubs','EV3Brick')]: - try:q=__import__(o,E,E,p);A[L]=n;del q;break - except(N,Q):pass - if A[L]==l:A['release']='2.0.0' - if A[L]==W: + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=V(sys.version.split(';')[1]) + except(H,Q):pass + if A[F]and S(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(b,a): + try:g=os.uname();A[D]=g.release + except(Q,H,TypeError):pass + for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(e,'pybricks.hubs','EV3Brick')]: + try:k=__import__(i,E,E,j);A[L]=h;del k;break + except(N,R):pass + if A[L]==e:A['release']='2.0.0' + if A[L]==Y: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - V=int(A[K]);Z=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if Z:A[e]=Z - A[K]='v{}.{}'.format(V&255,V>>8&3) - A[a]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def f(info,board_descr,filename): - with V(filename,'r')as C: + O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] + if W:A[Z]=W + A[K]='v{}.{}'.format(O&255,O>>8&3) + A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def A2(info,desc=B): + G='with ';D=info;E=A + for F in[A+'/board_info.csv'for A in A1]: + if i(F): + B=desc or D[I].strip() + if h(D,B,F):E=K;break + if M in B: + B=B.split(M)[0].strip() + if h(D,B,F):E=K;break + if not E: + B=desc or D[I].strip() + if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() + D[I]=B + D[I]=D[I].replace(' ',T);C.collect() +def h(info,board_descr,filename): + with X(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return K + if D==board_descr:info[I]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=I + except(F,H):A=J B=A - for B in[A,'/sd','/flash',G,I]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def g(filename): +def i(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def h():sys.exit(1) +def j():sys.exit(1) def read_path(): path=B - if R(sys.argv)==3: + if S(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:h() - elif R(sys.argv)==2:h() + else:j() + elif S(sys.argv)==2:j() return path -def i(): - try:B=bytes('abc',encoding='utf8');C=i.__module__;return A - except(j,H):return K -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',W,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,b,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or i(): - try:A0=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except l:pass - if not g('no_auto_stubber.txt'): +def k(): + try:B=bytes('abc',encoding='utf8');C=k.__module__;return A + except(l,H):return K +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',y,d,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or k(): + try:A3=logging.getLogger(x);logging.basicConfig(level=logging.INFO) + except n:pass + if not i('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_mpy.mpy b/mip/v6/createstubs_mpy.mpy index 1794cec8e07c9371e6dfd3181f657f3a018efe2a..4d49f2263943663524cc05ffe483495afcfa5385 100644 GIT binary patch delta 5791 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 dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -466,9 +466,9 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -479,19 +479,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -569,6 +557,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/src/stubber/board/createstubs_db_min.py b/src/stubber/board/createstubs_db_min.py index 34ba0bee4..8f5a7e7f8 100644 --- a/src/stubber/board/createstubs_db_min.py +++ b/src/stubber/board/createstubs_db_min.py @@ -1,178 +1,180 @@ -v='stubber' -u='{}/{}' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n=NameError -m=sorted -l=MemoryError -k=NotImplementedError -b=',\n' -a='dict' -Z='list' -Y='tuple' -X='micropython' -W=str -V=repr -T='_' -S=KeyError -R=IndexError -Q=dir -P=ImportError +x='stubber' +w='{}/{}' +v='method' +u='function' +t='bool' +s='str' +r='float' +q='int' +p=NameError +o=sorted +n=MemoryError +m=NotImplementedError +d=',\n' +c='dict' +b='list' +a='tuple' +Z='micropython' +Y=str +X=repr +V='cpu' +U='_' +T=KeyError +S=IndexError +R=dir +Q=ImportError +P='with' O='family' N=print -M=True -L=len +M=len +L='.' K='board' -J='.' +J=True I=open H=AttributeError G='/' -F=False -E=None -D='version' +F=None +E='version' +D=False A=OSError C='' import gc as B,os,sys -from ujson import dumps as c +from ujson import dumps as e try:from machine import reset -except P:pass -try:from collections import OrderedDict as d -except P:from ucollections import OrderedDict as d +except Q:pass +try:from collections import OrderedDict as f +except Q:from ucollections import OrderedDict as f __version__='v1.16.2' -w=2 -x=2 -e=[J,'/lib','/sd/lib','/flash/lib','lib'] +y=2 +z=2 +g=[L,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: - def __init__(C,path=E,firmware_id=E): + def __init__(C,path=F,firmware_id=F): D=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') except H:pass C._report=[];C.info=_info();B.collect() if D:C._fwid=D.lower() - elif C.info[O]==X:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) + elif C.info[O]==Z:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) else:C._fwid='{family}-{ver}-{port}'.format(**C.info) C._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) - try:f(path+G) + try:h(path+G) except A:N('error creating stub folder {}'.format(path)) C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in Q(I): - if A.startswith(T)and not A in L.modules:continue + for A in R(I): + if A.startswith(U)and not A in L.modules:continue try: E=getattr(I,A) - try:F=V(type(E)).split("'")[1] - except R:F=C - if F in{o,p,q,r,Y,Z,a}:G=1 - elif F in{s,t}:G=2 + try:F=X(type(E)).split("'")[1] + except S:F=C + if F in{q,r,s,t,a,b,c}:G=1 + elif F in{u,v}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,V(E),V(type(E)),E,G)) + D.append((A,X(E),X(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) - except l as K:sleep(1);reset() - D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) + except n as K:sleep(1);reset() + D=o([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J + def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) def create_one_stub(C,module_name): - D=module_name - if D in C.problematic:return F - if D in C.excluded:return F - H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=F - try:E=C.create_module_stub(D,H) - except A:return F - B.collect();return E - def create_module_stub(K,module_name,file_name=E): - H=file_name;D=module_name - if H is E:O=D.replace(J,T)+'.py';H=K.path+G+O + E=module_name + if E in C.problematic:return D + if E in C.excluded:return D + H='{}/{}.py'.format(C.path,E.replace(L,G));B.collect();F=D + try:F=C.create_module_stub(E,H) + except A:return D + B.collect();return F + def create_module_stub(K,module_name,file_name=F): + H=file_name;E=module_name + if H is F:O=E.replace(L,U)+'.py';H=K.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,J) - L=E - try:L=__import__(D,E,E,'*');U=B.mem_free() - except P:return F - f(H) - with I(H,'w')as N:Q=W(K.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,K._fwid,Q,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,L,D,C) - K._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: - try:del L - except(A,S):pass - try:del sys.modules[D] - except S:pass - B.collect();return M + if G in E:E=E.replace(G,L) + M=F + try:M=__import__(E,F,F,'*');S=B.mem_free() + except Q:return D + h(H) + with I(H,'w')as N:P=Y(K.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(E,K._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,M,E,C) + K._report.append('{{"module": "{}", "file": "{}"}}'.format(E,H.replace('\\',G))) + if E not in{'os','sys','logging','gc'}: + try:del M + except(A,T):pass + try:del sys.modules[E] + except T:pass + B.collect();return J def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() + d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() if P in K.problematic:return - R,M=K.get_obj_attributes(P) - if M:N(M) - for(F,J,G,T,f)in R: + R,L=K.get_obj_attributes(P) + if L:N(L) + for(F,J,G,S,f)in R: if F in['classmethod','staticmethod','BaseException',O]:continue if F[0].isdigit():continue - if G==""and L(E)<=x*4: + if G==""and M(E)<=z*4: U=C;V=F.endswith(O)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O D='\n{}class {}({}):\n'.format(E,F,U) if V:D+=E+' ...\n';H.write(D);return - H.write(D);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) - elif any(A in G for A in[t,s,'closure']): - W=b;X=C + H.write(D);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) + elif any(A in G for A in[v,u,'closure']): + W=Y;X=C if Q>0:X='self, ' - if c in G or c in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) + if Z in G or Z in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,X,W) D+=E+' ...\n\n';H.write(D) elif G=="":0 elif G.startswith("5:A[F]=C - if A[D]==C and sys.platform not in(k,j): - try:o=os.uname();A[D]=o.release - except(R,H,TypeError):pass - for(p,q,r)in[(l,l,'const'),(m,m,'FAT'),(n,'pybricks.hubs','EV3Brick')]: - try:s=__import__(q,E,E,r);A[O]=p;del s;break - except(P,S):pass - if A[O]==n:A['release']='2.0.0' - if A[O]==X: - if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] + A[D]=W(os.uname()[3]) + if not A[D]:A[D]=W(os.uname()[2]) + if not A[D]and';'in sys.version:A[D]=W(sys.version.split(';')[1]) + except(H,S):pass + if A[D]and M(A[D])>5:A[D]=C + if A[E]==C and sys.platform not in(c,b): + try:h=os.uname();A[E]=h.release + except(S,H,TypeError):pass + for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: + try:l=__import__(j,F,F,k);A[O]=i;del l;break + except(Q,T):pass + if A[O]==g:A['release']='2.0.0' + if A[O]==Z: + if A[E]and A[E].endswith('.0')and A[E]>='1.10.0'and A[E]<='1.19.9':A[E]=A[E][:-2] if I in A and A[I]: - V=int(A[I]);a=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if a:A[f]=a - A[I]='v{}.{}'.format(V&255,V>>8&3) - A[b]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def g(info,board_descr,filename): + J=int(A[I]);U=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][J>>10] + if U:A[a]=U + A[I]='v{}.{}'.format(J&255,J>>8&3) + A[X]=f"v{A[E]}-{A[D]}"if A[D]else f"v{A[E]}";return A +def A0(info,desc=C): + G='with ';C=info;E=D + for F in[A+'/board_info.csv'for A in g]: + if j(F): + A=desc or C[K].strip() + if i(C,A,F):E=J;break + if P in A: + A=A.split(P)[0].strip() + if i(C,A,F):E=J;break + if not E: + A=desc or C[K].strip() + if G+C[V].upper()in A:A=A.split(G+C[V].upper())[0].strip() + C[K]=A + C[K]=C[K].replace(' ',U);B.collect() +def i(info,board_descr,filename): with I(filename,'r')as B: while 1: A=B.readline() if not A:break - C,D=A.split(',')[0].strip(),A.split(',')[1].strip() - if C==board_descr:info[K]=D;return M - return F + C,E=A.split(',')[0].strip(),A.split(',')[1].strip() + if C==board_descr:info[K]=E;return J + return D def get_root(): try:B=os.getcwd() - except(A,H):B=J + except(A,H):B=L C=B - for C in[B,'/sd','/flash',G,J]: + for C in[B,'/sd','/flash',G,L]: try:D=os.stat(C);break except A:continue return C -def h(filename): +def j(filename): try: - if os.stat(filename)[0]>>14:return M - return F - except A:return F -def i():sys.exit(1) + if os.stat(filename)[0]>>14:return J + return D + except A:return D +def k():sys.exit(1) def read_path(): path=C - if L(sys.argv)==3: + if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:i() - elif L(sys.argv)==2:i() + else:k() + elif M(sys.argv)==2:k() return path -def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return F - except(k,H):return M +def l(): + try:A=bytes('abc',encoding='utf8');B=l.__module__;return D + except(m,H):return J def main(): - K='failed';G='modulelist.done';import machine as O - try:C=I(G,'r+b');N=M - except A:C=I(G,'w+b');N=F + L='failed';G='modulelist.done';import machine as O + try:C=I(G,'r+b');N=J + except A:C=I(G,'w+b');N=D stubber=Stubber(path=read_path()) if not N:stubber.clean() - y(stubber);D={} + A1(stubber);E={} try: with I(G)as C: - for E in C.read().split('\n'): - E=E.strip();B.collect() - if L(E)>0:P,Q=E.split('=',1);D[P]=Q + for F in C.read().split('\n'): + F=F.strip();B.collect() + if M(F)>0:P,Q=F.split('=',1);E[P]=Q except(A,SyntaxError):pass - B.collect();R=[A for A in stubber.modules if A not in D.keys()];B.collect() + B.collect();R=[A for A in stubber.modules if A not in E.keys()];B.collect() for H in R: - J=F - try:J=stubber.create_one_stub(H) - except l:O.reset() - B.collect();D[H]=W(stubber._report[-1]if J else K) - with I(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if J else K)) - if D:stubber._report=[A for(B,A)in D.items()if A!=K];stubber.report() -def y(stubber): + K=D + try:K=stubber.create_one_stub(H) + except n:O.reset() + B.collect();E[H]=Y(stubber._report[-1]if K else L) + with I(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if K else L)) + if E:stubber._report=[A for(B,A)in E.items()if A!=L];stubber.report() +def A1(stubber): E='/modulelist.txt';stubber.modules=[] - for D in e: + for D in g: try: with I(D+E)as F: N('DEBUG: list of modules: '+D+E) for C in F.read().split('\n'): C=C.strip() - if L(C)>0 and C[0]!='#':stubber.modules.append(C) + if M(C)>0 and C[0]!='#':stubber.modules.append(C) B.collect();break except A:pass - if not stubber.modules:stubber.modules=[X];_log.warn('Could not find modulelist.txt, using default modules') + if not stubber.modules:stubber.modules=[Z];_log.warn('Could not find modulelist.txt, using default modules') B.collect() -if __name__=='__main__'or j(): - try:z=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except n:pass - if not h('no_auto_stubber.txt'): +if __name__=='__main__'or l(): + try:A2=logging.getLogger(x);logging.basicConfig(level=logging.INFO) + except p:pass + if not j('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_db_mpy.mpy b/src/stubber/board/createstubs_db_mpy.mpy index 417ae41e091c4a913e5a2698ddb3850acb8cba45..64d1e8e29bbbf14df647538108ee5fa73855aeb0 100644 GIT binary patch delta 5749 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 JuI-D&{}&58bMXKG delta 5560 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 diff --git a/src/stubber/board/createstubs_lvgl.py b/src/stubber/board/createstubs_lvgl.py index 68f8a5e7e..4f881cc48 100644 --- a/src/stubber/board/createstubs_lvgl.py +++ b/src/stubber/board/createstubs_lvgl.py @@ -433,7 +433,7 @@ def _info(): # type:() -> dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -451,9 +451,9 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -464,19 +464,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -554,6 +542,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/src/stubber/board/createstubs_lvgl_min.py b/src/stubber/board/createstubs_lvgl_min.py index 69b505b09..9ccf49b17 100644 --- a/src/stubber/board/createstubs_lvgl_min.py +++ b/src/stubber/board/createstubs_lvgl_min.py @@ -1,33 +1,35 @@ -t='stubber' -s='{}/{}' -r='method' -q='function' -p='bool' -o='str' -n='float' -m='int' -l='micropython' -k=Exception -j=NameError -i=sorted -h=NotImplementedError -Z=',\n' -Y='dict' -X='list' -W='tuple' -V=open -U=repr -S='_' -R=len -Q=KeyError -P=IndexError -O=dir -M=print +v='stubber' +u='{}/{}' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n='micropython' +m=Exception +l=NameError +k=sorted +j=NotImplementedError +b=',\n' +a='dict' +Z='list' +Y='tuple' +X=open +W=repr +U='cpu' +T='_' +S=len +R=KeyError +Q=IndexError +P=dir +O=print N=ImportError -K=True +M='with' L='family' -J='board' -I='.' +K=True +J='.' +I='board' H=AttributeError A=False G='/' @@ -36,51 +38,51 @@ F=OSError B='' import gc as C,os,sys -from ujson import dumps as a +from ujson import dumps as c try:from machine import reset except N:pass -try:from collections import OrderedDict as b -except N:from ucollections import OrderedDict as b +try:from collections import OrderedDict as d +except N:from ucollections import OrderedDict as d __version__='v1.16.2' -u=2 -v=2 -w=[I,'/lib','/sd/lib','/flash/lib','lib'] +w=2 +x=2 +y=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise h('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') except H:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[L]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==n:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:c(path+G) - except F:M('error creating stub folder {}'.format(path)) + try:e(path+G) + except F:O('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in O(I): - if A.startswith(S)and not A in L.modules:continue + for A in P(I): + if A.startswith(T)and not A in L.modules:continue try: E=getattr(I,A) - try:F=U(type(E)).split("'")[1] - except P:F=B - if F in{m,n,o,p,W,X,Y}:G=1 - elif F in{q,r}:G=2 + try:F=W(type(E)).split("'")[1] + except Q:F=B + if F in{o,p,q,r,Y,Z,a}:G=1 + elif F in{s,t}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,U(E),U(type(E)),E,G)) + D.append((A,W(E),W(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) except MemoryError as K:sleep(1);reset() - D=i([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J - def add_modules(A,modules):A.modules=i(set(A.modules)|set(modules)) + D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) def create_all_stubs(A): C.collect() for B in A.modules:A.create_one_stub(B) @@ -88,90 +90,90 @@ def create_one_stub(B,module_name): D=module_name if D in B.problematic:return A if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(I,G));C.collect();E=A + H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A try:E=B.create_module_stub(D,H) except F:return A C.collect();return E - def create_module_stub(J,module_name,file_name=E): + def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:O=D.replace(I,S)+'.py';H=J.path+G+O + if H is E:O=D.replace(J,T)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,I) + if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');T=C.mem_free() + try:L=__import__(D,E,E,'*');S=C.mem_free() except N:return A - c(H) - with V(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) - J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) + e(H) + with X(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del L - except(F,Q):pass + except(F,R):pass try:del sys.modules[D] - except Q:pass + except R:pass C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;N='Exception';H=fp;D=indent;C.collect() - if O in K.problematic:return - S,L=K.get_obj_attributes(O) - if L:M(L) - for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',N]:continue + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;D=indent;C.collect() + if N in K.problematic:return + Q,L=K.get_obj_attributes(N) + if L:O(L) + for(E,J,G,T,f)in Q: + if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and R(D)<=v*4: - U=B;V=E.endswith(N)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=N + if G==""and S(D)<=x*4: + U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): - Z=b;a=B - if P>0:a='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,Z) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,Z) + elif any(A in G for A in[t,s,'closure']): + W=b;X=B + if P>0:X='self, ' + if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(h,g): - try:m=os.uname();A[D]=m.release - except(P,H,TypeError):pass - for(n,o,p)in[(i,i,'const'),(j,j,'FAT'),(k,'pybricks.hubs','EV3Brick')]: - try:q=__import__(o,E,E,p);A[L]=n;del q;break - except(N,Q):pass - if A[L]==k:A['release']='2.0.0' - if A[L]==l: + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=V(sys.version.split(';')[1]) + except(H,Q):pass + if A[F]and S(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(a,Z): + try:f=os.uname();A[D]=f.release + except(Q,H,TypeError):pass + for(g,h,i)in[(b,b,'const'),(c,c,'FAT'),(e,'pybricks.hubs','EV3Brick')]: + try:j=__import__(h,E,E,i);A[L]=g;del j;break + except(N,R):pass + if A[L]==e:A['release']='2.0.0' + if A[L]==n: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - V=int(A[K]);Y=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if Y:A[c]=Y - A[K]='v{}.{}'.format(V&255,V>>8&3) - A[Z]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def d(info,board_descr,filename): - with V(filename,'r')as C: + O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] + if W:A[Y]=W + A[K]='v{}.{}'.format(O&255,O>>8&3) + A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def z(info,desc=B): + G='with ';D=info;E=A + for F in[A+'/board_info.csv'for A in y]: + if g(F): + B=desc or D[I].strip() + if f(D,B,F):E=K;break + if M in B: + B=B.split(M)[0].strip() + if f(D,B,F):E=K;break + if not E: + B=desc or D[I].strip() + if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() + D[I]=B + D[I]=D[I].replace(' ',T);C.collect() +def f(info,board_descr,filename): + with X(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return K + if D==board_descr:info[I]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=I + except(F,H):A=J B=A - for B in[A,'/sd','/flash',G,I]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def e(filename): +def g(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def f():sys.exit(1) +def h():sys.exit(1) def read_path(): path=B - if R(sys.argv)==3: + if S(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:f() - elif R(sys.argv)==2:f() + else:h() + elif S(sys.argv)==2:h() return path -def g(): - try:B=bytes('abc',encoding='utf8');C=g.__module__;return A - except(h,H):return K +def i(): + try:B=bytes('abc',encoding='utf8');C=i.__module__;return A + except(j,H):return K def main(): D='lvgl' try:import lvgl as A - except k:return + except m:return B=D try:B='lvgl-{0}_{1}_{2}-{3}-{4}'.format(A.version_major(),A.version_minor(),A.version_patch(),A.version_info(),sys.platform) - except k:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) + except m:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) finally:stubber=Stubber(firmware_id=B) stubber.clean();stubber.modules=['io','lodepng','rtch',D];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or g(): - try:x=logging.getLogger(t);logging.basicConfig(level=logging.INFO) - except j:pass - if not e('no_auto_stubber.txt'): +if __name__=='__main__'or i(): + try:A0=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + except l:pass + if not g('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_lvgl_mpy.mpy b/src/stubber/board/createstubs_lvgl_mpy.mpy index b2bc3e029e3008b8eb9ca7c845b78bebf15f3beb..1d49c0c035c95c693f88724b781619116ae006a6 100644 GIT binary patch delta 5243 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 diff --git a/src/stubber/board/createstubs_mem.py b/src/stubber/board/createstubs_mem.py index f0dc3b37d..c22022161 100644 --- a/src/stubber/board/createstubs_mem.py +++ b/src/stubber/board/createstubs_mem.py @@ -439,7 +439,7 @@ def _info(): # type:() -> dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -457,9 +457,9 @@ def _info(): # type:() -> dict[str, str] except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -470,19 +470,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -560,6 +548,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/src/stubber/board/createstubs_mem_min.py b/src/stubber/board/createstubs_mem_min.py index 53bc8a3ae..b80e20c14 100644 --- a/src/stubber/board/createstubs_mem_min.py +++ b/src/stubber/board/createstubs_mem_min.py @@ -1,33 +1,35 @@ -u='stubber' -t='{}/{}' -s='method' -r='function' -q='bool' -p='str' -o='float' -n='int' -m=NameError -l=sorted -k=NotImplementedError -b=',\n' -a='dict' -Z='list' -Y='tuple' -X='micropython' -W=str -V=repr -T='_' -S=KeyError -R=open -Q=IndexError -P=dir -O=ImportError -N=True -M='family' -L=len -K=print -J='board' -I='.' +w='stubber' +v='{}/{}' +u='method' +t='function' +s='bool' +r='str' +q='float' +p='int' +o=NameError +n=sorted +m=NotImplementedError +d=',\n' +c='dict' +b='list' +a='tuple' +Z='micropython' +Y=str +X=repr +V='cpu' +U='_' +T=KeyError +S=open +R=IndexError +Q=dir +P=ImportError +O='with' +N='family' +M=len +L=print +K=True +J='.' +I='board' H=AttributeError A=False G='/' @@ -36,51 +38,51 @@ F=OSError C='' import gc as B,os,sys -from ujson import dumps as c +from ujson import dumps as e try:from machine import reset -except O:pass -try:from collections import OrderedDict as d -except O:from ucollections import OrderedDict as d +except P:pass +try:from collections import OrderedDict as f +except P:from ucollections import OrderedDict as f __version__='v1.16.2' -v=2 -w=2 -e=[I,'/lib','/sd/lib','/flash/lib','lib'] +x=2 +y=2 +g=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): C=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') except H:pass A._report=[];A.info=_info();B.collect() if C:A._fwid=C.lower() - elif A.info[M]==X:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[N]==Z:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:f(path+G) - except F:K('error creating stub folder {}'.format(path)) + try:h(path+G) + except F:L('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in P(I): - if A.startswith(T)and not A in L.modules:continue + for A in Q(I): + if A.startswith(U)and not A in L.modules:continue try: E=getattr(I,A) - try:F=V(type(E)).split("'")[1] - except Q:F=C - if F in{n,o,p,q,Y,Z,a}:G=1 - elif F in{r,s}:G=2 + try:F=X(type(E)).split("'")[1] + except R:F=C + if F in{p,q,r,s,a,b,c}:G=1 + elif F in{t,u}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,V(E),V(type(E)),E,G)) + D.append((A,X(E),X(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) except MemoryError as K:sleep(1);reset() - D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) + D=n([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J + def add_modules(A,modules):A.modules=n(set(A.modules)|set(modules)) def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) @@ -88,90 +90,90 @@ def create_one_stub(C,module_name): D=module_name if D in C.problematic:return A if D in C.excluded:return A - H='{}/{}.py'.format(C.path,D.replace(I,G));B.collect();E=A + H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=A try:E=C.create_module_stub(D,H) except F:return A B.collect();return E - def create_module_stub(J,module_name,file_name=E): + def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:M=D.replace(I,T)+'.py';H=J.path+G+M - else:M=H.split(G)[-1] - if G in D:D=D.replace(G,I) - K=E - try:K=__import__(D,E,E,'*');U=B.mem_free() - except O:return A - f(H) - with R(H,'w')as L:P=W(J.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);L.write(Q);L.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(L,K,D,C) - J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) + if H is E:N=D.replace(J,U)+'.py';H=I.path+G+N + else:N=H.split(G)[-1] + if G in D:D=D.replace(G,J) + L=E + try:L=__import__(D,E,E,'*');R=B.mem_free() + except P:return A + h(H) + with S(H,'w')as M:O=Y(I.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,O,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,C) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: - try:del K - except(F,S):pass + try:del L + except(F,T):pass try:del sys.modules[D] - except S:pass - B.collect();return N - def write_object_stub(M,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() - if P in M.problematic:return - R,N=M.get_obj_attributes(P) - if N:K(N) - for(E,J,G,T,f)in R: + except T:pass + B.collect();return K + def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): + d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() + if P in K.problematic:return + R,N=K.get_obj_attributes(P) + if N:L(N) + for(E,J,G,S,f)in R: if E in['classmethod','staticmethod','BaseException',O]:continue if E[0].isdigit():continue - if G==""and L(D)<=w*4: + if G==""and M(D)<=y*4: U=C;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return - H.write(A);M.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[s,r,'closure']): - W=b;X=C + H.write(A);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) + elif any(A in G for A in[u,t,'closure']): + W=Y;X=C if Q>0:X='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) + if Z in G or Z in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=C - if A[D]==C and sys.platform not in(k,j): - try:o=os.uname();A[D]=o.release - except(Q,H,TypeError):pass - for(p,q,r)in[(l,l,'const'),(m,m,'FAT'),(n,'pybricks.hubs','EV3Brick')]: - try:s=__import__(q,E,E,r);A[M]=p;del s;break - except(O,S):pass - if A[M]==n:A['release']='2.0.0' - if A[M]==X: + A[F]=W(os.uname()[3]) + if not A[F]:A[F]=W(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=W(sys.version.split(';')[1]) + except(H,R):pass + if A[F]and M(A[F])>5:A[F]=C + if A[D]==C and sys.platform not in(c,b): + try:h=os.uname();A[D]=h.release + except(R,H,TypeError):pass + for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: + try:l=__import__(j,E,E,k);A[N]=i;del l;break + except(P,T):pass + if A[N]==g:A['release']='2.0.0' + if A[N]==Z: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - V=int(A[K]);a=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if a:A[f]=a - A[K]='v{}.{}'.format(V&255,V>>8&3) - A[b]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def g(info,board_descr,filename): - with R(filename,'r')as C: + L=int(A[K]);U=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][L>>10] + if U:A[a]=U + A[K]='v{}.{}'.format(L&255,L>>8&3) + A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def z(info,desc=C): + G='with ';D=info;E=A + for F in[A+'/board_info.csv'for A in g]: + if j(F): + C=desc or D[I].strip() + if i(D,C,F):E=K;break + if O in C: + C=C.split(O)[0].strip() + if i(D,C,F):E=K;break + if not E: + C=desc or D[I].strip() + if G+D[V].upper()in C:C=C.split(G+D[V].upper())[0].strip() + D[I]=C + D[I]=D[I].replace(' ',U);B.collect() +def i(info,board_descr,filename): + with S(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return N + if D==board_descr:info[I]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=I + except(F,H):A=J B=A - for B in[A,'/sd','/flash',G,I]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def h(filename): +def j(filename): try: - if os.stat(filename)[0]>>14:return N + if os.stat(filename)[0]>>14:return K return A except F:return A -def i():sys.exit(1) +def k():sys.exit(1) def read_path(): path=C - if L(sys.argv)==3: + if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:i() - elif L(sys.argv)==2:i() + else:k() + elif M(sys.argv)==2:k() return path -def j(): - try:B=bytes('abc',encoding='utf8');C=j.__module__;return A - except(k,H):return N +def l(): + try:B=bytes('abc',encoding='utf8');C=l.__module__;return A + except(m,H):return K def main(): E='/modulelist.txt';stubber=Stubber(path=read_path());stubber.clean();stubber.modules=[] - for C in e: + for C in g: try: F=B.mem_free() - with R(C+E)as D: - K('Debug: List of modules: '+C+E);A=D.readline() + with S(C+E)as D: + L('Debug: List of modules: '+C+E);A=D.readline() while A: A=A.strip() - if L(A)>0 and A[0]!='#':stubber.modules.append(A) + if M(A)>0 and A[0]!='#':stubber.modules.append(A) A=D.readline() - B.collect();K('Debug: Used memory to load modulelist.txt: '+W(F-B.mem_free())+' bytes');break + B.collect();L('Debug: Used memory to load modulelist.txt: '+Y(F-B.mem_free())+' bytes');break except Exception:pass - if not stubber.modules:stubber.modules=[X] + if not stubber.modules:stubber.modules=[Z] B.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or j(): - try:x=logging.getLogger(u);logging.basicConfig(level=logging.INFO) - except m:pass - if not h('no_auto_stubber.txt'): +if __name__=='__main__'or l(): + try:A0=logging.getLogger(w);logging.basicConfig(level=logging.INFO) + except o:pass + if not j('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mem_mpy.mpy b/src/stubber/board/createstubs_mem_mpy.mpy index 6edd7f8c5aa97432c91fabe4da220cfc9adb97d6..5c07e7bb7c4a07f9f2ecaaa99c99dfb6743ad364 100644 GIT binary patch delta 5445 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 JkcUGg{@*zyBZB|{ delta 5227 zcmZ`dTTmO>mEA4z#`t#AG{Rs6bW4B)7KldJGq#6mHMS6bAcMfN!7>PJunpK4{20fm zPkUT(oT}_3WT*1CsmgBc*4ES(;^7B2Gv?vfOeU$?e9SOA>{LFoKU>+mXNI#m+*v*O`rymjc+;e>+!9=SL$JkCHh7oP5AJ*9bvTaLAyX!SFhedDnqCOvj}l1aZdIL>5V zAD$SR{*Y~${%2ORn3k+*k^2REe)=U>T{gsU!%XJjjo}GK7$58#h+giS7@{1`Ut=K3 zU6>=554bav3^&1WR~haK!(C>$F@_suPIDuSS>u0z=hC9V@5r#X-aNUfV z#&t1VC)2@oFfhWMU_xAofg-M*Im#VpxMK`=l!0#U2m{xr*>t5L#&83S6pf<7SBJ+& zqfv&t#&Cm-hr7WvlFQ>`mj}luZZaccG&($Td2D2%T$0u*#Q75q#e&nadrr$=%MV1VRFFv#P{b3B}vV2JFLV3>ys5?tirk_00> zj7l)Z!(|Ds@GvgH)e{oLCkT;Xl80*&T<7721UCsU!FxoI;1&npzv^ul#>b~ z6UCh-nb`($AhEN=Avq$QUWQbvoK)#$C6AYr8od^2pVumlc+;dS-gIfwn;~8EW=c1_ zS<)>pI+2O%603RW^s$neOBXKU#!r5Y&ty^t^lTZxPs)tS z`iBAqyqPA}R{Wgtu@MUH@oiDoZBqiHGLcX$=iZUbJ(c(Cf5hJ9Ra2UMRNv znEY-6IqQ0tkXnfZa=*|60-TkzRCW-zKXJPBNFsw~Yc!L)p%w?_oHDeu4&K9-^} zvml>~d3L#m%g`nKc2f%&Kg(?RV_+1+i6tVbnahfO=Xs{F+u3xX%h^!R&&{ zy$BQvFeI4L0~J*gn@AjreJq4u26v*5$G*`IM+DRQ5>Vg$-W6%p*L*eSrR zWJ>wCHx?oNS|A76m(R}mxV7MpRC2XoXr^Ml+iJ|m{<{5d__v@O-ZO1xkr7qw4tIlM z$1Y&E@84fn>1mW_R}*VBDxaqB!se=mSE-3=!N$YS@jJhv zA4$^3Q9INCIlKrI3nrOI2!9C3s`bV81$s#pq(ygIK@Wxrbsd=_ps3v8qpt)whtl#e z{W@hSj_H=VOAZ1~ANN`=6xDg$-}zWDGkw-iABj-8h<>GC*@ggmqUzBDlx_7{BcYyN zq}_oDCl}$lIeICpsqP&9Wh3*Xkk|;gh*WFc_>DdquvVo933Z?V7hN2dlz6f=?8eS$3>`uNpqK3Y?he2%~Ip?J1)1YzM;0s?y9WaXSY|p zRpqiP9-pgbkKJwWRqNgMa;3Id-t~fj`z3*zR|~IaKP6E6S>l)TpC`G;v3M<_378pL zD2BG}LSyT=U;X+M{V-OKPtbQCN8A41T9@V|PQJ3(DLC^LLSPR84}rQTZYv(tN)>_$ z4)s0;7rdibE?(FF4g|QqL{nIK|3AOdKLqrcQ&fo9^Tfxt6j6YH7o*&gM;SH{Pzf}; zEgQ}Pr9k&Taf)(@s4gi)5q%b?gt)LGEfMf-{>~{q#b_uJdN>q&1Jb}eRRjV}qB^G# zABV(yHy^{MFDI7ss{uXQp7g-_S!3QWAKjh)U3Y zYf#GmWQ80+2kMtKam&e1NyEo=3O z*u5L~^Gks<(||QTtnqmquJD0GvW~RiF?KnSkA1s7POBdRa0r2w?OS#`dCM?OdXe#= zRRO}-4rv_=ckS&nj|nouk}gVht&GMBDi1hzrgw%=;{e zom$gsaot8~Ql*7#*R?;s2>aJjUiX!r&btm-? zC#usvTXnnHp$BKgrUdvnBm9i)-CC2qbP|bCk|*L%%ZBzD zpV;m8O7EUMc3DQK-c#kSa@RRMb=7ZIcvQQ?)70ei+RN?b^&YoF9igjZxFSc_^+R*G zifhdQ8}?1{n3qY)6IHylODHYXYPQGPz(sN#r#MQYvKu)2Qr(Vg0dy~&k4t{_u^93( zOQ=xS$70iC>Zv5+VHY{^opUF&lZ#u(_@B7>H9uOgwAe-OCfvqxFLgKZQf=QBFJ@sj z9VAcuTA0M%qrWhy$fPJI5k|1iexh3RLlOL=jXqY$h91R6LiNG^g9?6!DBik|R9gEe zp5oL=!pX{##BR$C91CtMHdLeGdBdIxSIfD>#N^+oc~ zckNnw8V~E}pX|xJ4^aVKZ%h6GDyym^JIt&yK@xj z{Xn!{~d*j1oCThdc7zaKaqH*eOh(Yt#=Bw%7mWc5Y$TNAY;s53?b2<*F$x=Ov zL*m=3bK;nfS)0e#%ji4?`SNyxZ7ovSf9m;*g~YlZd@w`r1)b8g3@qDpFuvP9AY3v2 zqo$#vzR?-T!sHtFG0%b`Em9awn)!z#bfA5P{-0T%Ay>%+);vVG)1qx9%gOdsPdi!j zaf}!3KzgLviLt6k#O~mK$V{Tz|5Z_66DUC5^)pnzAAL)w`-vEppE|NN1BYTaNcuJ7 zzXh9k9g@}euFWRgFyjBC)Ve*DDrVv{Oj1n6n<{%}UGJk1nurhD<%FEJp|?_m8GeSZ z&};Y-((s+IMQvi)N#UAjVt0t1dFun~zJMgaLGnFvn@r)`=$UXUKaN45O2OGJ1y9;~*jPLG`aOu#?U1B=4l|GYZn%1dBEqy^#zs1ajtX02$P$T z_O;%Yz|ot&7|}5);srlmoz%OYa>~T~!DmZK%pX;DlRyUL+}vUI^d{%^+O6?G`}Zlz a%#SbNK{uOHG{pzC&qVF"and R(D)<=y*4: - U=B;V=E.endswith(N)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=N + if G==""and S(D)<=A0*4: + U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): - W=b;a=B - if P>0:a='self, ' + elif any(A in G for A in[t,s,'closure']): + W=Y;X=B + if P>0:X='self, ' if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(j,i): - try:m=os.uname();A[D]=m.release - except(P,H,TypeError):pass - for(n,o,p)in[(k,k,'const'),(b,b,'FAT'),(l,'pybricks.hubs','EV3Brick')]: - try:q=__import__(o,E,E,p);A[L]=n;del q;break - except(N,Q):pass - if A[L]==l:A['release']='2.0.0' - if A[L]==W: + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=V(sys.version.split(';')[1]) + except(H,Q):pass + if A[F]and S(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(b,a): + try:g=os.uname();A[D]=g.release + except(Q,H,TypeError):pass + for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(e,'pybricks.hubs','EV3Brick')]: + try:k=__import__(i,E,E,j);A[L]=h;del k;break + except(N,R):pass + if A[L]==e:A['release']='2.0.0' + if A[L]==Y: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - V=int(A[K]);Z=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if Z:A[e]=Z - A[K]='v{}.{}'.format(V&255,V>>8&3) - A[a]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def f(info,board_descr,filename): - with V(filename,'r')as C: + O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] + if W:A[Z]=W + A[K]='v{}.{}'.format(O&255,O>>8&3) + A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def A2(info,desc=B): + G='with ';D=info;E=A + for F in[A+'/board_info.csv'for A in A1]: + if i(F): + B=desc or D[I].strip() + if h(D,B,F):E=K;break + if M in B: + B=B.split(M)[0].strip() + if h(D,B,F):E=K;break + if not E: + B=desc or D[I].strip() + if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() + D[I]=B + D[I]=D[I].replace(' ',T);C.collect() +def h(info,board_descr,filename): + with X(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return K + if D==board_descr:info[I]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=I + except(F,H):A=J B=A - for B in[A,'/sd','/flash',G,I]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def g(filename): +def i(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def h():sys.exit(1) +def j():sys.exit(1) def read_path(): path=B - if R(sys.argv)==3: + if S(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:h() - elif R(sys.argv)==2:h() + else:j() + elif S(sys.argv)==2:j() return path -def i(): - try:B=bytes('abc',encoding='utf8');C=i.__module__;return A - except(j,H):return K -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',W,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,b,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or i(): - try:A0=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except l:pass - if not g('no_auto_stubber.txt'): +def k(): + try:B=bytes('abc',encoding='utf8');C=k.__module__;return A + except(l,H):return K +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',y,d,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or k(): + try:A3=logging.getLogger(x);logging.basicConfig(level=logging.INFO) + except n:pass + if not i('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mpy.mpy b/src/stubber/board/createstubs_mpy.mpy index 80672bb8cad3af11ee358e5ea5250d5a68369569..623b1f452b413ce98aa51e055e216d934364a86d 100644 GIT binary patch delta 5797 zcmZ`dSx{S9cJDoe%w}`m7Gec zpnLDR=br7J?dpE`QN(`8E;y{lAKK4svB$=)33A4b^H`O&OcQhdU1+ z={Y>{O58J1CjFUW+vgLqIOQ^d?PF<~(z%IcsoHj4kS6##26{IVIbXkzb1Zh+_A&m&ETpAYoq)UP{C`d6u8W5y@K{_r-QGpIiZwV}2>Jg-{ zAax70N9q!~q+>!z3JJ7OIx5f`(h=d1bXbrM3DQA9>YTWo<=i_YNM{7CuMY*ka(;BA zuTPL}3$}d?_}?hh+x9gHTVZT`bZlt+>Mdbd?dv-~JT^Lh74b3#hpxn?Kg$Ydwf$vD z&0k1jMe5_i!R>aZ7JS4-a*Z2qSA`29O|{!eb3=v8)ll=^-FI>ZTiz*sf78V2e9i2I zG>x4Co5t!OU1NP<*Vt*;ps{|)(AWTEYU7Zlu^41)Y!GrZHYBq%8apeqa~eA@vkMx# z2pcta2{vhL7;-f>0-&)`kTo_2ipDO>Y+PekWOh|!*C0=0*Fn|T4Vm54*e%&)w>5T0 zW^ZfkuFURf%#Mr*V~><#9|!HKA(#Hm?ow4)%kcQl#;yVk&BFH~q&KGQ4>|2NAhoEs{k z3aY*7npF@757O|Kcr;J6+b2McU(#xPqUQHW+74fuwnw&Pk12LF*|bZ(bnUXwu3htO z&~EuMwA;Q+?QLI{X8N)HhP;BGxXZ#{A>P)e+ zX}aZ%Z*w{w^+d08I2&t7Q$@4hFtrqPD_hi%F62dk<*gWzwN()?^%q7^VHe2>zc_@~ zt5{iUcJT_61uS3Lv% zNs|RMJ(#2T6S#Wq7rDYAH%QZFYm!1VTE9{zLRm}NOBy|@smoC!q z^N!peh24E+96*uf=P2nzg$*feP+>7;Tw!Ah8&%jy?S@supf3V^cR*pm{#pqE>_yKfb51^FCqPF9NIdiGC(7y}9`rj}((wMtcs6vf6kAE!Wqn zEF|J#wG-HJU2JVk)T@D-*l9V3onWWpk;!+$F;?XPR%K8z=7xVBa# z7N-!i6pexr5aV;_+8mfiZJx}d=~L>cVr@vekS>{TG(!C4U^bHXPEG65a>vG$H?`r_ zWXF2f#h8ix!O=gJcQCJ&VO3gH@j;iP!rSC>xGUTa$Ie}imGxW6)KX%3TCq0%gV8&a z;)R|e0jqial=J8AI{SJlfT6QXF}c5+;im|kSv3wO@pDi-lmIC_3!ddT)+t$!uMznSFB8-2Buyfa&5>wB09toquI( zNOyxdh{_FeT_7<$7Jk# z#{-{ZMW}NXmkAhZ{g_681-xme{G#a>jc?+Q+?%=71@rN*jW%Gd?t+IE#jCCRAG+jK zqla8Z`E-$tr^MW>ry-BP5ppH9E^uwuZAqrUjPG;(TZ%Tix?;2jzQ7sJ3~iVq{~YJ{ z?_qv-7oz{mc(jlwyj12J2eu#B0k3`42+gG!$gV=pAn=cIjyRG`ieqR&<5Eo;Ff3Rj zs7^bAap=ITIp8i@J6Yr^46hv?auotY0S*E?glE4pS|7O!$+g-Pi^7Uxm#n9M$KZip zZg6s4ZLTQRMZ5vNoak|sncSxpcGk1r`h;R4J-yfh>?EtjRLHs#U0t1-i&GWC>e*;u zD`vBXD6k@{KK@75jXdTSfE`|(>g(LNlu$>fdD)N_0*#5-{hROSl~TJU)AabC)admU zp73rgZkR{fc-~kD=3%AQO`iR5!j9l%aV^TMtW=bRV!cRs|B}M$u>SEp7R=_jM`!R* zhc}hdV$opUq)P1^#y3OBO-ij%9yLY>pq|F6N z=+fePa0RjaU71Ryp1LJ;(PPt`x@BMHiKDMmeu}WJ>Dd`QjVILQKrODjIZi6K6t3sB z|9IAsmy)Ct5k+znBNN5JWM9<*?3g8+mKy&lu<&96F9cWwN${Cs<<*GDOPd<-il=nmdegr4RP~tYNuN}k}Tg) zo=RfU1}Cs?ju=m*gnKIqfA1!JAeH*@R;OLW<8JKn>W=bw&%$EhzvGkYR?MSQ=m81y z?~Q+rC*mu3+wpK<|70kEN-PDl_@$$vmOBn6?NVnf#hU+qo?} z%2TF`K5NhA#*?tfZ*f+eJJ>+{Q&L$EI~OKfu`KueP@Z+i1o%Mc4Mg6vIexJj+tFhke*k0rCRBt6|Phjr? zv@F8DB?v4->r*hELECfK|H4!(wI&mj|AD+9Hi!dAJ$VC`{D{wI2XL$X;Q(|fRz`A@ zUFX9b|C+)3c{%?O+X{vC^41Uz&OeLM*Y0@QSg2imzIN1z17VBR(O? zvdC{@{LUlCWZ8Ms(*~IcN3n(DNPck@J6|r~(LfLl&b#CC&lJn19{CWfv}M!9WJjut z>M>nFS{adbxEW4?*!2i>{T8{dz*}>Q`I}6PKr5;?KNm@cZx;4|Z;Ir4Kq;5zc|Bii zw1fMV9VxM_uwR^i6q$b%ZauONW50%-gfOa6v}$zWCQh)|4C^LdY4X%>vqL(@F)Uy> z`o(v@HuiJ5kUUxoy-Qv(#*s?<)U-#!lzAp7r-bq$<4O*We$frQ!|H?6&<_I;gFzUAGjJBpd9z*c{sPvj7s>5-6fUUENmjVhr9dZOv&7dX=A!x8$UGK`;J#GD{36*f zXDujM*!NHMg|+E=SRK)Y*GQxXX?zEwi)*yzxB!uq6r+Go7A$8;(7Nx2V%Z{XS=0NUCqi!3 zyo_p=VNLmWZ<)Jdw?A1r#<6MLxiqa_(S_w1d_IlLpzmH?XS24TN%@aIeKwm|F*@cZ zIcwfE1~y~ic#{heRv4;_M*DqQt zMn9jSiuj^lNRaeZqn!g-_zAv)Z{y1>(ESFRVeU)8S|(#wgOOoA*t9!Xq_6`(1)w5O z37>0E6f=*eEu;iv7uO8Xb|}il#hUt)n_vH^A%of;fKmhaGI`rC_?hs8HwXB-2f6`h z2GC5PSwORa<`6qU&_Mh=-qe#uz_mc6KW@KW3N|ndHa(NUBm>xJTQuI_6^>pp)I?&rG(`X8nGtTTdicKWwcg?Mgmqvf|&AWC~2-2`19TB9MARQK@LjoO@1_hQaMFnX< zpogRb!hjSJB2vFV%ccDSy(;Y$_DcH%sZWsh2vS&(dWGFmNRW05QjZ{Y3ByviAWi>S zeqMV*kWLC}JdVy^IyXKRj|v#wVxZ z@wxBvqxr6nk2U0$D0M3fU?< z23C~~L5?~Oxhgvjc`A!TzRFHOfy#!#rm_(`OQ`Imot;wIX*)Zkva?XAvU51mnnkftQ4*?f=%}nxt774TLw06-t9Qo2;!tQq5~^{krm|W!HyE*SS!S|7mf_c? z`CJl+Y64SDJN}dHrUjhf0yot8vQ@J<2_95ZU+Gajv4egAya7q|`bE|6m((qOi@L*~ zrH=Wt)k(iqz2eVNuljS<>;63T9e=(`MZ2khZ>6)xZoCr^^p#|&(w?m}*x3;kYHSg_Lh!7Av&xT6uW}&jV_Gf}7#yHuctx0O@l2i-`u}Gre=E2-1 z?}vdO+i!sD)Q#K^?H|;f@AxqPR-WsW-82-HqVuY$+If_7z0yFdpt23P6IP8|VJ_SY zE5yw(H=h;?N#x|H%Dw&l@qph~q(M+@^M{P?3X?1PYHqS1H+;W8y(S+i|z+gomTpN`Evwx+B zWOkMu4Tz`kRAn=JZMQyQri{t*jsX7_%NUS@7?3%=Z%%nz<2)reIaADM#Hh^1R`daK zOlcpOF_4#RXBmkI8REPju(%>tl2)Lm^nsKzB%3*!sQ08IMw1j>3U zryl!+WuNdwW^d01#CYF#;?o7CPiB|U^Y8-tX;`A2QiNEK6xpXG@?o$utS>I*^+8jf(?lib{jiv+LH%o-j61j z#|zA5TA3}0S#w%uy*zl_|K3zU{EvW$XM(4}JiCinp=nJX@~j)=a`C=`r5S~}@tkA9 z)=1(dNvHtTduHb}=}EXSlU!YRP}T%yY32gVCw|)h=k{&PV@hU?S(_YjI$XY1rvuA@ z!?ArwOP$f&MrM~&Pv&GZ_n-Bl`HU^h6bV@UtEb#PPv3=C%R#(K+qf5^5q*l^`Bi;S zT0956Ll02FvrvU>md_)FzrehKtY_;N=s9-#NiWGcrF|Z!m3y)YTGnTG71neg!^*$pJQ5g)=DWAiv`x#3MUD-j ztjx3M07aeml(K@9JSj#UWc<; z^ENa&e2$?&i_cNxY^)#`p8+#ko&)p0Sa>=68L-yRQ$L^oVqN`x+yf>?Fp|K{RpV|q zOTYN#r+N>f$EO&(PvU)lowYgJ4Q_i~gl@wpBZ@I|D^5^`9%y1$IVXT^L9&P|+zJfAV7t$<>Mn7X z=$#MT3K>({A3DLQXco7Myr@%s2yDlz@7(Gl9*0xK5JwWPNq#bmP8rxvrG3r`nuNk{ zyt+qUY1y%d#29~tO4NsB;(x6Ve$Hgm|XL~ zy$e`}yX=muVzsmTj?=!XA0ls}dzwflGhUWz7PJuDPcCJ~WzJG9D{T_k?pNO#KX5wu z6~!1$t>~S>FOcHE5JbfM80nkuA=V^nMrV0+ZS^T9mV^+nUSMHd{H5M` z*IiC7XH1m4Dx7vL`-i>{@qm*nO1rB<6Y&K2aQc>`+TbZIvy)!STJ}Z~B0cfA16YiC z5ekz7seysMyvMUHVf9Qb*oJ7fIR>oMtWW;5zJ*`8C18DzXXAZ^%PA!~$E%366l_T) zZeF`pTtzLWjY`QsY0#Qo-sn!ObqFI}95$9h#aOok21h?6*d8PvuU#@TJ9Eh*i6Kr(Kp5lP$(p+~F; z5w;@vmu(2KTYOuLv~KQDN|PS1->ncwk{$y;5`M|EWl(tGJ^gd{C~yCb?zJ<-b_{*>o=`q zY}oWB|Gu$*t}~og_ge96T9A5bi&zBZlK+r#je8JDd~l6^BvtwGNK;PYb+;VyX^xuY zp{2*c-y~<0Rs_-MU)NOaz=OqLJPGf~?0q@;w0G-5aT``i)4rmQhVt>CG#;*SO-3U2 ztak%%dnBcOdZ4!6*usXA4@q4!Y+ah^#M);|q-Iw2@Qku8MKviIeFWRr#;~1tA_*>X zf9ema&+bS*b~qf))}|&0AxO0}dwd>mv#YVWetT_mz~O3cZ`b?|m!qbo+2`2O;PBSB z5z8akxdd-KhF#0h@dS1oPa*gWI-i670=iy8_h-=axomD|$V0>r758G7ID!V#fj4ar zIDKaXr^5F~u*67we4GEd$Nwzgnf!e5J~k3E^YPvg_AK5X3?4()+zO8N^3gsV!M+u} zdzOznj1cyS7G=L*NE<8*;FVoObLm3!x~UCafPU=ZxJW=;#m<*I*B=aFaCvv^_~M~* zKofACH26^2c9+K~&A2@X1HZR!Ab9xRYo@WTtt;4xTUfj|n7*0W*zCP7f9rR}k2#2C zIo`MD7xI-)5P=^hxyiJtU&>>PpMDas=-n~=37)_E>8gJ0)3h&GdCM`<|xwaL33bll1=e!aE?%6beVW8dk@GCydg$DU$ zXV>xBA)95d5jB;9nAak+bNCBKyp|b~1xLLWpC#V6b+g57=fyd+NjA%!a;7zM78`*q zthsj7DGqv+jseP>qaXGj!E8PkoxzNOV~cQ@`?&UUxyn6>>J#Y?7VG1fbBXi-;{T+_ zGSrE0^!;fn!Ydc22JbDd>R%)m??v_JNkhgn#~8Rvc&9cDBancTa0*Vt88{2);JmNE zS#s<9C@++Hms4F_7zAvkoF%o?_?5Hd=J)2WGzqhYN3L|?;mJI{W5(w3*x%H|Ov0@VGB@GK(`O5*6+L`=hTjq1uLW}u zz-800CT{eflqZwlH?-Eaw7Elhm~WRf;Za!Oc!dYduK|DcSRNsq&n(Tr6kJC1LxwLq z-dDMlE>rnI!>G4{m$2#0tiE2{`6aSy)3cCGkeAI?YP<3F2`}gDTd7CdFmZAO3 znzeQ~lDG!etI6NUR^=K^1M!WrGWmM)znzV~=DGmp<|E8oOwP9gqPe0Ea|*YJPg{&v z_Nv~?87%q;-=kOYO%y!%TACpQWq2Jk3A0SkednW`Z6TvnW;(nJ?}35Oq(|~Q#Z*}0 zF9*y+Y`)XG=dK9}EM6pb9A=Dk&vpq?~Ld z6{M1E0$Ku81zHNU3}`vfjiib=NHwV;wS)kz09rY{qrQntRzVF=2heJuNYnzwc_-Nh z)CJTHv~K$S`dVWn&{m)Uplv`kpzT1n0Nn}{#kP~}Kz9J$3G@x1yMT7^7XsZ4Gzhd4 zs1CFXP=7bsL3WZi@IMiN_K;nq184|nFVHa1KA?Mm?ghFJ(6#+!H^H_2KqI7+;Q9mg zq>FR|9e}XRd>k$4L7-8fgFp`fJxqFlVmyxkJvzP5TZVuz1oR}-13d-wGzpPj5+;3Q z57|rh0X+lsEZ{y-%Xy#|fL;VT3KZQM2RZ>5k~hhIg4QQVgd89PKraEEB53h4iIPEr z7Ow!k3iKM#>p;>^TjjuuMU9%8IfMt^-z^uS>fZ-!A c4_H310w2A=-@@w%j@?or<_3O>@DoY=5412a82|tP From bdea1d4a06e12167b22656ea6b1c3447ce348bfc Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 2 Jan 2024 09:28:16 +0100 Subject: [PATCH 12/68] workaround: for v1.22.0 sys.implementation.version has an additional empty node in it https://github.com/micropython/micropython/issues/13317 Signed-off-by: Jos Verlinde --- src/stubber/board/createstubs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index af07c6418..5908631ad 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -469,7 +469,7 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]) + info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") except AttributeError: pass try: From 11b754d8e945c859d5037a88872be2071f588197 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 2 Jan 2024 10:21:38 +0100 Subject: [PATCH 13/68] Update board_stubber.py: Set LOCAL_FILES to True and change variant and form values Signed-off-by: Jos Verlinde --- scripts/board_stubber.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/board_stubber.py b/scripts/board_stubber.py index 960d0ea50..aecba9bd3 100644 --- a/scripts/board_stubber.py +++ b/scripts/board_stubber.py @@ -27,7 +27,7 @@ ERROR = -1 RETRIES = 3 TESTING = False -LOCAL_FILES = False +LOCAL_FILES = True ############################################################################################### reset_before = False @@ -257,9 +257,9 @@ def copy_createstubs(board: MPRemoteBoard, variant: Variant, form: Form) -> bool """Copy createstubs to the board""" # copy createstubs.py to the destination folder origin = "./src/stubber/board" - # origin = "./micropython-stubber-1.7.0/minified" _py = [ + "rm :no_auto_stubber.txt", "rm :lib/createstubs.mpy", "rm :lib/createstubs_mem.mpy", "rm :lib/createstubs_db.mpy", @@ -356,7 +356,7 @@ def run_createstubs(dest: Path, board: MPRemoteBoard, variant: Variant = Variant board.run_command.retry.wait = wait_fixed(15) # some boards need 2-3 minutes to run createstubs - so increase the default timeout # but slows down esp8266 restarts so keep that to 60 seconds - timeout = 60 if board.uname.nodename == "esp8266" else 4 * 60 + timeout = 60 if board.uname.nodename == "esp8266" else 4 * 60 # type: ignore rc, out = board.run_command(cmd, timeout=timeout) # check last line for exception or error and raise that if found if ( @@ -534,8 +534,8 @@ def copy_to_repo(source: Path, fw: dict) -> Optional[Path]: if __name__ == "__main__": set_loglevel(0) - variant = Variant.mem - form = Form.min + variant = Variant.full + form = Form.py # BUG : Minified geeft problemen ? tempdir = mkdtemp(prefix="board_stubber") dest = Path(tempdir) From c0cc471ee63041575cff5cf6b4d88c1fcb0f0ecc Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 2 Jan 2024 10:21:58 +0100 Subject: [PATCH 14/68] Fix file deletion bug in merge_docstubs.py Signed-off-by: Jos Verlinde --- scripts/get_firmwares.ipynb | 307 ++++++++++++++++++-------- src/stubber/publish/merge_docstubs.py | 4 +- 2 files changed, 220 insertions(+), 91 deletions(-) diff --git a/scripts/get_firmwares.ipynb b/scripts/get_firmwares.ipynb index b70a0e7e4..bdcf53ca9 100644 --- a/scripts/get_firmwares.ipynb +++ b/scripts/get_firmwares.ipynb @@ -11,7 +11,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -21,7 +21,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 2, "metadata": { "tags": [] }, @@ -38,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 3, "metadata": { "tags": [] }, @@ -68,7 +68,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -92,7 +92,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 11, "metadata": { "tags": [] }, @@ -101,7 +101,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Found 138 firmwares\n" + "Found 169 firmwares\n" ] } ], @@ -118,6 +118,7 @@ "RELEVANT_BOARDS = [\n", " \"PYBV11\",\n", " \"ESP32_GENERIC\",\n", + " \"ESP32_GENERIC_S3\",\n", " \"RPI_PICO\",\n", " \"RPI_PICO_W\",\n", " \"ARDUINO_NANO_RP2040_CONNECT\",\n", @@ -172,7 +173,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Found 75 relevant firmwares\n" + "Found 85 relevant firmwares\n" ] } ], @@ -180,7 +181,7 @@ "relevant = [\n", " board\n", " for board in board_urls\n", - " if board[\"board\"] in RELEVANT_BOARDS and (board[\"version\"] in [\"1.21.0\"] or board[\"preview\"])\n", + " if board[\"board\"] in RELEVANT_BOARDS and (board[\"version\"] in [\"1.22.0\"] or board[\"preview\"])\n", " # and b[\"port\"] in [\"esp32\", \"rp2\"]\n", "]\n", "# relevant\n", @@ -189,88 +190,98 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Downloading https://micropython.org/resources/firmware/PYBV11-20231005-v1.21.0.hex to firmware\\stm32\\PYBV11-v1.21.0.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-20231019-v1.22.0-preview.32.g86c7b957a.hex to firmware\\stm32\\PYBV11-v1.22.0-preview.32.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-20231017-v1.22.0-preview.31.g3883f2948.hex to firmware\\stm32\\PYBV11-v1.22.0-preview.31.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-20231017-v1.22.0-preview.30.ge78471416.hex to firmware\\stm32\\PYBV11-v1.22.0-preview.30.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-20231017-v1.22.0-preview.27.gc2361328e.hex to firmware\\stm32\\PYBV11-v1.22.0-preview.27.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-DP-20231005-v1.21.0.hex to firmware\\stm32\\PYBV11-DP-v1.21.0.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-DP-20231019-v1.22.0-preview.32.g86c7b957a.hex to firmware\\stm32\\PYBV11-DP-v1.22.0-preview.32.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-DP-20231017-v1.22.0-preview.31.g3883f2948.hex to firmware\\stm32\\PYBV11-DP-v1.22.0-preview.31.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-DP-20231017-v1.22.0-preview.30.ge78471416.hex to firmware\\stm32\\PYBV11-DP-v1.22.0-preview.30.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-DP-20231017-v1.22.0-preview.27.gc2361328e.hex to firmware\\stm32\\PYBV11-DP-v1.22.0-preview.27.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-NETWORK-20231005-v1.21.0.hex to firmware\\stm32\\PYBV11-NETWORK-v1.21.0.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-NETWORK-20231019-v1.22.0-preview.32.g86c7b957a.hex to firmware\\stm32\\PYBV11-NETWORK-v1.22.0-preview.32.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-NETWORK-20231017-v1.22.0-preview.31.g3883f2948.hex to firmware\\stm32\\PYBV11-NETWORK-v1.22.0-preview.31.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-NETWORK-20231017-v1.22.0-preview.30.ge78471416.hex to firmware\\stm32\\PYBV11-NETWORK-v1.22.0-preview.30.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-NETWORK-20231017-v1.22.0-preview.27.gc2361328e.hex to firmware\\stm32\\PYBV11-NETWORK-v1.22.0-preview.27.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-THREAD-20231005-v1.21.0.hex to firmware\\stm32\\PYBV11-THREAD-v1.21.0.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-THREAD-20231019-v1.22.0-preview.32.g86c7b957a.hex to firmware\\stm32\\PYBV11-THREAD-v1.22.0-preview.32.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-THREAD-20231017-v1.22.0-preview.31.g3883f2948.hex to firmware\\stm32\\PYBV11-THREAD-v1.22.0-preview.31.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-THREAD-20231017-v1.22.0-preview.30.ge78471416.hex to firmware\\stm32\\PYBV11-THREAD-v1.22.0-preview.30.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-THREAD-20231017-v1.22.0-preview.27.gc2361328e.hex to firmware\\stm32\\PYBV11-THREAD-v1.22.0-preview.27.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-DP_THREAD-20231005-v1.21.0.hex to firmware\\stm32\\PYBV11-DP_THREAD-v1.21.0.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-DP_THREAD-20231019-v1.22.0-preview.32.g86c7b957a.hex to firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0-preview.32.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-DP_THREAD-20231017-v1.22.0-preview.31.g3883f2948.hex to firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0-preview.31.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-DP_THREAD-20231017-v1.22.0-preview.30.ge78471416.hex to firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0-preview.30.hex\n", - "Downloading https://micropython.org/resources/firmware/PYBV11-DP_THREAD-20231017-v1.22.0-preview.27.gc2361328e.hex to firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0-preview.27.hex\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-20231005-v1.21.0.bin to firmware\\esp32\\ESP32_GENERIC-v1.21.0.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-20231019-v1.22.0-preview.32.g86c7b957a.bin to firmware\\esp32\\ESP32_GENERIC-v1.22.0-preview.32.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-20231017-v1.22.0-preview.31.g3883f2948.bin to firmware\\esp32\\ESP32_GENERIC-v1.22.0-preview.31.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-20231017-v1.22.0-preview.30.ge78471416.bin to firmware\\esp32\\ESP32_GENERIC-v1.22.0-preview.30.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-20231017-v1.22.0-preview.27.gc2361328e.bin to firmware\\esp32\\ESP32_GENERIC-v1.22.0-preview.27.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-UNICORE-20231005-v1.21.0.bin to firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.21.0.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-UNICORE-20231019-v1.22.0-preview.32.g86c7b957a.bin to firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0-preview.32.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-UNICORE-20231017-v1.22.0-preview.31.g3883f2948.bin to firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0-preview.31.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-UNICORE-20231017-v1.22.0-preview.30.ge78471416.bin to firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0-preview.30.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-UNICORE-20231017-v1.22.0-preview.27.gc2361328e.bin to firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0-preview.27.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-OTA-20231005-v1.21.0.bin to firmware\\esp32\\ESP32_GENERIC-OTA-v1.21.0.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-OTA-20231019-v1.22.0-preview.32.g86c7b957a.bin to firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0-preview.32.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-OTA-20231017-v1.22.0-preview.31.g3883f2948.bin to firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0-preview.31.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-OTA-20231017-v1.22.0-preview.30.ge78471416.bin to firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0-preview.30.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-OTA-20231017-v1.22.0-preview.27.gc2361328e.bin to firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0-preview.27.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-D2WD-20231005-v1.21.0.bin to firmware\\esp32\\ESP32_GENERIC-D2WD-v1.21.0.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-D2WD-20231019-v1.22.0-preview.32.g86c7b957a.bin to firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0-preview.32.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-D2WD-20231017-v1.22.0-preview.31.g3883f2948.bin to firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0-preview.31.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-D2WD-20231017-v1.22.0-preview.30.ge78471416.bin to firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0-preview.30.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-D2WD-20231017-v1.22.0-preview.27.gc2361328e.bin to firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0-preview.27.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-SPIRAM-20231005-v1.21.0.bin to firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.21.0.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-SPIRAM-20231019-v1.22.0-preview.32.g86c7b957a.bin to firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.32.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-SPIRAM-20231017-v1.22.0-preview.31.g3883f2948.bin to firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.31.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-SPIRAM-20231017-v1.22.0-preview.30.ge78471416.bin to firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.30.bin\n", - "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-SPIRAM-20231017-v1.22.0-preview.27.gc2361328e.bin to firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.27.bin\n", - "Downloading https://micropython.org/resources/firmware/ARDUINO_NANO_RP2040_CONNECT-20231005-v1.21.0.uf2 to firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.21.0.uf2\n", - "Downloading https://micropython.org/resources/firmware/ARDUINO_NANO_RP2040_CONNECT-20231019-v1.22.0-preview.32.g86c7b957a.uf2 to firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0-preview.32.uf2\n", - "Downloading https://micropython.org/resources/firmware/ARDUINO_NANO_RP2040_CONNECT-20231017-v1.22.0-preview.31.g3883f2948.uf2 to firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0-preview.31.uf2\n", - "Downloading https://micropython.org/resources/firmware/ARDUINO_NANO_RP2040_CONNECT-20231017-v1.22.0-preview.30.ge78471416.uf2 to firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0-preview.30.uf2\n", - "Downloading https://micropython.org/resources/firmware/ARDUINO_NANO_RP2040_CONNECT-20231017-v1.22.0-preview.27.gc2361328e.uf2 to firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0-preview.27.uf2\n", - "Downloading https://micropython.org/resources/firmware/PIMORONI_PICOLIPO_16MB-20231005-v1.21.0.uf2 to firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.21.0.uf2\n", - "Downloading https://micropython.org/resources/firmware/PIMORONI_PICOLIPO_16MB-20231019-v1.22.0-preview.32.g86c7b957a.uf2 to firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0-preview.32.uf2\n", - "Downloading https://micropython.org/resources/firmware/PIMORONI_PICOLIPO_16MB-20231017-v1.22.0-preview.31.g3883f2948.uf2 to firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0-preview.31.uf2\n", - "Downloading https://micropython.org/resources/firmware/PIMORONI_PICOLIPO_16MB-20231017-v1.22.0-preview.30.ge78471416.uf2 to firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0-preview.30.uf2\n", - "Downloading https://micropython.org/resources/firmware/PIMORONI_PICOLIPO_16MB-20231017-v1.22.0-preview.27.gc2361328e.uf2 to firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0-preview.27.uf2\n", - "Downloading https://micropython.org/resources/firmware/RPI_PICO-20231005-v1.21.0.uf2 to firmware\\rp2\\RPI_PICO-v1.21.0.uf2\n", - "Downloading https://micropython.org/resources/firmware/RPI_PICO-20231019-v1.22.0-preview.32.g86c7b957a.uf2 to firmware\\rp2\\RPI_PICO-v1.22.0-preview.32.uf2\n", - "Downloading https://micropython.org/resources/firmware/RPI_PICO-20231017-v1.22.0-preview.31.g3883f2948.uf2 to firmware\\rp2\\RPI_PICO-v1.22.0-preview.31.uf2\n", - "Downloading https://micropython.org/resources/firmware/RPI_PICO-20231017-v1.22.0-preview.30.ge78471416.uf2 to firmware\\rp2\\RPI_PICO-v1.22.0-preview.30.uf2\n", - "Downloading https://micropython.org/resources/firmware/RPI_PICO-20231017-v1.22.0-preview.27.gc2361328e.uf2 to firmware\\rp2\\RPI_PICO-v1.22.0-preview.27.uf2\n", - "Downloading https://micropython.org/resources/firmware/RPI_PICO_W-20231005-v1.21.0.uf2 to firmware\\rp2\\RPI_PICO_W-v1.21.0.uf2\n", - "Downloading https://micropython.org/resources/firmware/RPI_PICO_W-20231019-v1.22.0-preview.32.g86c7b957a.uf2 to firmware\\rp2\\RPI_PICO_W-v1.22.0-preview.32.uf2\n", - "Downloading https://micropython.org/resources/firmware/RPI_PICO_W-20231017-v1.22.0-preview.31.g3883f2948.uf2 to firmware\\rp2\\RPI_PICO_W-v1.22.0-preview.31.uf2\n", - "Downloading https://micropython.org/resources/firmware/RPI_PICO_W-20231017-v1.22.0-preview.30.ge78471416.uf2 to firmware\\rp2\\RPI_PICO_W-v1.22.0-preview.30.uf2\n", - "Downloading https://micropython.org/resources/firmware/RPI_PICO_W-20231017-v1.22.0-preview.27.gc2361328e.uf2 to firmware\\rp2\\RPI_PICO_W-v1.22.0-preview.27.uf2\n", - "Downloading https://micropython.org/resources/firmware/SEEED_WIO_TERMINAL-20231005-v1.21.0.uf2 to firmware\\samd\\SEEED_WIO_TERMINAL-v1.21.0.uf2\n", - "Downloading https://micropython.org/resources/firmware/SEEED_WIO_TERMINAL-20231019-v1.22.0-preview.32.g86c7b957a.uf2 to firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0-preview.32.uf2\n", - "Downloading https://micropython.org/resources/firmware/SEEED_WIO_TERMINAL-20231017-v1.22.0-preview.31.g3883f2948.uf2 to firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0-preview.31.uf2\n", - "Downloading https://micropython.org/resources/firmware/SEEED_WIO_TERMINAL-20231017-v1.22.0-preview.30.ge78471416.uf2 to firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0-preview.30.uf2\n", - "Downloading https://micropython.org/resources/firmware/SEEED_WIO_TERMINAL-20231017-v1.22.0-preview.27.gc2361328e.uf2 to firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0-preview.27.uf2\n" + " firmware\\stm32\\PYBV11-v1.22.0.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-v1.22.0-preview.289.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-v1.22.0-preview.283.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-v1.22.0-preview.281.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-v1.22.0-preview.278.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-DP-v1.22.0.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-DP-v1.22.0-preview.289.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-DP-v1.22.0-preview.283.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-DP-v1.22.0-preview.281.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-DP-v1.22.0-preview.278.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-NETWORK-v1.22.0.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-NETWORK-v1.22.0-preview.289.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-NETWORK-v1.22.0-preview.283.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-NETWORK-v1.22.0-preview.281.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-NETWORK-v1.22.0-preview.278.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-THREAD-v1.22.0.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-THREAD-v1.22.0-preview.289.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-THREAD-v1.22.0-preview.283.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-THREAD-v1.22.0-preview.281.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-THREAD-v1.22.0-preview.278.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0-preview.289.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0-preview.283.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0-preview.281.hex already exists, skip download\n", + " firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0-preview.278.hex already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-v1.22.0.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-v1.22.0-preview.289.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-v1.22.0-preview.283.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-v1.22.0-preview.281.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-v1.22.0-preview.278.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0-preview.289.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0-preview.283.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0-preview.281.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0-preview.278.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0-preview.289.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0-preview.283.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0-preview.281.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0-preview.278.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0-preview.289.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0-preview.283.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0-preview.281.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0-preview.278.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.289.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.283.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.281.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.278.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC_S3-v1.22.0.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC_S3-v1.22.0-preview.289.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC_S3-v1.22.0-preview.283.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC_S3-v1.22.0-preview.281.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC_S3-v1.22.0-preview.278.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.289.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.283.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.281.bin already exists, skip download\n", + " firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.278.bin already exists, skip download\n", + " firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0.uf2 already exists, skip download\n", + " firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0-preview.289.uf2 already exists, skip download\n", + " firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0-preview.283.uf2 already exists, skip download\n", + " firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0-preview.281.uf2 already exists, skip download\n", + " firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0-preview.278.uf2 already exists, skip download\n", + " firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0.uf2 already exists, skip download\n", + " firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0-preview.289.uf2 already exists, skip download\n", + " firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0-preview.283.uf2 already exists, skip download\n", + " firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0-preview.281.uf2 already exists, skip download\n", + " firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0-preview.278.uf2 already exists, skip download\n", + " firmware\\rp2\\RPI_PICO-v1.22.0.uf2 already exists, skip download\n", + " firmware\\rp2\\RPI_PICO-v1.22.0-preview.289.uf2 already exists, skip download\n", + " firmware\\rp2\\RPI_PICO-v1.22.0-preview.283.uf2 already exists, skip download\n", + " firmware\\rp2\\RPI_PICO-v1.22.0-preview.281.uf2 already exists, skip download\n", + " firmware\\rp2\\RPI_PICO-v1.22.0-preview.278.uf2 already exists, skip download\n", + " firmware\\rp2\\RPI_PICO_W-v1.22.0.uf2 already exists, skip download\n", + " firmware\\rp2\\RPI_PICO_W-v1.22.0-preview.289.uf2 already exists, skip download\n", + " firmware\\rp2\\RPI_PICO_W-v1.22.0-preview.283.uf2 already exists, skip download\n", + " firmware\\rp2\\RPI_PICO_W-v1.22.0-preview.281.uf2 already exists, skip download\n", + " firmware\\rp2\\RPI_PICO_W-v1.22.0-preview.278.uf2 already exists, skip download\n", + " firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0.uf2 already exists, skip download\n", + " firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0-preview.289.uf2 already exists, skip download\n", + " firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0-preview.283.uf2 already exists, skip download\n", + " firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0-preview.281.uf2 already exists, skip download\n", + " firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0-preview.278.uf2 already exists, skip download\n" ] } ], @@ -291,6 +302,9 @@ " fname = re.sub(hash_re, \".\", fname)\n", " filename = firmware_folder / board[\"port\"] / fname\n", " filename.parent.mkdir(exist_ok=True)\n", + " if filename.exists():\n", + " print(f\" {filename} already exists, skip download\")\n", + " continue\n", " print(f\"Downloading {board['firmware']} to {filename}\")\n", " r = requests.get(board[\"firmware\"], allow_redirects=True)\n", " with open(filename, \"wb\") as f:\n", @@ -300,14 +314,129 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 18, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "COM4 017154B9 10c4:ea60 Silicon Labs None\n" + ] + } + ], + "source": [ + "!mpremote devs" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "esptool.py v4.6.2\n", + "Serial port COM6\n", + "Connecting......\n", + "Chip is ESP32-D0WD (revision v1.0)\n", + "Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None\n", + "Crystal is 40MHz\n", + "MAC: b4:e6:2d:df:40:8d\n", + "Uploading stub...\n", + "Running stub...\n", + "Stub running...\n", + "Configuring flash size...\n", + "Flash will be erased from 0x00001000 to 0x0018bfff...\n", + "Compressed 1614624 bytes to 1055696...\n", + "Writing at 0x00001000... (1 %)\n", + "Writing at 0x00010a5e... (3 %)\n", + "Writing at 0x00018790... (4 %)\n", + "Writing at 0x000205a9... (6 %)\n", + "Writing at 0x0002684e... (7 %)\n", + "Writing at 0x0002fbb1... (9 %)\n", + "Writing at 0x00039936... (10 %)\n", + "Writing at 0x0003f7ce... (12 %)\n", + "Writing at 0x0004bc0d... (13 %)\n", + "Writing at 0x000515d9... (15 %)\n", + "Writing at 0x00056c57... (16 %)\n", + "Writing at 0x0005bf86... (18 %)\n", + "Writing at 0x00061230... (20 %)\n", + "Writing at 0x00066429... (21 %)\n", + "Writing at 0x0006b602... (23 %)\n", + "Writing at 0x00070ab8... (24 %)\n", + "Writing at 0x00075967... (26 %)\n", + "Writing at 0x0007aa31... (27 %)\n", + "Writing at 0x00081627... (29 %)\n", + "Writing at 0x00086ead... (30 %)\n", + "Writing at 0x0008c367... (32 %)\n", + "Writing at 0x00091e5a... (33 %)\n", + "Writing at 0x00097de4... (35 %)\n", + "Writing at 0x0009d681... (36 %)\n", + "Writing at 0x000a3295... (38 %)\n", + "Writing at 0x000a91fb... (40 %)\n", + "Writing at 0x000af5bb... (41 %)\n", + "Writing at 0x000b5347... (43 %)\n", + "Writing at 0x000ba99a... (44 %)\n", + "Writing at 0x000c0140... (46 %)\n", + "Writing at 0x000c5c8e... (47 %)\n", + "Writing at 0x000cbc50... (49 %)\n", + "Writing at 0x000d171c... (50 %)\n", + "Writing at 0x000d68a2... (52 %)\n", + "Writing at 0x000dbe93... (53 %)\n", + "Writing at 0x000e1181... (55 %)\n", + "Writing at 0x000e69fb... (56 %)\n", + "Writing at 0x000ec3eb... (58 %)\n", + "Writing at 0x000f18e5... (60 %)\n", + "Writing at 0x000f6a94... (61 %)\n", + "Writing at 0x000fc862... (63 %)\n", + "Writing at 0x001019dd... (64 %)\n", + "Writing at 0x00106fef... (66 %)\n", + "Writing at 0x0010c8ab... (67 %)\n", + "Writing at 0x00111ff1... (69 %)\n", + "Writing at 0x00117970... (70 %)\n", + "Writing at 0x0011cded... (72 %)\n", + "Writing at 0x00122154... (73 %)\n", + "Writing at 0x00127538... (75 %)\n", + "Writing at 0x0012c8d3... (76 %)\n", + "Writing at 0x00131f88... (78 %)\n", + "Writing at 0x001376a8... (80 %)\n", + "Writing at 0x0013d61b... (81 %)\n", + "Writing at 0x00143168... (83 %)\n", + "Writing at 0x00148c86... (84 %)\n", + "Writing at 0x0014fc61... (86 %)\n", + "Writing at 0x00158bb6... (87 %)\n", + "Writing at 0x00160b5e... (89 %)\n", + "Writing at 0x00166caa... (90 %)\n", + "Writing at 0x0016be53... (92 %)\n", + "Writing at 0x00172329... (93 %)\n", + "Writing at 0x00177896... (95 %)\n", + "Writing at 0x0017d43b... (96 %)\n", + "Writing at 0x00182bf6... (98 %)\n", + "Writing at 0x00188b28... (100 %)\n", + "Wrote 1614624 bytes (1055696 compressed) at 0x00001000 in 93.1 seconds (effective 138.7 kbit/s)...\n", + "Hash of data verified.\n", + "\n", + "Leaving...\n", + "Hard resetting via RTS pin...\n" + ] + } + ], "source": [ - "# serialport = \"COM9\"\n", + "serialport = \"COM6\"\n", "# !esptool --chip esp32 --port {serialport} erase_flash\n", - "# !esptool --chip esp32 --port {serialport} --baud 460800 write_flash -z 0x1000 firmware/ESP32_GENERIC-SPIRAM-v1.21.0.bin" + "# !esptool --chip esp32 --port {serialport} write_flash -z 0x1000 \"firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0.bin\"\n", + "!esptool --chip esp32 --port {serialport} write_flash -z 0x1000 \"firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.289.bin\"" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -326,7 +455,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.7" } }, "nbformat": 4, diff --git a/src/stubber/publish/merge_docstubs.py b/src/stubber/publish/merge_docstubs.py index d5a3c9012..74ae2cc1c 100644 --- a/src/stubber/publish/merge_docstubs.py +++ b/src/stubber/publish/merge_docstubs.py @@ -120,8 +120,8 @@ def copy_and_merge_docstubs(fw_path: Path, dest_path: Path, docstub_path: Path): "pycopy_imphook", # is not intended to be used directly, and has an unresolved subclass ]: for suffix in [".py", ".pyi"]: - if (dest_path / name).with_suffix(suffix).exists(): - (dest_path / name).with_suffix(suffix).unlink() + if (dest_path / name).with_suffix(suffix).exists(): # type: ignore + (dest_path / name).with_suffix(suffix).unlink() # type: ignore # 2 - Enrich the firmware stubs with the document stubs result = enrich_folder(dest_path, docstub_path=docstub_path, write_back=True) From e7cecac8846e86da56089df99cea0bb164b14849 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 2 Jan 2024 10:22:13 +0100 Subject: [PATCH 15/68] update variants Signed-off-by: Jos Verlinde --- src/stubber/board/createstubs_db.py | 51 +-- src/stubber/board/createstubs_db_min.py | 355 +++++++++++---------- src/stubber/board/createstubs_db_mpy.mpy | Bin 8362 -> 8544 bytes src/stubber/board/createstubs_lvgl.py | 51 +-- src/stubber/board/createstubs_lvgl_min.py | 265 +++++++-------- src/stubber/board/createstubs_lvgl_mpy.mpy | Bin 7843 -> 8020 bytes src/stubber/board/createstubs_mem.py | 51 +-- src/stubber/board/createstubs_mem_min.py | 291 ++++++++--------- src/stubber/board/createstubs_mem_mpy.mpy | Bin 7875 -> 8055 bytes src/stubber/board/createstubs_min.py | 273 ++++++++-------- src/stubber/board/createstubs_mpy.mpy | Bin 10888 -> 11077 bytes 11 files changed, 705 insertions(+), 632 deletions(-) diff --git a/src/stubber/board/createstubs_db.py b/src/stubber/board/createstubs_db.py index c6c5ecb27..c65a5507c 100644 --- a/src/stubber/board/createstubs_db.py +++ b/src/stubber/board/createstubs_db.py @@ -448,7 +448,7 @@ def _info(): # type:() -> dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -462,13 +462,13 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]) + info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -479,19 +479,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -569,6 +557,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/src/stubber/board/createstubs_db_min.py b/src/stubber/board/createstubs_db_min.py index 34ba0bee4..1f8c304b5 100644 --- a/src/stubber/board/createstubs_db_min.py +++ b/src/stubber/board/createstubs_db_min.py @@ -1,178 +1,180 @@ -v='stubber' -u='{}/{}' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n=NameError -m=sorted -l=MemoryError -k=NotImplementedError -b=',\n' -a='dict' -Z='list' -Y='tuple' -X='micropython' -W=str -V=repr -T='_' -S=KeyError -R=IndexError -Q=dir -P=ImportError +x='stubber' +w='{}/{}' +v='method' +u='function' +t='bool' +s='str' +r='float' +q='int' +p=NameError +o=sorted +n=MemoryError +m=NotImplementedError +d=',\n' +c='dict' +b='list' +a='tuple' +Z='micropython' +Y=str +X=repr +V='cpu' +U='_' +T=KeyError +S=IndexError +R=dir +Q=ImportError +P='with' O='family' N=print -M=True -L=len -K='board' +M=len +L='board' +K=True J='.' I=open H=AttributeError G='/' -F=False -E=None -D='version' +F=None +E='version' +D=False A=OSError C='' import gc as B,os,sys -from ujson import dumps as c +from ujson import dumps as e try:from machine import reset -except P:pass -try:from collections import OrderedDict as d -except P:from ucollections import OrderedDict as d +except Q:pass +try:from collections import OrderedDict as f +except Q:from ucollections import OrderedDict as f __version__='v1.16.2' -w=2 -x=2 -e=[J,'/lib','/sd/lib','/flash/lib','lib'] +y=2 +z=2 +g=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: - def __init__(C,path=E,firmware_id=E): + def __init__(C,path=F,firmware_id=F): D=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') except H:pass C._report=[];C.info=_info();B.collect() if D:C._fwid=D.lower() - elif C.info[O]==X:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) + elif C.info[O]==Z:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) else:C._fwid='{family}-{ver}-{port}'.format(**C.info) C._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) - try:f(path+G) + try:h(path+G) except A:N('error creating stub folder {}'.format(path)) C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in Q(I): - if A.startswith(T)and not A in L.modules:continue + for A in R(I): + if A.startswith(U)and not A in L.modules:continue try: E=getattr(I,A) - try:F=V(type(E)).split("'")[1] - except R:F=C - if F in{o,p,q,r,Y,Z,a}:G=1 - elif F in{s,t}:G=2 + try:F=X(type(E)).split("'")[1] + except S:F=C + if F in{q,r,s,t,a,b,c}:G=1 + elif F in{u,v}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,V(E),V(type(E)),E,G)) + D.append((A,X(E),X(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) - except l as K:sleep(1);reset() - D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) + except n as K:sleep(1);reset() + D=o([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J + def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) def create_one_stub(C,module_name): - D=module_name - if D in C.problematic:return F - if D in C.excluded:return F - H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=F - try:E=C.create_module_stub(D,H) - except A:return F - B.collect();return E - def create_module_stub(K,module_name,file_name=E): - H=file_name;D=module_name - if H is E:O=D.replace(J,T)+'.py';H=K.path+G+O + E=module_name + if E in C.problematic:return D + if E in C.excluded:return D + H='{}/{}.py'.format(C.path,E.replace(J,G));B.collect();F=D + try:F=C.create_module_stub(E,H) + except A:return D + B.collect();return F + def create_module_stub(L,module_name,file_name=F): + H=file_name;E=module_name + if H is F:O=E.replace(J,U)+'.py';H=L.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,J) - L=E - try:L=__import__(D,E,E,'*');U=B.mem_free() - except P:return F - f(H) - with I(H,'w')as N:Q=W(K.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,K._fwid,Q,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,L,D,C) - K._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: - try:del L - except(A,S):pass - try:del sys.modules[D] - except S:pass - B.collect();return M + if G in E:E=E.replace(G,J) + M=F + try:M=__import__(E,F,F,'*');S=B.mem_free() + except Q:return D + h(H) + with I(H,'w')as N:P=Y(L.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(E,L._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');L.write_object_stub(N,M,E,C) + L._report.append('{{"module": "{}", "file": "{}"}}'.format(E,H.replace('\\',G))) + if E not in{'os','sys','logging','gc'}: + try:del M + except(A,T):pass + try:del sys.modules[E] + except T:pass + B.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() + d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() if P in K.problematic:return - R,M=K.get_obj_attributes(P) - if M:N(M) - for(F,J,G,T,f)in R: + R,L=K.get_obj_attributes(P) + if L:N(L) + for(F,J,G,S,f)in R: if F in['classmethod','staticmethod','BaseException',O]:continue if F[0].isdigit():continue - if G==""and L(E)<=x*4: + if G==""and M(E)<=z*4: U=C;V=F.endswith(O)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O D='\n{}class {}({}):\n'.format(E,F,U) if V:D+=E+' ...\n';H.write(D);return - H.write(D);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) - elif any(A in G for A in[t,s,'closure']): - W=b;X=C + H.write(D);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) + elif any(A in G for A in[v,u,'closure']): + W=Y;X=C if Q>0:X='self, ' - if c in G or c in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) + if Z in G or Z in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,X,W) D+=E+' ...\n\n';H.write(D) elif G=="":0 elif G.startswith("5:A[F]=C - if A[D]==C and sys.platform not in(k,j): - try:o=os.uname();A[D]=o.release - except(R,H,TypeError):pass - for(p,q,r)in[(l,l,'const'),(m,m,'FAT'),(n,'pybricks.hubs','EV3Brick')]: - try:s=__import__(q,E,E,r);A[O]=p;del s;break - except(P,S):pass - if A[O]==n:A['release']='2.0.0' - if A[O]==X: - if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] + A[D]=W(os.uname()[3]) + if not A[D]:A[D]=W(os.uname()[2]) + if not A[D]and';'in sys.version:A[D]=W(sys.version.split(';')[1]) + except(H,S):pass + if A[D]and M(A[D])>5:A[D]=C + if A[E]==C and sys.platform not in(c,b): + try:h=os.uname();A[E]=h.release + except(S,H,TypeError):pass + for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: + try:l=__import__(j,F,F,k);A[O]=i;del l;break + except(Q,T):pass + if A[O]==g:A['release']='2.0.0' + if A[O]==Z: + if A[E]and A[E].endswith('.0')and A[E]>='1.10.0'and A[E]<='1.19.9':A[E]=A[E][:-2] if I in A and A[I]: - V=int(A[I]);a=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if a:A[f]=a - A[I]='v{}.{}'.format(V&255,V>>8&3) - A[b]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def g(info,board_descr,filename): + K=int(A[I]);U=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if U:A[a]=U + A[I]='v{}.{}'.format(K&255,K>>8&3) + A[X]=f"v{A[E]}-{A[D]}"if A[D]else f"v{A[E]}";return A +def A0(info,desc=C): + G='with ';C=info;E=D + for F in[A+'/board_info.csv'for A in g]: + if j(F): + A=desc or C[L].strip() + if i(C,A,F):E=K;break + if P in A: + A=A.split(P)[0].strip() + if i(C,A,F):E=K;break + if not E: + A=desc or C[L].strip() + if G+C[V].upper()in A:A=A.split(G+C[V].upper())[0].strip() + C[L]=A + C[L]=C[L].replace(' ',U);B.collect() +def i(info,board_descr,filename): with I(filename,'r')as B: while 1: A=B.readline() if not A:break - C,D=A.split(',')[0].strip(),A.split(',')[1].strip() - if C==board_descr:info[K]=D;return M - return F + C,E=A.split(',')[0].strip(),A.split(',')[1].strip() + if C==board_descr:info[L]=E;return K + return D def get_root(): try:B=os.getcwd() except(A,H):B=J @@ -244,61 +251,61 @@ def get_root(): try:D=os.stat(C);break except A:continue return C -def h(filename): +def j(filename): try: - if os.stat(filename)[0]>>14:return M - return F - except A:return F -def i():sys.exit(1) + if os.stat(filename)[0]>>14:return K + return D + except A:return D +def k():sys.exit(1) def read_path(): path=C - if L(sys.argv)==3: + if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:i() - elif L(sys.argv)==2:i() + else:k() + elif M(sys.argv)==2:k() return path -def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return F - except(k,H):return M +def l(): + try:A=bytes('abc',encoding='utf8');B=l.__module__;return D + except(m,H):return K def main(): - K='failed';G='modulelist.done';import machine as O - try:C=I(G,'r+b');N=M - except A:C=I(G,'w+b');N=F + L='failed';G='modulelist.done';import machine as O + try:C=I(G,'r+b');N=K + except A:C=I(G,'w+b');N=D stubber=Stubber(path=read_path()) if not N:stubber.clean() - y(stubber);D={} + A1(stubber);E={} try: with I(G)as C: - for E in C.read().split('\n'): - E=E.strip();B.collect() - if L(E)>0:P,Q=E.split('=',1);D[P]=Q + for F in C.read().split('\n'): + F=F.strip();B.collect() + if M(F)>0:P,Q=F.split('=',1);E[P]=Q except(A,SyntaxError):pass - B.collect();R=[A for A in stubber.modules if A not in D.keys()];B.collect() + B.collect();R=[A for A in stubber.modules if A not in E.keys()];B.collect() for H in R: - J=F + J=D try:J=stubber.create_one_stub(H) - except l:O.reset() - B.collect();D[H]=W(stubber._report[-1]if J else K) - with I(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if J else K)) - if D:stubber._report=[A for(B,A)in D.items()if A!=K];stubber.report() -def y(stubber): + except n:O.reset() + B.collect();E[H]=Y(stubber._report[-1]if J else L) + with I(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if J else L)) + if E:stubber._report=[A for(B,A)in E.items()if A!=L];stubber.report() +def A1(stubber): E='/modulelist.txt';stubber.modules=[] - for D in e: + for D in g: try: with I(D+E)as F: N('DEBUG: list of modules: '+D+E) for C in F.read().split('\n'): C=C.strip() - if L(C)>0 and C[0]!='#':stubber.modules.append(C) + if M(C)>0 and C[0]!='#':stubber.modules.append(C) B.collect();break except A:pass - if not stubber.modules:stubber.modules=[X];_log.warn('Could not find modulelist.txt, using default modules') + if not stubber.modules:stubber.modules=[Z];_log.warn('Could not find modulelist.txt, using default modules') B.collect() -if __name__=='__main__'or j(): - try:z=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except n:pass - if not h('no_auto_stubber.txt'): +if __name__=='__main__'or l(): + try:A2=logging.getLogger(x);logging.basicConfig(level=logging.INFO) + except p:pass + if not j('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_db_mpy.mpy b/src/stubber/board/createstubs_db_mpy.mpy index 417ae41e091c4a913e5a2698ddb3850acb8cba45..4f9ed861a5c9db7160eec192e15bcba502a6bfb7 100644 GIT binary patch delta 5750 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 diff --git a/src/stubber/board/createstubs_lvgl.py b/src/stubber/board/createstubs_lvgl.py index 68f8a5e7e..b2e811193 100644 --- a/src/stubber/board/createstubs_lvgl.py +++ b/src/stubber/board/createstubs_lvgl.py @@ -433,7 +433,7 @@ def _info(): # type:() -> dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -447,13 +447,13 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]) + info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -464,19 +464,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -554,6 +542,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/src/stubber/board/createstubs_lvgl_min.py b/src/stubber/board/createstubs_lvgl_min.py index 69b505b09..2576dee94 100644 --- a/src/stubber/board/createstubs_lvgl_min.py +++ b/src/stubber/board/createstubs_lvgl_min.py @@ -1,31 +1,33 @@ -t='stubber' -s='{}/{}' -r='method' -q='function' -p='bool' -o='str' -n='float' -m='int' -l='micropython' -k=Exception -j=NameError -i=sorted -h=NotImplementedError -Z=',\n' -Y='dict' -X='list' -W='tuple' -V=open -U=repr -S='_' -R=len -Q=KeyError -P=IndexError -O=dir -M=print +v='stubber' +u='{}/{}' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n='micropython' +m=Exception +l=NameError +k=sorted +j=NotImplementedError +b=',\n' +a='dict' +Z='list' +Y='tuple' +X=open +W=repr +U='cpu' +T='_' +S=len +R=KeyError +Q=IndexError +P=dir +O=print N=ImportError -K=True +M='with' L='family' +K=True J='board' I='.' H=AttributeError @@ -36,51 +38,51 @@ F=OSError B='' import gc as C,os,sys -from ujson import dumps as a +from ujson import dumps as c try:from machine import reset except N:pass -try:from collections import OrderedDict as b -except N:from ucollections import OrderedDict as b +try:from collections import OrderedDict as d +except N:from ucollections import OrderedDict as d __version__='v1.16.2' -u=2 -v=2 -w=[I,'/lib','/sd/lib','/flash/lib','lib'] +w=2 +x=2 +y=[I,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise h('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') except H:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[L]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==n:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:c(path+G) - except F:M('error creating stub folder {}'.format(path)) + try:e(path+G) + except F:O('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in O(I): - if A.startswith(S)and not A in L.modules:continue + for A in P(I): + if A.startswith(T)and not A in L.modules:continue try: E=getattr(I,A) - try:F=U(type(E)).split("'")[1] - except P:F=B - if F in{m,n,o,p,W,X,Y}:G=1 - elif F in{q,r}:G=2 + try:F=W(type(E)).split("'")[1] + except Q:F=B + if F in{o,p,q,r,Y,Z,a}:G=1 + elif F in{s,t}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,U(E),U(type(E)),E,G)) + D.append((A,W(E),W(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) except MemoryError as K:sleep(1);reset() - D=i([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J - def add_modules(A,modules):A.modules=i(set(A.modules)|set(modules)) + D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) def create_all_stubs(A): C.collect() for B in A.modules:A.create_one_stub(B) @@ -94,84 +96,84 @@ def create_one_stub(B,module_name): C.collect();return E def create_module_stub(J,module_name,file_name=E): H=file_name;D=module_name - if H is E:O=D.replace(I,S)+'.py';H=J.path+G+O + if H is E:O=D.replace(I,T)+'.py';H=J.path+G+O else:O=H.split(G)[-1] if G in D:D=D.replace(G,I) L=E - try:L=__import__(D,E,E,'*');T=C.mem_free() + try:L=__import__(D,E,E,'*');S=C.mem_free() except N:return A - c(H) - with V(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) + e(H) + with X(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del L - except(F,Q):pass + except(F,R):pass try:del sys.modules[D] - except Q:pass + except R:pass C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;N='Exception';H=fp;D=indent;C.collect() - if O in K.problematic:return - S,L=K.get_obj_attributes(O) - if L:M(L) - for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',N]:continue + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;D=indent;C.collect() + if N in K.problematic:return + Q,L=K.get_obj_attributes(N) + if L:O(L) + for(E,J,G,T,f)in Q: + if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and R(D)<=v*4: - U=B;V=E.endswith(N)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=N + if G==""and S(D)<=x*4: + U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): - Z=b;a=B - if P>0:a='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,Z) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,Z) + elif any(A in G for A in[t,s,'closure']): + W=b;X=B + if P>0:X='self, ' + if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(h,g): - try:m=os.uname();A[D]=m.release - except(P,H,TypeError):pass - for(n,o,p)in[(i,i,'const'),(j,j,'FAT'),(k,'pybricks.hubs','EV3Brick')]: - try:q=__import__(o,E,E,p);A[L]=n;del q;break - except(N,Q):pass - if A[L]==k:A['release']='2.0.0' - if A[L]==l: + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=V(sys.version.split(';')[1]) + except(H,Q):pass + if A[F]and S(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(a,Z): + try:f=os.uname();A[D]=f.release + except(Q,H,TypeError):pass + for(g,h,i)in[(b,b,'const'),(c,c,'FAT'),(e,'pybricks.hubs','EV3Brick')]: + try:j=__import__(h,E,E,i);A[L]=g;del j;break + except(N,R):pass + if A[L]==e:A['release']='2.0.0' + if A[L]==n: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - V=int(A[K]);Y=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if Y:A[c]=Y - A[K]='v{}.{}'.format(V&255,V>>8&3) - A[Z]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def d(info,board_descr,filename): - with V(filename,'r')as C: + O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] + if W:A[Y]=W + A[K]='v{}.{}'.format(O&255,O>>8&3) + A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def z(info,desc=B): + G='with ';D=info;E=A + for F in[A+'/board_info.csv'for A in y]: + if g(F): + B=desc or D[J].strip() + if f(D,B,F):E=K;break + if M in B: + B=B.split(M)[0].strip() + if f(D,B,F):E=K;break + if not E: + B=desc or D[J].strip() + if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() + D[J]=B + D[J]=D[J].replace(' ',T);C.collect() +def f(info,board_descr,filename): + with X(filename,'r')as C: while 1: B=C.readline() if not B:break @@ -243,36 +250,36 @@ def get_root(): try:C=os.stat(B);break except F:continue return B -def e(filename): +def g(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def f():sys.exit(1) +def h():sys.exit(1) def read_path(): path=B - if R(sys.argv)==3: + if S(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:f() - elif R(sys.argv)==2:f() + else:h() + elif S(sys.argv)==2:h() return path -def g(): - try:B=bytes('abc',encoding='utf8');C=g.__module__;return A - except(h,H):return K +def i(): + try:B=bytes('abc',encoding='utf8');C=i.__module__;return A + except(j,H):return K def main(): D='lvgl' try:import lvgl as A - except k:return + except m:return B=D try:B='lvgl-{0}_{1}_{2}-{3}-{4}'.format(A.version_major(),A.version_minor(),A.version_patch(),A.version_info(),sys.platform) - except k:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) + except m:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) finally:stubber=Stubber(firmware_id=B) stubber.clean();stubber.modules=['io','lodepng','rtch',D];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or g(): - try:x=logging.getLogger(t);logging.basicConfig(level=logging.INFO) - except j:pass - if not e('no_auto_stubber.txt'): +if __name__=='__main__'or i(): + try:A0=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + except l:pass + if not g('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_lvgl_mpy.mpy b/src/stubber/board/createstubs_lvgl_mpy.mpy index b2bc3e029e3008b8eb9ca7c845b78bebf15f3beb..aa512aaf33e5fa9e0611a115ba33b81e4427fe25 100644 GIT binary patch delta 5263 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 dict[str, str] "build": "", "ver": "", "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "GENERIC", + "board": "UNKNOWN", "cpu": "", "mpy": "", "arch": "", @@ -453,13 +453,13 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]) + info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") except AttributeError: pass try: - machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = machine.strip() - info["cpu"] = machine.split("with")[1].strip() + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy if "_mpy" in dir(sys.implementation) @@ -470,19 +470,7 @@ def _info(): # type:() -> dict[str, str] except (AttributeError, IndexError): pass gc.collect() - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - # print("Found board info file: {}".format(filename)) - b = info["board"].strip() - if find_board(info, b, filename): - break - if "with" in b: - b = b.split("with")[0].strip() - if find_board(info, b, filename): - break - info["board"] = "GENERIC" - info["board"] = info["board"].replace(" ", "_") + read_boardname(info) gc.collect() try: @@ -560,6 +548,33 @@ def _info(): # type:() -> dict[str, str] return info +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + print("searching info file: {}".format(filename)) + if find_board(info, descr, filename): + found = True + break + if "with" in descr: + descr = descr.split("with")[0].strip() + print("searching for: {}".format(descr)) + if find_board(info, descr, filename): + found = True + break + if not found: + print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + def find_board(info: dict, board_descr: str, filename: str): "Find the board in the provided board_info.csv file" with open(filename, "r") as file: diff --git a/src/stubber/board/createstubs_mem_min.py b/src/stubber/board/createstubs_mem_min.py index 53bc8a3ae..af8f6e677 100644 --- a/src/stubber/board/createstubs_mem_min.py +++ b/src/stubber/board/createstubs_mem_min.py @@ -1,31 +1,33 @@ -u='stubber' -t='{}/{}' -s='method' -r='function' -q='bool' -p='str' -o='float' -n='int' -m=NameError -l=sorted -k=NotImplementedError -b=',\n' -a='dict' -Z='list' -Y='tuple' -X='micropython' -W=str -V=repr -T='_' -S=KeyError -R=open -Q=IndexError -P=dir -O=ImportError -N=True -M='family' -L=len -K=print +w='stubber' +v='{}/{}' +u='method' +t='function' +s='bool' +r='str' +q='float' +p='int' +o=NameError +n=sorted +m=NotImplementedError +d=',\n' +c='dict' +b='list' +a='tuple' +Z='micropython' +Y=str +X=repr +V='cpu' +U='_' +T=KeyError +S=open +R=IndexError +Q=dir +P=ImportError +O='with' +N='family' +M=len +L=print +K=True J='board' I='.' H=AttributeError @@ -36,51 +38,51 @@ F=OSError C='' import gc as B,os,sys -from ujson import dumps as c +from ujson import dumps as e try:from machine import reset -except O:pass -try:from collections import OrderedDict as d -except O:from ucollections import OrderedDict as d +except P:pass +try:from collections import OrderedDict as f +except P:from ucollections import OrderedDict as f __version__='v1.16.2' -v=2 -w=2 -e=[I,'/lib','/sd/lib','/flash/lib','lib'] +x=2 +y=2 +g=[I,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): C=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') except H:pass A._report=[];A.info=_info();B.collect() if C:A._fwid=C.lower() - elif A.info[M]==X:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[N]==Z:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:f(path+G) - except F:K('error creating stub folder {}'.format(path)) + try:h(path+G) + except F:L('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in P(I): - if A.startswith(T)and not A in L.modules:continue + for A in Q(I): + if A.startswith(U)and not A in L.modules:continue try: E=getattr(I,A) - try:F=V(type(E)).split("'")[1] - except Q:F=C - if F in{n,o,p,q,Y,Z,a}:G=1 - elif F in{r,s}:G=2 + try:F=X(type(E)).split("'")[1] + except R:F=C + if F in{p,q,r,s,a,b,c}:G=1 + elif F in{t,u}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,V(E),V(type(E)),E,G)) + D.append((A,X(E),X(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) except MemoryError as K:sleep(1);reset() - D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) + D=n([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J + def add_modules(A,modules):A.modules=n(set(A.modules)|set(modules)) def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) @@ -94,84 +96,84 @@ def create_one_stub(C,module_name): B.collect();return E def create_module_stub(J,module_name,file_name=E): H=file_name;D=module_name - if H is E:M=D.replace(I,T)+'.py';H=J.path+G+M - else:M=H.split(G)[-1] + if H is E:N=D.replace(I,U)+'.py';H=J.path+G+N + else:N=H.split(G)[-1] if G in D:D=D.replace(G,I) - K=E - try:K=__import__(D,E,E,'*');U=B.mem_free() - except O:return A - f(H) - with R(H,'w')as L:P=W(J.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);L.write(Q);L.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(L,K,D,C) + L=E + try:L=__import__(D,E,E,'*');R=B.mem_free() + except P:return A + h(H) + with S(H,'w')as M:O=Y(J.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,O,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,C) J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: - try:del K - except(F,S):pass + try:del L + except(F,T):pass try:del sys.modules[D] - except S:pass - B.collect();return N - def write_object_stub(M,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() - if P in M.problematic:return - R,N=M.get_obj_attributes(P) - if N:K(N) - for(E,J,G,T,f)in R: + except T:pass + B.collect();return K + def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): + d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() + if P in K.problematic:return + R,N=K.get_obj_attributes(P) + if N:L(N) + for(E,J,G,S,f)in R: if E in['classmethod','staticmethod','BaseException',O]:continue if E[0].isdigit():continue - if G==""and L(D)<=w*4: + if G==""and M(D)<=y*4: U=C;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return - H.write(A);M.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[s,r,'closure']): - W=b;X=C + H.write(A);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) + elif any(A in G for A in[u,t,'closure']): + W=Y;X=C if Q>0:X='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) + if Z in G or Z in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=C - if A[D]==C and sys.platform not in(k,j): - try:o=os.uname();A[D]=o.release - except(Q,H,TypeError):pass - for(p,q,r)in[(l,l,'const'),(m,m,'FAT'),(n,'pybricks.hubs','EV3Brick')]: - try:s=__import__(q,E,E,r);A[M]=p;del s;break - except(O,S):pass - if A[M]==n:A['release']='2.0.0' - if A[M]==X: + A[F]=W(os.uname()[3]) + if not A[F]:A[F]=W(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=W(sys.version.split(';')[1]) + except(H,R):pass + if A[F]and M(A[F])>5:A[F]=C + if A[D]==C and sys.platform not in(c,b): + try:h=os.uname();A[D]=h.release + except(R,H,TypeError):pass + for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: + try:l=__import__(j,E,E,k);A[N]=i;del l;break + except(P,T):pass + if A[N]==g:A['release']='2.0.0' + if A[N]==Z: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - V=int(A[K]);a=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if a:A[f]=a - A[K]='v{}.{}'.format(V&255,V>>8&3) - A[b]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def g(info,board_descr,filename): - with R(filename,'r')as C: + L=int(A[K]);U=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][L>>10] + if U:A[a]=U + A[K]='v{}.{}'.format(L&255,L>>8&3) + A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def z(info,desc=C): + G='with ';D=info;E=A + for F in[A+'/board_info.csv'for A in g]: + if j(F): + C=desc or D[J].strip() + if i(D,C,F):E=K;break + if O in C: + C=C.split(O)[0].strip() + if i(D,C,F):E=K;break + if not E: + C=desc or D[J].strip() + if G+D[V].upper()in C:C=C.split(G+D[V].upper())[0].strip() + D[J]=C + D[J]=D[J].replace(' ',U);B.collect() +def i(info,board_descr,filename): + with S(filename,'r')as C: while 1: B=C.readline() if not B:break D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return N + if D==board_descr:info[J]=E;return K return A def get_root(): try:A=os.getcwd() @@ -243,42 +250,42 @@ def get_root(): try:C=os.stat(B);break except F:continue return B -def h(filename): +def j(filename): try: - if os.stat(filename)[0]>>14:return N + if os.stat(filename)[0]>>14:return K return A except F:return A -def i():sys.exit(1) +def k():sys.exit(1) def read_path(): path=C - if L(sys.argv)==3: + if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:i() - elif L(sys.argv)==2:i() + else:k() + elif M(sys.argv)==2:k() return path -def j(): - try:B=bytes('abc',encoding='utf8');C=j.__module__;return A - except(k,H):return N +def l(): + try:B=bytes('abc',encoding='utf8');C=l.__module__;return A + except(m,H):return K def main(): E='/modulelist.txt';stubber=Stubber(path=read_path());stubber.clean();stubber.modules=[] - for C in e: + for C in g: try: F=B.mem_free() - with R(C+E)as D: - K('Debug: List of modules: '+C+E);A=D.readline() + with S(C+E)as D: + L('Debug: List of modules: '+C+E);A=D.readline() while A: A=A.strip() - if L(A)>0 and A[0]!='#':stubber.modules.append(A) + if M(A)>0 and A[0]!='#':stubber.modules.append(A) A=D.readline() - B.collect();K('Debug: Used memory to load modulelist.txt: '+W(F-B.mem_free())+' bytes');break + B.collect();L('Debug: Used memory to load modulelist.txt: '+Y(F-B.mem_free())+' bytes');break except Exception:pass - if not stubber.modules:stubber.modules=[X] + if not stubber.modules:stubber.modules=[Z] B.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or j(): - try:x=logging.getLogger(u);logging.basicConfig(level=logging.INFO) - except m:pass - if not h('no_auto_stubber.txt'): +if __name__=='__main__'or l(): + try:A0=logging.getLogger(w);logging.basicConfig(level=logging.INFO) + except o:pass + if not j('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mem_mpy.mpy b/src/stubber/board/createstubs_mem_mpy.mpy index 6edd7f8c5aa97432c91fabe4da220cfc9adb97d6..0b23f697f21268798fcfaf0aca3ed44f94dd16e5 100644 GIT binary patch delta 5443 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 delta 5172 zcmZ`dYfKwylHG0d3WR*!Gz|oT!QD2-hB%m}NoFP)#%>a0^1uN@oIsplm_QO9A&|$g z!Cjq+Hk*}pXP3Rv{=1d-PCA`NcbG>WB+LZJb7p5(y8SWB+%lv4u_v8QcdN;+?xfS5 zboJRLySmXOgs-Z;>Uw?kRn?dOJg~k$`$#rpGwnahKFsnzI{h!wyA0IiUY zxiBz1!9Xn+neAh}m4$~|kG39f3oyB7C*ng)c6@w_$-Xi;!Q@^Yo*bI}kZqj(2exYV zkF4EdTJmNk?&s{e*_T{x)eyrCGr5D;h9?7)w+6m&Wj zTxP@h8tH*9kAddqj|6nuqU5aHB(l8B&C-Vaa5OD48s8a*}Bw z#gb_?!sU`=X5msImEiAEsnj54Znk`9MVVw~M}vh1DMz%TqFgGEhVpxOxcs#qh=$m{ z;0}ZAO5k2)#V*OriH1tkn;lW4BiWWAvwfsWGILGI%rhlWc$g;D#7<*J&*pGDf|vq~erEa{RjTblCaNLPHh(luY6H0{G6G6~+y zC$5daA%0qA^xqmm8xL-=mWM8lmCOQ)xQPdsqB_lF(hl@y9N?#9Mr8v-!D8Ob66@_h zV>C8O!QEPhbI%qhFe(!b$MbI=&fQ&er{M?uE#erwmHT}@@xAKvE#KdEC(kj6mPiRw zBbnQIlffT1*V)KOunm2Io#+fyqBoF>?tqPMvz?7u5>y)$z^rlcW}z=fMP@#;iwVTZ zEZxQ|%A@YK`7mcfKFpc+aD4kua=$PVtOna)23WJm@Y(G)udMC1*&FKQM#nyF&-{AO zDU^sE8dKCmAb&&e&R`;ef-m%-0B7Vpl^w)$72rn3Sr0Q;3fqN!DqRZ&j7KNNV?l3U z5Z}`%ZHIqit_XKvDk3Cca6|8uw~1;er5Vj;njl@EKK20 z3yQwYmboqNiZM9SI;kK+>_AubaJ)g(agmAw#-#NY+ZV_?#G+cOqH^U$WvSwH}%6Qc1+%BR4ACt zvtYSkl0}5@hk&eFpKaZj=hPlrbhqsB;;Eo%BMSr+l{<9g1&VnW)fHm4b;%NDSNiHW z2skzFrCcJai@3exfnerp)=%$?P_v9-q^n$t06Olve;0LIHET57+lRc{Y1WkCcMJ3m z)>7L!{L4lcNeL+>;3iVNb@SKyXwd4)4kZW;m;e{t+*WJI7fSKe7CTRMr%KC(41Ft> z0!+p~(m!@w02fS|JI!*l!rWz68sl%fJ?@6a`evKErhcEzW`D!wwkclCUANojvGu79 z9$U3iUoP)_M!@r&K;4U_m-C-`2-JU;{KewuTjH0|1rF`XQ_p zvxkey61xd_3G8|3u_BYdQX!bS(4aAh@Q!l1d_(_h5a8+x%}(Y0KYpoy2pAows1ULD zp~kkBQGkFC!9s-)Xe6K#X!2M#oyAJA9(d>!-?h$5{J&|dw{DLryw z#jHs6{23<&{(NACs%ocqvk> zXd|`n&6IsxHu=8*M|ncFZ|DL4=Lpj4{T9}}ze4!-4AyLC8C5GOWvLpLE@nLh_7gbZ z$==k%cheeprHpFu|C2#E`%`sp0E4Aptg{e!8%g~HT9Ay(I|2;!J9lQj+^Liuj%2hJIm#7Y%fjHkHolL7vLdPutiKp+iq4J|S5?tW6`( zU%OLO37nY)tnp!;=5@Fu`;&NmztUUrGj=stgw3{rRxDiMAOdTl%uTtGzA52&AId$r zEA@{#Bn2rzuNCcpDG#uj`0ppe@!LUaQ682> z!T4Ddmc_lEy(!t$o}|XDZC#LHJJyf+bp6=9j>6j(sBoBkf}Go9?R?@X5`ZrItk6}VLTEFyyvE-UIJ}m`=o2`C0w^Sy z*>xLG&bJkJ_!HgG9 zn$^bN)-MD?DUBJyP&1$61DCxJ+L6upC~exY6#0AC-~+DG3p-ik?-beXZ0PZ5wrZni zbG%+*EDyz> zR1NJjKC#(sHNM@uZL*9|gV*J8dG#E5hF)7 z^n(kCCHyVHQtW=>Q6H1iC#rZyS5RBJVQkH!!3*RVj$V{SWjAqPrM4aO2Qj>KsIB4>+Ti+e`pIFWi6MvEx@CVR?mE~@FIpGG*Xs_GY)^+h= z7H*@{-|=4wQ=eeTeP&RVDOFA)j9^*)M78J#qxi=^`amI@dJJ0xwFf&38u%@yMB7rz zX#Yovw4^Q)NmZ5(RxWYMn>G!J8=^MoI1N{ zEK(nR+pm>JiHMHzxr*{s_SSFogERst9^;Q0Y~9c&QA%(DCq1mQL#aZB;db&0U(}O6 zB)s%6M#E+9cwI>6=gA4TC7C2qw`ESYl9O(W2Pe0Edn``DS>zOhyKu%)is+D&Fd3}O zR&197dOX$bDsJhdL-6H4pCbHObT2Z8IYUmZkRG&;J~`-%<7&!OeLS^bFYd#vi>DBB z`XBXZ8j5|XA4@@D+N>zly}Yuie{QTSqyNthA#Y_F{deNX#E>)OEa@k4GC&5&yW|`h zBEz11MY{7%#95-0=&ef0%H3{qUQ`vy4vF6@((P|<{vO-(GCdT%gIvHyM8k)e#`)XH z#SD&FeZPAp&OygJse#$R*Th^bf%7a*Z8-Vjq}&*Xmdxgh)G(d5nv`9yaHlDL>&&^z z5hyfyEb0I3sd75@tEtjGij&`)>kHzT#ynZX2gv9mp85DzzGaZ~WjOit*-~;t58a)k z*MyE<{+tAsaXQ`J>KG6%8UJ3_Xm4n82JVt8?Ts znZy!^1W#71y<#=hu4s!}YdMC;M;nqJZE<2dvM1v=@qbyS(Cq)f=V-7PMK{b*`+o2Z z4(JKAg6dCylbLM8@oOaeit%4UsdyDq<@i=8Sjtx+*CA7jp9W?om>n;ZIB z3ZaYmD8+bXZR%~5U`8I}OY#c7X8btoXShwQLTOsdT>K`{a}(1aSoZ}b0S=JwkQ-zM zA2^SN>7oQ43N;GOWSpm#O~(7e@gI`gf&$D3Is095t;c6~9;mgcPOqH(Siru<3fELd zHPH_2(;5@?FiCvPV9|)R|Cn718dyKlk6&!{BlB~w@Y!}~7~hoF<(&Cfh~i*PPx7h% z{1Pn}_(-_Aq_Q~8buAeY0$IP++mkp?(^ntHCC$4Oz?+nQn^Qr#m`)2@YW|?IuL$H& r!7ZI;Z(nK%ug^>i{(qfGI#F5xpRt1;Hf?EI5SpKh=HrrwOE~_&JA~PM diff --git a/src/stubber/board/createstubs_min.py b/src/stubber/board/createstubs_min.py index a74db7725..ee96441bf 100644 --- a/src/stubber/board/createstubs_min.py +++ b/src/stubber/board/createstubs_min.py @@ -1,34 +1,36 @@ -w='pyb' -v='stubber' -u='{}/{}' -t='logging' -s='sys' -r='method' -q='function' -p='bool' -o='str' -n='float' -m='int' -l=NameError -k=sorted -j=NotImplementedError -b='pycom' -a=',\n' -Z='dict' -Y='list' -X='tuple' -W='micropython' -V=open -U=repr -S='_' -R=len -Q=KeyError -P=IndexError -O=dir -M=print +y='pyb' +x='stubber' +w='{}/{}' +v='logging' +u='sys' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n=NameError +m=sorted +l=NotImplementedError +d='pycom' +c=',\n' +b='dict' +a='list' +Z='tuple' +Y='micropython' +X=open +W=repr +U='cpu' +T='_' +S=len +R=KeyError +Q=IndexError +P=dir +O=print N=ImportError -K=True +M='with' L='family' +K=True J='board' I='.' H=AttributeError @@ -39,51 +41,51 @@ D='version' B='' import gc as C,os,sys -from ujson import dumps as c +from ujson import dumps as e try:from machine import reset except N:pass -try:from collections import OrderedDict as d -except N:from ucollections import OrderedDict as d +try:from collections import OrderedDict as f +except N:from ucollections import OrderedDict as f __version__='v1.16.2' -x=2 -y=2 -z=[I,'/lib','/sd/lib','/flash/lib','lib'] +z=2 +A0=2 +A1=[I,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise l('MicroPython 1.13.0 cannot be stubbed') except H:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[L]==W:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==Y:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:e(path+G) - except F:M('error creating stub folder {}'.format(path)) + try:g(path+G) + except F:O('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): I=item_instance;D=[];J=[] - for A in O(I): - if A.startswith(S)and not A in L.modules:continue + for A in P(I): + if A.startswith(T)and not A in L.modules:continue try: E=getattr(I,A) - try:F=U(type(E)).split("'")[1] - except P:F=B - if F in{m,n,o,p,X,Y,Z}:G=1 - elif F in{q,r}:G=2 + try:F=W(type(E)).split("'")[1] + except Q:F=B + if F in{o,p,q,r,Z,a,b}:G=1 + elif F in{s,t}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,U(E),U(type(E)),E,G)) + D.append((A,W(E),W(type(E)),E,G)) except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) except MemoryError as K:sleep(1);reset() - D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J - def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) + D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) def create_all_stubs(A): C.collect() for B in A.modules:A.create_one_stub(B) @@ -97,84 +99,84 @@ def create_one_stub(B,module_name): C.collect();return E def create_module_stub(J,module_name,file_name=E): H=file_name;D=module_name - if H is E:O=D.replace(I,S)+'.py';H=J.path+G+O + if H is E:O=D.replace(I,T)+'.py';H=J.path+G+O else:O=H.split(G)[-1] if G in D:D=D.replace(G,I) L=E - try:L=__import__(D,E,E,'*');T=C.mem_free() + try:L=__import__(D,E,E,'*');S=C.mem_free() except N:return A - e(H) - with V(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) + g(H) + with X(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os',s,t,'gc'}: + if D not in{'os',u,v,'gc'}: try:del L - except(F,Q):pass + except(F,R):pass try:del sys.modules[D] - except Q:pass + except R:pass C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;N='Exception';H=fp;D=indent;C.collect() - if O in K.problematic:return - S,L=K.get_obj_attributes(O) - if L:M(L) - for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',N]:continue + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;D=indent;C.collect() + if N in K.problematic:return + Q,L=K.get_obj_attributes(N) + if L:O(L) + for(E,J,G,T,f)in Q: + if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and R(D)<=y*4: - U=B;V=E.endswith(N)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=N + if G==""and S(D)<=A0*4: + U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): - W=b;a=B - if P>0:a='self, ' + elif any(A in G for A in[t,s,'closure']): + W=Y;X=B + if P>0:X='self, ' if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(j,i): - try:m=os.uname();A[D]=m.release - except(P,H,TypeError):pass - for(n,o,p)in[(k,k,'const'),(b,b,'FAT'),(l,'pybricks.hubs','EV3Brick')]: - try:q=__import__(o,E,E,p);A[L]=n;del q;break - except(N,Q):pass - if A[L]==l:A['release']='2.0.0' - if A[L]==W: + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=V(sys.version.split(';')[1]) + except(H,Q):pass + if A[F]and S(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(b,a): + try:g=os.uname();A[D]=g.release + except(Q,H,TypeError):pass + for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(e,'pybricks.hubs','EV3Brick')]: + try:k=__import__(i,E,E,j);A[L]=h;del k;break + except(N,R):pass + if A[L]==e:A['release']='2.0.0' + if A[L]==Y: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - V=int(A[K]);Z=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][V>>10] - if Z:A[e]=Z - A[K]='v{}.{}'.format(V&255,V>>8&3) - A[a]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def f(info,board_descr,filename): - with V(filename,'r')as C: + O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] + if W:A[Z]=W + A[K]='v{}.{}'.format(O&255,O>>8&3) + A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def A2(info,desc=B): + G='with ';D=info;E=A + for F in[A+'/board_info.csv'for A in A1]: + if i(F): + B=desc or D[J].strip() + if h(D,B,F):E=K;break + if M in B: + B=B.split(M)[0].strip() + if h(D,B,F):E=K;break + if not E: + B=desc or D[J].strip() + if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() + D[J]=B + D[J]=D[J].replace(' ',T);C.collect() +def h(info,board_descr,filename): + with X(filename,'r')as C: while 1: B=C.readline() if not B:break @@ -246,28 +253,28 @@ def get_root(): try:C=os.stat(B);break except F:continue return B -def g(filename): +def i(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def h():sys.exit(1) +def j():sys.exit(1) def read_path(): path=B - if R(sys.argv)==3: + if S(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:h() - elif R(sys.argv)==2:h() + else:j() + elif S(sys.argv)==2:j() return path -def i(): - try:B=bytes('abc',encoding='utf8');C=i.__module__;return A - except(j,H):return K -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',W,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,b,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or i(): - try:A0=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except l:pass - if not g('no_auto_stubber.txt'): +def k(): + try:B=bytes('abc',encoding='utf8');C=k.__module__;return A + except(l,H):return K +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',y,d,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or k(): + try:A3=logging.getLogger(x);logging.basicConfig(level=logging.INFO) + except n:pass + if not i('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mpy.mpy b/src/stubber/board/createstubs_mpy.mpy index 80672bb8cad3af11ee358e5ea5250d5a68369569..cc71f0e4e7fdc218aa38a01a30038f8aafce13cb 100644 GIT binary patch delta 5819 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 IhiKxz0i)}9s{jB1 delta 5576 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 UyN2)BOBLHNbnsn*uUPWG0bnU7;s5{u From da82432ce28bc75b34ed60d4623f33c9d1f73b40 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 2 Jan 2024 23:58:52 +0100 Subject: [PATCH 16/68] Update get_boardnames.py and board_info.csv to get more board descriptions Signed-off-by: Jos Verlinde --- .gitignore | 1 + scripts/get_boardnames.py | 18 ++- src/stubber/board/board_info.csv | 234 ++++++++++++++++++------------- src/stubber/board/createstubs.py | 7 +- src/stubber/data/board_info.csv | 20 +++ src/stubber/data/board_info.json | 180 ++++++++++++++++++++++++ 6 files changed, 355 insertions(+), 105 deletions(-) diff --git a/.gitignore b/.gitignore index cd1548488..4b6a47857 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,4 @@ empty # do not check in any downloaded firmwares **/firmware tmp_minified.py +src/stubber/board/board_info.json diff --git a/scripts/get_boardnames.py b/scripts/get_boardnames.py index 2ff8bdb8a..0cc99647b 100644 --- a/scripts/get_boardnames.py +++ b/scripts/get_boardnames.py @@ -40,8 +40,8 @@ def default(self, o: object): # and the #define MICROPY_HW_MCU_NAME "STM32F767xx" -RE_BOARD_NAME = re.compile(r"#define MICROPY_HW_BOARD_NAME\s+\"(.+)\"") -RE_MCU_NAME = re.compile(r"#define MICROPY_HW_MCU_NAME\s+\"(.+)\"") +RE_BOARD_NAME = re.compile(r"#define\s+MICROPY_HW_BOARD_NAME\s+\"(.+)\"") +RE_MCU_NAME = re.compile(r"#define\s+MICROPY_HW_MCU_NAME\s+\"(.+)\"") RE_CMAKE_BOARD_NAME = re.compile(r"MICROPY_HW_BOARD_NAME\s?=\s?\"(?P[\w\s\S]*)\"") RE_CMAKE_MCU_NAME = re.compile(r"MICROPY_HW_MCU_NAME\s?=\s?\"(?P[\w\s\S]*)\"") # TODO: normal make files @@ -88,6 +88,19 @@ def collect_boardinfo(mpy_path: Path, version: str) -> List[Board]: ) ) found = 0 + if found == 1: + description = board_name + board_list.append( + Board( + port=port, + board=board, + board_name=board_name, + mcu_name=mcu_name, + description=description, + path=path.relative_to(mpy_path), + version=version, + ) + ) # look for variants in the .cmake files for path in mpy_path.glob("ports/**/mpconfigboard.cmake"): board = path.parent.name @@ -195,6 +208,7 @@ def main(): print(tabulate(board_list, headers="keys")) # type: ignore write_files(board_list, folder=Path("src/stubber/data")) + write_files(board_list, folder=Path("src/stubber/board")) if __name__ == "__main__": diff --git a/src/stubber/board/board_info.csv b/src/stubber/board/board_info.csv index bfc5016bc..d41eeacf9 100644 --- a/src/stubber/board/board_info.csv +++ b/src/stubber/board/board_info.csv @@ -1,115 +1,101 @@ board,description -LaunchPad with CC3200,LAUNCHXL -WiPy with CC3200,WIPY -ESP32-S2-WROVER with ESP32-S2,ESP32_S2_WROVER +4MB/OTA module with ESP32,GENERIC_OTA +Actinius Icarus with NRF9160,actinius_icarus +Adafruit Feather RP2040,ADAFRUIT_FEATHER_RP2040 +Adafruit Feather STM32F405 with STM32F405RG,ADAFRUIT_F405_EXPRESS +Adafruit ItsyBitsy RP2040,ADAFRUIT_ITSYBITSY_RP2040 +Adafruit Metro M7 with MIMXRT1011DAE5A,ADAFRUIT_METRO_M7 +Adafruit QT Py RP2040,ADAFRUIT_QTPY_RP2040 +Arduino GIGA R1 WiFi with STM32H747,ARDUINO_GIGA +Arduino Nano 33 BLE Sense with NRF52840,arduino_nano_33_ble_sense +Arduino Nano ESP32 with ESP32S3,ARDUINO_NANO_ESP32 +Arduino Nano RP2040 Connect,ARDUINO_NANO_RP2040_CONNECT +Arduino Nicla Vision with STM32H747,ARDUINO_NICLA_VISION +Arduino Portenta C33 with RA6M5,ARDUINO_PORTENTA_C33 +Arduino Portenta H7 with STM32H747,ARDUINO_PORTENTA_H7 +Arduino Primo with NRF52832,arduino_primo +B-L072Z-LRWAN1 with STM32L072CZ,B_L072Z_LRWAN1 +B-L475E-IOT01A with STM32L475,B_L475E_IOT01A +Bluefruit nRF52 Feather with NRF52832,feather52 +BLUEIO-TAG-EVIM with NRF52832,blueio_tag_evim +Cerb40 with STM32F405RG,CERB40 +CustomPCB with STM32F439,STM32F439 +DVK-BL652 with NRF52832,dvk_bl652 +EK-RA4M1 with RA4M1,EK_RA4M1 +EK-RA4W1 with RA4W1,EK_RA4W1 +EK-RA6M1 with RA6M1,EK_RA6M1 +EK-RA6M2 with RA6M2,EK_RA6M2 +ESP module (1M) with ESP8266,GENERIC_1M +ESP module (512K) with ESP8266,GENERIC_512K +ESP module with ESP8266,GENERIC +ESP32 module (spiram) with ESP32,GENERIC_SPIRAM ESP32 module with ESP32,GENERIC +ESP32 Unicore module with ESP32-UNICORE,GENERIC_UNICORE +ESP32-D2WD,ESP32_GENERIC +ESP32-S2-WROVER with ESP32-S2,ESP32_S2_WROVER +ESP32-UNICORE,ESP32_GENERIC ESP32C3 module with ESP32C3,GENERIC_C3 -ESP32C3 module with ESP32C3,GENERIC_C3_USB -Generic ESP32-D2WD module with ESP32-D2WD,GENERIC_D2WD -4MB/OTA module with ESP32,GENERIC_OTA ESP32S2 module with ESP32S2,GENERIC_S2 -ESP32S3 module with ESP32S3,GENERIC_S3 -ESP32S3 module (spiram) with ESP32S3,GENERIC_S3_SPIRAM ESP32S3 module (spiram octal) with ESP32S3,GENERIC_S3_SPIRAM_OCT -ESP32 module (spiram) with ESP32,GENERIC_SPIRAM -ESP32 Unicore module with ESP32-UNICORE,GENERIC_UNICORE -LILYGO TTGO LoRa32 with ESP32,LILYGO_TTGO_LORA32 -LOLIN_C3_MINI with ESP32-C3FH4,LOLIN_C3_MINI -LOLIN_S2_MINI with ESP32-S2FN4R2,LOLIN_S2_MINI -LOLIN_S2_PICO with ESP32-S2FN4R2,LOLIN_S2_PICO -M5Stack ATOM with ESP32-PICO-D4,M5STACK_ATOM -Olimex ESP32 ETH with ESP32,OLIMEX_ESP32_POE -Silicognition wESP32 with ESP32,SIL_WESP32 -FeatherS2 with ESP32-S2,UM_FEATHERS2 +ESP32S3 module (spiram) with ESP32S3,GENERIC_S3_SPIRAM +ESP32S3 module with ESP32S3,GENERIC_S3 +Espruino Pico with STM32F401CD,ESPRUINO_PICO +EVK_NINA_B1 with NRF52832,evk_nina_b1 +EVK_NINA_B3 with NRF52840,evk_nina_b3 +F411DISC with STM32F411,STM32F411DISC +F429I-DISCO with STM32F429,STM32F429DISC +F4DISC with STM32F407,STM32F4DISC +F769DISC with STM32F769,STM32F769DISC +F7DISC with STM32F746,STM32F7DISC +Feather M0 Express with SAMD21G18A,ADAFRUIT_FEATHER_M0_EXPRESS +Feather M4 Express with SAMD51J19A,ADAFRUIT_FEATHER_M4_EXPRESS FeatherS2 Neo with ESP32-S2FN4R2,UM_FEATHERS2NEO +FeatherS2 with ESP32-S2,UM_FEATHERS2 FeatherS3 with ESP32-S3,UM_FEATHERS3 -ProS3 with ESP32-S3,UM_PROS3 -TinyPICO with ESP32-PICO-D4,UM_TINYPICO -TinyS2 with ESP32-S2FN4R2,UM_TINYS2 -TinyS3 with ESP32-S3-FN8,UM_TINYS3 -ESP module with ESP8266,GENERIC -ESP module (1M) with ESP8266,GENERIC_1M -ESP module (512K) with ESP8266,GENERIC_512K +GARATRONIC_PYBSTICK26_RP2040,GARATRONIC_PYBSTICK26_RP2040 +Generic ESP32 module with ESP32,ESP32_GENERIC +Generic ESP32 module with OTA,ESP32_GENERIC +Generic ESP32 module with SPIRAM,ESP32_GENERIC +Generic ESP32-D2WD module with ESP32-D2WD,GENERIC_D2WD +Generic ESP32S2 module with ESP32S2,ESP32_GENERIC_S2 +Generic ESP32S3 module with ESP32S3,ESP32_GENERIC_S3 +Generic ESP32S3 module with Octal-SPIRAM,ESP32_GENERIC_S3 +GIGA with STM32H747,ARDUINO_GIGA +HydraBus1.0 with STM32F4,HYDRABUS i.MX RT1010 EVK with MIMXRT1011DAE5A,MIMXRT1010_EVK i.MX RT1015 EVK with MIMXRT1015DAF5A,MIMXRT1015_EVK i.MX RT1020 EVK with MIMXRT1021DAG5A,MIMXRT1020_EVK +i.MX RT1050 EVK with MIMXRT1052DVL6B,MIMXRT1050_EVK +i.MX RT1050 EVKB with MIMXRT1052DVL6B,MIMXRT1050_EVKB i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B,MIMXRT1050_EVK i.MX RT1060 EVK with MIMXRT1062DVJ6A,MIMXRT1060_EVK i.MX RT1064 EVK with MIMXRT1064DVL6A,MIMXRT1064_EVK i.MX RT1170 EVK with MIMXRT1176DVMAA,MIMXRT1170_EVK -RT1010-Py-DevKIT with MIMXRT1011DAE5A,OLIMEX_RT1010 -Seeed ARCH MIX with MIMXRT1052DVL5B,SEEED_ARCH_MIX -Teensy 4.0 with MIMXRT1062DVJ6A,TEENSY40 -Teensy 4.1 with MIMXRT1062DVJ6A,TEENSY41 -Actinius Icarus with NRF9160,actinius_icarus -Arduino Nano 33 BLE Sense with NRF52840,arduino_nano_33_ble_sense -Arduino Primo with NRF52832,arduino_primo -BLUEIO-TAG-EVIM with NRF52832,blueio_tag_evim -DVK-BL652 with NRF52832,dvk_bl652 -EVK_NINA_B1 with NRF52832,evk_nina_b1 -EVK_NINA_B3 with NRF52840,evk_nina_b3 -Bluefruit nRF52 Feather with NRF52832,feather52 IBK-BLYST-NANO with NRF52832,ibk_blyst_nano IDK-BLYST-NANO with NRF52832,idk_blyst_nano -micro:bit with NRF51822,microbit -MDK-USB-DONGLE with NRF52840,nrf52840-mdk-usb-dongle -XENON with NRF52840,particle_xenon -PCA10000 with NRF51822,pca10000 -PCA10001 with NRF51822,pca10001 -PCA10028 with NRF51822,pca10028 -PCA10031 with NRF51822,pca10031 -PCA10040 with NRF52832,pca10040 -PCA10056 with NRF52840,pca10056 -PCA10059 with NRF52840,pca10059 -PCA10090 with NRF9160,pca10090 -XIAO nRF52840 Sense with NRF52840,seeed_xiao_nrf52 -WT51822-S4AT with NRF51822,wt51822_s4at -RA4M1_CLICKER with RA4M1,RA4M1_CLICKER -RA4M1_EK with RA4M1,RA4M1_EK -RA4W1_EK with RA4W1,RA4W1_EK -RA6M1_EK with RA6M1,RA6M1_EK -RA6M2_EK with RA6M2,RA6M2_EK -Adafruit Feather RP2040,ADAFRUIT_FEATHER_RP2040 -Adafruit ItsyBitsy RP2040,ADAFRUIT_ITSYBITSY_RP2040 -Adafruit QT Py RP2040,ADAFRUIT_QTPY_RP2040 -Arduino Nano RP2040 Connect,ARDUINO_NANO_RP2040_CONNECT -GARATRONIC_PYBSTICK26_RP2040,GARATRONIC_PYBSTICK26_RP2040 -nullbits Bit-C PRO,NULLBITS_BIT_C_PRO -Raspberry Pi Pico,PICO -Raspberry Pi Pico W,PICO_W -Pimoroni Pico LiPo 16MB,PIMORONI_PICOLIPO_16MB -Pimoroni Pico LiPo 4MB,PIMORONI_PICOLIPO_4MB -Pimoroni Tiny 2040,PIMORONI_TINY2040 -SparkFun Pro Micro RP2040,SPARKFUN_PROMICRO -SparkFun Thing Plus RP2040,SPARKFUN_THINGPLUS -W5100S-EVB-Pico,W5100S_EVB_PICO -W5500-EVB-Pico,W5500_EVB_PICO -WeAct Studio RP2040,WEACTSTUDIO -Feather M0 Express with SAMD21G18A,ADAFRUIT_FEATHER_M0_EXPRESS -Feather M4 Express with SAMD51J19A,ADAFRUIT_FEATHER_M4_EXPRESS ItsyBitsy M0 Express with SAMD21G18A,ADAFRUIT_ITSYBITSY_M0_EXPRESS ItsyBitsy M4 Express with SAMD51G19A,ADAFRUIT_ITSYBITSY_M4_EXPRESS -Trinket M0 with SAMD21E18A,ADAFRUIT_TRINKET_M0 -Mini SAM M4 with SAMD51G19A,MINISAM_M4 -SAMD21-XPLAINED-PRO with SAMD21J18A,SAMD21_XPLAINED_PRO -Wio Terminal D51R with SAMD51P19A,SEEED_WIO_TERMINAL -Seeed Xiao with SAMD21G18A,SEEED_XIAO_SAMD21 -Sparkfun SAMD51 Thing Plus with SAMD51J20A,SPARKFUN_SAMD51_THING_PLUS -Adafruit Feather STM32F405 with STM32F405RG,ADAFRUIT_F405_EXPRESS -PORTENTA with STM32H747,ARDUINO_PORTENTA_H7 -B-L072Z-LRWAN1 with STM32L072CZ,B_L072Z_LRWAN1 -B-L475E-IOT01A with STM32L475,B_L475E_IOT01A -Cerb40 with STM32F405RG,CERB40 -Espruino Pico with STM32F401CD,ESPRUINO_PICO -NADHAT_PYBF405 with STM32F405RG,GARATRONIC_NADHAT_F405 -PYBSTICK26_STD with STM32F411RE,GARATRONIC_PYBSTICK26_F411 -HydraBus1.0 with STM32F4,HYDRABUS +L476-DISCO with STM32L476,STM32L476DISC +L496G-DISCO with STM32L496,STM32L496GDISC +LaunchPad with CC3200,LAUNCHXL LEGO Technic Hub No.6 with STM32F413,LEGO_HUB_NO6 LEGO Technic Hub No.7 with STM32F413,LEGO_HUB_NO7 +LILYGO TTGO LoRa32 with ESP32,LILYGO_TTGO_LORA32 LIMIFROG with STM32L476,LIMIFROG -MIKROE_CLICKER2_STM32 with STM32F407,MIKROE_CLICKER2_STM32 +LOLIN_C3_MINI with ESP32-C3FH4,LOLIN_C3_MINI +LOLIN_S2_MINI with ESP32-S2FN4R2,LOLIN_S2_MINI +LOLIN_S2_PICO with ESP32-S2FN4R2,LOLIN_S2_PICO +M5Stack ATOM with ESP32-PICO-D4,M5STACK_ATOM +MDK-USB-DONGLE with NRF52840,nrf52840-mdk-usb-dongle +Metro M4 Express Airlift with SAMD51J19A,ADAFRUIT_METRO_M4_EXPRESS +micro:bit with NRF51822,microbit MikroE Quail with STM32F427VI,MIKROE_QUAIL +MIKROE_CLICKER2_STM32 with STM32F407,MIKROE_CLICKER2_STM32 +Mini SAM M4 with SAMD51G19A,MINISAM_M4 +NADHAT_PYBF405 with STM32F405RG,NADHAT_PYBF405 +NanoS3 with ESP32-S3-FN8,UM_NANOS3 NetduinoPlus2 with STM32F405RG,NETDUINO_PLUS_2 +NICLAVISION with STM32H747,ARDUINO_NICLA_VISION NUCLEO-F091RC with STM32F091RCT6,NUCLEO_F091RC NUCLEO-F401RE with STM32F401xE,NUCLEO_F401RE NUCLEO-F411RE with STM32F411xE,NUCLEO_F411RE @@ -123,37 +109,85 @@ NUCLEO-F746ZG with STM32F746,NUCLEO_F746ZG NUCLEO-F756ZG with STM32F756,NUCLEO_F756ZG NUCLEO-F767ZI with STM32F767,NUCLEO_F767ZI NUCLEO-G0B1RE with STM32G0B1xE,NUCLEO_G0B1RE -NUCLEO_G474RE with STM32G474,NUCLEO_G474RE -NUCLEO_H743ZI with STM32H743,NUCLEO_H743ZI -NUCLEO_H743ZI2,NUCLEO_H743ZI2 NUCLEO-L073RZ with STM32L073RZT6,NUCLEO_L073RZ NUCLEO-L152RE with STM32L152xE,NUCLEO_L152RE NUCLEO-L432KC with STM32L432KC,NUCLEO_L432KC NUCLEO-L452RE with STM32L452RE,NUCLEO_L452RE NUCLEO-L476RG with STM32L476RG,NUCLEO_L476RG +NUCLEO-L4A6ZG with STM32L4A6ZG,NUCLEO_L4A6ZG NUCLEO-WB55 with STM32WB55RGV6,NUCLEO_WB55 NUCLEO-WL55 with STM32WL55JCI7,NUCLEO_WL55 +NUCLEO_G474RE with STM32G474,NUCLEO_G474RE +NUCLEO_H563ZI with STM32H563ZI,NUCLEO_H563ZI +NUCLEO_H723ZG with STM32H723ZGT6,NUCLEO_H723ZG +NUCLEO_H743ZI with STM32H743,NUCLEO_H743ZI +NUCLEO_H743ZI2,NUCLEO_H743ZI2 +nullbits Bit-C PRO,NULLBITS_BIT_C_PRO +Olimex ESP32 ETH with ESP32,OLIMEX_ESP32_POE OLIMEX STM32-E407 with STM32F407,OLIMEX_E407 OLIMEX STM32-H407 with STM32F407,OLIMEX_H407 +PCA10000 with NRF51822,pca10000 +PCA10001 with NRF51822,pca10001 +PCA10028 with NRF51822,pca10028 +PCA10031 with NRF51822,pca10031 +PCA10040 with NRF52832,pca10040 +PCA10056 with NRF52840,pca10056 +PCA10059 with NRF52840,pca10059 +PCA10090 with NRF9160,pca10090 +Pimoroni Pico LiPo 16MB,PIMORONI_PICOLIPO_16MB +Pimoroni Pico LiPo 4MB,PIMORONI_PICOLIPO_4MB +Pimoroni Tiny 2040,PIMORONI_TINY2040 +Pololu 3pi+ 2040 Robot,POLOLU_3PI_2040_ROBOT +Pololu Zumo 2040 Robot,POLOLU_ZUMO_2040_ROBOT +PORTENTA C33 with RA6M5,ARDUINO_PORTENTA_C33 +PORTENTA with STM32H747,ARDUINO_PORTENTA_H7 +ProS3 with ESP32-S3,UM_PROS3 PYBD-SF2W with STM32F722IEK,PYBD_SF2 PYBD-SF3W with STM32F733IEK,PYBD_SF3 PYBD-SF6W with STM32F767IIK,PYBD_SF6 PYBLITEv1.0 with STM32F411RE,PYBLITEV10 +PYBSTICK26_STD with STM32F411RE,GARATRONIC_PYBSTICK26_F411 PYBv1.0 with STM32F405RG,PYBV10 PYBv1.1 with STM32F405RG,PYBV11 PYBv3 with STM32F405RG,PYBV3 PYBv4 with STM32F405RG,PYBV4 +RA4M1 CLICKER with RA4M1,RA4M1_CLICKER +RA4M1_CLICKER with RA4M1,RA4M1_CLICKER +RA4M1_EK with RA4M1,RA4M1_EK +RA4W1_EK with RA4W1,RA4W1_EK +RA6M1_EK with RA6M1,RA6M1_EK +RA6M2_EK with RA6M2,RA6M2_EK +Raspberry Pi Pico,PICO +Raspberry Pi Pico W,PICO_W +RT1010-Py-DevKIT with MIMXRT1011DAE5A,OLIMEX_RT1010 +SAMD21-XPLAINED-PRO with SAMD21J18A,SAMD21_XPLAINED_PRO +Seeed ARCH MIX with MIMXRT1052DVL5B,SEEED_ARCH_MIX +Seeed Xiao with SAMD21G18A,SEEED_XIAO +Silicognition RP2040-Shim,SIL_RP2040_SHIM +Silicognition wESP32 with ESP32,SIL_WESP32 +SparkFun Pro Micro RP2040,SPARKFUN_PROMICRO +Sparkfun SAMD51 Thing Plus with SAMD51J20A,SPARKFUN_SAMD51_THING_PLUS SparkFun STM32 MicroMod Processor with STM32F405RG,SPARKFUN_MICROMOD_STM32 -F411DISC with STM32F411,STM32F411DISC -F429I-DISCO with STM32F429,STM32F429DISC -CustomPCB with STM32F439,STM32F439 -F4DISC with STM32F407,STM32F4DISC -F769DISC with STM32F769,STM32F769DISC -F7DISC with STM32F746,STM32F7DISC +SparkFun Thing Plus RP2040,SPARKFUN_THINGPLUS +STM32H573I-DK with STM32H573IIK3Q,STM32H573I_DK STM32H7B3I-DK with STM32H7B3LIH6Q,STM32H7B3I_DK -L476-DISCO with STM32L476,STM32L476DISC -L496G-DISCO with STM32L496,STM32L496GDISC +Teensy 4.0 with MIMXRT1062DVJ6A,TEENSY40 +Teensy 4.1 with MIMXRT1062DVJ6A,TEENSY41 +TinyPICO with ESP32-PICO-D4,TINYPICO +TinyS2 with ESP32-S2FN4R2,UM_TINYS2 +TinyS3 with ESP32-S3-FN8,UM_TINYS3 +TinyWATCH S3 with ESP32-S3-PICO-1-N8R2,UM_TINYWATCHS3 +Trinket M0 with SAMD21E18A,ADAFRUIT_TRINKET_M0 USBDongle-WB55 with STM32WB55CGU6,USBDONGLE_WB55 VCC-GND STM32F407VE with STM32F407VE,VCC_GND_F407VE VCC-GND STM32F407ZG with STM32F407ZG,VCC_GND_F407ZG VCC-GND STM32H743VI with STM32H743VI,VCC_GND_H743VI +VK-RA6M5 with RA6M5,VK_RA6M5 +W5100S-EVB-Pico,W5100S_EVB_PICO +W5500-EVB-Pico,W5500_EVB_PICO +WeAct Studio RP2040,WEACTSTUDIO +Wio Terminal D51R with SAMD51P19A,SEEED_WIO_TERMINAL +WiPy with CC3200,WIPY +WT51822-S4AT with NRF51822,wt51822_s4at +XENON with NRF52840,particle_xenon +XIAO nRF52840 Sense with NRF52840,seeed_xiao_nrf52 diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index 5908631ad..6127fd04e 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -478,7 +478,8 @@ def _info(): # type:() -> dict[str, str] if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore ) - info["board"] = "with".join(_machine.split("with")[:-1]).strip() + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy @@ -575,13 +576,13 @@ def read_boardname(info, desc: str = ""): # print("look up the board name in the file", filename) if file_exists(filename): descr = desc or info["board"].strip() - print("searching info file: {}".format(filename)) + print("searching info file: {} for: '{}'".format(filename, descr)) if find_board(info, descr, filename): found = True break if "with" in descr: descr = descr.split("with")[0].strip() - print("searching for: {}".format(descr)) + print("search(2) for: '{}'".format(descr)) if find_board(info, descr, filename): found = True break diff --git a/src/stubber/data/board_info.csv b/src/stubber/data/board_info.csv index 86c740e01..d41eeacf9 100644 --- a/src/stubber/data/board_info.csv +++ b/src/stubber/data/board_info.csv @@ -1,11 +1,15 @@ board,description 4MB/OTA module with ESP32,GENERIC_OTA Actinius Icarus with NRF9160,actinius_icarus +Adafruit Feather RP2040,ADAFRUIT_FEATHER_RP2040 Adafruit Feather STM32F405 with STM32F405RG,ADAFRUIT_F405_EXPRESS +Adafruit ItsyBitsy RP2040,ADAFRUIT_ITSYBITSY_RP2040 Adafruit Metro M7 with MIMXRT1011DAE5A,ADAFRUIT_METRO_M7 +Adafruit QT Py RP2040,ADAFRUIT_QTPY_RP2040 Arduino GIGA R1 WiFi with STM32H747,ARDUINO_GIGA Arduino Nano 33 BLE Sense with NRF52840,arduino_nano_33_ble_sense Arduino Nano ESP32 with ESP32S3,ARDUINO_NANO_ESP32 +Arduino Nano RP2040 Connect,ARDUINO_NANO_RP2040_CONNECT Arduino Nicla Vision with STM32H747,ARDUINO_NICLA_VISION Arduino Portenta C33 with RA6M5,ARDUINO_PORTENTA_C33 Arduino Portenta H7 with STM32H747,ARDUINO_PORTENTA_H7 @@ -48,6 +52,7 @@ Feather M4 Express with SAMD51J19A,ADAFRUIT_FEATHER_M4_EXPRESS FeatherS2 Neo with ESP32-S2FN4R2,UM_FEATHERS2NEO FeatherS2 with ESP32-S2,UM_FEATHERS2 FeatherS3 with ESP32-S3,UM_FEATHERS3 +GARATRONIC_PYBSTICK26_RP2040,GARATRONIC_PYBSTICK26_RP2040 Generic ESP32 module with ESP32,ESP32_GENERIC Generic ESP32 module with OTA,ESP32_GENERIC Generic ESP32 module with SPIRAM,ESP32_GENERIC @@ -116,6 +121,8 @@ NUCLEO_G474RE with STM32G474,NUCLEO_G474RE NUCLEO_H563ZI with STM32H563ZI,NUCLEO_H563ZI NUCLEO_H723ZG with STM32H723ZGT6,NUCLEO_H723ZG NUCLEO_H743ZI with STM32H743,NUCLEO_H743ZI +NUCLEO_H743ZI2,NUCLEO_H743ZI2 +nullbits Bit-C PRO,NULLBITS_BIT_C_PRO Olimex ESP32 ETH with ESP32,OLIMEX_ESP32_POE OLIMEX STM32-E407 with STM32F407,OLIMEX_E407 OLIMEX STM32-H407 with STM32F407,OLIMEX_H407 @@ -127,6 +134,11 @@ PCA10040 with NRF52832,pca10040 PCA10056 with NRF52840,pca10056 PCA10059 with NRF52840,pca10059 PCA10090 with NRF9160,pca10090 +Pimoroni Pico LiPo 16MB,PIMORONI_PICOLIPO_16MB +Pimoroni Pico LiPo 4MB,PIMORONI_PICOLIPO_4MB +Pimoroni Tiny 2040,PIMORONI_TINY2040 +Pololu 3pi+ 2040 Robot,POLOLU_3PI_2040_ROBOT +Pololu Zumo 2040 Robot,POLOLU_ZUMO_2040_ROBOT PORTENTA C33 with RA6M5,ARDUINO_PORTENTA_C33 PORTENTA with STM32H747,ARDUINO_PORTENTA_H7 ProS3 with ESP32-S3,UM_PROS3 @@ -145,13 +157,18 @@ RA4M1_EK with RA4M1,RA4M1_EK RA4W1_EK with RA4W1,RA4W1_EK RA6M1_EK with RA6M1,RA6M1_EK RA6M2_EK with RA6M2,RA6M2_EK +Raspberry Pi Pico,PICO +Raspberry Pi Pico W,PICO_W RT1010-Py-DevKIT with MIMXRT1011DAE5A,OLIMEX_RT1010 SAMD21-XPLAINED-PRO with SAMD21J18A,SAMD21_XPLAINED_PRO Seeed ARCH MIX with MIMXRT1052DVL5B,SEEED_ARCH_MIX Seeed Xiao with SAMD21G18A,SEEED_XIAO +Silicognition RP2040-Shim,SIL_RP2040_SHIM Silicognition wESP32 with ESP32,SIL_WESP32 +SparkFun Pro Micro RP2040,SPARKFUN_PROMICRO Sparkfun SAMD51 Thing Plus with SAMD51J20A,SPARKFUN_SAMD51_THING_PLUS SparkFun STM32 MicroMod Processor with STM32F405RG,SPARKFUN_MICROMOD_STM32 +SparkFun Thing Plus RP2040,SPARKFUN_THINGPLUS STM32H573I-DK with STM32H573IIK3Q,STM32H573I_DK STM32H7B3I-DK with STM32H7B3LIH6Q,STM32H7B3I_DK Teensy 4.0 with MIMXRT1062DVJ6A,TEENSY40 @@ -166,6 +183,9 @@ VCC-GND STM32F407VE with STM32F407VE,VCC_GND_F407VE VCC-GND STM32F407ZG with STM32F407ZG,VCC_GND_F407ZG VCC-GND STM32H743VI with STM32H743VI,VCC_GND_H743VI VK-RA6M5 with RA6M5,VK_RA6M5 +W5100S-EVB-Pico,W5100S_EVB_PICO +W5500-EVB-Pico,W5500_EVB_PICO +WeAct Studio RP2040,WEACTSTUDIO Wio Terminal D51R with SAMD51P19A,SEEED_WIO_TERMINAL WiPy with CC3200,WIPY WT51822-S4AT with NRF51822,wt51822_s4at diff --git a/src/stubber/data/board_info.json b/src/stubber/data/board_info.json index a47fdee8b..e38cc5f28 100644 --- a/src/stubber/data/board_info.json +++ b/src/stubber/data/board_info.json @@ -17,6 +17,15 @@ "path": "ports/nrf/boards/actinius_icarus/mpconfigboard.h", "version": "v1.13" }, + { + "description": "Adafruit Feather RP2040", + "port": "rp2", + "board": "ADAFRUIT_FEATHER_RP2040", + "board_name": "Adafruit Feather RP2040", + "mcu_name": "-", + "path": "ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h", + "version": "v1.15" + }, { "description": "Adafruit Feather STM32F405 with STM32F405RG", "port": "stm32", @@ -26,6 +35,15 @@ "path": "ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h", "version": "v1.12" }, + { + "description": "Adafruit ItsyBitsy RP2040", + "port": "rp2", + "board": "ADAFRUIT_ITSYBITSY_RP2040", + "board_name": "Adafruit ItsyBitsy RP2040", + "mcu_name": "-", + "path": "ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h", + "version": "v1.17" + }, { "description": "Adafruit Metro M7 with MIMXRT1011DAE5A", "port": "mimxrt", @@ -35,6 +53,15 @@ "path": "ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.h", "version": "v1.21.0" }, + { + "description": "Adafruit QT Py RP2040", + "port": "rp2", + "board": "ADAFRUIT_QTPY_RP2040", + "board_name": "Adafruit QT Py RP2040", + "mcu_name": "-", + "path": "ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h", + "version": "v1.17" + }, { "description": "Arduino GIGA R1 WiFi with STM32H747", "port": "stm32", @@ -62,6 +89,15 @@ "path": "ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.h", "version": "v1.21.0" }, + { + "description": "Arduino Nano RP2040 Connect", + "port": "rp2", + "board": "ARDUINO_NANO_RP2040_CONNECT", + "board_name": "Arduino Nano RP2040 Connect", + "mcu_name": "-", + "path": "ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h", + "version": "v1.18" + }, { "description": "Arduino Nicla Vision with STM32H747", "port": "stm32", @@ -440,6 +476,15 @@ "path": "ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h", "version": "v1.19.1" }, + { + "description": "GARATRONIC_PYBSTICK26_RP2040", + "port": "rp2", + "board": "GARATRONIC_PYBSTICK26_RP2040", + "board_name": "GARATRONIC_PYBSTICK26_RP2040", + "mcu_name": "-", + "path": "ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.h", + "version": "v1.18" + }, { "description": "Generic ESP32 module with ESP32", "port": "esp32", @@ -1052,6 +1097,24 @@ "path": "ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h", "version": "v1.10" }, + { + "description": "NUCLEO_H743ZI2", + "port": "stm32", + "board": "NUCLEO_H743ZI2", + "board_name": "NUCLEO_H743ZI2", + "mcu_name": "-", + "path": "ports/stm32/boards/NUCLEO_H743ZI2/mpconfigboard.h", + "version": "v1.17" + }, + { + "description": "nullbits Bit-C PRO", + "port": "rp2", + "board": "NULLBITS_BIT_C_PRO", + "board_name": "nullbits Bit-C PRO", + "mcu_name": "-", + "path": "ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.h", + "version": "v1.20.0" + }, { "description": "Olimex ESP32 ETH with ESP32", "port": "esp32", @@ -1151,6 +1214,51 @@ "path": "ports/nrf/boards/pca10090/mpconfigboard.h", "version": "v1.12" }, + { + "description": "Pimoroni Pico LiPo 16MB", + "port": "rp2", + "board": "PIMORONI_PICOLIPO_16MB", + "board_name": "Pimoroni Pico LiPo 16MB", + "mcu_name": "-", + "path": "ports/rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h", + "version": "v1.17" + }, + { + "description": "Pimoroni Pico LiPo 4MB", + "port": "rp2", + "board": "PIMORONI_PICOLIPO_4MB", + "board_name": "Pimoroni Pico LiPo 4MB", + "mcu_name": "-", + "path": "ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h", + "version": "v1.17" + }, + { + "description": "Pimoroni Tiny 2040", + "port": "rp2", + "board": "PIMORONI_TINY2040", + "board_name": "Pimoroni Tiny 2040", + "mcu_name": "-", + "path": "ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h", + "version": "v1.17" + }, + { + "description": "Pololu 3pi+ 2040 Robot", + "port": "rp2", + "board": "POLOLU_3PI_2040_ROBOT", + "board_name": "Pololu 3pi+ 2040 Robot", + "mcu_name": "-", + "path": "ports/rp2/boards/POLOLU_3PI_2040_ROBOT/mpconfigboard.h", + "version": "v1.22.0" + }, + { + "description": "Pololu Zumo 2040 Robot", + "port": "rp2", + "board": "POLOLU_ZUMO_2040_ROBOT", + "board_name": "Pololu Zumo 2040 Robot", + "mcu_name": "-", + "path": "ports/rp2/boards/POLOLU_ZUMO_2040_ROBOT/mpconfigboard.h", + "version": "v1.22.0" + }, { "description": "PORTENTA C33 with RA6M5", "port": "renesas-ra", @@ -1313,6 +1421,24 @@ "path": "ports/renesas-ra/boards/RA6M2_EK/mpconfigboard.h", "version": "v1.19.1" }, + { + "description": "Raspberry Pi Pico", + "port": "rp2", + "board": "PICO", + "board_name": "Raspberry Pi Pico", + "mcu_name": "-", + "path": "ports/rp2/boards/PICO/mpconfigboard.h", + "version": "v1.15" + }, + { + "description": "Raspberry Pi Pico W", + "port": "rp2", + "board": "PICO_W", + "board_name": "Raspberry Pi Pico W", + "mcu_name": "-", + "path": "ports/rp2/boards/PICO_W/mpconfigboard.h", + "version": "v1.20.0" + }, { "description": "RT1010-Py-DevKIT with MIMXRT1011DAE5A", "port": "mimxrt", @@ -1349,6 +1475,15 @@ "path": "ports/samd/boards/SEEED_XIAO/mpconfigboard.h", "version": "v1.18" }, + { + "description": "Silicognition RP2040-Shim", + "port": "rp2", + "board": "SIL_RP2040_SHIM", + "board_name": "Silicognition RP2040-Shim", + "mcu_name": "-", + "path": "ports/rp2/boards/SIL_RP2040_SHIM/mpconfigboard.h", + "version": "v1.22.0" + }, { "description": "Silicognition wESP32 with ESP32", "port": "esp32", @@ -1358,6 +1493,15 @@ "path": "ports/esp32/boards/SIL_WESP32/mpconfigboard.h", "version": "v1.17" }, + { + "description": "SparkFun Pro Micro RP2040", + "port": "rp2", + "board": "SPARKFUN_PROMICRO", + "board_name": "SparkFun Pro Micro RP2040", + "mcu_name": "-", + "path": "ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h", + "version": "v1.16" + }, { "description": "Sparkfun SAMD51 Thing Plus with SAMD51J20A", "port": "samd", @@ -1376,6 +1520,15 @@ "path": "ports/stm32/boards/SPARKFUN_MICROMOD_STM32/mpconfigboard.h", "version": "v1.17" }, + { + "description": "SparkFun Thing Plus RP2040", + "port": "rp2", + "board": "SPARKFUN_THINGPLUS", + "board_name": "SparkFun Thing Plus RP2040", + "mcu_name": "-", + "path": "ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h", + "version": "v1.16" + }, { "description": "STM32H573I-DK with STM32H573IIK3Q", "port": "stm32", @@ -1502,6 +1655,33 @@ "path": "ports/renesas-ra/boards/VK_RA6M5/mpconfigboard.h", "version": "v1.21.0" }, + { + "description": "W5100S-EVB-Pico", + "port": "rp2", + "board": "W5100S_EVB_PICO", + "board_name": "W5100S-EVB-Pico", + "mcu_name": "-", + "path": "ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.h", + "version": "v1.19.1" + }, + { + "description": "W5500-EVB-Pico", + "port": "rp2", + "board": "W5500_EVB_PICO", + "board_name": "W5500-EVB-Pico", + "mcu_name": "-", + "path": "ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.h", + "version": "v1.20.0" + }, + { + "description": "WeAct Studio RP2040", + "port": "rp2", + "board": "WEACTSTUDIO", + "board_name": "WeAct Studio RP2040", + "mcu_name": "-", + "path": "ports/rp2/boards/WEACTSTUDIO/mpconfigboard.h", + "version": "v1.20.0" + }, { "description": "Wio Terminal D51R with SAMD51P19A", "port": "samd", From 550162be33f6e348d4b4a42ad767607919923753 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 2 Jan 2024 23:59:27 +0100 Subject: [PATCH 17/68] Update function to handle edge cases This commit updates the function to handle edge cases, improving the overall reliability and robustness of the code. Signed-off-by: Jos Verlinde --- scripts/board_stubber.py | 107 ++++++++++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 29 deletions(-) diff --git a/scripts/board_stubber.py b/scripts/board_stubber.py index aecba9bd3..0ccc2e3c4 100644 --- a/scripts/board_stubber.py +++ b/scripts/board_stubber.py @@ -93,7 +93,11 @@ def run( output = [] try: proc = subprocess.Popen( - cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, + encoding="utf-8", ) except FileNotFoundError as e: raise FileNotFoundError(f"Failed to start {cmd[0]}") from e @@ -165,13 +169,15 @@ class Form(str, Enum): class MPRemoteBoard: """Class to run mpremote commands""" - def __init__(self, port: str = ""): - self.port = port + def __init__(self, serialport: str = ""): + self.serialport = serialport # self.board = "" self.firmware = {} self.uname: Optional[UName] = None self.connected = False self.path: Optional[Path] = None + self.description = "" + self.version = "" @staticmethod def connected_boards(): @@ -179,8 +185,41 @@ def connected_boards(): devices = [p.device for p in serial.tools.list_ports.comports()] return sorted(devices) + @retry(stop=stop_after_attempt(RETRIES), wait=wait_fixed(1)) + def get_mcu_info(self): + # TODO: switch from uname to sys.implementation os the primary source of info + rc, result = self.run_command( + [ + "exec", + "import sys;print(repr(sys.implementation) if 'implementation' in dir(sys) else 'no.implementation');print(sys.platform)", + ], + no_info=True, + ) + if rc == 0: + s = result[0] + if "name=" in s: + implementation = eval(f"dict{s}") + self.version = ".".join([str(n) for n in implementation["version"]]) + self.description = implementation["_machine"] + if len(result) > 1: + self.port = result[1].strip() + @retry(stop=stop_after_attempt(RETRIES), wait=wait_fixed(1)) def get_uname(self): + # TODO: switch from uname to sys.implementation os the primary source of info + rc, result = self.run_command( + [ + "exec", + "import sys;print(repr(sys.implementation) if 'implementation' in dir(sys) else 'no.implementation')", + ], + no_info=True, + ) + s = result[0] + if "name=" in s: + implementation = eval(f"dict{s}") + version = ".".join([str(n) for n in implementation["version"]]) + UName("implementation", implementation.name, version, version, "?") + rc, result = self.run_command( ["exec", "import os;print(os.uname() if 'uname' in dir(os) else 'no.uname')"], no_info=True, @@ -199,11 +238,11 @@ def disconnect(self) -> bool: """Disconnect from a board""" if not self.connected: return True - if not self.port: + if not self.serialport: log.error("No port connected") self.connected = False return False - log.info(f"Disconnecting from {self.port}") + log.info(f"Disconnecting from {self.serialport}") result = self.run_command(["disconnect"])[0] == OK self.connected = False return result @@ -232,7 +271,7 @@ def run_command( """ if isinstance(cmd, str): cmd = cmd.split(" ") - prefix = ["mpremote", "connect", self.port] if self.port else ["mpremote"] + prefix = ["mpremote", "connect", self.serialport] if self.serialport else ["mpremote"] # if connected add resume to keep state between commands if self.connected: prefix += ["resume"] @@ -259,7 +298,6 @@ def copy_createstubs(board: MPRemoteBoard, variant: Variant, form: Form) -> bool origin = "./src/stubber/board" _py = [ - "rm :no_auto_stubber.txt", "rm :lib/createstubs.mpy", "rm :lib/createstubs_mem.mpy", "rm :lib/createstubs_db.mpy", @@ -296,9 +334,8 @@ def copy_createstubs(board: MPRemoteBoard, variant: Variant, form: Form) -> bool _get_ready = [ "rm :modulelist.done", - # "rm :lib/modulelist.txt", + "rm :no_auto_stubber.txt", f"cp {origin}/modulelist.txt :lib/modulelist.txt", - # "cp ./board_info.csv :lib/board_info.csv", ] if form == Form.py: do = _lib + _py + _get_ready @@ -344,19 +381,20 @@ def run_createstubs(dest: Path, board: MPRemoteBoard, variant: Variant = Variant board.run_command(cmd_path, timeout=5) if reset_before: - log.info(f"Resetting {board.port} {board.uname[4] if board.uname else ''}") + log.info(f"Resetting {board.serialport} {board.uname[4] if board.uname else ''}") board.run_command("reset", timeout=5) time.sleep(2) log.info( - f"Running createstubs {variant} on {board.port} {board.uname[4] if board.uname else ''}" + f"Running createstubs {variant} on {board.serialport} {board.uname[4] if board.uname else ''} using temp path: {dest}" ) cmd = build_cmd(dest, variant) board.run_command.retry.wait = wait_fixed(15) # some boards need 2-3 minutes to run createstubs - so increase the default timeout + # esp32s3 > 240 seconds with mounted fs # but slows down esp8266 restarts so keep that to 60 seconds - timeout = 60 if board.uname.nodename == "esp8266" else 4 * 60 # type: ignore + timeout = 60 if board.port == "esp8266" else 6 * 60 # type: ignore rc, out = board.run_command(cmd, timeout=timeout) # check last line for exception or error and raise that if found if ( @@ -387,7 +425,11 @@ def build_cmd(dest: Path, variant: Variant = Variant.db): def generate_board_stubs( - dest: Path, mcu: MPRemoteBoard, variant: Variant = Variant.db, form: Form = Form.mpy + dest: Path, + mcu: MPRemoteBoard, + variant: Variant = Variant.db, + form: Form = Form.mpy, + host_mounted=True, ) -> Tuple[int, Optional[Path]]: """ Generate the board stubs. @@ -399,7 +441,6 @@ def generate_board_stubs( The port the board is connected to """ - # board_info_path = Path(__file__).parent.parent / "board_info.csv" board_info_path = Path(__file__).parent.parent / "src/stubber/data/board_info.csv" # HOST -> MCU : copy createstubs to board if LOCAL_FILES: @@ -417,18 +458,28 @@ def generate_board_stubs( if not ok and not TESTING: log.warning("Error copying createstubs to board") return ERROR, None - # HOST: remove .done file - (dest / "modulelist.done").unlink(missing_ok=True) - # HOST: copy board_info.csv to destination - shutil.copyfile(board_info_path, dest / "board_info.csv") - # MCU: add lib to path - rc, out = run_createstubs(dest, mcu, variant) + if host_mounted: + # HOST: remove .done file + (dest / "modulelist.done").unlink(missing_ok=True) + # HOST: copy board_info.csv to destination + shutil.copyfile(board_info_path, dest / "board_info.csv") + else: + cmd = f"cp {board_info_path} :board_info.csv" + rc, _ = board.run_command(cmd) + if rc != OK and "rm" not in cmd: + log.error(f"Error during copy createstubs running command: {cmd}") + + rc, out = run_createstubs(dest, mcu, variant) # , host_mounted=host_mounted) if rc != OK: log.warning("Error running createstubs: %s", out) return ERROR, None + if not host_mounted: + # Waiting for MPRemote to support copying folder from board to host + raise NotImplementedError("TODO: Copy stubs from board to host") + # Find the output starting with 'Path: ' folder = get_stubfolder(out) if not folder: @@ -478,13 +529,13 @@ def scan_boards(optimistic: bool = False) -> List[MPRemoteBoard]: boards = [] for mpr_port in MPRemoteBoard.connected_boards(): board = MPRemoteBoard(mpr_port) - log.info(f"Attempt to connect to: {board.port}") + log.info(f"Attempt to connect to: {board.serialport}") try: - _, uname = board.get_uname() - log.success(f"Detected board {uname.machine} {uname.release}") + board.get_mcu_info() + log.success(f"Detected board {board.description} {board.version}") boards.append(board) except Exception: - log.error(f"Failed to get uname for {board.port}") + log.error(f"Failed to get mcu_info for {board.serialport}") if optimistic: boards.append(board) continue @@ -539,8 +590,6 @@ def copy_to_repo(source: Path, fw: dict) -> Optional[Path]: tempdir = mkdtemp(prefix="board_stubber") dest = Path(tempdir) - # copy board_info.csv to the folder - # shutil.copyfile(Path("board_info.csv"), dest / "board_info.csv") # scan boards and just work with the ones that reponded with understandable data connected_boards = scan_boards(True) @@ -548,11 +597,11 @@ def copy_to_repo(source: Path, fw: dict) -> Optional[Path]: log.error("No micropython boards were found") sys.exit(1) - print(tabulate([[b.port] + (list(b.uname) if b.uname else ["unable to connect"]) for b in connected_boards])) # type: ignore + print(tabulate([[b.serialport, b.port, b.description, b.version] for b in connected_boards])) # type: ignore # scan boards and generate stubs for board in connected_boards: - log.info(f"Connecting to {board.port} {board.uname[4] if board.uname else ''}") + log.info(f"Connecting to {board.serialport} {board.uname[4] if board.uname else ''}") rc, my_stubs = generate_board_stubs(dest, board, variant, form) if rc == OK and my_stubs: log.success(f'Stubs generated for {board.firmware["port"]}-{board.firmware["board"]}') @@ -573,4 +622,4 @@ def copy_to_repo(source: Path, fw: dict) -> Optional[Path]: # Then Build the package else: - log.error(f"Failed to generate stubs for {board.port}") + log.error(f"Failed to generate stubs for {board.serialport}") From aaed16be7f4ccad49116343cadd0a7d6f07b4a85 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 2 Jan 2024 23:59:39 +0100 Subject: [PATCH 18/68] Refactor board name search in createstubs.py Signed-off-by: Jos Verlinde --- src/stubber/board/createstubs.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index 6127fd04e..85421cd2d 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -576,16 +576,15 @@ def read_boardname(info, desc: str = ""): # print("look up the board name in the file", filename) if file_exists(filename): descr = desc or info["board"].strip() - print("searching info file: {} for: '{}'".format(filename, descr)) - if find_board(info, descr, filename): + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): found = True break - if "with" in descr: - descr = descr.split("with")[0].strip() - print("search(2) for: '{}'".format(descr)) - if find_board(info, descr, filename): - found = True - break if not found: print("Board not found, guessing board name") descr = desc or info["board"].strip() @@ -597,18 +596,30 @@ def read_boardname(info, desc: str = ""): gc.collect() -def find_board(info: dict, board_descr: str, filename: str): +def find_board(info: dict, descr: str, filename: str, short_descr: str): "Find the board in the provided board_info.csv file" + short_hit = "" with open(filename, "r") as file: # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) while 1: line = file.readline() if not line: break descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == board_descr: + if descr_ == descr: info["board"] = board_ return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True return False From afb73f6c056ba6ca29dd4267f3b1689638e18ef6 Mon Sep 17 00:00:00 2001 From: Josverl Date: Tue, 2 Jan 2024 23:01:09 +0000 Subject: [PATCH 19/68] Update mip packages --- mip/v5/createstubs.py | 36 ++- mip/v5/createstubs_db.py | 36 ++- mip/v5/createstubs_db_min.py | 304 +++++++++--------- mip/v5/createstubs_db_mpy.mpy | Bin 8748 -> 8786 bytes mip/v5/createstubs_lvgl.py | 36 ++- mip/v5/createstubs_lvgl_min.py | 296 +++++++++--------- mip/v5/createstubs_lvgl_mpy.mpy | Bin 8198 -> 8236 bytes mip/v5/createstubs_mem.py | 36 ++- mip/v5/createstubs_mem_min.py | 338 ++++++++++---------- mip/v5/createstubs_mem_mpy.mpy | Bin 8236 -> 8275 bytes mip/v5/createstubs_min.py | 302 +++++++++--------- mip/v5/createstubs_mpy.mpy | Bin 10809 -> 10848 bytes mip/v6/createstubs.py | 36 ++- mip/v6/createstubs_db.py | 36 ++- mip/v6/createstubs_db_min.py | 304 +++++++++--------- mip/v6/createstubs_db_mpy.mpy | Bin 8556 -> 8613 bytes mip/v6/createstubs_lvgl.py | 36 ++- mip/v6/createstubs_lvgl_min.py | 296 +++++++++--------- mip/v6/createstubs_lvgl_mpy.mpy | Bin 8033 -> 8090 bytes mip/v6/createstubs_mem.py | 36 ++- mip/v6/createstubs_mem_min.py | 338 ++++++++++---------- mip/v6/createstubs_mem_mpy.mpy | Bin 8067 -> 8124 bytes mip/v6/createstubs_min.py | 302 +++++++++--------- mip/v6/createstubs_mpy.mpy | Bin 11085 -> 11142 bytes src/stubber/board/createstubs_db.py | 34 +- src/stubber/board/createstubs_db_min.py | 320 +++++++++---------- src/stubber/board/createstubs_db_mpy.mpy | Bin 8544 -> 8590 bytes src/stubber/board/createstubs_lvgl.py | 34 +- src/stubber/board/createstubs_lvgl_min.py | 308 +++++++++--------- src/stubber/board/createstubs_lvgl_mpy.mpy | Bin 8020 -> 8066 bytes src/stubber/board/createstubs_mem.py | 34 +- src/stubber/board/createstubs_mem_min.py | 348 +++++++++++---------- src/stubber/board/createstubs_mem_mpy.mpy | Bin 8055 -> 8101 bytes src/stubber/board/createstubs_min.py | 314 ++++++++++--------- src/stubber/board/createstubs_mpy.mpy | Bin 11077 -> 11120 bytes 35 files changed, 2170 insertions(+), 1990 deletions(-) diff --git a/mip/v5/createstubs.py b/mip/v5/createstubs.py index af07c6418..85421cd2d 100644 --- a/mip/v5/createstubs.py +++ b/mip/v5/createstubs.py @@ -469,7 +469,7 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]) + info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") except AttributeError: pass try: @@ -478,7 +478,8 @@ def _info(): # type:() -> dict[str, str] if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore ) - info["board"] = "with".join(_machine.split("with")[:-1]).strip() + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy @@ -575,16 +576,15 @@ def read_boardname(info, desc: str = ""): # print("look up the board name in the file", filename) if file_exists(filename): descr = desc or info["board"].strip() - print("searching info file: {}".format(filename)) - if find_board(info, descr, filename): + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): found = True break - if "with" in descr: - descr = descr.split("with")[0].strip() - print("searching for: {}".format(descr)) - if find_board(info, descr, filename): - found = True - break if not found: print("Board not found, guessing board name") descr = desc or info["board"].strip() @@ -596,18 +596,30 @@ def read_boardname(info, desc: str = ""): gc.collect() -def find_board(info: dict, board_descr: str, filename: str): +def find_board(info: dict, descr: str, filename: str, short_descr: str): "Find the board in the provided board_info.csv file" + short_hit = "" with open(filename, "r") as file: # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) while 1: line = file.readline() if not line: break descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == board_descr: + if descr_ == descr: info["board"] = board_ return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True return False diff --git a/mip/v5/createstubs_db.py b/mip/v5/createstubs_db.py index ecb9ffe19..7a9761f7e 100644 --- a/mip/v5/createstubs_db.py +++ b/mip/v5/createstubs_db.py @@ -462,12 +462,13 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]) + info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") except AttributeError: pass try: _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = "with".join(_machine.split("with")[:-1]).strip() + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy @@ -563,16 +564,15 @@ def read_boardname(info, desc: str = ""): # print("look up the board name in the file", filename) if file_exists(filename): descr = desc or info["board"].strip() - print("searching info file: {}".format(filename)) - if find_board(info, descr, filename): + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): found = True break - if "with" in descr: - descr = descr.split("with")[0].strip() - print("searching for: {}".format(descr)) - if find_board(info, descr, filename): - found = True - break if not found: print("Board not found, guessing board name") descr = desc or info["board"].strip() @@ -584,18 +584,30 @@ def read_boardname(info, desc: str = ""): gc.collect() -def find_board(info: dict, board_descr: str, filename: str): +def find_board(info: dict, descr: str, filename: str, short_descr: str): "Find the board in the provided board_info.csv file" + short_hit = "" with open(filename, "r") as file: # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) while 1: line = file.readline() if not line: break descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == board_descr: + if descr_ == descr: info["board"] = board_ return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True return False diff --git a/mip/v5/createstubs_db_min.py b/mip/v5/createstubs_db_min.py index 8f5a7e7f8..751c0c400 100644 --- a/mip/v5/createstubs_db_min.py +++ b/mip/v5/createstubs_db_min.py @@ -1,37 +1,37 @@ -x='stubber' -w='{}/{}' -v='method' -u='function' -t='bool' -s='str' -r='float' -q='int' -p=NameError -o=sorted -n=MemoryError -m=NotImplementedError -d=',\n' -c='dict' -b='list' -a='tuple' -Z='micropython' -Y=str -X=repr -V='cpu' -U='_' -T=KeyError -S=IndexError -R=dir -Q=ImportError -P='with' +w='with' +v='stubber' +u='{}/{}' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n=NameError +m=sorted +l=MemoryError +k=NotImplementedError +c=',\n' +b='dict' +a='list' +Z='tuple' +Y='micropython' +X=str +W=repr +U='cpu' +T='_' +S=KeyError +R=IndexError +Q=dir +P=ImportError O='family' N=print M=len L='.' -K='board' +K=open J=True -I=open -H=AttributeError +I=AttributeError +H='board' G='/' F=None E='version' @@ -39,51 +39,51 @@ A=OSError C='' import gc as B,os,sys -from ujson import dumps as e +from ujson import dumps as d try:from machine import reset -except Q:pass -try:from collections import OrderedDict as f -except Q:from ucollections import OrderedDict as f +except P:pass +try:from collections import OrderedDict as e +except P:from ucollections import OrderedDict as e __version__='v1.16.2' +x=2 y=2 -z=2 -g=[L,'/lib','/sd/lib','/flash/lib','lib'] +f=[L,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(C,path=F,firmware_id=F): D=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') - except H:pass + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + except I:pass C._report=[];C.info=_info();B.collect() if D:C._fwid=D.lower() - elif C.info[O]==Z:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) + elif C.info[O]==Y:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) else:C._fwid='{family}-{ver}-{port}'.format(**C.info) C._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) - try:h(path+G) + try:g(path+G) except A:N('error creating stub folder {}'.format(path)) C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] def get_obj_attributes(L,item_instance): - I=item_instance;D=[];J=[] - for A in R(I): - if A.startswith(U)and not A in L.modules:continue + H=item_instance;D=[];J=[] + for A in Q(H): + if A.startswith(T)and not A in L.modules:continue try: - E=getattr(I,A) - try:F=X(type(E)).split("'")[1] - except S:F=C - if F in{q,r,s,t,a,b,c}:G=1 - elif F in{u,v}:G=2 + E=getattr(H,A) + try:F=W(type(E)).split("'")[1] + except R:F=C + if F in{o,p,q,r,Z,a,b}:G=1 + elif F in{s,t}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,X(E),X(type(E)),E,G)) - except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) - except n as K:sleep(1);reset() - D=o([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) + D.append((A,W(E),W(type(E)),E,G)) + except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) + except l as K:sleep(1);reset() + D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J + def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) @@ -95,86 +95,86 @@ def create_one_stub(C,module_name): try:F=C.create_module_stub(E,H) except A:return D B.collect();return F - def create_module_stub(K,module_name,file_name=F): + def create_module_stub(I,module_name,file_name=F): H=file_name;E=module_name - if H is F:O=E.replace(L,U)+'.py';H=K.path+G+O + if H is F:O=E.replace(L,T)+'.py';H=I.path+G+O else:O=H.split(G)[-1] if G in E:E=E.replace(G,L) M=F - try:M=__import__(E,F,F,'*');S=B.mem_free() - except Q:return D - h(H) - with I(H,'w')as N:P=Y(K.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(E,K._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,M,E,C) - K._report.append('{{"module": "{}", "file": "{}"}}'.format(E,H.replace('\\',G))) + try:M=__import__(E,F,F,'*');U=B.mem_free() + except P:return D + g(H) + with K(H,'w')as N:Q=X(I.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(E,I._fwid,Q,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,E,C) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(E,H.replace('\\',G))) if E not in{'os','sys','logging','gc'}: try:del M - except(A,T):pass + except(A,S):pass try:del sys.modules[E] - except T:pass + except S:pass B.collect();return J def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() if P in K.problematic:return R,L=K.get_obj_attributes(P) if L:N(L) - for(F,J,G,S,f)in R: + for(F,J,G,T,f)in R: if F in['classmethod','staticmethod','BaseException',O]:continue if F[0].isdigit():continue - if G==""and M(E)<=z*4: + if G==""and M(E)<=y*4: U=C;V=F.endswith(O)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O D='\n{}class {}({}):\n'.format(E,F,U) if V:D+=E+' ...\n';H.write(D);return - H.write(D);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) - elif any(A in G for A in[v,u,'closure']): + H.write(D);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) + elif any(A in G for A in[t,s,'closure']): W=Y;X=C if Q>0:X='self, ' - if Z in G or Z in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) + if c in G or c in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,X,W) D+=E+' ...\n\n';H.write(D) elif G=="":0 elif G.startswith("5:A[D]=C - if A[E]==C and sys.platform not in(c,b): - try:h=os.uname();A[E]=h.release - except(S,H,TypeError):pass - for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: - try:l=__import__(j,F,F,k);A[O]=i;del l;break - except(Q,T):pass - if A[O]==g:A['release']='2.0.0' - if A[O]==Z: + if A[E]==C and sys.platform not in(b,a): + try:g=os.uname();A[E]=g.release + except(R,I,TypeError):pass + for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(f,'pybricks.hubs','EV3Brick')]: + try:k=__import__(i,F,F,j);A[O]=h;del k;break + except(P,S):pass + if A[O]==f:A['release']='2.0.0' + if A[O]==Y: if A[E]and A[E].endswith('.0')and A[E]>='1.10.0'and A[E]<='1.19.9':A[E]=A[E][:-2] - if I in A and A[I]: - J=int(A[I]);U=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][J>>10] - if U:A[a]=U - A[I]='v{}.{}'.format(J&255,J>>8&3) - A[X]=f"v{A[E]}-{A[D]}"if A[D]else f"v{A[E]}";return A -def A0(info,desc=C): - G='with ';C=info;E=D - for F in[A+'/board_info.csv'for A in g]: - if j(F): - A=desc or C[K].strip() - if i(C,A,F):E=J;break - if P in A: - A=A.split(P)[0].strip() - if i(C,A,F):E=J;break - if not E: - A=desc or C[K].strip() - if G+C[V].upper()in A:A=A.split(G+C[V].upper())[0].strip() - C[K]=A - C[K]=C[K].replace(' ',U);B.collect() -def i(info,board_descr,filename): - with I(filename,'r')as B: + if J in A and A[J]: + K=int(A[J]);T=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if T:A[Z]=T + A[J]='v{}.{}'.format(K&255,K>>8&3) + A[W]=f"v{A[E]}-{A[D]}"if A[D]else f"v{A[E]}";return A +def z(info,desc=C): + L='with ';A=info;F=D + for G in[A+'/board_info.csv'for A in f]: + if h(G): + E=desc or A[H].strip();I=E.rfind(' with') + if I!=-1:K=E[:I].strip() + else:K=C + if A0(A,E,G,K):F=J;break + if not F: + E=desc or A[H].strip() + if L+A[U].upper()in E:E=E.split(L+A[U].upper())[0].strip() + A[H]=E + A[H]=A[H].replace(' ',T);B.collect() +def A0(info,descr,filename,short_descr): + B=short_descr;A=info;E=C + with K(filename,'r')as L: while 1: - A=B.readline() - if not A:break - C,E=A.split(',')[0].strip(),A.split(',')[1].strip() - if C==board_descr:info[K]=E;return J + F=L.readline() + if not F:break + I,G=F.split(',')[0].strip(),F.split(',')[1].strip() + if I==descr:A[H]=G;return J + elif B and I==B: + if w in B:A[H]=G;return J + E=G + if E:A[H]=E;return J return D def get_root(): try:B=os.getcwd() - except(A,H):B=L + except(A,I):B=L C=B for C in[B,'/sd','/flash',G,L]: try:D=os.stat(C);break except A:continue return C -def j(filename): +def h(filename): try: if os.stat(filename)[0]>>14:return J return D except A:return D -def k():sys.exit(1) +def i():sys.exit(1) def read_path(): path=C if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:k() - elif M(sys.argv)==2:k() + else:i() + elif M(sys.argv)==2:i() return path -def l(): - try:A=bytes('abc',encoding='utf8');B=l.__module__;return D - except(m,H):return J +def j(): + try:A=bytes('abc',encoding='utf8');B=j.__module__;return D + except(k,I):return J def main(): L='failed';G='modulelist.done';import machine as O - try:C=I(G,'r+b');N=J - except A:C=I(G,'w+b');N=D + try:C=K(G,'r+b');N=J + except A:C=K(G,'w+b');N=D stubber=Stubber(path=read_path()) if not N:stubber.clean() A1(stubber);E={} try: - with I(G)as C: + with K(G)as C: for F in C.read().split('\n'): F=F.strip();B.collect() if M(F)>0:P,Q=F.split('=',1);E[P]=Q except(A,SyntaxError):pass B.collect();R=[A for A in stubber.modules if A not in E.keys()];B.collect() for H in R: - K=D - try:K=stubber.create_one_stub(H) - except n:O.reset() - B.collect();E[H]=Y(stubber._report[-1]if K else L) - with I(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if K else L)) + I=D + try:I=stubber.create_one_stub(H) + except l:O.reset() + B.collect();E[H]=X(stubber._report[-1]if I else L) + with K(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if I else L)) if E:stubber._report=[A for(B,A)in E.items()if A!=L];stubber.report() def A1(stubber): E='/modulelist.txt';stubber.modules=[] - for D in g: + for D in f: try: - with I(D+E)as F: + with K(D+E)as F: N('DEBUG: list of modules: '+D+E) for C in F.read().split('\n'): C=C.strip() if M(C)>0 and C[0]!='#':stubber.modules.append(C) B.collect();break except A:pass - if not stubber.modules:stubber.modules=[Z];_log.warn('Could not find modulelist.txt, using default modules') + if not stubber.modules:stubber.modules=[Y];_log.warn('Could not find modulelist.txt, using default modules') B.collect() -if __name__=='__main__'or l(): - try:A2=logging.getLogger(x);logging.basicConfig(level=logging.INFO) - except p:pass - if not j('no_auto_stubber.txt'): +if __name__=='__main__'or j(): + try:A2=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + except n:pass + if not h('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_db_mpy.mpy b/mip/v5/createstubs_db_mpy.mpy index c57a213d3cb43455e77fbeb3717fb5bb3a0073a0..0b759468c8f98656dc87f151bdd2fa2e234a1582 100644 GIT binary patch delta 1495 zcmX|BYfPI}7(VB13#Hsn4WjXi}XQ&{O;vSn(jAfXX97b_D~UUCA{5k?3Gdd#DO`?o%Zs%v;C)tK=F6YsnO`#mqvgGC8(3SGQLZNfeLHFfd+j!m~(?xTed z+b}x0Od&>LjKWz8aSHtu0u+MPnHz4Ee0kkfDvKY+DJ1x9^(HkJjJK- zzE&ng0)8leRwEc}Q;GAx^Y>&1x2W`U6ZurxNgl*6ojdqLpGS=~rSr9;2 zuWQL{2~wd*H}BE;1pF7eU9}RrMl+pwm6rH+jM{W74w${7gX|ZRkq3l`z;48 zwMLs25lwnpP4{Mnpziy2pfH&3Bp-S}VR+Gj-L3N6s~R~)p`}|wx14BgNkUhN#*{wh z#1EH~zq<3~CGT<#Z11nTlrn|pby_d_J+-vB;!wJ?MWpS1pLkpf+4V_sp}BDfHERcS zUL@$|FG`%kap!I;l$G*RyQ`AZ(pAY?sF44xs5X_C8!Zm2eQym)-Jg9xb!(#Ig!ggL zaYN|gvV@XOw7$|T67Pu;$(0n5{?E& z!)$yw7Ek!Mf^W1B?D~J!OXPpJq~9YZszHCkaJX;=%#J$LQi5oflr@{CdGon2oti_` z%;)sFEMphRgOU814E~eeqETDwY7SH$K(yfNSVKz6GUJ+Nx IN2NFZ15HJeb^rhX delta 1465 zcmX|BT}+!*7(VB13#H}f^z7>?8-uSMg%!qc$GVVZ%Ak{yD%(lB;(F^C5dRlPb#g}tV-aOCq zzVGwCkG)@dmjap6MdPAT?WhsIMeAaTTW)pM%Qa3!N@vouk%*dNaE_QRTx`B@k-J4XWR$@iA>*?NB|Vu;FqkFiB?f7NK436IOylunIL#nM&?yFIEvS*fv;{3ONLo+> zgM=mBD}o)iUrCH0}T2sXpTXz1=)EBk7AX7gB|z~ z{~0&pac+boh6TZKo*#o+Ji%w7t~=(|F$lQz%oLhTj3+IJ>+#@z1JfUAaThR{bQdx* zp{7HrWHRj*f=;`O7@TpN7)`0+XlOc|j=9YY;`|vLz~^{{t_e?P`*fvHGF7c>!)jj% z3Q*|bs=<%P_zlCGIF{`wc#6ruN*fOO{zdoKB*ZBU^CqJmkMh@yI}Z$QdW~9;T7T%n z=;RFwXDOs8%uq;E2vdkqP#Oz2yaw&k!%l}L0%j@9@oUDHaSz`x*5Cx!6*b^wwxx&y z9_C%TXEy;uw!xU&jmlC+h+Z@NU*o^>O)cB)Zi-vvx<8<(7l3t#Z9noMd?)|C~keer~k& z6#61mRAht)Y$Ldme{I|4x=AZWwmY=x)oXbPJ)a^%LQ`QSHknW<4A7DtCH%Rq)=8mX zLa}cp^d7|??9Vj8um?-%Ll3%1Yew?#I$l@qYZ=TXzl}zrQz})G@wlp_Jt#ez=r!d4CyfVH@t{8Yz6DI&W|#yT^-xNh1-EE zf@6gLTHz5!kayQYwamMB*JrNSCw5zP+V73_y?bS+M`SHb04d?USJ2(8gfbp%|aTwZHhG$~|IKPF0@Jw_CM;`0YyObSTuJh~*KWC0nDS%RARE zP%DQ>DV!-=0{(ZU)2w&4G_}{YiwwGWZB;}cw=5O&cdA diff --git a/mip/v5/createstubs_lvgl.py b/mip/v5/createstubs_lvgl.py index 4f881cc48..fe5417871 100644 --- a/mip/v5/createstubs_lvgl.py +++ b/mip/v5/createstubs_lvgl.py @@ -447,12 +447,13 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]) + info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") except AttributeError: pass try: _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = "with".join(_machine.split("with")[:-1]).strip() + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy @@ -548,16 +549,15 @@ def read_boardname(info, desc: str = ""): # print("look up the board name in the file", filename) if file_exists(filename): descr = desc or info["board"].strip() - print("searching info file: {}".format(filename)) - if find_board(info, descr, filename): + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): found = True break - if "with" in descr: - descr = descr.split("with")[0].strip() - print("searching for: {}".format(descr)) - if find_board(info, descr, filename): - found = True - break if not found: print("Board not found, guessing board name") descr = desc or info["board"].strip() @@ -569,18 +569,30 @@ def read_boardname(info, desc: str = ""): gc.collect() -def find_board(info: dict, board_descr: str, filename: str): +def find_board(info: dict, descr: str, filename: str, short_descr: str): "Find the board in the provided board_info.csv file" + short_hit = "" with open(filename, "r") as file: # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) while 1: line = file.readline() if not line: break descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == board_descr: + if descr_ == descr: info["board"] = board_ return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True return False diff --git a/mip/v5/createstubs_lvgl_min.py b/mip/v5/createstubs_lvgl_min.py index 9ccf49b17..24d22c1d8 100644 --- a/mip/v5/createstubs_lvgl_min.py +++ b/mip/v5/createstubs_lvgl_min.py @@ -1,36 +1,36 @@ -v='stubber' -u='{}/{}' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n='micropython' -m=Exception -l=NameError -k=sorted -j=NotImplementedError -b=',\n' -a='dict' -Z='list' -Y='tuple' -X=open -W=repr -U='cpu' -T='_' -S=len -R=KeyError -Q=IndexError -P=dir -O=print -N=ImportError -M='with' +u='with' +t='stubber' +s='{}/{}' +r='method' +q='function' +p='bool' +o='str' +n='float' +m='int' +l='micropython' +k=Exception +j=NameError +i=sorted +h=NotImplementedError +a=',\n' +Z='dict' +Y='list' +X='tuple' +W=open +V=repr +T='cpu' +S='_' +R=len +Q=KeyError +P=IndexError +O=dir +N=print +M=ImportError L='family' K=True J='.' -I='board' -H=AttributeError +I=AttributeError +H='board' A=False G='/' E=None @@ -38,51 +38,51 @@ F=OSError B='' import gc as C,os,sys -from ujson import dumps as c +from ujson import dumps as b try:from machine import reset -except N:pass -try:from collections import OrderedDict as d -except N:from ucollections import OrderedDict as d +except M:pass +try:from collections import OrderedDict as c +except M:from ucollections import OrderedDict as c __version__='v1.16.2' +v=2 w=2 -x=2 -y=[J,'/lib','/sd/lib','/flash/lib','lib'] +x=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') - except H:pass + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise h('MicroPython 1.13.0 cannot be stubbed') + except I:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[L]==n:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:e(path+G) - except F:O('error creating stub folder {}'.format(path)) + try:d(path+G) + except F:N('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): - I=item_instance;D=[];J=[] - for A in P(I): - if A.startswith(T)and not A in L.modules:continue + H=item_instance;D=[];J=[] + for A in O(H): + if A.startswith(S)and not A in L.modules:continue try: - E=getattr(I,A) - try:F=W(type(E)).split("'")[1] - except Q:F=B - if F in{o,p,q,r,Y,Z,a}:G=1 - elif F in{s,t}:G=2 + E=getattr(H,A) + try:F=V(type(E)).split("'")[1] + except P:F=B + if F in{m,n,o,p,X,Y,Z}:G=1 + elif F in{q,r}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,W(E),W(type(E)),E,G)) - except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) + D.append((A,V(E),V(type(E)),E,G)) + except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J - def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) + D=i([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=i(set(A.modules)|set(modules)) def create_all_stubs(A): C.collect() for B in A.modules:A.create_one_stub(B) @@ -96,84 +96,84 @@ def create_one_stub(B,module_name): C.collect();return E def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:O=D.replace(J,T)+'.py';H=I.path+G+O + if H is E:O=D.replace(J,S)+'.py';H=I.path+G+O else:O=H.split(G)[-1] if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');S=C.mem_free() - except N:return A - e(H) - with X(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) + try:L=__import__(D,E,E,'*');T=C.mem_free() + except M:return A + d(H) + with W(H,'w')as N:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,L,D,B) I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del L - except(F,R):pass + except(F,Q):pass try:del sys.modules[D] - except R:pass + except Q:pass C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;D=indent;C.collect() - if N in K.problematic:return - Q,L=K.get_obj_attributes(N) - if L:O(L) - for(E,J,G,T,f)in Q: + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() + if O in K.problematic:return + S,L=K.get_obj_attributes(O) + if L:N(L) + for(E,J,G,T,f)in S: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and S(D)<=x*4: + if G==""and R(D)<=w*4: U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[t,s,'closure']): - W=b;X=B - if P>0:X='self, ' + elif any(A in G for A in[r,q,'closure']): + W=b;a=B + if P>0:a='self, ' if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(a,Z): - try:f=os.uname();A[D]=f.release - except(Q,H,TypeError):pass - for(g,h,i)in[(b,b,'const'),(c,c,'FAT'),(e,'pybricks.hubs','EV3Brick')]: - try:j=__import__(h,E,E,i);A[L]=g;del j;break - except(N,R):pass - if A[L]==e:A['release']='2.0.0' - if A[L]==n: + A[F]=U(os.uname()[3]) + if not A[F]:A[F]=U(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=U(sys.version.split(';')[1]) + except(I,P):pass + if A[F]and R(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(Z,Y): + try:e=os.uname();A[D]=e.release + except(P,I,TypeError):pass + for(f,g,h)in[(a,a,'const'),(b,b,'FAT'),(d,'pybricks.hubs','EV3Brick')]: + try:i=__import__(g,E,E,h);A[L]=f;del i;break + except(M,Q):pass + if A[L]==d:A['release']='2.0.0' + if A[L]==l: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] - if W:A[Y]=W - A[K]='v{}.{}'.format(O&255,O>>8&3) - A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def z(info,desc=B): - G='with ';D=info;E=A - for F in[A+'/board_info.csv'for A in y]: - if g(F): - B=desc or D[I].strip() - if f(D,B,F):E=K;break - if M in B: - B=B.split(M)[0].strip() - if f(D,B,F):E=K;break - if not E: - B=desc or D[I].strip() - if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() - D[I]=B - D[I]=D[I].replace(' ',T);C.collect() -def f(info,board_descr,filename): - with X(filename,'r')as C: + N=int(A[K]);V=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] + if V:A[X]=V + A[K]='v{}.{}'.format(N&255,N>>8&3) + A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def y(info,desc=B): + L='with ';D=info;F=A + for G in[A+'/board_info.csv'for A in x]: + if e(G): + E=desc or D[H].strip();I=E.rfind(' with') + if I!=-1:J=E[:I].strip() + else:J=B + if z(D,E,G,J):F=K;break + if not F: + E=desc or D[H].strip() + if L+D[T].upper()in E:E=E.split(L+D[T].upper())[0].strip() + D[H]=E + D[H]=D[H].replace(' ',S);C.collect() +def z(info,descr,filename,short_descr): + D=short_descr;C=info;E=B + with W(filename,'r')as J: while 1: - B=C.readline() - if not B:break - D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[I]=E;return K + F=J.readline() + if not F:break + I,G=F.split(',')[0].strip(),F.split(',')[1].strip() + if I==descr:C[H]=G;return K + elif D and I==D: + if u in D:C[H]=G;return K + E=G + if E:C[H]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=J + except(F,I):A=J B=A for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def g(filename): +def e(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def h():sys.exit(1) +def f():sys.exit(1) def read_path(): path=B - if S(sys.argv)==3: + if R(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:h() - elif S(sys.argv)==2:h() + else:f() + elif R(sys.argv)==2:f() return path -def i(): - try:B=bytes('abc',encoding='utf8');C=i.__module__;return A - except(j,H):return K +def g(): + try:B=bytes('abc',encoding='utf8');C=g.__module__;return A + except(h,I):return K def main(): D='lvgl' try:import lvgl as A - except m:return + except k:return B=D try:B='lvgl-{0}_{1}_{2}-{3}-{4}'.format(A.version_major(),A.version_minor(),A.version_patch(),A.version_info(),sys.platform) - except m:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) + except k:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) finally:stubber=Stubber(firmware_id=B) stubber.clean();stubber.modules=['io','lodepng','rtch',D];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or i(): - try:A0=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except l:pass - if not g('no_auto_stubber.txt'): +if __name__=='__main__'or g(): + try:A0=logging.getLogger(t);logging.basicConfig(level=logging.INFO) + except j:pass + if not e('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_lvgl_mpy.mpy b/mip/v5/createstubs_lvgl_mpy.mpy index e59be1e35eda71ffb194cd820f2aeee89d7802a9..64b1c6821d1c9ee88c75e08d56a63556c67e8c39 100644 GIT binary patch delta 1399 zcmX|BT}+c#7(VB13vCg4zQfm35KD`cD#&lGC73v|R9D0w%1`;3+LX4?Vrj7y6piWU zHa6ph!JO1UFRNg~^iLn9Yz~EZK!wvh2z$cWRB_#h33r?>W!& zp67ku@1yqb+vok6;<@5EZKSZF zY`Sof!4%mt5lKgrVFoEeMyC^@bS#-*aE73F7)%oM8G|IzkH(Y1G=l^|rx;8SG{qn; zAsd6!5^7*DE}?mL0%8(sVh|syZ$+w|Md0??vnp<01EDoFa zvNZEgSV*++CG!?~N2rcMANQL4xQ2gi+S(+e%e2siS80X+jpCagwK9~utoJe^Brp*S zMPrEwh2zvvYT$pG>|5@w(rW)b8C|0=&3Bb`HFej)+fx)e05E+nLyUCk+` zku@Un4k8Nu{6<+LZs5O_?Z!P^TmGH;CNun|1ZIZF_8c zZB3SXJ0kkrxLJQ%_?g0ibq7#5m-B!hJ){s>a$--Xa_gX8$x`t4%jk0#dbBK~4~gEI zJLbZVS2BNi49c=^r4jP^4YyhmHrb$XKD)eh$Eo%diMVUMYDhe8mEyjcS?p+k1FCz2 zd0XK3@qa2@qHi_Z>`-0Bk8Z2W%*h|hcB4vpv9rOtV~54&v^#b+qU`#@Luz^?{BoN> z$_ej|p~ovS%DB+Roen`TpxhBM5~z1!C6E6)#x8s*9}YkH5>@%BDnxgL5GvP)BU7Oi8I8pw ziQq(pO+}Nbbl~;k2i@VVZ%4I4dC67g?ZS?B^NGs+#(7-rY)0M+M0K)mAy?+re}zG4 zb%<8;>t>VA(nm^Q)G)8%Yi3(Xp{=>Gt+ox()-?(}{6F(4^_Vno;Qf^?ILbe+G+U`{ jkA1tPt*u`CKI1cE@ingwDZUE);IJV#@Tarum2Uh$GGun4 delta 1370 zcmX|=ZERCj7{||f+HPG-yK~QO&o;)|4$9cdUQ4-TCc@|n6eh6lrK~t;y7q4E=-SbB zAX`W;5{&V~GINajK_wv?jlnopHWP#dc@twW@slxz?2{oe`au(oUkskM)0>l&vU)^wce#r-g?D&#i;gf7r!f29!Iy!?bz-@#5$Xs8y{D*49*eL!o|*oiwx$- zrfD^o$ix}s2$`5m$8yO`n!zkVdl_U2dWXSTVwy;0qB#aL1f6D(A!wFCT0$-c(-LZD zkdn|6gEJE9WH3d>^lc^v;{^3Hh!T`yaFU?+8H6Qtj=`veUS)8CRK#ZH7>p2PWH2nD zGYp0#)XHE`LM;q}5_*ZjfP@wp9G6ftgJZ;aKAB7KZd_*}rtwTPE8cuqLQWpSqd3Mt z$4z)Q{~ovFIDd}!8_o;LEBpX7;|n|mtp`<)jzP$yXQoIpJ&}=KbmO621_tw<3I-FN zN=7EtTqK*x--$IKwfe}YbYj+=EII8}H-X9dgDHk}u% zM=awYJp1-0PCLSvLKo4>(>h51b%VSJoBt$me4cf6PigOb*}`kc_@ z?bXXB0WH(B{8{zZ%4mrm=7fBrAEb~f+$KL`0lG$Ct_`?h-Cv=FgC){Rq(6x6Q<&p& z%^P@>U#)pta1=Q#3bQ0P;BkIkb_(B~$cw_5F~+N{kmVTg^Oti zt|3Aq)6rNWnN}$bP)m)4KdWtaQ8+52#FsL9lVSx2^BpjvU>Uuupj&i%sC2L6^>zK7 z!D4b7Y83ipYb=vWsj-}bgqicVik=!|gE$375rq)vbscyozgM>l5Anb1KGh$iFvvfw zZ^7xpllm!~_y2)gU|y%KyW3hjm6q-vSEr+`84**lqn-Dbg>(BKc!0u%Vw*(KLkg3t zUhE&%ZX7Ua1qz2pO3!>mVWP0M>eczp8ioD`Ve$DqVtaJ$segyIwvn0kU$mhd+$^FE zpuXjVZawBp@Fh=+f4T`9)bxSieIk>XLoxkjy++x#dzqLDe>~Odgk?ZIR zfvgt}9YpsFGRiCH!OcFQsc1I^n?Rd_H{hkSaQRZ1aPr}!)f+$hP1@QrwS{Oy%y&B< z96Lp~#SpTw(lkfn>TE1aCXy*N9i3J$55z5-|DQ>l_9u5YZWS$mv~g^2k4^h$o3{%E z8W63LtCow@#otB6Xj4qABa#?KOL-D>rTz>GOye-ILZW&J^Jk5&YMraAqo=h;q~yCx iVTjk;PwSJ?l9?~qyYUqN%-)Et{9C&nPZxf%`|!UUA7-Qg diff --git a/mip/v5/createstubs_mem.py b/mip/v5/createstubs_mem.py index c22022161..487300f41 100644 --- a/mip/v5/createstubs_mem.py +++ b/mip/v5/createstubs_mem.py @@ -453,12 +453,13 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]) + info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") except AttributeError: pass try: _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = "with".join(_machine.split("with")[:-1]).strip() + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy @@ -554,16 +555,15 @@ def read_boardname(info, desc: str = ""): # print("look up the board name in the file", filename) if file_exists(filename): descr = desc or info["board"].strip() - print("searching info file: {}".format(filename)) - if find_board(info, descr, filename): + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): found = True break - if "with" in descr: - descr = descr.split("with")[0].strip() - print("searching for: {}".format(descr)) - if find_board(info, descr, filename): - found = True - break if not found: print("Board not found, guessing board name") descr = desc or info["board"].strip() @@ -575,18 +575,30 @@ def read_boardname(info, desc: str = ""): gc.collect() -def find_board(info: dict, board_descr: str, filename: str): +def find_board(info: dict, descr: str, filename: str, short_descr: str): "Find the board in the provided board_info.csv file" + short_hit = "" with open(filename, "r") as file: # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) while 1: line = file.readline() if not line: break descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == board_descr: + if descr_ == descr: info["board"] = board_ return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True return False diff --git a/mip/v5/createstubs_mem_min.py b/mip/v5/createstubs_mem_min.py index b80e20c14..139f88f81 100644 --- a/mip/v5/createstubs_mem_min.py +++ b/mip/v5/createstubs_mem_min.py @@ -1,179 +1,179 @@ -w='stubber' -v='{}/{}' -u='method' -t='function' -s='bool' -r='str' -q='float' -p='int' -o=NameError -n=sorted -m=NotImplementedError -d=',\n' -c='dict' -b='list' -a='tuple' -Z='micropython' -Y=str -X=repr -V='cpu' -U='_' -T=KeyError -S=open -R=IndexError -Q=dir -P=ImportError -O='with' +v='with' +u='stubber' +t='{}/{}' +s='method' +r='function' +q='bool' +p='str' +o='float' +n='int' +m=NameError +l=sorted +k=NotImplementedError +c=',\n' +b='dict' +a='list' +Z='tuple' +Y='micropython' +X=str +W=repr +U='cpu' +T='_' +S=KeyError +R=open +Q=IndexError +P=dir +O=ImportError N='family' M=len L=print K=True J='.' -I='board' -H=AttributeError +I=AttributeError +H='board' A=False G='/' E=None D='version' F=OSError -C='' -import gc as B,os,sys -from ujson import dumps as e +B='' +import gc as C,os,sys +from ujson import dumps as d try:from machine import reset -except P:pass -try:from collections import OrderedDict as f -except P:from ucollections import OrderedDict as f +except O:pass +try:from collections import OrderedDict as e +except O:from ucollections import OrderedDict as e __version__='v1.16.2' +w=2 x=2 -y=2 -g=[J,'/lib','/sd/lib','/flash/lib','lib'] +f=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): - C=firmware_id + B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') - except H:pass - A._report=[];A.info=_info();B.collect() - if C:A._fwid=C.lower() - elif A.info[N]==Z:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + except I:pass + A._report=[];A.info=_info();C.collect() + if B:A._fwid=B.lower() + elif A.info[N]==Y:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) - A._start_free=B.mem_free() + A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:h(path+G) + try:g(path+G) except F:L('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): - I=item_instance;D=[];J=[] - for A in Q(I): - if A.startswith(U)and not A in L.modules:continue + H=item_instance;D=[];J=[] + for A in P(H): + if A.startswith(T)and not A in L.modules:continue try: - E=getattr(I,A) - try:F=X(type(E)).split("'")[1] - except R:F=C - if F in{p,q,r,s,a,b,c}:G=1 - elif F in{t,u}:G=2 + E=getattr(H,A) + try:F=W(type(E)).split("'")[1] + except Q:F=B + if F in{n,o,p,q,Z,a,b}:G=1 + elif F in{r,s}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,X(E),X(type(E)),E,G)) - except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) + D.append((A,W(E),W(type(E)),E,G)) + except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=n([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=n(set(A.modules)|set(modules)) + D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) def create_all_stubs(A): - B.collect() - for C in A.modules:A.create_one_stub(C) - def create_one_stub(C,module_name): + C.collect() + for B in A.modules:A.create_one_stub(B) + def create_one_stub(B,module_name): D=module_name - if D in C.problematic:return A - if D in C.excluded:return A - H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=A - try:E=C.create_module_stub(D,H) + if D in B.problematic:return A + if D in B.excluded:return A + H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A + try:E=B.create_module_stub(D,H) except F:return A - B.collect();return E + C.collect();return E def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:N=D.replace(J,U)+'.py';H=I.path+G+N + if H is E:N=D.replace(J,T)+'.py';H=I.path+G+N else:N=H.split(G)[-1] if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');R=B.mem_free() - except P:return A - h(H) - with S(H,'w')as M:O=Y(I.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,O,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,C) + try:L=__import__(D,E,E,'*');U=C.mem_free() + except O:return A + g(H) + with R(H,'w')as M:P=X(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del L - except(F,T):pass + except(F,S):pass try:del sys.modules[D] - except T:pass - B.collect();return K + except S:pass + C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;C.collect() if P in K.problematic:return R,N=K.get_obj_attributes(P) if N:L(N) - for(E,J,G,S,f)in R: + for(E,J,G,T,f)in R: if E in['classmethod','staticmethod','BaseException',O]:continue if E[0].isdigit():continue - if G==""and M(D)<=y*4: - U=C;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if G==""and M(D)<=x*4: + U=B;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[u,t,'closure']): - W=Y;X=C + H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) + elif any(A in G for A in[s,r,'closure']): + W=Y;X=B if Q>0:X='self, ' - if Z in G or Z in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) + if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=C - if A[D]==C and sys.platform not in(c,b): - try:h=os.uname();A[D]=h.release - except(R,H,TypeError):pass - for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: - try:l=__import__(j,E,E,k);A[N]=i;del l;break - except(P,T):pass - if A[N]==g:A['release']='2.0.0' - if A[N]==Z: + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=V(sys.version.split(';')[1]) + except(I,Q):pass + if A[F]and M(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(b,a): + try:g=os.uname();A[D]=g.release + except(Q,I,TypeError):pass + for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(f,'pybricks.hubs','EV3Brick')]: + try:k=__import__(i,E,E,j);A[N]=h;del k;break + except(O,S):pass + if A[N]==f:A['release']='2.0.0' + if A[N]==Y: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - L=int(A[K]);U=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][L>>10] - if U:A[a]=U + L=int(A[K]);T=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][L>>10] + if T:A[Z]=T A[K]='v{}.{}'.format(L&255,L>>8&3) - A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def z(info,desc=C): - G='with ';D=info;E=A - for F in[A+'/board_info.csv'for A in g]: - if j(F): - C=desc or D[I].strip() - if i(D,C,F):E=K;break - if O in C: - C=C.split(O)[0].strip() - if i(D,C,F):E=K;break - if not E: - C=desc or D[I].strip() - if G+D[V].upper()in C:C=C.split(G+D[V].upper())[0].strip() - D[I]=C - D[I]=D[I].replace(' ',U);B.collect() -def i(info,board_descr,filename): - with S(filename,'r')as C: + A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def y(info,desc=B): + L='with ';D=info;F=A + for G in[A+'/board_info.csv'for A in f]: + if h(G): + E=desc or D[H].strip();I=E.rfind(' with') + if I!=-1:J=E[:I].strip() + else:J=B + if z(D,E,G,J):F=K;break + if not F: + E=desc or D[H].strip() + if L+D[U].upper()in E:E=E.split(L+D[U].upper())[0].strip() + D[H]=E + D[H]=D[H].replace(' ',T);C.collect() +def z(info,descr,filename,short_descr): + D=short_descr;C=info;E=B + with R(filename,'r')as J: while 1: - B=C.readline() - if not B:break - D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[I]=E;return K + F=J.readline() + if not F:break + I,G=F.split(',')[0].strip(),F.split(',')[1].strip() + if I==descr:C[H]=G;return K + elif D and I==D: + if v in D:C[H]=G;return K + E=G + if E:C[H]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=J + except(F,I):A=J B=A for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def j(filename): +def h(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def k():sys.exit(1) +def i():sys.exit(1) def read_path(): - path=C + path=B if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:k() - elif M(sys.argv)==2:k() + else:i() + elif M(sys.argv)==2:i() return path -def l(): - try:B=bytes('abc',encoding='utf8');C=l.__module__;return A - except(m,H):return K +def j(): + try:B=bytes('abc',encoding='utf8');C=j.__module__;return A + except(k,I):return K def main(): E='/modulelist.txt';stubber=Stubber(path=read_path());stubber.clean();stubber.modules=[] - for C in g: + for B in f: try: - F=B.mem_free() - with S(C+E)as D: - L('Debug: List of modules: '+C+E);A=D.readline() + F=C.mem_free() + with R(B+E)as D: + L('Debug: List of modules: '+B+E);A=D.readline() while A: A=A.strip() if M(A)>0 and A[0]!='#':stubber.modules.append(A) A=D.readline() - B.collect();L('Debug: Used memory to load modulelist.txt: '+Y(F-B.mem_free())+' bytes');break + C.collect();L('Debug: Used memory to load modulelist.txt: '+X(F-C.mem_free())+' bytes');break except Exception:pass - if not stubber.modules:stubber.modules=[Z] - B.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or l(): - try:A0=logging.getLogger(w);logging.basicConfig(level=logging.INFO) - except o:pass - if not j('no_auto_stubber.txt'): - try:B.threshold(4*1024);B.enable() + if not stubber.modules:stubber.modules=[Y] + C.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or j(): + try:A0=logging.getLogger(u);logging.basicConfig(level=logging.INFO) + except m:pass + if not h('no_auto_stubber.txt'): + try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_mem_mpy.mpy b/mip/v5/createstubs_mem_mpy.mpy index f88cb945ec36e00c587b4d47a15400aa6ef7cd4e..6ee7538f8331873daf140cc57c4c3c6a5f31a336 100644 GIT binary patch delta 1573 zcmYjRYfO_@7(VB1E2W4%-{Io`Vkz2E0f9oTH7rrEt*(d**OrUAj$WY1rC17hiRq^s zk(kA>on%|GY%`0-{a7}jTokAA0?PKoWZC|hP05z*#}YH+9}|-$?i7sK_v7R{@A=;M zdA|2~&iifcFSV1tMCN$rxHeo{B$jc#%~)kFH5Qo>(T?@TBMe5#rs4QVAP|l*7$LgT zXRN2sFo=_l1L1fi8e%X^NcYHKFy0#-WDp~0FN5O*eac{n=(_u(U2z6cg5G5?D4}u& z0}`5K&@Uk?gFd1z(={>(5>(G1Ku|w}E`q*b&`HoRgAOTGr(Htl7_^ZM!J!cbUV^j? zS|wD%phZHX44NfW%%Dj^hZrs4E_^WiU9#e*-HX;Tfumyn$7>TIo25 z(NQVKgzVT=p?GqU1g>PW>IKg1GpX!2d@vKWQK;iyO%v|mS2Yv3Ct11S2_}s*cI>Zz zg_h@J#3{7$0&O8~<2BkmN7JfXt8`FsK1dZ`pfE@wN@0k?aSELjx+nz7(;mAu%Gnj? zRz-XeqcF@bYHM&Ef2eJy{Wew7jtT0usqN?RJt`>K((hsH$jx^ z)>w6NO1@FIP#8$wB7b3lbeSH;bsuMC<2YwoV=}npO~Gh?e>fO-pbk$15{Ud#mI+t$ zrL1Gv#I15RF5(B|dPArTPi1LSO3ei9_-vvAybjzkEu+g6g8Vz#2r$AQ%H=qZ|0}j60I6d53YLecFz#vh#T& zh!E18moG>bIH^%qOUp{CcbVTZTa9HFM0BZ9P!opE=O|c^Q2`bcLxj2Y#@S_}#5n=9?CTBx~m@PSHwmuFy(2m7JfuW>>p2 zM4*1DLp)BE;=G!eb=AHun*O@xjHvJB|KvM#tqw?1l~4RRuh?RMqOJU$Ev1QZ`2*RK ztx}#Amltl|ZZz91wjC8Hxiqy*bM6b<%n*nPqxPT&3o=SL(8@KJKx$L2iN+Erb6{m1 zXl;)j`0V<&^T(gAPd{?&l*KukE`N#@2OX-PnJ(Qc89KjJ9CMh+DU{qvNOcZ)>4Hqw5$y zl72vl#2B3(jb3O_gV76v+sbBwK!h>G#9)j!8UssAOfb;Y0r!|TY6D>Q5orJ5WkCM7GsyG#n@m%q;xVf6%0nw45o?d%vtl9vkXp< zjfqGmnhG`Nd_5$b~2bG=xqjRq8f{*0vQI!2|B`HLW9~Fq%>%TK~jUv z3=%}%reY8#sEoAVKdj2oN;MU{sUG@oCU`1_#K7(8Lr2FF{HM9t~<{Fswl* z7z}Ap6N5nw+RwnPL5&Osh;llXiSh<)Dj}+1Dv%aBdo`$*dvTM>A-SvM;~@riehD|? z2>%S%;cosNZpUN%8Q!fpDd)h}N6ZgCo`}>}u zVO3TX+p*#nL zsJI{~hjIj_t?=9cx=+E!Z>n$N;oO;xe_(uyA1nP*J|(!gxolP?#1vFb@?Xm~7ll?; z1vn+2$cHJUa<|AYSTJ3o2eIo7tsbA?OgpVD)|G}*@pvSZu_2$U9|=PKfwmrR=gZoo zxQ=(~^Z*XNSJ!8VwBcE;GT*8BpcS9Xc7Vr*eRDc=g+iEL)fsUs|5n#7EL+h{a)Ztv)>QTn_Nb&Bg6vREz;sziqf|K!WHY$ zibAkVvcH?X=IB`iE?Ntm7aU&xLzPYCu|bZ?ydr&GQEh;FBi~-#lD$wnUagl&zqi+J z*Ji@^q!f;o&0zl6U{cFWogLlH-68`AXEi~2 zTr;EQFV=M71ixBiz@_|~8b|fGzwdo?$MuScvg=49lJJkEBM}=CeH!Ae#t`=L*Nolb JVfotl^1r`emKgv5 diff --git a/mip/v5/createstubs_min.py b/mip/v5/createstubs_min.py index 75a060686..cca13284d 100644 --- a/mip/v5/createstubs_min.py +++ b/mip/v5/createstubs_min.py @@ -1,39 +1,39 @@ -y='pyb' -x='stubber' -w='{}/{}' -v='logging' -u='sys' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n=NameError -m=sorted -l=NotImplementedError -d='pycom' -c=',\n' -b='dict' -a='list' -Z='tuple' -Y='micropython' -X=open -W=repr -U='cpu' -T='_' -S=len -R=KeyError -Q=IndexError -P=dir -O=print -N=ImportError -M='with' +x='with' +w='pyb' +v='stubber' +u='{}/{}' +t='logging' +s='sys' +r='method' +q='function' +p='bool' +o='str' +n='float' +m='int' +l=NameError +k=sorted +j=NotImplementedError +c='pycom' +b=',\n' +a='dict' +Z='list' +Y='tuple' +X='micropython' +W=open +V=repr +T='cpu' +S='_' +R=len +Q=KeyError +P=IndexError +O=dir +N=print +M=ImportError L='family' K=True J='.' -I='board' -H=AttributeError +I=AttributeError +H='board' A=False G='/' E=None @@ -41,51 +41,51 @@ D='version' B='' import gc as C,os,sys -from ujson import dumps as e +from ujson import dumps as d try:from machine import reset -except N:pass -try:from collections import OrderedDict as f -except N:from ucollections import OrderedDict as f +except M:pass +try:from collections import OrderedDict as e +except M:from ucollections import OrderedDict as e __version__='v1.16.2' +y=2 z=2 -A0=2 -A1=[J,'/lib','/sd/lib','/flash/lib','lib'] +A0=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise l('MicroPython 1.13.0 cannot be stubbed') - except H:pass + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') + except I:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[L]==Y:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==X:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:g(path+G) - except F:O('error creating stub folder {}'.format(path)) + try:f(path+G) + except F:N('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): - I=item_instance;D=[];J=[] - for A in P(I): - if A.startswith(T)and not A in L.modules:continue + H=item_instance;D=[];J=[] + for A in O(H): + if A.startswith(S)and not A in L.modules:continue try: - E=getattr(I,A) - try:F=W(type(E)).split("'")[1] - except Q:F=B - if F in{o,p,q,r,Z,a,b}:G=1 - elif F in{s,t}:G=2 + E=getattr(H,A) + try:F=V(type(E)).split("'")[1] + except P:F=B + if F in{m,n,o,p,Y,Z,a}:G=1 + elif F in{q,r}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,W(E),W(type(E)),E,G)) - except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) + D.append((A,V(E),V(type(E)),E,G)) + except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J - def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) + D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) def create_all_stubs(A): C.collect() for B in A.modules:A.create_one_stub(B) @@ -99,37 +99,37 @@ def create_one_stub(B,module_name): C.collect();return E def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:O=D.replace(J,T)+'.py';H=I.path+G+O + if H is E:O=D.replace(J,S)+'.py';H=I.path+G+O else:O=H.split(G)[-1] if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');S=C.mem_free() - except N:return A - g(H) - with X(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) + try:L=__import__(D,E,E,'*');T=C.mem_free() + except M:return A + f(H) + with W(H,'w')as N:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,L,D,B) I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os',u,v,'gc'}: + if D not in{'os',s,t,'gc'}: try:del L - except(F,R):pass + except(F,Q):pass try:del sys.modules[D] - except R:pass + except Q:pass C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;D=indent;C.collect() - if N in K.problematic:return - Q,L=K.get_obj_attributes(N) - if L:O(L) - for(E,J,G,T,f)in Q: + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() + if O in K.problematic:return + S,L=K.get_obj_attributes(O) + if L:N(L) + for(E,J,G,T,f)in S: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and S(D)<=A0*4: + if G==""and R(D)<=z*4: U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[t,s,'closure']): - W=Y;X=B + elif any(A in G for A in[r,q,'closure']): + W=b;X=B if P>0:X='self, ' if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) @@ -137,46 +137,46 @@ def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(b,a): - try:g=os.uname();A[D]=g.release - except(Q,H,TypeError):pass - for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(e,'pybricks.hubs','EV3Brick')]: - try:k=__import__(i,E,E,j);A[L]=h;del k;break - except(N,R):pass - if A[L]==e:A['release']='2.0.0' - if A[L]==Y: + A[F]=U(os.uname()[3]) + if not A[F]:A[F]=U(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=U(sys.version.split(';')[1]) + except(I,P):pass + if A[F]and R(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(a,Z): + try:f=os.uname();A[D]=f.release + except(P,I,TypeError):pass + for(g,h,i)in[(b,b,'const'),(c,c,'FAT'),(d,'pybricks.hubs','EV3Brick')]: + try:j=__import__(h,E,E,i);A[L]=g;del j;break + except(M,Q):pass + if A[L]==d:A['release']='2.0.0' + if A[L]==X: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] - if W:A[Z]=W - A[K]='v{}.{}'.format(O&255,O>>8&3) - A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def A2(info,desc=B): - G='with ';D=info;E=A - for F in[A+'/board_info.csv'for A in A1]: - if i(F): - B=desc or D[I].strip() - if h(D,B,F):E=K;break - if M in B: - B=B.split(M)[0].strip() - if h(D,B,F):E=K;break - if not E: - B=desc or D[I].strip() - if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() - D[I]=B - D[I]=D[I].replace(' ',T);C.collect() -def h(info,board_descr,filename): - with X(filename,'r')as C: + N=int(A[K]);V=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] + if V:A[Y]=V + A[K]='v{}.{}'.format(N&255,N>>8&3) + A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def A1(info,desc=B): + L='with ';D=info;F=A + for G in[A+'/board_info.csv'for A in A0]: + if g(G): + E=desc or D[H].strip();I=E.rfind(' with') + if I!=-1:J=E[:I].strip() + else:J=B + if A2(D,E,G,J):F=K;break + if not F: + E=desc or D[H].strip() + if L+D[T].upper()in E:E=E.split(L+D[T].upper())[0].strip() + D[H]=E + D[H]=D[H].replace(' ',S);C.collect() +def A2(info,descr,filename,short_descr): + D=short_descr;C=info;E=B + with W(filename,'r')as J: while 1: - B=C.readline() - if not B:break - D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[I]=E;return K + F=J.readline() + if not F:break + I,G=F.split(',')[0].strip(),F.split(',')[1].strip() + if I==descr:C[H]=G;return K + elif D and I==D: + if x in D:C[H]=G;return K + E=G + if E:C[H]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=J + except(F,I):A=J B=A for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def i(filename): +def g(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def j():sys.exit(1) +def h():sys.exit(1) def read_path(): path=B - if S(sys.argv)==3: + if R(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:j() - elif S(sys.argv)==2:j() + else:h() + elif R(sys.argv)==2:h() return path -def k(): - try:B=bytes('abc',encoding='utf8');C=k.__module__;return A - except(l,H):return K -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',y,d,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or k(): - try:A3=logging.getLogger(x);logging.basicConfig(level=logging.INFO) - except n:pass - if not i('no_auto_stubber.txt'): +def i(): + try:B=bytes('abc',encoding='utf8');C=i.__module__;return A + except(j,I):return K +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',X,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,c,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or i(): + try:A3=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + except l:pass + if not g('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_mpy.mpy b/mip/v5/createstubs_mpy.mpy index 7d0b02dbef6ab6346dda4f6614e643c0c7a8fff1..eceb28c7253b323608835bf4f8b2e58de5c6ea9e 100644 GIT binary patch delta 1694 zcmX|BZERCj7(VB1yN_<`&ON<5-GtI^>ozv`)ly0@L0GBSZ7|lcZ-Lr%cWbw<9c{-p z2==0o5Ddxm#6V&snrP&Y$wt{=sF9BiCeavwm`D_64E{3FM1JTG6FprC_s7ZkxbO2m z=Y5~&EO-CXJvWdlI$Lx$PuWu?hAM}}ZmY9Y*$~N_4ktqlW=PKD>=1)#Vn`&XhK7_l zgX2Vh@>J8wQw*kvArc!M4M#^ABuP$UHo+i43MZ6gC^pO>PRPhqG?)y>q704^^fH4< zf-W+M5&cLc7DzIPk`y}1U_wF-3?dSmV=ykECI(|fKRFwWO)v-&ZM~ks5JBw>0t7`E z3=;GKg8_m>zJ3WEXV531HyQMjoZ#dXgKmQI7#xz&ID;+;)iUr&Xe)zG3GHWaP(mje zbV#V0!2wcUI1-o$M`ju9?_$tSppikFgsco&iGC;+h!67_+>eL(_qZI}`BU706=F%1P?(CZsv1P>m6}u81y)_Oz#gzM`F^hI(%rGj%i!$jvO&M9J!2)DoKAl7E3w= zy-`O#gOEedXj};l`zHg*kfVS>_+3pCKF*spjX09_YYb2{R;h7frL73{QE25SbUxhA zztNpDjVw^zUrs#GwkdP6Z{0)H0SX=I@tifBI(XHI{q6su)kPU`3Wr?SQ>ZS^8;c+9 z)u`?#Depx@QQy@?C*1RvAqu?|U0!lxCzjDW1ZrIPbkBWJ1_9i;?#aslyYIJQbmTgP z2?|jPF$$9u#Qq?KKtt{$k4`OjlxJ;+<-zK|DoU$ZGu9Qzfo9G1BRKK!qwF~Q6V^Qnv`Mp||*6;|cH(&NXAwyYJ6{sr~i=}>t-EMK% z#LUvnm)IbH!X=Y8*E>Y>DRlGKO){S5Q>NW*Rid?RG733>mKe=O!*L~^5O#E8muU1k zn(M;LbW`s$ZLNE>>c&mI=fw5=6MR@a8hD?7b-@LScrtl(yqe zexcM%?aP@a>SUb@4S4%S${zkjX(Mjnzn5;qUEET31PA%4vJUM53O@c_*;d@2{-nTvF z4cb=*#OD^4_%wBG@1AF<`OiSFiUi#}f3r&{Y0u_rs4VB9&2_1>@)^0hM5F$>wZU3b zW3f4_9WOSb^ve7yHQf_h78;8Sjg6xF*JYG)p|u+s&-JM{HoR5u!fF{eH@K_{fsjUs|M^ zUaASwnjk`D`e7vzj0=56lxSc=VTn*Ip7d{QzSTMW!t+;Xllm{;Vy+MdX)zzx?k<_r z@{i2SRvDy~!42;hWxcA|@TyNhTe^t>LdA1={3o-`ptm(Q?yTL3=#EQEgb7 zqkM9U-8x3M*FiSC=6U#g&L2N)HlSnDoSeSBWeISS&y>5xbM|@pCG9kYAn&V)<3##F HMJ)G!jRVL$ delta 1644 zcmX|BOH5lw6rH)Y!5A>(u{}Wf7=sC)@Uw9ovB(cxVjv;>445Xd{CODjv57Gdf)c+Z zid02vOFIj)Xd9_&rKnORz(7RRsA&`Ok=jKUU1Wi%qO|I&Y7(jHrfSEA=IQBa-g|fM zIrrXk=9hu3fhA8udqaIgEgi2Ek4l@#YN<6O15)jd$B?ePE)W~3xXr>ne(J2N&qO8*}2oTi8z)#R510O-3Fc=|7 z;CXatj=``FU1KmrG6K`H4BP~%84T#q1cQDZs$tNlL)8p=b?6j>9vxa_a7Kp?Fz6=g z`EY!U!D(X78TCztCl?r;>SNGFpn*Xr(fFgjn5d;ghsyXxJd7p&6E@>R{57t}qudN9 zGA>mPZu)`x)A)+uu(WjesY{v%lA%Q9fzUqG5sY@m9-F2!{iCZ6cVs!2< zg(!t-3KuBED2!0>QSjGi?l@KQ)hDfHSp>{bz;T{bAHy#GTHS}IlI>Y~zyo|FJDA_S zm(CPOWup*EiV7$U^PjW7P|i}A<5zMDa9?sc=MKha_;GEUy8oUX(^RW(YVRxKB0cZU zThR#oJt8r#Cgqv_G?5W*C3lp46e7tT@+%gQ59m9Bg-LJ3^Zbzhre%1IWZB_l6MC>> zD4&moboEp~+;bJ8ZR@ zYAs@AG9BdWY(z+qa}$-DyB$HlRj* ziC#M=#b$(0?bw00Xwl%l$abAdIbE{rGf}5^$`=?5MSGc`C5pD zimkng25>usbZ$A&7Ofmie^>Cvf-c<47Yjgvw~*a z&vOgU;UJ$V>{fPD=;QYatFb5fTj4mS&R4iv7)T*MudS~bpo9ZGTu(XAA+M($R_DO`@acEa#H)KCBioNQR-ZXF^5zOP4$`7P>o{-;{K{Cz$)zo1?`j|IOP=%7y5|C1;Pe7?)6my$QLB z5X~}Vt)x)je<{XG%>i+z9iF@ANJZL_y#l6WfM{VnZ%N4&rIx%5OH)HjO^Yb0^*)7u zeyH@kazeMH<;$g3JjtJymSU3py>t`s9KUUD6^GMv^DX59g&@CD9>cTAm*vsS{{T>I BvFZQ- diff --git a/mip/v6/createstubs.py b/mip/v6/createstubs.py index af07c6418..85421cd2d 100644 --- a/mip/v6/createstubs.py +++ b/mip/v6/createstubs.py @@ -469,7 +469,7 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]) + info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") except AttributeError: pass try: @@ -478,7 +478,8 @@ def _info(): # type:() -> dict[str, str] if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore ) - info["board"] = "with".join(_machine.split("with")[:-1]).strip() + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy @@ -575,16 +576,15 @@ def read_boardname(info, desc: str = ""): # print("look up the board name in the file", filename) if file_exists(filename): descr = desc or info["board"].strip() - print("searching info file: {}".format(filename)) - if find_board(info, descr, filename): + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): found = True break - if "with" in descr: - descr = descr.split("with")[0].strip() - print("searching for: {}".format(descr)) - if find_board(info, descr, filename): - found = True - break if not found: print("Board not found, guessing board name") descr = desc or info["board"].strip() @@ -596,18 +596,30 @@ def read_boardname(info, desc: str = ""): gc.collect() -def find_board(info: dict, board_descr: str, filename: str): +def find_board(info: dict, descr: str, filename: str, short_descr: str): "Find the board in the provided board_info.csv file" + short_hit = "" with open(filename, "r") as file: # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) while 1: line = file.readline() if not line: break descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == board_descr: + if descr_ == descr: info["board"] = board_ return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True return False diff --git a/mip/v6/createstubs_db.py b/mip/v6/createstubs_db.py index ecb9ffe19..7a9761f7e 100644 --- a/mip/v6/createstubs_db.py +++ b/mip/v6/createstubs_db.py @@ -462,12 +462,13 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]) + info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") except AttributeError: pass try: _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = "with".join(_machine.split("with")[:-1]).strip() + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy @@ -563,16 +564,15 @@ def read_boardname(info, desc: str = ""): # print("look up the board name in the file", filename) if file_exists(filename): descr = desc or info["board"].strip() - print("searching info file: {}".format(filename)) - if find_board(info, descr, filename): + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): found = True break - if "with" in descr: - descr = descr.split("with")[0].strip() - print("searching for: {}".format(descr)) - if find_board(info, descr, filename): - found = True - break if not found: print("Board not found, guessing board name") descr = desc or info["board"].strip() @@ -584,18 +584,30 @@ def read_boardname(info, desc: str = ""): gc.collect() -def find_board(info: dict, board_descr: str, filename: str): +def find_board(info: dict, descr: str, filename: str, short_descr: str): "Find the board in the provided board_info.csv file" + short_hit = "" with open(filename, "r") as file: # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) while 1: line = file.readline() if not line: break descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == board_descr: + if descr_ == descr: info["board"] = board_ return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True return False diff --git a/mip/v6/createstubs_db_min.py b/mip/v6/createstubs_db_min.py index 8f5a7e7f8..751c0c400 100644 --- a/mip/v6/createstubs_db_min.py +++ b/mip/v6/createstubs_db_min.py @@ -1,37 +1,37 @@ -x='stubber' -w='{}/{}' -v='method' -u='function' -t='bool' -s='str' -r='float' -q='int' -p=NameError -o=sorted -n=MemoryError -m=NotImplementedError -d=',\n' -c='dict' -b='list' -a='tuple' -Z='micropython' -Y=str -X=repr -V='cpu' -U='_' -T=KeyError -S=IndexError -R=dir -Q=ImportError -P='with' +w='with' +v='stubber' +u='{}/{}' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n=NameError +m=sorted +l=MemoryError +k=NotImplementedError +c=',\n' +b='dict' +a='list' +Z='tuple' +Y='micropython' +X=str +W=repr +U='cpu' +T='_' +S=KeyError +R=IndexError +Q=dir +P=ImportError O='family' N=print M=len L='.' -K='board' +K=open J=True -I=open -H=AttributeError +I=AttributeError +H='board' G='/' F=None E='version' @@ -39,51 +39,51 @@ A=OSError C='' import gc as B,os,sys -from ujson import dumps as e +from ujson import dumps as d try:from machine import reset -except Q:pass -try:from collections import OrderedDict as f -except Q:from ucollections import OrderedDict as f +except P:pass +try:from collections import OrderedDict as e +except P:from ucollections import OrderedDict as e __version__='v1.16.2' +x=2 y=2 -z=2 -g=[L,'/lib','/sd/lib','/flash/lib','lib'] +f=[L,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(C,path=F,firmware_id=F): D=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') - except H:pass + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + except I:pass C._report=[];C.info=_info();B.collect() if D:C._fwid=D.lower() - elif C.info[O]==Z:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) + elif C.info[O]==Y:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) else:C._fwid='{family}-{ver}-{port}'.format(**C.info) C._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) - try:h(path+G) + try:g(path+G) except A:N('error creating stub folder {}'.format(path)) C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] def get_obj_attributes(L,item_instance): - I=item_instance;D=[];J=[] - for A in R(I): - if A.startswith(U)and not A in L.modules:continue + H=item_instance;D=[];J=[] + for A in Q(H): + if A.startswith(T)and not A in L.modules:continue try: - E=getattr(I,A) - try:F=X(type(E)).split("'")[1] - except S:F=C - if F in{q,r,s,t,a,b,c}:G=1 - elif F in{u,v}:G=2 + E=getattr(H,A) + try:F=W(type(E)).split("'")[1] + except R:F=C + if F in{o,p,q,r,Z,a,b}:G=1 + elif F in{s,t}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,X(E),X(type(E)),E,G)) - except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) - except n as K:sleep(1);reset() - D=o([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) + D.append((A,W(E),W(type(E)),E,G)) + except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) + except l as K:sleep(1);reset() + D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J + def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) @@ -95,86 +95,86 @@ def create_one_stub(C,module_name): try:F=C.create_module_stub(E,H) except A:return D B.collect();return F - def create_module_stub(K,module_name,file_name=F): + def create_module_stub(I,module_name,file_name=F): H=file_name;E=module_name - if H is F:O=E.replace(L,U)+'.py';H=K.path+G+O + if H is F:O=E.replace(L,T)+'.py';H=I.path+G+O else:O=H.split(G)[-1] if G in E:E=E.replace(G,L) M=F - try:M=__import__(E,F,F,'*');S=B.mem_free() - except Q:return D - h(H) - with I(H,'w')as N:P=Y(K.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(E,K._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,M,E,C) - K._report.append('{{"module": "{}", "file": "{}"}}'.format(E,H.replace('\\',G))) + try:M=__import__(E,F,F,'*');U=B.mem_free() + except P:return D + g(H) + with K(H,'w')as N:Q=X(I.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(E,I._fwid,Q,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,E,C) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(E,H.replace('\\',G))) if E not in{'os','sys','logging','gc'}: try:del M - except(A,T):pass + except(A,S):pass try:del sys.modules[E] - except T:pass + except S:pass B.collect();return J def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() if P in K.problematic:return R,L=K.get_obj_attributes(P) if L:N(L) - for(F,J,G,S,f)in R: + for(F,J,G,T,f)in R: if F in['classmethod','staticmethod','BaseException',O]:continue if F[0].isdigit():continue - if G==""and M(E)<=z*4: + if G==""and M(E)<=y*4: U=C;V=F.endswith(O)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O D='\n{}class {}({}):\n'.format(E,F,U) if V:D+=E+' ...\n';H.write(D);return - H.write(D);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) - elif any(A in G for A in[v,u,'closure']): + H.write(D);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) + elif any(A in G for A in[t,s,'closure']): W=Y;X=C if Q>0:X='self, ' - if Z in G or Z in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) + if c in G or c in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,X,W) D+=E+' ...\n\n';H.write(D) elif G=="":0 elif G.startswith("5:A[D]=C - if A[E]==C and sys.platform not in(c,b): - try:h=os.uname();A[E]=h.release - except(S,H,TypeError):pass - for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: - try:l=__import__(j,F,F,k);A[O]=i;del l;break - except(Q,T):pass - if A[O]==g:A['release']='2.0.0' - if A[O]==Z: + if A[E]==C and sys.platform not in(b,a): + try:g=os.uname();A[E]=g.release + except(R,I,TypeError):pass + for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(f,'pybricks.hubs','EV3Brick')]: + try:k=__import__(i,F,F,j);A[O]=h;del k;break + except(P,S):pass + if A[O]==f:A['release']='2.0.0' + if A[O]==Y: if A[E]and A[E].endswith('.0')and A[E]>='1.10.0'and A[E]<='1.19.9':A[E]=A[E][:-2] - if I in A and A[I]: - J=int(A[I]);U=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][J>>10] - if U:A[a]=U - A[I]='v{}.{}'.format(J&255,J>>8&3) - A[X]=f"v{A[E]}-{A[D]}"if A[D]else f"v{A[E]}";return A -def A0(info,desc=C): - G='with ';C=info;E=D - for F in[A+'/board_info.csv'for A in g]: - if j(F): - A=desc or C[K].strip() - if i(C,A,F):E=J;break - if P in A: - A=A.split(P)[0].strip() - if i(C,A,F):E=J;break - if not E: - A=desc or C[K].strip() - if G+C[V].upper()in A:A=A.split(G+C[V].upper())[0].strip() - C[K]=A - C[K]=C[K].replace(' ',U);B.collect() -def i(info,board_descr,filename): - with I(filename,'r')as B: + if J in A and A[J]: + K=int(A[J]);T=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if T:A[Z]=T + A[J]='v{}.{}'.format(K&255,K>>8&3) + A[W]=f"v{A[E]}-{A[D]}"if A[D]else f"v{A[E]}";return A +def z(info,desc=C): + L='with ';A=info;F=D + for G in[A+'/board_info.csv'for A in f]: + if h(G): + E=desc or A[H].strip();I=E.rfind(' with') + if I!=-1:K=E[:I].strip() + else:K=C + if A0(A,E,G,K):F=J;break + if not F: + E=desc or A[H].strip() + if L+A[U].upper()in E:E=E.split(L+A[U].upper())[0].strip() + A[H]=E + A[H]=A[H].replace(' ',T);B.collect() +def A0(info,descr,filename,short_descr): + B=short_descr;A=info;E=C + with K(filename,'r')as L: while 1: - A=B.readline() - if not A:break - C,E=A.split(',')[0].strip(),A.split(',')[1].strip() - if C==board_descr:info[K]=E;return J + F=L.readline() + if not F:break + I,G=F.split(',')[0].strip(),F.split(',')[1].strip() + if I==descr:A[H]=G;return J + elif B and I==B: + if w in B:A[H]=G;return J + E=G + if E:A[H]=E;return J return D def get_root(): try:B=os.getcwd() - except(A,H):B=L + except(A,I):B=L C=B for C in[B,'/sd','/flash',G,L]: try:D=os.stat(C);break except A:continue return C -def j(filename): +def h(filename): try: if os.stat(filename)[0]>>14:return J return D except A:return D -def k():sys.exit(1) +def i():sys.exit(1) def read_path(): path=C if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:k() - elif M(sys.argv)==2:k() + else:i() + elif M(sys.argv)==2:i() return path -def l(): - try:A=bytes('abc',encoding='utf8');B=l.__module__;return D - except(m,H):return J +def j(): + try:A=bytes('abc',encoding='utf8');B=j.__module__;return D + except(k,I):return J def main(): L='failed';G='modulelist.done';import machine as O - try:C=I(G,'r+b');N=J - except A:C=I(G,'w+b');N=D + try:C=K(G,'r+b');N=J + except A:C=K(G,'w+b');N=D stubber=Stubber(path=read_path()) if not N:stubber.clean() A1(stubber);E={} try: - with I(G)as C: + with K(G)as C: for F in C.read().split('\n'): F=F.strip();B.collect() if M(F)>0:P,Q=F.split('=',1);E[P]=Q except(A,SyntaxError):pass B.collect();R=[A for A in stubber.modules if A not in E.keys()];B.collect() for H in R: - K=D - try:K=stubber.create_one_stub(H) - except n:O.reset() - B.collect();E[H]=Y(stubber._report[-1]if K else L) - with I(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if K else L)) + I=D + try:I=stubber.create_one_stub(H) + except l:O.reset() + B.collect();E[H]=X(stubber._report[-1]if I else L) + with K(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if I else L)) if E:stubber._report=[A for(B,A)in E.items()if A!=L];stubber.report() def A1(stubber): E='/modulelist.txt';stubber.modules=[] - for D in g: + for D in f: try: - with I(D+E)as F: + with K(D+E)as F: N('DEBUG: list of modules: '+D+E) for C in F.read().split('\n'): C=C.strip() if M(C)>0 and C[0]!='#':stubber.modules.append(C) B.collect();break except A:pass - if not stubber.modules:stubber.modules=[Z];_log.warn('Could not find modulelist.txt, using default modules') + if not stubber.modules:stubber.modules=[Y];_log.warn('Could not find modulelist.txt, using default modules') B.collect() -if __name__=='__main__'or l(): - try:A2=logging.getLogger(x);logging.basicConfig(level=logging.INFO) - except p:pass - if not j('no_auto_stubber.txt'): +if __name__=='__main__'or j(): + try:A2=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + except n:pass + if not h('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_db_mpy.mpy b/mip/v6/createstubs_db_mpy.mpy index e1e5d09b8bc7f7df04626c838f32f68dbd2f3186..deb27e592e68ab067146ec731ba4880e9163f418 100644 GIT binary patch delta 5344 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 delta 5244 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 diff --git a/mip/v6/createstubs_lvgl.py b/mip/v6/createstubs_lvgl.py index 4f881cc48..fe5417871 100644 --- a/mip/v6/createstubs_lvgl.py +++ b/mip/v6/createstubs_lvgl.py @@ -447,12 +447,13 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]) + info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") except AttributeError: pass try: _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = "with".join(_machine.split("with")[:-1]).strip() + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy @@ -548,16 +549,15 @@ def read_boardname(info, desc: str = ""): # print("look up the board name in the file", filename) if file_exists(filename): descr = desc or info["board"].strip() - print("searching info file: {}".format(filename)) - if find_board(info, descr, filename): + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): found = True break - if "with" in descr: - descr = descr.split("with")[0].strip() - print("searching for: {}".format(descr)) - if find_board(info, descr, filename): - found = True - break if not found: print("Board not found, guessing board name") descr = desc or info["board"].strip() @@ -569,18 +569,30 @@ def read_boardname(info, desc: str = ""): gc.collect() -def find_board(info: dict, board_descr: str, filename: str): +def find_board(info: dict, descr: str, filename: str, short_descr: str): "Find the board in the provided board_info.csv file" + short_hit = "" with open(filename, "r") as file: # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) while 1: line = file.readline() if not line: break descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == board_descr: + if descr_ == descr: info["board"] = board_ return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True return False diff --git a/mip/v6/createstubs_lvgl_min.py b/mip/v6/createstubs_lvgl_min.py index 9ccf49b17..24d22c1d8 100644 --- a/mip/v6/createstubs_lvgl_min.py +++ b/mip/v6/createstubs_lvgl_min.py @@ -1,36 +1,36 @@ -v='stubber' -u='{}/{}' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n='micropython' -m=Exception -l=NameError -k=sorted -j=NotImplementedError -b=',\n' -a='dict' -Z='list' -Y='tuple' -X=open -W=repr -U='cpu' -T='_' -S=len -R=KeyError -Q=IndexError -P=dir -O=print -N=ImportError -M='with' +u='with' +t='stubber' +s='{}/{}' +r='method' +q='function' +p='bool' +o='str' +n='float' +m='int' +l='micropython' +k=Exception +j=NameError +i=sorted +h=NotImplementedError +a=',\n' +Z='dict' +Y='list' +X='tuple' +W=open +V=repr +T='cpu' +S='_' +R=len +Q=KeyError +P=IndexError +O=dir +N=print +M=ImportError L='family' K=True J='.' -I='board' -H=AttributeError +I=AttributeError +H='board' A=False G='/' E=None @@ -38,51 +38,51 @@ F=OSError B='' import gc as C,os,sys -from ujson import dumps as c +from ujson import dumps as b try:from machine import reset -except N:pass -try:from collections import OrderedDict as d -except N:from ucollections import OrderedDict as d +except M:pass +try:from collections import OrderedDict as c +except M:from ucollections import OrderedDict as c __version__='v1.16.2' +v=2 w=2 -x=2 -y=[J,'/lib','/sd/lib','/flash/lib','lib'] +x=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') - except H:pass + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise h('MicroPython 1.13.0 cannot be stubbed') + except I:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[L]==n:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:e(path+G) - except F:O('error creating stub folder {}'.format(path)) + try:d(path+G) + except F:N('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): - I=item_instance;D=[];J=[] - for A in P(I): - if A.startswith(T)and not A in L.modules:continue + H=item_instance;D=[];J=[] + for A in O(H): + if A.startswith(S)and not A in L.modules:continue try: - E=getattr(I,A) - try:F=W(type(E)).split("'")[1] - except Q:F=B - if F in{o,p,q,r,Y,Z,a}:G=1 - elif F in{s,t}:G=2 + E=getattr(H,A) + try:F=V(type(E)).split("'")[1] + except P:F=B + if F in{m,n,o,p,X,Y,Z}:G=1 + elif F in{q,r}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,W(E),W(type(E)),E,G)) - except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) + D.append((A,V(E),V(type(E)),E,G)) + except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J - def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) + D=i([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=i(set(A.modules)|set(modules)) def create_all_stubs(A): C.collect() for B in A.modules:A.create_one_stub(B) @@ -96,84 +96,84 @@ def create_one_stub(B,module_name): C.collect();return E def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:O=D.replace(J,T)+'.py';H=I.path+G+O + if H is E:O=D.replace(J,S)+'.py';H=I.path+G+O else:O=H.split(G)[-1] if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');S=C.mem_free() - except N:return A - e(H) - with X(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) + try:L=__import__(D,E,E,'*');T=C.mem_free() + except M:return A + d(H) + with W(H,'w')as N:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,L,D,B) I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del L - except(F,R):pass + except(F,Q):pass try:del sys.modules[D] - except R:pass + except Q:pass C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;D=indent;C.collect() - if N in K.problematic:return - Q,L=K.get_obj_attributes(N) - if L:O(L) - for(E,J,G,T,f)in Q: + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() + if O in K.problematic:return + S,L=K.get_obj_attributes(O) + if L:N(L) + for(E,J,G,T,f)in S: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and S(D)<=x*4: + if G==""and R(D)<=w*4: U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[t,s,'closure']): - W=b;X=B - if P>0:X='self, ' + elif any(A in G for A in[r,q,'closure']): + W=b;a=B + if P>0:a='self, ' if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(a,Z): - try:f=os.uname();A[D]=f.release - except(Q,H,TypeError):pass - for(g,h,i)in[(b,b,'const'),(c,c,'FAT'),(e,'pybricks.hubs','EV3Brick')]: - try:j=__import__(h,E,E,i);A[L]=g;del j;break - except(N,R):pass - if A[L]==e:A['release']='2.0.0' - if A[L]==n: + A[F]=U(os.uname()[3]) + if not A[F]:A[F]=U(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=U(sys.version.split(';')[1]) + except(I,P):pass + if A[F]and R(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(Z,Y): + try:e=os.uname();A[D]=e.release + except(P,I,TypeError):pass + for(f,g,h)in[(a,a,'const'),(b,b,'FAT'),(d,'pybricks.hubs','EV3Brick')]: + try:i=__import__(g,E,E,h);A[L]=f;del i;break + except(M,Q):pass + if A[L]==d:A['release']='2.0.0' + if A[L]==l: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] - if W:A[Y]=W - A[K]='v{}.{}'.format(O&255,O>>8&3) - A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def z(info,desc=B): - G='with ';D=info;E=A - for F in[A+'/board_info.csv'for A in y]: - if g(F): - B=desc or D[I].strip() - if f(D,B,F):E=K;break - if M in B: - B=B.split(M)[0].strip() - if f(D,B,F):E=K;break - if not E: - B=desc or D[I].strip() - if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() - D[I]=B - D[I]=D[I].replace(' ',T);C.collect() -def f(info,board_descr,filename): - with X(filename,'r')as C: + N=int(A[K]);V=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] + if V:A[X]=V + A[K]='v{}.{}'.format(N&255,N>>8&3) + A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def y(info,desc=B): + L='with ';D=info;F=A + for G in[A+'/board_info.csv'for A in x]: + if e(G): + E=desc or D[H].strip();I=E.rfind(' with') + if I!=-1:J=E[:I].strip() + else:J=B + if z(D,E,G,J):F=K;break + if not F: + E=desc or D[H].strip() + if L+D[T].upper()in E:E=E.split(L+D[T].upper())[0].strip() + D[H]=E + D[H]=D[H].replace(' ',S);C.collect() +def z(info,descr,filename,short_descr): + D=short_descr;C=info;E=B + with W(filename,'r')as J: while 1: - B=C.readline() - if not B:break - D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[I]=E;return K + F=J.readline() + if not F:break + I,G=F.split(',')[0].strip(),F.split(',')[1].strip() + if I==descr:C[H]=G;return K + elif D and I==D: + if u in D:C[H]=G;return K + E=G + if E:C[H]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=J + except(F,I):A=J B=A for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def g(filename): +def e(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def h():sys.exit(1) +def f():sys.exit(1) def read_path(): path=B - if S(sys.argv)==3: + if R(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:h() - elif S(sys.argv)==2:h() + else:f() + elif R(sys.argv)==2:f() return path -def i(): - try:B=bytes('abc',encoding='utf8');C=i.__module__;return A - except(j,H):return K +def g(): + try:B=bytes('abc',encoding='utf8');C=g.__module__;return A + except(h,I):return K def main(): D='lvgl' try:import lvgl as A - except m:return + except k:return B=D try:B='lvgl-{0}_{1}_{2}-{3}-{4}'.format(A.version_major(),A.version_minor(),A.version_patch(),A.version_info(),sys.platform) - except m:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) + except k:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) finally:stubber=Stubber(firmware_id=B) stubber.clean();stubber.modules=['io','lodepng','rtch',D];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or i(): - try:A0=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except l:pass - if not g('no_auto_stubber.txt'): +if __name__=='__main__'or g(): + try:A0=logging.getLogger(t);logging.basicConfig(level=logging.INFO) + except j:pass + if not e('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_lvgl_mpy.mpy b/mip/v6/createstubs_lvgl_mpy.mpy index ba80b338d66088ec097403f074c74b62165e5c7d..cecb4fb0b5c3041df3d37a53dfc7496bc7c07a2a 100644 GIT binary patch delta 4993 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 MTt_w;Ke5#R0ioBWZ2$lO delta 4879 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 dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]) + info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") except AttributeError: pass try: _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = "with".join(_machine.split("with")[:-1]).strip() + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy @@ -554,16 +555,15 @@ def read_boardname(info, desc: str = ""): # print("look up the board name in the file", filename) if file_exists(filename): descr = desc or info["board"].strip() - print("searching info file: {}".format(filename)) - if find_board(info, descr, filename): + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): found = True break - if "with" in descr: - descr = descr.split("with")[0].strip() - print("searching for: {}".format(descr)) - if find_board(info, descr, filename): - found = True - break if not found: print("Board not found, guessing board name") descr = desc or info["board"].strip() @@ -575,18 +575,30 @@ def read_boardname(info, desc: str = ""): gc.collect() -def find_board(info: dict, board_descr: str, filename: str): +def find_board(info: dict, descr: str, filename: str, short_descr: str): "Find the board in the provided board_info.csv file" + short_hit = "" with open(filename, "r") as file: # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) while 1: line = file.readline() if not line: break descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == board_descr: + if descr_ == descr: info["board"] = board_ return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True return False diff --git a/mip/v6/createstubs_mem_min.py b/mip/v6/createstubs_mem_min.py index b80e20c14..139f88f81 100644 --- a/mip/v6/createstubs_mem_min.py +++ b/mip/v6/createstubs_mem_min.py @@ -1,179 +1,179 @@ -w='stubber' -v='{}/{}' -u='method' -t='function' -s='bool' -r='str' -q='float' -p='int' -o=NameError -n=sorted -m=NotImplementedError -d=',\n' -c='dict' -b='list' -a='tuple' -Z='micropython' -Y=str -X=repr -V='cpu' -U='_' -T=KeyError -S=open -R=IndexError -Q=dir -P=ImportError -O='with' +v='with' +u='stubber' +t='{}/{}' +s='method' +r='function' +q='bool' +p='str' +o='float' +n='int' +m=NameError +l=sorted +k=NotImplementedError +c=',\n' +b='dict' +a='list' +Z='tuple' +Y='micropython' +X=str +W=repr +U='cpu' +T='_' +S=KeyError +R=open +Q=IndexError +P=dir +O=ImportError N='family' M=len L=print K=True J='.' -I='board' -H=AttributeError +I=AttributeError +H='board' A=False G='/' E=None D='version' F=OSError -C='' -import gc as B,os,sys -from ujson import dumps as e +B='' +import gc as C,os,sys +from ujson import dumps as d try:from machine import reset -except P:pass -try:from collections import OrderedDict as f -except P:from ucollections import OrderedDict as f +except O:pass +try:from collections import OrderedDict as e +except O:from ucollections import OrderedDict as e __version__='v1.16.2' +w=2 x=2 -y=2 -g=[J,'/lib','/sd/lib','/flash/lib','lib'] +f=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): - C=firmware_id + B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') - except H:pass - A._report=[];A.info=_info();B.collect() - if C:A._fwid=C.lower() - elif A.info[N]==Z:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + except I:pass + A._report=[];A.info=_info();C.collect() + if B:A._fwid=B.lower() + elif A.info[N]==Y:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) - A._start_free=B.mem_free() + A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:h(path+G) + try:g(path+G) except F:L('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): - I=item_instance;D=[];J=[] - for A in Q(I): - if A.startswith(U)and not A in L.modules:continue + H=item_instance;D=[];J=[] + for A in P(H): + if A.startswith(T)and not A in L.modules:continue try: - E=getattr(I,A) - try:F=X(type(E)).split("'")[1] - except R:F=C - if F in{p,q,r,s,a,b,c}:G=1 - elif F in{t,u}:G=2 + E=getattr(H,A) + try:F=W(type(E)).split("'")[1] + except Q:F=B + if F in{n,o,p,q,Z,a,b}:G=1 + elif F in{r,s}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,X(E),X(type(E)),E,G)) - except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) + D.append((A,W(E),W(type(E)),E,G)) + except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=n([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=n(set(A.modules)|set(modules)) + D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) def create_all_stubs(A): - B.collect() - for C in A.modules:A.create_one_stub(C) - def create_one_stub(C,module_name): + C.collect() + for B in A.modules:A.create_one_stub(B) + def create_one_stub(B,module_name): D=module_name - if D in C.problematic:return A - if D in C.excluded:return A - H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=A - try:E=C.create_module_stub(D,H) + if D in B.problematic:return A + if D in B.excluded:return A + H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A + try:E=B.create_module_stub(D,H) except F:return A - B.collect();return E + C.collect();return E def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:N=D.replace(J,U)+'.py';H=I.path+G+N + if H is E:N=D.replace(J,T)+'.py';H=I.path+G+N else:N=H.split(G)[-1] if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');R=B.mem_free() - except P:return A - h(H) - with S(H,'w')as M:O=Y(I.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,O,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,C) + try:L=__import__(D,E,E,'*');U=C.mem_free() + except O:return A + g(H) + with R(H,'w')as M:P=X(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del L - except(F,T):pass + except(F,S):pass try:del sys.modules[D] - except T:pass - B.collect();return K + except S:pass + C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;C.collect() if P in K.problematic:return R,N=K.get_obj_attributes(P) if N:L(N) - for(E,J,G,S,f)in R: + for(E,J,G,T,f)in R: if E in['classmethod','staticmethod','BaseException',O]:continue if E[0].isdigit():continue - if G==""and M(D)<=y*4: - U=C;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if G==""and M(D)<=x*4: + U=B;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[u,t,'closure']): - W=Y;X=C + H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) + elif any(A in G for A in[s,r,'closure']): + W=Y;X=B if Q>0:X='self, ' - if Z in G or Z in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) + if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=C - if A[D]==C and sys.platform not in(c,b): - try:h=os.uname();A[D]=h.release - except(R,H,TypeError):pass - for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: - try:l=__import__(j,E,E,k);A[N]=i;del l;break - except(P,T):pass - if A[N]==g:A['release']='2.0.0' - if A[N]==Z: + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=V(sys.version.split(';')[1]) + except(I,Q):pass + if A[F]and M(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(b,a): + try:g=os.uname();A[D]=g.release + except(Q,I,TypeError):pass + for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(f,'pybricks.hubs','EV3Brick')]: + try:k=__import__(i,E,E,j);A[N]=h;del k;break + except(O,S):pass + if A[N]==f:A['release']='2.0.0' + if A[N]==Y: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - L=int(A[K]);U=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][L>>10] - if U:A[a]=U + L=int(A[K]);T=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][L>>10] + if T:A[Z]=T A[K]='v{}.{}'.format(L&255,L>>8&3) - A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def z(info,desc=C): - G='with ';D=info;E=A - for F in[A+'/board_info.csv'for A in g]: - if j(F): - C=desc or D[I].strip() - if i(D,C,F):E=K;break - if O in C: - C=C.split(O)[0].strip() - if i(D,C,F):E=K;break - if not E: - C=desc or D[I].strip() - if G+D[V].upper()in C:C=C.split(G+D[V].upper())[0].strip() - D[I]=C - D[I]=D[I].replace(' ',U);B.collect() -def i(info,board_descr,filename): - with S(filename,'r')as C: + A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def y(info,desc=B): + L='with ';D=info;F=A + for G in[A+'/board_info.csv'for A in f]: + if h(G): + E=desc or D[H].strip();I=E.rfind(' with') + if I!=-1:J=E[:I].strip() + else:J=B + if z(D,E,G,J):F=K;break + if not F: + E=desc or D[H].strip() + if L+D[U].upper()in E:E=E.split(L+D[U].upper())[0].strip() + D[H]=E + D[H]=D[H].replace(' ',T);C.collect() +def z(info,descr,filename,short_descr): + D=short_descr;C=info;E=B + with R(filename,'r')as J: while 1: - B=C.readline() - if not B:break - D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[I]=E;return K + F=J.readline() + if not F:break + I,G=F.split(',')[0].strip(),F.split(',')[1].strip() + if I==descr:C[H]=G;return K + elif D and I==D: + if v in D:C[H]=G;return K + E=G + if E:C[H]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=J + except(F,I):A=J B=A for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def j(filename): +def h(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def k():sys.exit(1) +def i():sys.exit(1) def read_path(): - path=C + path=B if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:k() - elif M(sys.argv)==2:k() + else:i() + elif M(sys.argv)==2:i() return path -def l(): - try:B=bytes('abc',encoding='utf8');C=l.__module__;return A - except(m,H):return K +def j(): + try:B=bytes('abc',encoding='utf8');C=j.__module__;return A + except(k,I):return K def main(): E='/modulelist.txt';stubber=Stubber(path=read_path());stubber.clean();stubber.modules=[] - for C in g: + for B in f: try: - F=B.mem_free() - with S(C+E)as D: - L('Debug: List of modules: '+C+E);A=D.readline() + F=C.mem_free() + with R(B+E)as D: + L('Debug: List of modules: '+B+E);A=D.readline() while A: A=A.strip() if M(A)>0 and A[0]!='#':stubber.modules.append(A) A=D.readline() - B.collect();L('Debug: Used memory to load modulelist.txt: '+Y(F-B.mem_free())+' bytes');break + C.collect();L('Debug: Used memory to load modulelist.txt: '+X(F-C.mem_free())+' bytes');break except Exception:pass - if not stubber.modules:stubber.modules=[Z] - B.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or l(): - try:A0=logging.getLogger(w);logging.basicConfig(level=logging.INFO) - except o:pass - if not j('no_auto_stubber.txt'): - try:B.threshold(4*1024);B.enable() + if not stubber.modules:stubber.modules=[Y] + C.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or j(): + try:A0=logging.getLogger(u);logging.basicConfig(level=logging.INFO) + except m:pass + if not h('no_auto_stubber.txt'): + try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_mem_mpy.mpy b/mip/v6/createstubs_mem_mpy.mpy index 32ba3d10d95c08775940a9637f1aec1520a946b0..72c6790b977ce0f74604ec76b3c96bad2166c99b 100644 GIT binary patch delta 4989 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 RzL8P=0u+c%AvUq(e*@DNogV-I diff --git a/mip/v6/createstubs_min.py b/mip/v6/createstubs_min.py index 75a060686..cca13284d 100644 --- a/mip/v6/createstubs_min.py +++ b/mip/v6/createstubs_min.py @@ -1,39 +1,39 @@ -y='pyb' -x='stubber' -w='{}/{}' -v='logging' -u='sys' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n=NameError -m=sorted -l=NotImplementedError -d='pycom' -c=',\n' -b='dict' -a='list' -Z='tuple' -Y='micropython' -X=open -W=repr -U='cpu' -T='_' -S=len -R=KeyError -Q=IndexError -P=dir -O=print -N=ImportError -M='with' +x='with' +w='pyb' +v='stubber' +u='{}/{}' +t='logging' +s='sys' +r='method' +q='function' +p='bool' +o='str' +n='float' +m='int' +l=NameError +k=sorted +j=NotImplementedError +c='pycom' +b=',\n' +a='dict' +Z='list' +Y='tuple' +X='micropython' +W=open +V=repr +T='cpu' +S='_' +R=len +Q=KeyError +P=IndexError +O=dir +N=print +M=ImportError L='family' K=True J='.' -I='board' -H=AttributeError +I=AttributeError +H='board' A=False G='/' E=None @@ -41,51 +41,51 @@ D='version' B='' import gc as C,os,sys -from ujson import dumps as e +from ujson import dumps as d try:from machine import reset -except N:pass -try:from collections import OrderedDict as f -except N:from ucollections import OrderedDict as f +except M:pass +try:from collections import OrderedDict as e +except M:from ucollections import OrderedDict as e __version__='v1.16.2' +y=2 z=2 -A0=2 -A1=[J,'/lib','/sd/lib','/flash/lib','lib'] +A0=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise l('MicroPython 1.13.0 cannot be stubbed') - except H:pass + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') + except I:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[L]==Y:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==X:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:g(path+G) - except F:O('error creating stub folder {}'.format(path)) + try:f(path+G) + except F:N('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): - I=item_instance;D=[];J=[] - for A in P(I): - if A.startswith(T)and not A in L.modules:continue + H=item_instance;D=[];J=[] + for A in O(H): + if A.startswith(S)and not A in L.modules:continue try: - E=getattr(I,A) - try:F=W(type(E)).split("'")[1] - except Q:F=B - if F in{o,p,q,r,Z,a,b}:G=1 - elif F in{s,t}:G=2 + E=getattr(H,A) + try:F=V(type(E)).split("'")[1] + except P:F=B + if F in{m,n,o,p,Y,Z,a}:G=1 + elif F in{q,r}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,W(E),W(type(E)),E,G)) - except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) + D.append((A,V(E),V(type(E)),E,G)) + except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J - def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) + D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) def create_all_stubs(A): C.collect() for B in A.modules:A.create_one_stub(B) @@ -99,37 +99,37 @@ def create_one_stub(B,module_name): C.collect();return E def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:O=D.replace(J,T)+'.py';H=I.path+G+O + if H is E:O=D.replace(J,S)+'.py';H=I.path+G+O else:O=H.split(G)[-1] if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');S=C.mem_free() - except N:return A - g(H) - with X(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) + try:L=__import__(D,E,E,'*');T=C.mem_free() + except M:return A + f(H) + with W(H,'w')as N:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,L,D,B) I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os',u,v,'gc'}: + if D not in{'os',s,t,'gc'}: try:del L - except(F,R):pass + except(F,Q):pass try:del sys.modules[D] - except R:pass + except Q:pass C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;D=indent;C.collect() - if N in K.problematic:return - Q,L=K.get_obj_attributes(N) - if L:O(L) - for(E,J,G,T,f)in Q: + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() + if O in K.problematic:return + S,L=K.get_obj_attributes(O) + if L:N(L) + for(E,J,G,T,f)in S: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and S(D)<=A0*4: + if G==""and R(D)<=z*4: U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[t,s,'closure']): - W=Y;X=B + elif any(A in G for A in[r,q,'closure']): + W=b;X=B if P>0:X='self, ' if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) @@ -137,46 +137,46 @@ def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(b,a): - try:g=os.uname();A[D]=g.release - except(Q,H,TypeError):pass - for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(e,'pybricks.hubs','EV3Brick')]: - try:k=__import__(i,E,E,j);A[L]=h;del k;break - except(N,R):pass - if A[L]==e:A['release']='2.0.0' - if A[L]==Y: + A[F]=U(os.uname()[3]) + if not A[F]:A[F]=U(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=U(sys.version.split(';')[1]) + except(I,P):pass + if A[F]and R(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(a,Z): + try:f=os.uname();A[D]=f.release + except(P,I,TypeError):pass + for(g,h,i)in[(b,b,'const'),(c,c,'FAT'),(d,'pybricks.hubs','EV3Brick')]: + try:j=__import__(h,E,E,i);A[L]=g;del j;break + except(M,Q):pass + if A[L]==d:A['release']='2.0.0' + if A[L]==X: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] - if W:A[Z]=W - A[K]='v{}.{}'.format(O&255,O>>8&3) - A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def A2(info,desc=B): - G='with ';D=info;E=A - for F in[A+'/board_info.csv'for A in A1]: - if i(F): - B=desc or D[I].strip() - if h(D,B,F):E=K;break - if M in B: - B=B.split(M)[0].strip() - if h(D,B,F):E=K;break - if not E: - B=desc or D[I].strip() - if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() - D[I]=B - D[I]=D[I].replace(' ',T);C.collect() -def h(info,board_descr,filename): - with X(filename,'r')as C: + N=int(A[K]);V=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] + if V:A[Y]=V + A[K]='v{}.{}'.format(N&255,N>>8&3) + A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def A1(info,desc=B): + L='with ';D=info;F=A + for G in[A+'/board_info.csv'for A in A0]: + if g(G): + E=desc or D[H].strip();I=E.rfind(' with') + if I!=-1:J=E[:I].strip() + else:J=B + if A2(D,E,G,J):F=K;break + if not F: + E=desc or D[H].strip() + if L+D[T].upper()in E:E=E.split(L+D[T].upper())[0].strip() + D[H]=E + D[H]=D[H].replace(' ',S);C.collect() +def A2(info,descr,filename,short_descr): + D=short_descr;C=info;E=B + with W(filename,'r')as J: while 1: - B=C.readline() - if not B:break - D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[I]=E;return K + F=J.readline() + if not F:break + I,G=F.split(',')[0].strip(),F.split(',')[1].strip() + if I==descr:C[H]=G;return K + elif D and I==D: + if x in D:C[H]=G;return K + E=G + if E:C[H]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=J + except(F,I):A=J B=A for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def i(filename): +def g(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def j():sys.exit(1) +def h():sys.exit(1) def read_path(): path=B - if S(sys.argv)==3: + if R(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:j() - elif S(sys.argv)==2:j() + else:h() + elif R(sys.argv)==2:h() return path -def k(): - try:B=bytes('abc',encoding='utf8');C=k.__module__;return A - except(l,H):return K -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',y,d,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or k(): - try:A3=logging.getLogger(x);logging.basicConfig(level=logging.INFO) - except n:pass - if not i('no_auto_stubber.txt'): +def i(): + try:B=bytes('abc',encoding='utf8');C=i.__module__;return A + except(j,I):return K +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',X,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,c,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or i(): + try:A3=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + except l:pass + if not g('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_mpy.mpy b/mip/v6/createstubs_mpy.mpy index 4d49f2263943663524cc05ffe483495afcfa5385..ed8c45959117acf6d67e8b86389380d30ea5c08c 100644 GIT binary patch delta 5416 zcmZu!YfxKBcE0!Weji<~FK+~DAwUusgpiHL9%FH_1=wTDSi<;)jljmn_<^yFUn6z5 zXS3r_KlB%SF5Mc1k>=+wk&vPraKW3PXGnHib=T>T*{L9uPr?0^4 zsf|ifpFVy1^y$;5zjONY@DB#6_hm{}-hQhxGC6u`YV^v~)!{46mu^T!+1JlbjY&T) zJ@Vt}-|43%TAzJo>eQ5UD|cdi1P!3A{N>BN=l!k^h&#w9!UvE$}UOSBPreSpXL@-j7Z9;qz?^U8=bsz_Tq)1 zAxXI*DL19`T`lp)x%R5ukR9FA01wAc}Sd!6{%kL(Yh9E zJ!#lUK+)MrNYhy>r0eVyWaw-dGIbV#ES-%&wtf|IbT$gPQJtNJJe{3^e4UL!fzHla z*g2hzTiAJ>O<33kon3@Non3+=om~dd*(6wWb_GI#09kbe(5dc&5&?K-bUk?1MVbffAkPT6mt$^PyDd z1qXCq2xU4i3hEpz+@f<8%5`206*|{q!HP$@Fi;qS z8tm3q*61~Zy?Fx`o)v#j*E&iDdrL*<8{@!W3~VT3ue9kL+46Cy(|IY=c^Ur7Ej$+- zP!A2z=*rM}Mf?vsiE2){zb###@MP#yo=kn(lcnGGWb1c4IeOHSt5e03r_(G8uY{(x zu7HIqUddRC1u89>TC;_n^2s`{LV7c_STc)SeM~Yc#UBUp%Z6bN)uCc%-3*V%9 zZ0|`vc~FpTK2x&5!nSXS(yaK;N=UR)ra!w|cU?C|tEZnyu3uB8y=R4h{FjLbxXu_F!xb1S17MfiGjS zk8R?GG@CnO(JeNcbu;m8w%S_Vq^+*Q*E0Jg;83fygFdNv0GPgJgx7oJz)HR}0xG*m zj(X)$JQS7ZuW!dC&6KiI^-Zs6%T(NQ2)CRx_9itd`vkMxKRHt@hO$E{ySirdlVe&( ze^l^dTUbgWNRA`#b(YY?Doh2H38O!u9aDLcPd4@>g3)FrwCwLzr@hiLIiYnVa9)*9 z(I$aa3n68ulx7F=Rc``&FTJt|9F?mga8#Z_hH!>YjtV|T4zmKQAt%WxGE5?5#Fd2> z*8;NvBf#url$>^DAgj*Yry7jJ^B<}n=HS`9J{D+jc}auSR=;zz%Vu?2$(F=pm-NIX zt*AV0)+-P7{a$`Lul1?y7Fymrk9Mjry8Qlzz&$yt@`l-Yud*5_QP~ZZH!gT(udHnc zR_~K(=vi+O+AM!#>_MBgXK3jIm7P`Dn99zm?6k_JRCYyWlTBGK41+%RAH(5M^=gxX zUH06+?*Xs|B>8i{|L*go#v12w6f0%j74oPIu0!L==|Ylh2N^mRJ~lGt{RpCt@M357=>^+|`=ctohxM zla_pTf}Ml@o!>o>QP*(ZsWq{`u6jpK8v)$sTgV4Gh)6&8q?oPYVm z- zc0CEK)vN5;`&`XK58yd#lVl8oD0M?Tz}kGu$KPx%m-5qDLWwWUP;pE8wu>=iYVtX{=C z4y@aic0yo<@pWv`Q6elTU5b5WbOYNRpRVqR?)lzQ{x2!oKDB0a`9DWWT+jf5(Jzqx z;oAtLjxwP^x0ji~l0ul%zxygTAxQSfTI_fHXGWtz)<3F<2REw}u*|;-pJ%WM}nVx)%-X3BttR?=LwKQ7A z+hRX$Y!xxS3@rF~cBrr5NkW@U3N%)h{jG_}yV>`Ot7#6`Xm;%9ZeMGiGqeM92HxCm zaZ{HA#h3tn0&uWp2a$N(tC~U0^F>g1<3S=gpyu6AR5pxxC5bl|qa3B9{c||4*CoWi zF(QM3;u($R2%Z={WDbfvii2hafqMLl(O~3<0knx}h->!PFWV8=wz{^Ox`jmvpYnJk zngi(c>$9o5-uwi^D3lb+dCrQssYB5|%Tr{Alk;=FGy!8P{wC}X2%*$%uH3+q|61)W zPFd22f*E8wl^O-a_7<`b*SxWR1a|mw0=*Ax5ETeY<+@wOrOIZ9y)qR!d1HWGMk=}? zqqy<9l&ZXVSY@Y%(cmNhue=Z^H-vE!)-sb`%EG+R%f`4j_D@a8u3l4{saR06rW|ds z6|w;oizNgT*in;xPonpg>PjyjYSK=ej@AK}&uWVeEI;;t7n{-A5w_z0TkCYA=T~A+ zd$!FNZ;6FeUbcp?m5Yb7Rk*0vmh#Av)gA=jjCjb_QZy3#h}3U}HLgaHwKe{Q&9}S6or8F{r#OJ6&oE9feZaLvLC+84P|t&5 z=v8@vImm8`W|0K;#K|36+{)`l=uc zj6)F14G^ZTXlQ25*bPUQU_cnRUI||pMudz@W`n5% zD<>mjcHqQsjlmQ(^tG{nzexrKUJEL`u=K+CJhrqDGM>fM0&Kmq!>kcb!YLSr2#mle zoQ5+n24`J)cDVO#$YHTtjBdMSX)X-s;$PI2MKO_^YSDK-#oq_#*ZUY$^Wh}~)WEJ( zefQj~?{b&bJgn2OuJcCz^87uEV}g}&TkPK(T@CFX`xeqzn-#bF(?i33Br#?zKJgZs%RiJ%xKE+|KJ_|JmTGaX5B(>RO#m z$(0!_-LzE`h_7PJb>!It?HcZ4v8&7fS!@xb_xgqz>m6#^bmZetmZFI@qxa#wuuarG zbHWk0TYf;3&-GiNWS!AE;M1TZbxy=AhQ+%Cr@g8>gOO>-ymLQW&C=ecCIG+FS*k|w=h~Z_ zTI$=;KacQ&;x(lBLgs76h)JR!@Oc=O(9apTU6aQ`kMLD@$14r`(G43@*cw)7CbM%U z!pDq!s@zwtwE?U+dx53_O$VBRuaieARf=imvS}o`fL(me1vw&52P1z!{ndLd*);3E zrn&)3@%E@!@-pd>NX__a1)2*q4`@En0-%LJi%2HP0t!GaKvkf{Bpav}|F)rg_a>k^ z&=R1fK+AxZlTAb?C8U&;k#bT&DoGX43ZRuhk*Ef01zJO@iIvolT4EyvXf04%JlNP= zja8bG^&?iR&3-2*fLv96z6~@AOadm8!@!h&U|5f)1IqxGNd|#s0m}xK s0}LO1#lZ5&5n%bi3V;;?D*}dfy2VAu#oKcO4zNrr#%RDs!zLK{KUab!+dfjbVKC!=UH;r%Eda^A`wz1`=!7zZ4+aSv@AdF-L7-P!@%wdDgWf(?! zubCu6Ww+Q;jvq-?rYhM~ZB-7-*I;I57jq5F46{{9)$Vvw4wYp0XR3Bde&kO!`JQCM zY__73^xpg4*WZ2h@Abcolpe4P4y)}}Wo&YE=*sBSm8-*3EtjT+;vZBWv*%tPyK+|e z!Hr*NX9U`iJ9TB~if}9c;`x!WNr5&>k>sTKVe-GlXW$d^Ickl-_OPrx>1=XUYP5|B z(z#@QR)u(eu0HEG_V~0Q-4LW}f^=1ot_aeUAYB%uOM)~Z9GAugRx4c;2BiyvG$Keb zK^hjMAwfDONKt`al#U84Tk032upk`~Xus4a^ht+>kQ5SVnRG~?*QJBP0qI>qIv_~< z1*un%f`Zf|?2!V3v`3Kk2~xLL7?So1k|{`jLFy8uQ9(K_XoG{-MklAnCdLN`1?i?> z+tZ4_w&crvm!=I*3{8#c42gU=;G*HQNix~cxBUHNn%~*o5@#xvo)(U`9B(o%O0_>-KJge zWowsxcI~P!N1OKLYBzm(+IzlyE$%DOs71ZhFQ?Dj!JFGzuQFOWg5+b zCe5mlxyd$oq`r1RV~S7I81bRw-9B_Y_|Wl<{2GNv_j?n3gCXFPtx8{xj>zR}x49a% z6Omu%X-r0q*kM$O_4zO)j)YXXCl7U>2z!+MvKGQ)<|MZUz)~o*dW3QFM`F<*%vZ6=q7=MrD`IS4}~ckD$tP zX78N(zQJLe{F5^!{3biBu*)lEA333R^v%Q(me|TN7$GviVc!99Laa1Rpe$wfrPSk! zRcMIjzEmjQB88Xz-O5#6SSBacjubvuZb<3`unLYO&6LvYK%t_i@bp?2dDJLY@hkIC zRIx-dh))=z9!EHa4XXrJMNW|+GE8D*#G8W>R|9hZs{vL^M#*V!HiDdKHH$;BWZ?tF z$B30}kwn1l)rs5TY}nQ6bvir_vNiR{D?IiJPZSoP)y2WyUy4r`)Lw;MN6CW=C};6% zm*4LW+!d9$<(gg4rDuUn3cIRUb&I;Fi|RYTT!u))p9hQk6?XfTxesNQKSxPFR@kV* zMidrPCKYx`VG{})Z_ZgYP5Ru=Z-*5&)GXndJ@+5@7+4){t>=FKo#%5Zt6xAa$l@)p zR&nvZCmW+Q*qQO>@fSVvJYteFYRAItl97dXq0kF=-axP#G3t}I%N_ACpD?G3z#4p_ z&cw%W+&%A+ViL>kDP&RBoQR;c278s|R3fbQ0y}1iU2Un&s=q0AN-ku_*~vs?=1w@q z+#XeJW_s+FFFpt_XQ$n+6)d|JQNym*L zy-^6!p9Bh!x_5TYke+aF@Cd5m?kI?%JJto6kNxqfzmT^xua#>xSnlM5ipuzge>Ml^ zGi1^860oM%PdO_djtj3J`!O}%;S9xi_$jXQtLFYRdLase%oJ0vbG0kLcWr7xIwLb_ZN}5Y}lfq69b65k;lb(d~S|sS^Ju`5O*G`6n09% zwp7_{Tm46KJYaLj?Lpw?QrInzv|h*y6g#?XzVCR1R}Xe;4Zdzh#j?l##{6;JdFHe1 zR-@&yyjGLdoVdE%xt-!Vc>-fZL zLnME-3ovlmc0<5}TvtIZu9!ch3Y-26W7FDn=RdzS|AeA>>Qxu0$3HQ|?lQgswgb0C zE&zsUyc5{2KXEw}ThE(KVp+A-$>L;4KZo@8frnVv!Q ze~HDq#Z^%wU`7mKf&=q=vrh6lVSbyqU%!cqP`Z@(#_R^xmHfl%j)3`Fy!=0-DEyTb zv&;V#?szJ8VV5Mb$TPpTp?%k4VYPV#Xo%pjRqpi*p-id7hGqRg!;Bue@TbjWu z2CnQNZXN}dGtLqw?jW$k zD2kf+TVUZwDf9%e2$JAC#VTnMk(V|*tc#TQ)%6Q@aeapt+0l@ab}8h%%x_oQka z-8knWp8B?aui1Uj+#lwl8kcQ2$V|k_vdxD(&Yp1hRj?It!0*>rTJaIU7wzsr62yx)Y zlYHeg_Nq;JSi1I=1aN>E#wXHdu;lxEzc7qfJs%H4P_c5;m+Tr}7Wv;i8tKK-$JhZC zHjq3{-0@PZ@9IIHkfv9zV`eNNwRAyzGfoAV2#0Wd;5fRtibEG?e#jp{rTAc0`-NiJ z)PoOr2eBDqdKfZ9^{^ozt=z~uJRZ(~*tH1st&xkrrPt>_y7)UxOn(=Oy|frfm+yQW zKi-t@^@vq2Eb&&eHsl5ND%&$+Sz%pVx*u7(AMQH14r6a&Cm@V!#LHLBKD@P;l;fO( zp+++pzsnBkn1`|6;;M@ud}HqAav^!N7CKp8F(;8o&+ME>!j^M7AZLX5@{^J@N`xl^ zyNx5NVpYAVC#h5%`aM|+yMSLf>dBfRHi&w%yjg?2dTZ8KFTYOr+|M#S_s6>Jr=KFf z?1;O#GfdMW;M&^BAoNufO|bHr+F#8U|TqWH8+NbQxJxMe=?(K zIGp^}Jeb~vcq!()$l}tf`7*Jz7&bpoD22G{Vm$`#1{j1>Fa*O8gAo{o({KjPdJ9}| z_t)Wi*(ICZE_rD_0%OUq>&oKi)Q&V+w4EXOdjY$4`i#N05Lv>a8rYK=(w?V>wESfy zABQa*&h*&#%-5p(0=_^w693xhbvL&+Y&J-X*Le*70OP8V0r;l;Ix#ml&=rzw*}9*X`8Pb$JqJsU45!)G0%FGLK{X_&kQ~m36Lb2bxyr z*wbeVsTDK0IKwMJgika694yj&Sp4A9h;lXYUrp`Kwyo|!9>(f5LwFcezteU2D3|jP z3--+N3|xmBSltkieAQ4I#{#!E+UXMU(qEm5Sv6Z=+N!-LINMtA%>jGa3>WD8zvdIJ zJ(eC$*Jjl>^I<4<1MD~N*%Z5ai>8a~2c@OTd-v?FX7A<(9TVyy<{D}u<%2C=ens2QU8%Q=xhaNs5Go|CT1NnbL01lb_XgIwhyQPR0JyF zYr;b%UP7~$)54+J>^!C>FD+a`J8!q4*pF^}^HFOqwcP`y32;(=PZxA1Je+C94vVjo zKy!fR0?h-O53~SiA+Zw#Z2(#Xv=}H5yp@xl#`3)i&=R03(2YPfpqt1>qLEFcl$4Qj zQb8(770^CKoj~^h^#kqV!!k92b_3lD z6b%)CTA)4T9kP?`!Z&1~L9&}5elO7dKo0z5Tw%w^a$x9NGRM$ zx(Sks0FGt@yt>hTphtnC*^U7{PLRh5paVcpCjZ=18pnYh=o#<=JqvV<1V|4Fl3uc( z93aT)9MJQCsv?z(K*xbj0KEhh#hL^<1rDHB$U%a_TqPlLn4lQffL dict[str, str] pass try: _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = "with".join(_machine.split("with")[:-1]).strip() + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy @@ -563,16 +564,15 @@ def read_boardname(info, desc: str = ""): # print("look up the board name in the file", filename) if file_exists(filename): descr = desc or info["board"].strip() - print("searching info file: {}".format(filename)) - if find_board(info, descr, filename): + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): found = True break - if "with" in descr: - descr = descr.split("with")[0].strip() - print("searching for: {}".format(descr)) - if find_board(info, descr, filename): - found = True - break if not found: print("Board not found, guessing board name") descr = desc or info["board"].strip() @@ -584,18 +584,30 @@ def read_boardname(info, desc: str = ""): gc.collect() -def find_board(info: dict, board_descr: str, filename: str): +def find_board(info: dict, descr: str, filename: str, short_descr: str): "Find the board in the provided board_info.csv file" + short_hit = "" with open(filename, "r") as file: # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) while 1: line = file.readline() if not line: break descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == board_descr: + if descr_ == descr: info["board"] = board_ return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True return False diff --git a/src/stubber/board/createstubs_db_min.py b/src/stubber/board/createstubs_db_min.py index 1f8c304b5..751c0c400 100644 --- a/src/stubber/board/createstubs_db_min.py +++ b/src/stubber/board/createstubs_db_min.py @@ -1,37 +1,37 @@ -x='stubber' -w='{}/{}' -v='method' -u='function' -t='bool' -s='str' -r='float' -q='int' -p=NameError -o=sorted -n=MemoryError -m=NotImplementedError -d=',\n' -c='dict' -b='list' -a='tuple' -Z='micropython' -Y=str -X=repr -V='cpu' -U='_' -T=KeyError -S=IndexError -R=dir -Q=ImportError -P='with' +w='with' +v='stubber' +u='{}/{}' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n=NameError +m=sorted +l=MemoryError +k=NotImplementedError +c=',\n' +b='dict' +a='list' +Z='tuple' +Y='micropython' +X=str +W=repr +U='cpu' +T='_' +S=KeyError +R=IndexError +Q=dir +P=ImportError O='family' N=print M=len -L='board' -K=True -J='.' -I=open -H=AttributeError +L='.' +K=open +J=True +I=AttributeError +H='board' G='/' F=None E='version' @@ -39,51 +39,51 @@ A=OSError C='' import gc as B,os,sys -from ujson import dumps as e +from ujson import dumps as d try:from machine import reset -except Q:pass -try:from collections import OrderedDict as f -except Q:from ucollections import OrderedDict as f +except P:pass +try:from collections import OrderedDict as e +except P:from ucollections import OrderedDict as e __version__='v1.16.2' +x=2 y=2 -z=2 -g=[J,'/lib','/sd/lib','/flash/lib','lib'] +f=[L,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(C,path=F,firmware_id=F): D=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') - except H:pass + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + except I:pass C._report=[];C.info=_info();B.collect() if D:C._fwid=D.lower() - elif C.info[O]==Z:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) + elif C.info[O]==Y:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) else:C._fwid='{family}-{ver}-{port}'.format(**C.info) C._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) - try:h(path+G) + try:g(path+G) except A:N('error creating stub folder {}'.format(path)) C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] def get_obj_attributes(L,item_instance): - I=item_instance;D=[];J=[] - for A in R(I): - if A.startswith(U)and not A in L.modules:continue + H=item_instance;D=[];J=[] + for A in Q(H): + if A.startswith(T)and not A in L.modules:continue try: - E=getattr(I,A) - try:F=X(type(E)).split("'")[1] - except S:F=C - if F in{q,r,s,t,a,b,c}:G=1 - elif F in{u,v}:G=2 + E=getattr(H,A) + try:F=W(type(E)).split("'")[1] + except R:F=C + if F in{o,p,q,r,Z,a,b}:G=1 + elif F in{s,t}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,X(E),X(type(E)),E,G)) - except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) - except n as K:sleep(1);reset() - D=o([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) + D.append((A,W(E),W(type(E)),E,G)) + except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) + except l as K:sleep(1);reset() + D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J + def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) @@ -91,90 +91,90 @@ def create_one_stub(C,module_name): E=module_name if E in C.problematic:return D if E in C.excluded:return D - H='{}/{}.py'.format(C.path,E.replace(J,G));B.collect();F=D + H='{}/{}.py'.format(C.path,E.replace(L,G));B.collect();F=D try:F=C.create_module_stub(E,H) except A:return D B.collect();return F - def create_module_stub(L,module_name,file_name=F): + def create_module_stub(I,module_name,file_name=F): H=file_name;E=module_name - if H is F:O=E.replace(J,U)+'.py';H=L.path+G+O + if H is F:O=E.replace(L,T)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in E:E=E.replace(G,J) + if G in E:E=E.replace(G,L) M=F - try:M=__import__(E,F,F,'*');S=B.mem_free() - except Q:return D - h(H) - with I(H,'w')as N:P=Y(L.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(E,L._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');L.write_object_stub(N,M,E,C) - L._report.append('{{"module": "{}", "file": "{}"}}'.format(E,H.replace('\\',G))) + try:M=__import__(E,F,F,'*');U=B.mem_free() + except P:return D + g(H) + with K(H,'w')as N:Q=X(I.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(E,I._fwid,Q,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,E,C) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(E,H.replace('\\',G))) if E not in{'os','sys','logging','gc'}: try:del M - except(A,T):pass + except(A,S):pass try:del sys.modules[E] - except T:pass - B.collect();return K + except S:pass + B.collect();return J def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() if P in K.problematic:return R,L=K.get_obj_attributes(P) if L:N(L) - for(F,J,G,S,f)in R: + for(F,J,G,T,f)in R: if F in['classmethod','staticmethod','BaseException',O]:continue if F[0].isdigit():continue - if G==""and M(E)<=z*4: + if G==""and M(E)<=y*4: U=C;V=F.endswith(O)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O D='\n{}class {}({}):\n'.format(E,F,U) if V:D+=E+' ...\n';H.write(D);return - H.write(D);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) - elif any(A in G for A in[v,u,'closure']): + H.write(D);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) + elif any(A in G for A in[t,s,'closure']): W=Y;X=C if Q>0:X='self, ' - if Z in G or Z in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) + if c in G or c in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,X,W) D+=E+' ...\n\n';H.write(D) elif G=="":0 elif G.startswith("5:A[D]=C - if A[E]==C and sys.platform not in(c,b): - try:h=os.uname();A[E]=h.release - except(S,H,TypeError):pass - for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: - try:l=__import__(j,F,F,k);A[O]=i;del l;break - except(Q,T):pass - if A[O]==g:A['release']='2.0.0' - if A[O]==Z: + if A[E]==C and sys.platform not in(b,a): + try:g=os.uname();A[E]=g.release + except(R,I,TypeError):pass + for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(f,'pybricks.hubs','EV3Brick')]: + try:k=__import__(i,F,F,j);A[O]=h;del k;break + except(P,S):pass + if A[O]==f:A['release']='2.0.0' + if A[O]==Y: if A[E]and A[E].endswith('.0')and A[E]>='1.10.0'and A[E]<='1.19.9':A[E]=A[E][:-2] - if I in A and A[I]: - K=int(A[I]);U=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if U:A[a]=U - A[I]='v{}.{}'.format(K&255,K>>8&3) - A[X]=f"v{A[E]}-{A[D]}"if A[D]else f"v{A[E]}";return A -def A0(info,desc=C): - G='with ';C=info;E=D - for F in[A+'/board_info.csv'for A in g]: - if j(F): - A=desc or C[L].strip() - if i(C,A,F):E=K;break - if P in A: - A=A.split(P)[0].strip() - if i(C,A,F):E=K;break - if not E: - A=desc or C[L].strip() - if G+C[V].upper()in A:A=A.split(G+C[V].upper())[0].strip() - C[L]=A - C[L]=C[L].replace(' ',U);B.collect() -def i(info,board_descr,filename): - with I(filename,'r')as B: + if J in A and A[J]: + K=int(A[J]);T=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if T:A[Z]=T + A[J]='v{}.{}'.format(K&255,K>>8&3) + A[W]=f"v{A[E]}-{A[D]}"if A[D]else f"v{A[E]}";return A +def z(info,desc=C): + L='with ';A=info;F=D + for G in[A+'/board_info.csv'for A in f]: + if h(G): + E=desc or A[H].strip();I=E.rfind(' with') + if I!=-1:K=E[:I].strip() + else:K=C + if A0(A,E,G,K):F=J;break + if not F: + E=desc or A[H].strip() + if L+A[U].upper()in E:E=E.split(L+A[U].upper())[0].strip() + A[H]=E + A[H]=A[H].replace(' ',T);B.collect() +def A0(info,descr,filename,short_descr): + B=short_descr;A=info;E=C + with K(filename,'r')as L: while 1: - A=B.readline() - if not A:break - C,E=A.split(',')[0].strip(),A.split(',')[1].strip() - if C==board_descr:info[L]=E;return K + F=L.readline() + if not F:break + I,G=F.split(',')[0].strip(),F.split(',')[1].strip() + if I==descr:A[H]=G;return J + elif B and I==B: + if w in B:A[H]=G;return J + E=G + if E:A[H]=E;return J return D def get_root(): try:B=os.getcwd() - except(A,H):B=J + except(A,I):B=L C=B - for C in[B,'/sd','/flash',G,J]: + for C in[B,'/sd','/flash',G,L]: try:D=os.stat(C);break except A:continue return C -def j(filename): +def h(filename): try: - if os.stat(filename)[0]>>14:return K + if os.stat(filename)[0]>>14:return J return D except A:return D -def k():sys.exit(1) +def i():sys.exit(1) def read_path(): path=C if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:k() - elif M(sys.argv)==2:k() + else:i() + elif M(sys.argv)==2:i() return path -def l(): - try:A=bytes('abc',encoding='utf8');B=l.__module__;return D - except(m,H):return K +def j(): + try:A=bytes('abc',encoding='utf8');B=j.__module__;return D + except(k,I):return J def main(): L='failed';G='modulelist.done';import machine as O - try:C=I(G,'r+b');N=K - except A:C=I(G,'w+b');N=D + try:C=K(G,'r+b');N=J + except A:C=K(G,'w+b');N=D stubber=Stubber(path=read_path()) if not N:stubber.clean() A1(stubber);E={} try: - with I(G)as C: + with K(G)as C: for F in C.read().split('\n'): F=F.strip();B.collect() if M(F)>0:P,Q=F.split('=',1);E[P]=Q except(A,SyntaxError):pass B.collect();R=[A for A in stubber.modules if A not in E.keys()];B.collect() for H in R: - J=D - try:J=stubber.create_one_stub(H) - except n:O.reset() - B.collect();E[H]=Y(stubber._report[-1]if J else L) - with I(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if J else L)) + I=D + try:I=stubber.create_one_stub(H) + except l:O.reset() + B.collect();E[H]=X(stubber._report[-1]if I else L) + with K(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if I else L)) if E:stubber._report=[A for(B,A)in E.items()if A!=L];stubber.report() def A1(stubber): E='/modulelist.txt';stubber.modules=[] - for D in g: + for D in f: try: - with I(D+E)as F: + with K(D+E)as F: N('DEBUG: list of modules: '+D+E) for C in F.read().split('\n'): C=C.strip() if M(C)>0 and C[0]!='#':stubber.modules.append(C) B.collect();break except A:pass - if not stubber.modules:stubber.modules=[Z];_log.warn('Could not find modulelist.txt, using default modules') + if not stubber.modules:stubber.modules=[Y];_log.warn('Could not find modulelist.txt, using default modules') B.collect() -if __name__=='__main__'or l(): - try:A2=logging.getLogger(x);logging.basicConfig(level=logging.INFO) - except p:pass - if not j('no_auto_stubber.txt'): +if __name__=='__main__'or j(): + try:A2=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + except n:pass + if not h('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_db_mpy.mpy b/src/stubber/board/createstubs_db_mpy.mpy index 4f9ed861a5c9db7160eec192e15bcba502a6bfb7..88b1e6cd73ab8d51080cdd566a931abbafac1545 100644 GIT binary patch delta 5299 zcmZ`-X;55OcE0bi2xyl39*;)@5{-D>&C<=*G*3d3ZS;5&O=FE{A&^@V!lH#1YX`Jh zvbxW;RI#1Zlx8}URDLB@Q&}pLg{GTTmMs>c#p5JZlgb#!#4|r8zcN2U@*|b1smi&p zfs)G=3i0ke_uO;OcE5A3er5cyv+__jaj-r0+aseRr^iRe#%~OdHD0?zigIpU7(Y*b zWbcsj&z`<~;nE!Nx^6Ib-9e$I0Ei%NNgF7$s0A4kQPK6GDaf zKFQ;|s|d@@tFq*<{VXFlbANOEl~`AGo`@Gn&dBWx<3z?&&kS8VjYs929zA!Hz>xS} zvN+?37`;iv8$=u@;usOH6Y&}muaXnu6~cCkmq}Q>M25tRM2rw|n25)T7$)L7gk_1x zh}ciWqohylBO&n!fif{f4vD=)JWSx0_yYpR#6v`Uo4{qUhloM4U+gAgfQVg0JV?X? zL^R21aX*P4&fZpjhKM6X9U8hhGCFqQ>Xo4(BHkt_HiDi9jc7}t(V4x^Q9k^7r-J!CIaL}G!>kX&LJ2%L} zAgxx}cBZl&_^(o8HmXr4by2q`OJ$CDZGjfG*9(2End&89mOAFkR&V*Xsds%j>OEhs zdf$h>6MX2SY#;i_F0m?FzuFm)K=2dun^?dh!Cu89!C75U*-k$3(gyq#H|mU78pD+h zjitL9@e7^j188rV(p3FtL>Iz1EK!>E4c7getdJdFL(QsG$f9*BtCm7sI-f|E0ecxYZAUv5d@Y~3&L1d>_lw`OlxW;t3R?$8B;(=mglcv&P9Ozqk@8mEo?;nx_4NUr^d9H0T2KKMxk6YQnc>7pi7| zjtb4la7l)XGQ1~`%Wz8uS%#Yp+ty4IUKo7!f(+*yM4Yo1#-W)Ig+?5I_`)zAyg-+i zPvJ3m#%qU7&(>#QHU>M=Q9JRnTS_6LrYic>cxo2a=P>3G_=KzqEm)?IM3Z88BkxN2aE9%O z9i4d4A7Qoi6q;En6vZ$DuE}teJBaIeG~pM1>le_!=vh{~zYtnjY3x{Sbn`&YIMicX zm{5RX(85M*DDr#sR3%VmXU(zW)n2c|+2%?tP9kRwIznb85kB^8j4AjO9p`zI%5|C9 ztn|>uErXDKIbcKSt&>SzTn-kb6D4{8!%-3$+*BhK`AP4eN_(J{QP#{_V#7{{%hT#~ zAhtUk`}Q^0G_`4yONr&A%!>cb989Ip!fX&J_}8ED^LZ*xtuGlpNu`}@Aw>J1;WxEr zzHPC~s2ys60#*VQXum6kL;R)C=FeQ&ybaGS4G||d6>PyUp{@l<3c6qHI`l$@J9wM} zbL_fSiaC|O7rQ9z*2R~aUC~pxTs0@N?Rw^`Sp|yc(XITemEizA(LOt!!t?EVW;k?m z5Sb;OEakW{$#2-64HqJFik8uG3VW%&A#?2)=9NHZZFZ1y56Td&7dOG&CYNIrQ++1} zIB-C8gTCoonH5I<#{A565!zV+^RZUuXBllwj|YkyqWhjxc;m&?%gI+1-uxo*^VFA{ z+vZU-47d@Bpw3=2qFMZhfBf9+!W;fMy5zH=p1;g&&T>7=^&ghKcF9IWeE;U`+< zx?6RsPc+AOwi{nCneB2`R1v%-=kd~02zoM3aqKX^j?KDxWZm|;*jFZ=-{ZE=xZ;nM zw&>g674k2DR%xqdr}1+f@hf@=@#&{H{^&kpsJo0yQJrNRY|^MRPT>a>4tuiK%+R!= zKXFp0&ac5bdj}lVWSOUr8!JNW4mKNscYe>zd&JNadN1q zU@4(oPjbi>7mSufc28uM!wFW(9B_rT$NK)ZA=w$Uj@*(wX>mexHHDL$G4}Uq<=(aEAK!*YVr2_P zHR06i-7UvFx?^YT*utXmyV!){LpY1?v)6mk`Ae~9-R)DweymaqyPwN}Jd95p_fl|Y z+9~0c?jm$c{KxjDq6@JnT1^w(y)e;i_hH;1G24Y5#<0hvkGBHZJj8U81JudFw!Sm?Rc zb_FidUYTWZfqr2PdowP%*9f4-ynn0w;_*C68hDJw26SF*lp{Ksm*L(3?fc%oKI5I4 z?-3276VINX8L*PPl46^(h3T7lCtsSk%1>Dw%6q-vVVR%nH;*8g;@2-c{K`bD?elX3 zsFi~5wa0%~URj7X@odAKz^%@BT}6G=^;x>?eeTb6(KDD(W$S^!`3Lok&urDX6DyS<;&Ro zOuzX&CgL}pm5hkAOR$#`Ul=^;UdUs~>8V+NrWxdyJ&Zp_r;&`N zI`4c($|U04y?*7IPS&T_%wy9^`)d?kz%qy;SEl)~1L?D`(@_f=EfR)1YPIzoY&$lr z{k3In?m|MVTSr^lA|H1=P`qPkYYnSqb+O;pdaB&+H+-&^`iA841U5T%Y-13m#<5R1 z{(MHcfmY0RVr`1eVn2LyQ;m%YSUMel`D!k)Y6j<{Q(QORE2PZhbE#DmJ4qdzr{Mh7 z!u*QSVf+Yp7@Y0-|{Qe|8i^5hKiSha2I!IuZGhw9&h)_K}G1r$7mcY@OgH z{O~_{6IvMI$8zyoty(B@n`Ym8lr5JlAAp5S53B6*{YN>@25(c1AKmj5uM6Jes9*SS z)#QK>MJMn_6#6)8&FqeH66=48PoH~!5;l%*@v~KId@NeWMC8K`GY^DE^vytp42LOT z4~m646Z`n5G6=i2%udW7d|F2N zE|!NE1zVpZQ=F*~bg@}nc|POHpB^wI4F6_TuKylheTw~5%6faeu*9LX*`c0`FVP{d z0(qzvozsO^LFt$bqu-j{SlV_V3pZfnU5n-S&b%2w8B(<0FkCjj;L4xFyyOPUnAjCu zeJqTMqR-9q=B$Ks=^_vK$w4C?b>*AyJgyROn*yqi|7noI=QEyMiU)=8ZDl_~`P&NG z9yvTDfv+px$|x|b6KtAVqLbG1ijgfYx5ZV|EG{l3UE~|npG1zP$nV#FELVd)<56v0 zO|{3{;&$xZ<=&%hTS&iS5p;%nt}F)7u!70NI{N)E!cmTvGr7)ZVSGux9)p_Y6pz8O z{4UGGh@tO~reggR%Dypsu<94#3xRhr241H0`@f@)VH{p>YK%wx#b4BUREFCg>%}KC Pj{+51E^gf17K;2IsObJY delta 5040 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 O3U;j!cjoqmqyGmrZlgf} diff --git a/src/stubber/board/createstubs_lvgl.py b/src/stubber/board/createstubs_lvgl.py index b2e811193..fe5417871 100644 --- a/src/stubber/board/createstubs_lvgl.py +++ b/src/stubber/board/createstubs_lvgl.py @@ -452,7 +452,8 @@ def _info(): # type:() -> dict[str, str] pass try: _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = "with".join(_machine.split("with")[:-1]).strip() + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy @@ -548,16 +549,15 @@ def read_boardname(info, desc: str = ""): # print("look up the board name in the file", filename) if file_exists(filename): descr = desc or info["board"].strip() - print("searching info file: {}".format(filename)) - if find_board(info, descr, filename): + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): found = True break - if "with" in descr: - descr = descr.split("with")[0].strip() - print("searching for: {}".format(descr)) - if find_board(info, descr, filename): - found = True - break if not found: print("Board not found, guessing board name") descr = desc or info["board"].strip() @@ -569,18 +569,30 @@ def read_boardname(info, desc: str = ""): gc.collect() -def find_board(info: dict, board_descr: str, filename: str): +def find_board(info: dict, descr: str, filename: str, short_descr: str): "Find the board in the provided board_info.csv file" + short_hit = "" with open(filename, "r") as file: # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) while 1: line = file.readline() if not line: break descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == board_descr: + if descr_ == descr: info["board"] = board_ return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True return False diff --git a/src/stubber/board/createstubs_lvgl_min.py b/src/stubber/board/createstubs_lvgl_min.py index 2576dee94..24d22c1d8 100644 --- a/src/stubber/board/createstubs_lvgl_min.py +++ b/src/stubber/board/createstubs_lvgl_min.py @@ -1,36 +1,36 @@ -v='stubber' -u='{}/{}' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n='micropython' -m=Exception -l=NameError -k=sorted -j=NotImplementedError -b=',\n' -a='dict' -Z='list' -Y='tuple' -X=open -W=repr -U='cpu' -T='_' -S=len -R=KeyError -Q=IndexError -P=dir -O=print -N=ImportError -M='with' +u='with' +t='stubber' +s='{}/{}' +r='method' +q='function' +p='bool' +o='str' +n='float' +m='int' +l='micropython' +k=Exception +j=NameError +i=sorted +h=NotImplementedError +a=',\n' +Z='dict' +Y='list' +X='tuple' +W=open +V=repr +T='cpu' +S='_' +R=len +Q=KeyError +P=IndexError +O=dir +N=print +M=ImportError L='family' K=True -J='board' -I='.' -H=AttributeError +J='.' +I=AttributeError +H='board' A=False G='/' E=None @@ -38,51 +38,51 @@ F=OSError B='' import gc as C,os,sys -from ujson import dumps as c +from ujson import dumps as b try:from machine import reset -except N:pass -try:from collections import OrderedDict as d -except N:from ucollections import OrderedDict as d +except M:pass +try:from collections import OrderedDict as c +except M:from ucollections import OrderedDict as c __version__='v1.16.2' +v=2 w=2 -x=2 -y=[I,'/lib','/sd/lib','/flash/lib','lib'] +x=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') - except H:pass + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise h('MicroPython 1.13.0 cannot be stubbed') + except I:pass A._report=[];A.info=_info();C.collect() if B:A._fwid=B.lower() - elif A.info[L]==n:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + elif A.info[L]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:e(path+G) - except F:O('error creating stub folder {}'.format(path)) + try:d(path+G) + except F:N('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): - I=item_instance;D=[];J=[] - for A in P(I): - if A.startswith(T)and not A in L.modules:continue + H=item_instance;D=[];J=[] + for A in O(H): + if A.startswith(S)and not A in L.modules:continue try: - E=getattr(I,A) - try:F=W(type(E)).split("'")[1] - except Q:F=B - if F in{o,p,q,r,Y,Z,a}:G=1 - elif F in{s,t}:G=2 + E=getattr(H,A) + try:F=V(type(E)).split("'")[1] + except P:F=B + if F in{m,n,o,p,X,Y,Z}:G=1 + elif F in{q,r}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,W(E),W(type(E)),E,G)) - except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) + D.append((A,V(E),V(type(E)),E,G)) + except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J - def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) + D=i([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=i(set(A.modules)|set(modules)) def create_all_stubs(A): C.collect() for B in A.modules:A.create_one_stub(B) @@ -90,90 +90,90 @@ def create_one_stub(B,module_name): D=module_name if D in B.problematic:return A if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(I,G));C.collect();E=A + H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A try:E=B.create_module_stub(D,H) except F:return A C.collect();return E - def create_module_stub(J,module_name,file_name=E): + def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:O=D.replace(I,T)+'.py';H=J.path+G+O + if H is E:O=D.replace(J,S)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,I) + if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');S=C.mem_free() - except N:return A - e(H) - with X(H,'w')as M:P=str(J.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,B) - J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) + try:L=__import__(D,E,E,'*');T=C.mem_free() + except M:return A + d(H) + with W(H,'w')as N:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,L,D,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del L - except(F,R):pass + except(F,Q):pass try:del sys.modules[D] - except R:pass + except Q:pass C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;D=indent;C.collect() - if N in K.problematic:return - Q,L=K.get_obj_attributes(N) - if L:O(L) - for(E,J,G,T,f)in Q: + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() + if O in K.problematic:return + S,L=K.get_obj_attributes(O) + if L:N(L) + for(E,J,G,T,f)in S: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and S(D)<=x*4: + if G==""and R(D)<=w*4: U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[t,s,'closure']): - W=b;X=B - if P>0:X='self, ' + elif any(A in G for A in[r,q,'closure']): + W=b;a=B + if P>0:a='self, ' if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(a,Z): - try:f=os.uname();A[D]=f.release - except(Q,H,TypeError):pass - for(g,h,i)in[(b,b,'const'),(c,c,'FAT'),(e,'pybricks.hubs','EV3Brick')]: - try:j=__import__(h,E,E,i);A[L]=g;del j;break - except(N,R):pass - if A[L]==e:A['release']='2.0.0' - if A[L]==n: + A[F]=U(os.uname()[3]) + if not A[F]:A[F]=U(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=U(sys.version.split(';')[1]) + except(I,P):pass + if A[F]and R(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(Z,Y): + try:e=os.uname();A[D]=e.release + except(P,I,TypeError):pass + for(f,g,h)in[(a,a,'const'),(b,b,'FAT'),(d,'pybricks.hubs','EV3Brick')]: + try:i=__import__(g,E,E,h);A[L]=f;del i;break + except(M,Q):pass + if A[L]==d:A['release']='2.0.0' + if A[L]==l: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] - if W:A[Y]=W - A[K]='v{}.{}'.format(O&255,O>>8&3) - A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def z(info,desc=B): - G='with ';D=info;E=A - for F in[A+'/board_info.csv'for A in y]: - if g(F): - B=desc or D[J].strip() - if f(D,B,F):E=K;break - if M in B: - B=B.split(M)[0].strip() - if f(D,B,F):E=K;break - if not E: - B=desc or D[J].strip() - if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() - D[J]=B - D[J]=D[J].replace(' ',T);C.collect() -def f(info,board_descr,filename): - with X(filename,'r')as C: + N=int(A[K]);V=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] + if V:A[X]=V + A[K]='v{}.{}'.format(N&255,N>>8&3) + A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def y(info,desc=B): + L='with ';D=info;F=A + for G in[A+'/board_info.csv'for A in x]: + if e(G): + E=desc or D[H].strip();I=E.rfind(' with') + if I!=-1:J=E[:I].strip() + else:J=B + if z(D,E,G,J):F=K;break + if not F: + E=desc or D[H].strip() + if L+D[T].upper()in E:E=E.split(L+D[T].upper())[0].strip() + D[H]=E + D[H]=D[H].replace(' ',S);C.collect() +def z(info,descr,filename,short_descr): + D=short_descr;C=info;E=B + with W(filename,'r')as J: while 1: - B=C.readline() - if not B:break - D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return K + F=J.readline() + if not F:break + I,G=F.split(',')[0].strip(),F.split(',')[1].strip() + if I==descr:C[H]=G;return K + elif D and I==D: + if u in D:C[H]=G;return K + E=G + if E:C[H]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=I + except(F,I):A=J B=A - for B in[A,'/sd','/flash',G,I]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def g(filename): +def e(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def h():sys.exit(1) +def f():sys.exit(1) def read_path(): path=B - if S(sys.argv)==3: + if R(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:h() - elif S(sys.argv)==2:h() + else:f() + elif R(sys.argv)==2:f() return path -def i(): - try:B=bytes('abc',encoding='utf8');C=i.__module__;return A - except(j,H):return K +def g(): + try:B=bytes('abc',encoding='utf8');C=g.__module__;return A + except(h,I):return K def main(): D='lvgl' try:import lvgl as A - except m:return + except k:return B=D try:B='lvgl-{0}_{1}_{2}-{3}-{4}'.format(A.version_major(),A.version_minor(),A.version_patch(),A.version_info(),sys.platform) - except m:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) + except k:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) finally:stubber=Stubber(firmware_id=B) stubber.clean();stubber.modules=['io','lodepng','rtch',D];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or i(): - try:A0=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except l:pass - if not g('no_auto_stubber.txt'): +if __name__=='__main__'or g(): + try:A0=logging.getLogger(t);logging.basicConfig(level=logging.INFO) + except j:pass + if not e('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_lvgl_mpy.mpy b/src/stubber/board/createstubs_lvgl_mpy.mpy index aa512aaf33e5fa9e0611a115ba33b81e4427fe25..3813ad3c6b8cd138c29a46101b894ccbff6d01de 100644 GIT binary patch delta 4788 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 E0^rng@Bjb+ delta 4763 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 diff --git a/src/stubber/board/createstubs_mem.py b/src/stubber/board/createstubs_mem.py index 544cd599c..487300f41 100644 --- a/src/stubber/board/createstubs_mem.py +++ b/src/stubber/board/createstubs_mem.py @@ -458,7 +458,8 @@ def _info(): # type:() -> dict[str, str] pass try: _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - info["board"] = "with".join(_machine.split("with")[:-1]).strip() + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( sys.implementation._mpy @@ -554,16 +555,15 @@ def read_boardname(info, desc: str = ""): # print("look up the board name in the file", filename) if file_exists(filename): descr = desc or info["board"].strip() - print("searching info file: {}".format(filename)) - if find_board(info, descr, filename): + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): found = True break - if "with" in descr: - descr = descr.split("with")[0].strip() - print("searching for: {}".format(descr)) - if find_board(info, descr, filename): - found = True - break if not found: print("Board not found, guessing board name") descr = desc or info["board"].strip() @@ -575,18 +575,30 @@ def read_boardname(info, desc: str = ""): gc.collect() -def find_board(info: dict, board_descr: str, filename: str): +def find_board(info: dict, descr: str, filename: str, short_descr: str): "Find the board in the provided board_info.csv file" + short_hit = "" with open(filename, "r") as file: # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) while 1: line = file.readline() if not line: break descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == board_descr: + if descr_ == descr: info["board"] = board_ return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True return False diff --git a/src/stubber/board/createstubs_mem_min.py b/src/stubber/board/createstubs_mem_min.py index af8f6e677..139f88f81 100644 --- a/src/stubber/board/createstubs_mem_min.py +++ b/src/stubber/board/createstubs_mem_min.py @@ -1,179 +1,179 @@ -w='stubber' -v='{}/{}' -u='method' -t='function' -s='bool' -r='str' -q='float' -p='int' -o=NameError -n=sorted -m=NotImplementedError -d=',\n' -c='dict' -b='list' -a='tuple' -Z='micropython' -Y=str -X=repr -V='cpu' -U='_' -T=KeyError -S=open -R=IndexError -Q=dir -P=ImportError -O='with' +v='with' +u='stubber' +t='{}/{}' +s='method' +r='function' +q='bool' +p='str' +o='float' +n='int' +m=NameError +l=sorted +k=NotImplementedError +c=',\n' +b='dict' +a='list' +Z='tuple' +Y='micropython' +X=str +W=repr +U='cpu' +T='_' +S=KeyError +R=open +Q=IndexError +P=dir +O=ImportError N='family' M=len L=print K=True -J='board' -I='.' -H=AttributeError +J='.' +I=AttributeError +H='board' A=False G='/' E=None D='version' F=OSError -C='' -import gc as B,os,sys -from ujson import dumps as e +B='' +import gc as C,os,sys +from ujson import dumps as d try:from machine import reset -except P:pass -try:from collections import OrderedDict as f -except P:from ucollections import OrderedDict as f +except O:pass +try:from collections import OrderedDict as e +except O:from ucollections import OrderedDict as e __version__='v1.16.2' +w=2 x=2 -y=2 -g=[I,'/lib','/sd/lib','/flash/lib','lib'] +f=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): - C=firmware_id + B=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') - except H:pass - A._report=[];A.info=_info();B.collect() - if C:A._fwid=C.lower() - elif A.info[N]==Z:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + except I:pass + A._report=[];A.info=_info();C.collect() + if B:A._fwid=B.lower() + elif A.info[N]==Y:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) else:A._fwid='{family}-{ver}-{port}'.format(**A.info) - A._start_free=B.mem_free() + A._start_free=C.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:h(path+G) + try:g(path+G) except F:L('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): - I=item_instance;D=[];J=[] - for A in Q(I): - if A.startswith(U)and not A in L.modules:continue + H=item_instance;D=[];J=[] + for A in P(H): + if A.startswith(T)and not A in L.modules:continue try: - E=getattr(I,A) - try:F=X(type(E)).split("'")[1] - except R:F=C - if F in{p,q,r,s,a,b,c}:G=1 - elif F in{t,u}:G=2 + E=getattr(H,A) + try:F=W(type(E)).split("'")[1] + except Q:F=B + if F in{n,o,p,q,Z,a,b}:G=1 + elif F in{r,s}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,X(E),X(type(E)),E,G)) - except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K)) + D.append((A,W(E),W(type(E)),E,G)) + except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=n([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=n(set(A.modules)|set(modules)) + D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) def create_all_stubs(A): - B.collect() - for C in A.modules:A.create_one_stub(C) - def create_one_stub(C,module_name): + C.collect() + for B in A.modules:A.create_one_stub(B) + def create_one_stub(B,module_name): D=module_name - if D in C.problematic:return A - if D in C.excluded:return A - H='{}/{}.py'.format(C.path,D.replace(I,G));B.collect();E=A - try:E=C.create_module_stub(D,H) + if D in B.problematic:return A + if D in B.excluded:return A + H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A + try:E=B.create_module_stub(D,H) except F:return A - B.collect();return E - def create_module_stub(J,module_name,file_name=E): + C.collect();return E + def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name - if H is E:N=D.replace(I,U)+'.py';H=J.path+G+N + if H is E:N=D.replace(J,T)+'.py';H=I.path+G+N else:N=H.split(G)[-1] - if G in D:D=D.replace(G,I) + if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');R=B.mem_free() - except P:return A - h(H) - with S(H,'w')as M:O=Y(J.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,O,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(M,L,D,C) - J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) + try:L=__import__(D,E,E,'*');U=C.mem_free() + except O:return A + g(H) + with R(H,'w')as M:P=X(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del L - except(F,T):pass + except(F,S):pass try:del sys.modules[D] - except T:pass - B.collect();return K + except S:pass + C.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';Z='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;C.collect() if P in K.problematic:return R,N=K.get_obj_attributes(P) if N:L(N) - for(E,J,G,S,f)in R: + for(E,J,G,T,f)in R: if E in['classmethod','staticmethod','BaseException',O]:continue if E[0].isdigit():continue - if G==""and M(D)<=y*4: - U=C;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if G==""and M(D)<=x*4: + U=B;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,S,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[u,t,'closure']): - W=Y;X=C + H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) + elif any(A in G for A in[s,r,'closure']): + W=Y;X=B if Q>0:X='self, ' - if Z in G or Z in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) + if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=C - if A[D]==C and sys.platform not in(c,b): - try:h=os.uname();A[D]=h.release - except(R,H,TypeError):pass - for(i,j,k)in[(d,d,'const'),(e,e,'FAT'),(g,'pybricks.hubs','EV3Brick')]: - try:l=__import__(j,E,E,k);A[N]=i;del l;break - except(P,T):pass - if A[N]==g:A['release']='2.0.0' - if A[N]==Z: + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=V(sys.version.split(';')[1]) + except(I,Q):pass + if A[F]and M(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(b,a): + try:g=os.uname();A[D]=g.release + except(Q,I,TypeError):pass + for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(f,'pybricks.hubs','EV3Brick')]: + try:k=__import__(i,E,E,j);A[N]=h;del k;break + except(O,S):pass + if A[N]==f:A['release']='2.0.0' + if A[N]==Y: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - L=int(A[K]);U=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][L>>10] - if U:A[a]=U + L=int(A[K]);T=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][L>>10] + if T:A[Z]=T A[K]='v{}.{}'.format(L&255,L>>8&3) - A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def z(info,desc=C): - G='with ';D=info;E=A - for F in[A+'/board_info.csv'for A in g]: - if j(F): - C=desc or D[J].strip() - if i(D,C,F):E=K;break - if O in C: - C=C.split(O)[0].strip() - if i(D,C,F):E=K;break - if not E: - C=desc or D[J].strip() - if G+D[V].upper()in C:C=C.split(G+D[V].upper())[0].strip() - D[J]=C - D[J]=D[J].replace(' ',U);B.collect() -def i(info,board_descr,filename): - with S(filename,'r')as C: + A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def y(info,desc=B): + L='with ';D=info;F=A + for G in[A+'/board_info.csv'for A in f]: + if h(G): + E=desc or D[H].strip();I=E.rfind(' with') + if I!=-1:J=E[:I].strip() + else:J=B + if z(D,E,G,J):F=K;break + if not F: + E=desc or D[H].strip() + if L+D[U].upper()in E:E=E.split(L+D[U].upper())[0].strip() + D[H]=E + D[H]=D[H].replace(' ',T);C.collect() +def z(info,descr,filename,short_descr): + D=short_descr;C=info;E=B + with R(filename,'r')as J: while 1: - B=C.readline() - if not B:break - D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return K + F=J.readline() + if not F:break + I,G=F.split(',')[0].strip(),F.split(',')[1].strip() + if I==descr:C[H]=G;return K + elif D and I==D: + if v in D:C[H]=G;return K + E=G + if E:C[H]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=I + except(F,I):A=J B=A - for B in[A,'/sd','/flash',G,I]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def j(filename): +def h(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def k():sys.exit(1) +def i():sys.exit(1) def read_path(): - path=C + path=B if M(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:k() - elif M(sys.argv)==2:k() + else:i() + elif M(sys.argv)==2:i() return path -def l(): - try:B=bytes('abc',encoding='utf8');C=l.__module__;return A - except(m,H):return K +def j(): + try:B=bytes('abc',encoding='utf8');C=j.__module__;return A + except(k,I):return K def main(): E='/modulelist.txt';stubber=Stubber(path=read_path());stubber.clean();stubber.modules=[] - for C in g: + for B in f: try: - F=B.mem_free() - with S(C+E)as D: - L('Debug: List of modules: '+C+E);A=D.readline() + F=C.mem_free() + with R(B+E)as D: + L('Debug: List of modules: '+B+E);A=D.readline() while A: A=A.strip() if M(A)>0 and A[0]!='#':stubber.modules.append(A) A=D.readline() - B.collect();L('Debug: Used memory to load modulelist.txt: '+Y(F-B.mem_free())+' bytes');break + C.collect();L('Debug: Used memory to load modulelist.txt: '+X(F-C.mem_free())+' bytes');break except Exception:pass - if not stubber.modules:stubber.modules=[Z] - B.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or l(): - try:A0=logging.getLogger(w);logging.basicConfig(level=logging.INFO) - except o:pass - if not j('no_auto_stubber.txt'): - try:B.threshold(4*1024);B.enable() + if not stubber.modules:stubber.modules=[Y] + C.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or j(): + try:A0=logging.getLogger(u);logging.basicConfig(level=logging.INFO) + except m:pass + if not h('no_auto_stubber.txt'): + try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mem_mpy.mpy b/src/stubber/board/createstubs_mem_mpy.mpy index 0b23f697f21268798fcfaf0aca3ed44f94dd16e5..560e2f8f5a33db15d79df94d4726560329115eaa 100644 GIT binary patch delta 4847 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"and S(D)<=A0*4: + if G==""and R(D)<=z*4: U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=M A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[t,s,'closure']): - W=Y;X=B + elif any(A in G for A in[r,q,'closure']): + W=b;X=B if P>0:X='self, ' if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) @@ -137,46 +137,46 @@ def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(b,a): - try:g=os.uname();A[D]=g.release - except(Q,H,TypeError):pass - for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(e,'pybricks.hubs','EV3Brick')]: - try:k=__import__(i,E,E,j);A[L]=h;del k;break - except(N,R):pass - if A[L]==e:A['release']='2.0.0' - if A[L]==Y: + A[F]=U(os.uname()[3]) + if not A[F]:A[F]=U(os.uname()[2]) + if not A[F]and';'in sys.version:A[F]=U(sys.version.split(';')[1]) + except(I,P):pass + if A[F]and R(A[F])>5:A[F]=B + if A[D]==B and sys.platform not in(a,Z): + try:f=os.uname();A[D]=f.release + except(P,I,TypeError):pass + for(g,h,i)in[(b,b,'const'),(c,c,'FAT'),(d,'pybricks.hubs','EV3Brick')]: + try:j=__import__(h,E,E,i);A[L]=g;del j;break + except(M,Q):pass + if A[L]==d:A['release']='2.0.0' + if A[L]==X: if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if K in A and A[K]: - O=int(A[K]);W=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][O>>10] - if W:A[Z]=W - A[K]='v{}.{}'.format(O&255,O>>8&3) - A[X]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def A2(info,desc=B): - G='with ';D=info;E=A - for F in[A+'/board_info.csv'for A in A1]: - if i(F): - B=desc or D[J].strip() - if h(D,B,F):E=K;break - if M in B: - B=B.split(M)[0].strip() - if h(D,B,F):E=K;break - if not E: - B=desc or D[J].strip() - if G+D[U].upper()in B:B=B.split(G+D[U].upper())[0].strip() - D[J]=B - D[J]=D[J].replace(' ',T);C.collect() -def h(info,board_descr,filename): - with X(filename,'r')as C: + N=int(A[K]);V=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] + if V:A[Y]=V + A[K]='v{}.{}'.format(N&255,N>>8&3) + A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A +def A1(info,desc=B): + L='with ';D=info;F=A + for G in[A+'/board_info.csv'for A in A0]: + if g(G): + E=desc or D[H].strip();I=E.rfind(' with') + if I!=-1:J=E[:I].strip() + else:J=B + if A2(D,E,G,J):F=K;break + if not F: + E=desc or D[H].strip() + if L+D[T].upper()in E:E=E.split(L+D[T].upper())[0].strip() + D[H]=E + D[H]=D[H].replace(' ',S);C.collect() +def A2(info,descr,filename,short_descr): + D=short_descr;C=info;E=B + with W(filename,'r')as J: while 1: - B=C.readline() - if not B:break - D,E=B.split(',')[0].strip(),B.split(',')[1].strip() - if D==board_descr:info[J]=E;return K + F=J.readline() + if not F:break + I,G=F.split(',')[0].strip(),F.split(',')[1].strip() + if I==descr:C[H]=G;return K + elif D and I==D: + if x in D:C[H]=G;return K + E=G + if E:C[H]=E;return K return A def get_root(): try:A=os.getcwd() - except(F,H):A=I + except(F,I):A=J B=A - for B in[A,'/sd','/flash',G,I]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except F:continue return B -def i(filename): +def g(filename): try: if os.stat(filename)[0]>>14:return K return A except F:return A -def j():sys.exit(1) +def h():sys.exit(1) def read_path(): path=B - if S(sys.argv)==3: + if R(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:j() - elif S(sys.argv)==2:j() + else:h() + elif R(sys.argv)==2:h() return path -def k(): - try:B=bytes('abc',encoding='utf8');C=k.__module__;return A - except(l,H):return K -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',y,d,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or k(): - try:A3=logging.getLogger(x);logging.basicConfig(level=logging.INFO) - except n:pass - if not i('no_auto_stubber.txt'): +def i(): + try:B=bytes('abc',encoding='utf8');C=i.__module__;return A + except(j,I):return K +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',X,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,c,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or i(): + try:A3=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + except l:pass + if not g('no_auto_stubber.txt'): try:C.threshold(4*1024);C.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mpy.mpy b/src/stubber/board/createstubs_mpy.mpy index cc71f0e4e7fdc218aa38a01a30038f8aafce13cb..69dd56b39ff91e89c180b5d820f2e407d16ec8af 100644 GIT binary patch delta 5287 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 Date: Wed, 3 Jan 2024 12:26:28 +0100 Subject: [PATCH 20/68] Update board_info.csv with preference for newest board names Signed-off-by: Jos Verlinde --- scripts/flash.ipynb | 463 +++++++++++++++++++++++++++++ src/stubber/board/board_info.csv | 64 ++-- src/stubber/data/board_info.csv | 64 ++-- src/stubber/data/board_info.json | 486 +++++++++++++++---------------- 4 files changed, 770 insertions(+), 307 deletions(-) create mode 100644 scripts/flash.ipynb diff --git a/scripts/flash.ipynb b/scripts/flash.ipynb new file mode 100644 index 000000000..e0ca14264 --- /dev/null +++ b/scripts/flash.ipynb @@ -0,0 +1,463 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "import shutil, time" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'port': 'esp32',\n", + " 'build': '',\n", + " 'arch': 'xtensawin',\n", + " 'family': 'micropython',\n", + " 'board': 'Generic ESP32S3 module with ESP32S3',\n", + " 'cpu': 'ESP32S3',\n", + " 'version': '1.22.0.',\n", + " 'mpy': 'v6.2',\n", + " 'ver': 'v1.22.0.',\n", + " 'serial_port': 'COM8'}]" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "devs = %mpy --list\n", + "ports = devs.fields(0) # list of ports\n", + "# build a list of dicts with info for each port and attached board \n", + "dev_info = []\n", + "for p in ports:\n", + " info = %mpy --select {p} --info\n", + " if info:\n", + " dev_info.append(info)\n", + "\n", + "target_version = \"1.22.0\"\n", + "# filter \n", + "# dev_info = [d for d in dev_info if d[\"version\"].rstrip(\".\") != target_version]\n", + "dev_info" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [], + "source": [ + "from pathlib import Path\n", + "\n", + "PORT_FWTYPES = {\n", + " \"stm32\": \".hex\",\n", + " \"esp32\": \".bin\",\n", + " \"rp2\": \".uf2\",\n", + " \"samd\": \".uf2\",\n", + "}\n", + "\n", + "\n", + "def find_firmware(version: str, *, board: str = \"*\", port: str):\n", + " fw_folder = Path.cwd() / \"firmware\" / port\n", + " if not fw_folder.exists():\n", + " print(f\"Folder {fw_folder} does not exist\")\n", + " return None\n", + " v_str = f\"v{version}\"\n", + " ext = PORT_FWTYPES[port]\n", + " fw_files = list(fw_folder.glob(f\"{board}-{v_str}{ext}\"))\n", + " if not fw_files:\n", + " print(f\"No firmware files found for {v_str}\")\n", + " return None\n", + " fw_files.sort()\n", + " yield from fw_files\n", + "\n", + "\n", + "# for fw in find_firmware(\"1.22.0\", port=\"samd\", board=\"SEEED_WIO_*\"):\n", + "# print(fw)\n", + "# for fw in find_firmware(\"1.22.0\", port=\"esp32\", board=\"ESP32_GENERIC-SPIRAM\"):\n", + "# print(fw)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [], + "source": [ + "import gc\n", + "import os\n", + "\n", + "\n", + "LIBS = [\"../src/stubber/data\"]\n", + "\n", + "\n", + "def file_exists(filename: str):\n", + " try:\n", + " if os.stat(filename)[0] >> 14:\n", + " return True\n", + " return False\n", + " except OSError:\n", + " return False\n", + "\n", + "\n", + "def read_boardname(info, desc: str = \"\"):\n", + " found = False\n", + " for filename in [d + \"/board_info.csv\" for d in LIBS]:\n", + " # print(\"look up the board name in the file\", filename)\n", + " if file_exists(filename):\n", + " descr = desc or info[\"board\"].strip()\n", + " print(\"searching info file: {} for: '{}' \".format(filename, descr))\n", + " if find_board(info, descr, filename):\n", + " found = True\n", + " break\n", + " if not found:\n", + " print(\"Board not found, guessing board name\")\n", + " descr = desc or info[\"board\"].strip()\n", + " if \"with \" + info[\"cpu\"].upper() in descr:\n", + " # remove the with cpu part\n", + " descr = descr.split(\"with \" + info[\"cpu\"].upper())[0].strip()\n", + " info[\"board\"] = descr\n", + " info[\"board\"] = info[\"board\"].replace(\" \", \"_\")\n", + " gc.collect()\n", + "\n", + "\n", + "def find_board(info: dict, descr: str, filename: str):\n", + " # find a board based on its description\n", + " short_hit = \"\"\n", + " lines = []\n", + " pos = descr.rfind(\" with\")\n", + " if pos != -1:\n", + " short_descr = descr[:pos].strip()\n", + " else:\n", + " short_descr = \"\"\n", + " try:\n", + " with open(filename, \"r\") as file:\n", + " lines = file.readlines()\n", + " for line in lines:\n", + " line = line.strip()\n", + " if line.startswith(\"#\"):\n", + " continue\n", + " _descr = line.split(\",\")[0].strip()\n", + " _board = line.split(\",\")[1].strip()\n", + " if _descr == descr:\n", + " info[\"board\"] = _board\n", + " return True\n", + " elif short_descr and _descr == short_descr:\n", + " if \"with\" in short_descr:\n", + " # Good enough - no need to trawl the entire file\n", + " info[\"board\"] = _board\n", + " return True\n", + " # good enough if not found in the rest of the file (but slow)\n", + " short_hit = _board\n", + " if short_hit:\n", + " info[\"board\"] = short_hit\n", + " return True\n", + " return False\n", + " finally:\n", + " del lines\n", + " gc.collect()\n", + "\n", + "\n", + "def find_board_old(info: dict, descr: str, filename: str, short_descr: str):\n", + " \"Find the board in the provided board_info.csv file\"\n", + " short_hit = \"\"\n", + " with open(filename, \"r\") as file:\n", + " # ugly code to make testable in python and micropython\n", + " # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file)\n", + " while 1:\n", + " line = file.readline()\n", + " if not line:\n", + " break\n", + " descr_, board_ = line.split(\",\")[0].strip(), line.split(\",\")[1].strip()\n", + " if descr_ == descr:\n", + " info[\"board\"] = board_\n", + " return True\n", + " elif short_descr and descr_ == short_descr:\n", + " if \"with\" in short_descr:\n", + " # Good enough - no need to trawl the entire file\n", + " info[\"board\"] = board_\n", + " return True\n", + " # good enough if not found in the rest of the file (but slow)\n", + " short_hit = board_\n", + " if short_hit:\n", + " info[\"board\"] = short_hit\n", + " return True\n", + " return False" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "searching info file: ../src/stubber/data/board_info.csv for: 'Generic ESP32S3 module with ESP32S3' \n" + ] + }, + { + "data": { + "text/plain": [ + "(WindowsPath('c:/develop/MyPython/micropython-stubber/scripts/firmware/esp32/ESP32_GENERIC_S3-v1.22.0.bin'),\n", + " {'port': 'esp32',\n", + " 'build': '',\n", + " 'arch': 'xtensawin',\n", + " 'family': 'micropython',\n", + " 'board': 'ESP32_GENERIC_S3',\n", + " 'cpu': 'ESP32S3',\n", + " 'version': '1.22.0.',\n", + " 'mpy': 'v6.2',\n", + " 'ver': 'v1.22.0.',\n", + " 'serial_port': 'COM8'})" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mcu = dev_info.pop()\n", + "read_boardname(mcu)\n", + "fw_file = find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"]).__next__()\n", + "fw_file, mcu" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Dict, Optional\n", + "import psutil\n", + "MCUInfo = Dict[str,str]\n", + "def flash_uf2(mcu:MCUInfo, fw_file:Optional[Path]= None) -> Optional[MCUInfo]:\n", + " if not PORT_FWTYPES[mcu[\"port\"]] in [\".uf2\"]:\n", + " print(f\"UF2 not supported on {mcu['board']} on {mcu['serial_port']}\")\n", + " return None\n", + "\n", + " print(f\"Entering bootloader on {mcu['board']} on {mcu['serial_port']}\")\n", + " %mpy --select {mcu['serial_port']}\n", + " %mpy --bootloader # TODO: add this to micropython-magic\n", + "\n", + " destination = \"\"\n", + " wait = 5\n", + " while not destination and wait > 0:\n", + " print(f\"Waiting for mcu to mount as a drive : {wait} seconds left\")\n", + " drives = [drive.device for drive in psutil.disk_partitions()]\n", + " for drive in drives:\n", + " if Path(drive, \"INFO_UF2.TXT\").exists():\n", + " destination = drive\n", + " break\n", + " time.sleep(1)\n", + " wait -= 1\n", + " if not destination or not Path(destination).exists() or not Path(destination, \"INFO_UF2.TXT\").exists():\n", + " print(\"Board is not in bootloader mode\")\n", + " return None\n", + " else:\n", + " print(\"Board is in bootloader mode\")\n", + " fw_file = fw_file or find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"]).__next__()\n", + " print(f\"Copying {fw_file} to {destination}\")\n", + " shutil.copy(fw_file, destination)\n", + " print(\"Done copying, resetting the board and wait for it to restart\")\n", + " time.sleep(5)\n", + " new_info:MCUInfo = %mpy --select {mcu['serial_port']} --info\n", + " return new_info" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [], + "source": [ + "def flash_esp32(mcu:MCUInfo, fw_file:Optional[Path]= None,*, erase_flash:bool=True) -> Optional[MCUInfo]:\n", + " if not mcu[\"port\"] in [\"esp32\"]:\n", + " print(f\"ESP32 not supported on {mcu['board']} on {mcu['serial_port']}\")\n", + " return None\n", + "\n", + " fw_file = fw_file or find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"]).__next__()\n", + " print(f\"Flashing {fw_file} on {mcu['board']} on {mcu['serial_port']}\")\n", + " baud_rate = str(2000000)\n", + " if mcu[\"cpu\"].upper()== \"ESP32\":\n", + " if erase_flash:\n", + " !esptool --chip esp32 --port {mcu[\"serial_port\"]} erase_flash\n", + " !esptool --chip esp32 --port {mcu[\"serial_port\"]} -b {baud_rate} write_flash -z 0x1000 {fw_file}\n", + " elif mcu[\"cpu\"].upper() == \"ESP32S3\":\n", + " if erase_flash:\n", + " !esptool --chip esp32s3 --port {mcu[\"serial_port\"]} erase_flash\n", + " !esptool --chip esp32s3 --port {mcu[\"serial_port\"]} -b {baud_rate} write_flash -z 0x0 {fw_file}\n", + "\n", + " print(\"Done flashing, resetting the board and wait for it to restart\")\n", + " time.sleep(5)\n", + " new_info:MCUInfo = %mpy --select {mcu['serial_port']} --info\n", + " return new_info\n" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'port': 'esp32', 'build': '', 'arch': 'xtensawin', 'family': 'micropython', 'board': 'ESP32_GENERIC_S3', 'cpu': 'ESP32S3', 'version': '1.22.0.', 'mpy': 'v6.2', 'ver': 'v1.22.0.', 'serial_port': 'COM8'}\n", + "Flashing c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\esp32\\ESP32_GENERIC_S3-v1.22.0.bin on ESP32_GENERIC_S3 on COM8\n", + "esptool.py v4.6.2\n", + "Serial port COM8\n", + "Connecting....\n", + "Chip is ESP32-S3 (revision v0.1)\n", + "Features: WiFi, BLE\n", + "Crystal is 40MHz\n", + "MAC: f4:12:fa:81:3b:8c\n", + "Uploading stub...\n", + "Running stub...\n", + "Stub running...\n", + "Changing baud rate to 2000000\n", + "Changed.\n", + "Configuring flash size...\n", + "Flash will be erased from 0x00000000 to 0x0018dfff...\n", + "Compressed 1628240 bytes to 1066966...\n", + "Writing at 0x00000000... (1 %)\n", + "Writing at 0x0001248d... (3 %)\n", + "Writing at 0x0001a1cd... (4 %)\n", + "Writing at 0x00021df4... (6 %)\n", + "Writing at 0x000283d4... (7 %)\n", + "Writing at 0x00032609... (9 %)\n", + "Writing at 0x00041899... (10 %)\n", + "Writing at 0x000476af... (12 %)\n", + "Writing at 0x00051717... (13 %)\n", + "Writing at 0x0005973a... (15 %)\n", + "Writing at 0x0005efe8... (16 %)\n", + "Writing at 0x000645b0... (18 %)\n", + "Writing at 0x00069dcf... (19 %)\n", + "Writing at 0x0006eea8... (21 %)\n", + "Writing at 0x000740f2... (22 %)\n", + "Writing at 0x000791ec... (24 %)\n", + "Writing at 0x0007e1ae... (25 %)\n", + "Writing at 0x00083403... (27 %)\n", + "Writing at 0x00088073... (28 %)\n", + "Writing at 0x0008cce9... (30 %)\n", + "Writing at 0x000933e6... (31 %)\n", + "Writing at 0x00098b29... (33 %)\n", + "Writing at 0x0009e6b2... (34 %)\n", + "Writing at 0x000a3f27... (36 %)\n", + "Writing at 0x000a92ac... (37 %)\n", + "Writing at 0x000af11a... (39 %)\n", + "Writing at 0x000b47d1... (40 %)\n", + "Writing at 0x000b9c29... (42 %)\n", + "Writing at 0x000bf40f... (43 %)\n", + "Writing at 0x000c4bbc... (45 %)\n", + "Writing at 0x000ca15b... (46 %)\n", + "Writing at 0x000cf23f... (48 %)\n", + "Writing at 0x000d4db4... (50 %)\n", + "Writing at 0x000da894... (51 %)\n", + "Writing at 0x000e0416... (53 %)\n", + "Writing at 0x000e6797... (54 %)\n", + "Writing at 0x000ebcef... (56 %)\n", + "Writing at 0x000f0c28... (57 %)\n", + "Writing at 0x000f5f2f... (59 %)\n", + "Writing at 0x000fae99... (60 %)\n", + "Writing at 0x00100475... (62 %)\n", + "Writing at 0x00105738... (63 %)\n", + "Writing at 0x0010ac09... (65 %)\n", + "Writing at 0x0010fcea... (66 %)\n", + "Writing at 0x00115378... (68 %)\n", + "Writing at 0x0011b934... (69 %)\n", + "Writing at 0x001208ba... (71 %)\n", + "Writing at 0x00125ba2... (72 %)\n", + "Writing at 0x0012b207... (74 %)\n", + "Writing at 0x00130579... (75 %)\n", + "Writing at 0x00135c0a... (77 %)\n", + "Writing at 0x0013afcf... (78 %)\n", + "Writing at 0x0013ff1a... (80 %)\n", + "Writing at 0x00144fca... (81 %)\n", + "Writing at 0x0014a084... (83 %)\n", + "Writing at 0x0014f380... (84 %)\n", + "Writing at 0x00154754... (86 %)\n", + "Writing at 0x0015a0e8... (87 %)\n", + "Writing at 0x0015f7bc... (89 %)\n", + "Writing at 0x001655b4... (90 %)\n", + "Writing at 0x0016e1f4... (92 %)\n", + "Writing at 0x0017614c... (93 %)\n", + "Writing at 0x0017ba83... (95 %)\n", + "Writing at 0x001810e8... (96 %)\n", + "Writing at 0x00186b0a... (98 %)\n", + "Writing at 0x0018caf6... (100 %)\n", + "Wrote 1628240 bytes (1066966 compressed) at 0x00000000 in 17.3 seconds (effective 751.2 kbit/s)...\n", + "Hash of data verified.\n", + "\n", + "Leaving...\n", + "Hard resetting via RTS pin...\n", + "Done flashing, resetting the board and wait for it to restart\n", + "searching info file: ../src/stubber/data/board_info.csv for: 'Generic ESP32S3 module with ESP32S3' \n", + "{'port': 'esp32', 'build': '', 'arch': 'xtensawin', 'family': 'micropython', 'board': 'ESP32_GENERIC_S3', 'cpu': 'ESP32S3', 'version': '1.22.0.', 'mpy': 'v6.2', 'ver': 'v1.22.0.', 'serial_port': 'COM8'}\n" + ] + } + ], + "source": [ + "print(mcu)\n", + "new = None\n", + "if mcu[\"port\"] in [\"samd\",\"rp2\"]:\n", + " new = flash_uf2(mcu)\n", + "elif mcu[\"port\"] in [\"esp32\"]:\n", + " new = flash_esp32(mcu, erase_flash=False)\n", + "if new:\n", + " read_boardname(new)\n", + " print(new)\n", + " mcu = new\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "PORT_FWTYPES[mcu[\"port\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/src/stubber/board/board_info.csv b/src/stubber/board/board_info.csv index d41eeacf9..9e9cb6aaa 100644 --- a/src/stubber/board/board_info.csv +++ b/src/stubber/board/board_info.csv @@ -1,47 +1,47 @@ board,description 4MB/OTA module with ESP32,GENERIC_OTA -Actinius Icarus with NRF9160,actinius_icarus +Actinius Icarus with NRF9160,ACTINIUS_ICARUS Adafruit Feather RP2040,ADAFRUIT_FEATHER_RP2040 Adafruit Feather STM32F405 with STM32F405RG,ADAFRUIT_F405_EXPRESS Adafruit ItsyBitsy RP2040,ADAFRUIT_ITSYBITSY_RP2040 Adafruit Metro M7 with MIMXRT1011DAE5A,ADAFRUIT_METRO_M7 Adafruit QT Py RP2040,ADAFRUIT_QTPY_RP2040 Arduino GIGA R1 WiFi with STM32H747,ARDUINO_GIGA -Arduino Nano 33 BLE Sense with NRF52840,arduino_nano_33_ble_sense +Arduino Nano 33 BLE Sense with NRF52840,ARDUINO_NANO_33_BLE_SENSE Arduino Nano ESP32 with ESP32S3,ARDUINO_NANO_ESP32 Arduino Nano RP2040 Connect,ARDUINO_NANO_RP2040_CONNECT Arduino Nicla Vision with STM32H747,ARDUINO_NICLA_VISION Arduino Portenta C33 with RA6M5,ARDUINO_PORTENTA_C33 Arduino Portenta H7 with STM32H747,ARDUINO_PORTENTA_H7 -Arduino Primo with NRF52832,arduino_primo +Arduino Primo with NRF52832,ARDUINO_PRIMO B-L072Z-LRWAN1 with STM32L072CZ,B_L072Z_LRWAN1 B-L475E-IOT01A with STM32L475,B_L475E_IOT01A -Bluefruit nRF52 Feather with NRF52832,feather52 -BLUEIO-TAG-EVIM with NRF52832,blueio_tag_evim +Bluefruit nRF52 Feather with NRF52832,FEATHER52 +BLUEIO-TAG-EVIM with NRF52832,BLUEIO_TAG_EVIM Cerb40 with STM32F405RG,CERB40 CustomPCB with STM32F439,STM32F439 -DVK-BL652 with NRF52832,dvk_bl652 +DVK-BL652 with NRF52832,DVK_BL652 EK-RA4M1 with RA4M1,EK_RA4M1 EK-RA4W1 with RA4W1,EK_RA4W1 EK-RA6M1 with RA6M1,EK_RA6M1 EK-RA6M2 with RA6M2,EK_RA6M2 -ESP module (1M) with ESP8266,GENERIC_1M -ESP module (512K) with ESP8266,GENERIC_512K -ESP module with ESP8266,GENERIC +ESP module (1M) with ESP8266,ESP8266_GENERIC +ESP module (512K) with ESP8266,ESP8266_GENERIC +ESP module with ESP8266,ESP8266_GENERIC ESP32 module (spiram) with ESP32,GENERIC_SPIRAM ESP32 module with ESP32,GENERIC ESP32 Unicore module with ESP32-UNICORE,GENERIC_UNICORE ESP32-D2WD,ESP32_GENERIC ESP32-S2-WROVER with ESP32-S2,ESP32_S2_WROVER ESP32-UNICORE,ESP32_GENERIC -ESP32C3 module with ESP32C3,GENERIC_C3 +ESP32C3 module with ESP32C3,ESP32_GENERIC_C3 ESP32S2 module with ESP32S2,GENERIC_S2 ESP32S3 module (spiram octal) with ESP32S3,GENERIC_S3_SPIRAM_OCT ESP32S3 module (spiram) with ESP32S3,GENERIC_S3_SPIRAM ESP32S3 module with ESP32S3,GENERIC_S3 Espruino Pico with STM32F401CD,ESPRUINO_PICO -EVK_NINA_B1 with NRF52832,evk_nina_b1 -EVK_NINA_B3 with NRF52840,evk_nina_b3 +EVK_NINA_B1 with NRF52832,EVK_NINA_B1 +EVK_NINA_B3 with NRF52840,EVK_NINA_B3 F411DISC with STM32F411,STM32F411DISC F429I-DISCO with STM32F429,STM32F429DISC F4DISC with STM32F407,STM32F4DISC @@ -71,8 +71,8 @@ i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B,MIMXRT1050_EVK i.MX RT1060 EVK with MIMXRT1062DVJ6A,MIMXRT1060_EVK i.MX RT1064 EVK with MIMXRT1064DVL6A,MIMXRT1064_EVK i.MX RT1170 EVK with MIMXRT1176DVMAA,MIMXRT1170_EVK -IBK-BLYST-NANO with NRF52832,ibk_blyst_nano -IDK-BLYST-NANO with NRF52832,idk_blyst_nano +IBK-BLYST-NANO with NRF52832,IBK_BLYST_NANO +IDK-BLYST-NANO with NRF52832,IDK_BLYST_NANO ItsyBitsy M0 Express with SAMD21G18A,ADAFRUIT_ITSYBITSY_M0_EXPRESS ItsyBitsy M4 Express with SAMD51G19A,ADAFRUIT_ITSYBITSY_M4_EXPRESS L476-DISCO with STM32L476,STM32L476DISC @@ -86,13 +86,13 @@ LOLIN_C3_MINI with ESP32-C3FH4,LOLIN_C3_MINI LOLIN_S2_MINI with ESP32-S2FN4R2,LOLIN_S2_MINI LOLIN_S2_PICO with ESP32-S2FN4R2,LOLIN_S2_PICO M5Stack ATOM with ESP32-PICO-D4,M5STACK_ATOM -MDK-USB-DONGLE with NRF52840,nrf52840-mdk-usb-dongle +MDK-USB-DONGLE with NRF52840,NRF52840_MDK_USB_DONGLE Metro M4 Express Airlift with SAMD51J19A,ADAFRUIT_METRO_M4_EXPRESS -micro:bit with NRF51822,microbit +micro:bit with NRF51822,MICROBIT MikroE Quail with STM32F427VI,MIKROE_QUAIL MIKROE_CLICKER2_STM32 with STM32F407,MIKROE_CLICKER2_STM32 Mini SAM M4 with SAMD51G19A,MINISAM_M4 -NADHAT_PYBF405 with STM32F405RG,NADHAT_PYBF405 +NADHAT_PYBF405 with STM32F405RG,GARATRONIC_NADHAT_F405 NanoS3 with ESP32-S3-FN8,UM_NANOS3 NetduinoPlus2 with STM32F405RG,NETDUINO_PLUS_2 NICLAVISION with STM32H747,ARDUINO_NICLA_VISION @@ -126,14 +126,14 @@ nullbits Bit-C PRO,NULLBITS_BIT_C_PRO Olimex ESP32 ETH with ESP32,OLIMEX_ESP32_POE OLIMEX STM32-E407 with STM32F407,OLIMEX_E407 OLIMEX STM32-H407 with STM32F407,OLIMEX_H407 -PCA10000 with NRF51822,pca10000 -PCA10001 with NRF51822,pca10001 -PCA10028 with NRF51822,pca10028 -PCA10031 with NRF51822,pca10031 -PCA10040 with NRF52832,pca10040 -PCA10056 with NRF52840,pca10056 -PCA10059 with NRF52840,pca10059 -PCA10090 with NRF9160,pca10090 +PCA10000 with NRF51822,PCA10000 +PCA10001 with NRF51822,PCA10001 +PCA10028 with NRF51822,PCA10028 +PCA10031 with NRF51822,PCA10031 +PCA10040 with NRF52832,PCA10040 +PCA10056 with NRF52840,PCA10056 +PCA10059 with NRF52840,PCA10059 +PCA10090 with NRF9160,PCA10090 Pimoroni Pico LiPo 16MB,PIMORONI_PICOLIPO_16MB Pimoroni Pico LiPo 4MB,PIMORONI_PICOLIPO_4MB Pimoroni Tiny 2040,PIMORONI_TINY2040 @@ -157,12 +157,12 @@ RA4M1_EK with RA4M1,RA4M1_EK RA4W1_EK with RA4W1,RA4W1_EK RA6M1_EK with RA6M1,RA6M1_EK RA6M2_EK with RA6M2,RA6M2_EK -Raspberry Pi Pico,PICO -Raspberry Pi Pico W,PICO_W +Raspberry Pi Pico,RPI_PICO +Raspberry Pi Pico W,RPI_PICO_W RT1010-Py-DevKIT with MIMXRT1011DAE5A,OLIMEX_RT1010 SAMD21-XPLAINED-PRO with SAMD21J18A,SAMD21_XPLAINED_PRO Seeed ARCH MIX with MIMXRT1052DVL5B,SEEED_ARCH_MIX -Seeed Xiao with SAMD21G18A,SEEED_XIAO +Seeed Xiao with SAMD21G18A,SEEED_XIAO_SAMD21 Silicognition RP2040-Shim,SIL_RP2040_SHIM Silicognition wESP32 with ESP32,SIL_WESP32 SparkFun Pro Micro RP2040,SPARKFUN_PROMICRO @@ -173,7 +173,7 @@ STM32H573I-DK with STM32H573IIK3Q,STM32H573I_DK STM32H7B3I-DK with STM32H7B3LIH6Q,STM32H7B3I_DK Teensy 4.0 with MIMXRT1062DVJ6A,TEENSY40 Teensy 4.1 with MIMXRT1062DVJ6A,TEENSY41 -TinyPICO with ESP32-PICO-D4,TINYPICO +TinyPICO with ESP32-PICO-D4,UM_TINYPICO TinyS2 with ESP32-S2FN4R2,UM_TINYS2 TinyS3 with ESP32-S3-FN8,UM_TINYS3 TinyWATCH S3 with ESP32-S3-PICO-1-N8R2,UM_TINYWATCHS3 @@ -188,6 +188,6 @@ W5500-EVB-Pico,W5500_EVB_PICO WeAct Studio RP2040,WEACTSTUDIO Wio Terminal D51R with SAMD51P19A,SEEED_WIO_TERMINAL WiPy with CC3200,WIPY -WT51822-S4AT with NRF51822,wt51822_s4at -XENON with NRF52840,particle_xenon -XIAO nRF52840 Sense with NRF52840,seeed_xiao_nrf52 +WT51822-S4AT with NRF51822,WT51822_S4AT +XENON with NRF52840,PARTICLE_XENON +XIAO nRF52840 Sense with NRF52840,SEEED_XIAO_NRF52 diff --git a/src/stubber/data/board_info.csv b/src/stubber/data/board_info.csv index d41eeacf9..9e9cb6aaa 100644 --- a/src/stubber/data/board_info.csv +++ b/src/stubber/data/board_info.csv @@ -1,47 +1,47 @@ board,description 4MB/OTA module with ESP32,GENERIC_OTA -Actinius Icarus with NRF9160,actinius_icarus +Actinius Icarus with NRF9160,ACTINIUS_ICARUS Adafruit Feather RP2040,ADAFRUIT_FEATHER_RP2040 Adafruit Feather STM32F405 with STM32F405RG,ADAFRUIT_F405_EXPRESS Adafruit ItsyBitsy RP2040,ADAFRUIT_ITSYBITSY_RP2040 Adafruit Metro M7 with MIMXRT1011DAE5A,ADAFRUIT_METRO_M7 Adafruit QT Py RP2040,ADAFRUIT_QTPY_RP2040 Arduino GIGA R1 WiFi with STM32H747,ARDUINO_GIGA -Arduino Nano 33 BLE Sense with NRF52840,arduino_nano_33_ble_sense +Arduino Nano 33 BLE Sense with NRF52840,ARDUINO_NANO_33_BLE_SENSE Arduino Nano ESP32 with ESP32S3,ARDUINO_NANO_ESP32 Arduino Nano RP2040 Connect,ARDUINO_NANO_RP2040_CONNECT Arduino Nicla Vision with STM32H747,ARDUINO_NICLA_VISION Arduino Portenta C33 with RA6M5,ARDUINO_PORTENTA_C33 Arduino Portenta H7 with STM32H747,ARDUINO_PORTENTA_H7 -Arduino Primo with NRF52832,arduino_primo +Arduino Primo with NRF52832,ARDUINO_PRIMO B-L072Z-LRWAN1 with STM32L072CZ,B_L072Z_LRWAN1 B-L475E-IOT01A with STM32L475,B_L475E_IOT01A -Bluefruit nRF52 Feather with NRF52832,feather52 -BLUEIO-TAG-EVIM with NRF52832,blueio_tag_evim +Bluefruit nRF52 Feather with NRF52832,FEATHER52 +BLUEIO-TAG-EVIM with NRF52832,BLUEIO_TAG_EVIM Cerb40 with STM32F405RG,CERB40 CustomPCB with STM32F439,STM32F439 -DVK-BL652 with NRF52832,dvk_bl652 +DVK-BL652 with NRF52832,DVK_BL652 EK-RA4M1 with RA4M1,EK_RA4M1 EK-RA4W1 with RA4W1,EK_RA4W1 EK-RA6M1 with RA6M1,EK_RA6M1 EK-RA6M2 with RA6M2,EK_RA6M2 -ESP module (1M) with ESP8266,GENERIC_1M -ESP module (512K) with ESP8266,GENERIC_512K -ESP module with ESP8266,GENERIC +ESP module (1M) with ESP8266,ESP8266_GENERIC +ESP module (512K) with ESP8266,ESP8266_GENERIC +ESP module with ESP8266,ESP8266_GENERIC ESP32 module (spiram) with ESP32,GENERIC_SPIRAM ESP32 module with ESP32,GENERIC ESP32 Unicore module with ESP32-UNICORE,GENERIC_UNICORE ESP32-D2WD,ESP32_GENERIC ESP32-S2-WROVER with ESP32-S2,ESP32_S2_WROVER ESP32-UNICORE,ESP32_GENERIC -ESP32C3 module with ESP32C3,GENERIC_C3 +ESP32C3 module with ESP32C3,ESP32_GENERIC_C3 ESP32S2 module with ESP32S2,GENERIC_S2 ESP32S3 module (spiram octal) with ESP32S3,GENERIC_S3_SPIRAM_OCT ESP32S3 module (spiram) with ESP32S3,GENERIC_S3_SPIRAM ESP32S3 module with ESP32S3,GENERIC_S3 Espruino Pico with STM32F401CD,ESPRUINO_PICO -EVK_NINA_B1 with NRF52832,evk_nina_b1 -EVK_NINA_B3 with NRF52840,evk_nina_b3 +EVK_NINA_B1 with NRF52832,EVK_NINA_B1 +EVK_NINA_B3 with NRF52840,EVK_NINA_B3 F411DISC with STM32F411,STM32F411DISC F429I-DISCO with STM32F429,STM32F429DISC F4DISC with STM32F407,STM32F4DISC @@ -71,8 +71,8 @@ i.MX RT1050 EVKB-A1 with MIMXRT1052DVL6B,MIMXRT1050_EVK i.MX RT1060 EVK with MIMXRT1062DVJ6A,MIMXRT1060_EVK i.MX RT1064 EVK with MIMXRT1064DVL6A,MIMXRT1064_EVK i.MX RT1170 EVK with MIMXRT1176DVMAA,MIMXRT1170_EVK -IBK-BLYST-NANO with NRF52832,ibk_blyst_nano -IDK-BLYST-NANO with NRF52832,idk_blyst_nano +IBK-BLYST-NANO with NRF52832,IBK_BLYST_NANO +IDK-BLYST-NANO with NRF52832,IDK_BLYST_NANO ItsyBitsy M0 Express with SAMD21G18A,ADAFRUIT_ITSYBITSY_M0_EXPRESS ItsyBitsy M4 Express with SAMD51G19A,ADAFRUIT_ITSYBITSY_M4_EXPRESS L476-DISCO with STM32L476,STM32L476DISC @@ -86,13 +86,13 @@ LOLIN_C3_MINI with ESP32-C3FH4,LOLIN_C3_MINI LOLIN_S2_MINI with ESP32-S2FN4R2,LOLIN_S2_MINI LOLIN_S2_PICO with ESP32-S2FN4R2,LOLIN_S2_PICO M5Stack ATOM with ESP32-PICO-D4,M5STACK_ATOM -MDK-USB-DONGLE with NRF52840,nrf52840-mdk-usb-dongle +MDK-USB-DONGLE with NRF52840,NRF52840_MDK_USB_DONGLE Metro M4 Express Airlift with SAMD51J19A,ADAFRUIT_METRO_M4_EXPRESS -micro:bit with NRF51822,microbit +micro:bit with NRF51822,MICROBIT MikroE Quail with STM32F427VI,MIKROE_QUAIL MIKROE_CLICKER2_STM32 with STM32F407,MIKROE_CLICKER2_STM32 Mini SAM M4 with SAMD51G19A,MINISAM_M4 -NADHAT_PYBF405 with STM32F405RG,NADHAT_PYBF405 +NADHAT_PYBF405 with STM32F405RG,GARATRONIC_NADHAT_F405 NanoS3 with ESP32-S3-FN8,UM_NANOS3 NetduinoPlus2 with STM32F405RG,NETDUINO_PLUS_2 NICLAVISION with STM32H747,ARDUINO_NICLA_VISION @@ -126,14 +126,14 @@ nullbits Bit-C PRO,NULLBITS_BIT_C_PRO Olimex ESP32 ETH with ESP32,OLIMEX_ESP32_POE OLIMEX STM32-E407 with STM32F407,OLIMEX_E407 OLIMEX STM32-H407 with STM32F407,OLIMEX_H407 -PCA10000 with NRF51822,pca10000 -PCA10001 with NRF51822,pca10001 -PCA10028 with NRF51822,pca10028 -PCA10031 with NRF51822,pca10031 -PCA10040 with NRF52832,pca10040 -PCA10056 with NRF52840,pca10056 -PCA10059 with NRF52840,pca10059 -PCA10090 with NRF9160,pca10090 +PCA10000 with NRF51822,PCA10000 +PCA10001 with NRF51822,PCA10001 +PCA10028 with NRF51822,PCA10028 +PCA10031 with NRF51822,PCA10031 +PCA10040 with NRF52832,PCA10040 +PCA10056 with NRF52840,PCA10056 +PCA10059 with NRF52840,PCA10059 +PCA10090 with NRF9160,PCA10090 Pimoroni Pico LiPo 16MB,PIMORONI_PICOLIPO_16MB Pimoroni Pico LiPo 4MB,PIMORONI_PICOLIPO_4MB Pimoroni Tiny 2040,PIMORONI_TINY2040 @@ -157,12 +157,12 @@ RA4M1_EK with RA4M1,RA4M1_EK RA4W1_EK with RA4W1,RA4W1_EK RA6M1_EK with RA6M1,RA6M1_EK RA6M2_EK with RA6M2,RA6M2_EK -Raspberry Pi Pico,PICO -Raspberry Pi Pico W,PICO_W +Raspberry Pi Pico,RPI_PICO +Raspberry Pi Pico W,RPI_PICO_W RT1010-Py-DevKIT with MIMXRT1011DAE5A,OLIMEX_RT1010 SAMD21-XPLAINED-PRO with SAMD21J18A,SAMD21_XPLAINED_PRO Seeed ARCH MIX with MIMXRT1052DVL5B,SEEED_ARCH_MIX -Seeed Xiao with SAMD21G18A,SEEED_XIAO +Seeed Xiao with SAMD21G18A,SEEED_XIAO_SAMD21 Silicognition RP2040-Shim,SIL_RP2040_SHIM Silicognition wESP32 with ESP32,SIL_WESP32 SparkFun Pro Micro RP2040,SPARKFUN_PROMICRO @@ -173,7 +173,7 @@ STM32H573I-DK with STM32H573IIK3Q,STM32H573I_DK STM32H7B3I-DK with STM32H7B3LIH6Q,STM32H7B3I_DK Teensy 4.0 with MIMXRT1062DVJ6A,TEENSY40 Teensy 4.1 with MIMXRT1062DVJ6A,TEENSY41 -TinyPICO with ESP32-PICO-D4,TINYPICO +TinyPICO with ESP32-PICO-D4,UM_TINYPICO TinyS2 with ESP32-S2FN4R2,UM_TINYS2 TinyS3 with ESP32-S3-FN8,UM_TINYS3 TinyWATCH S3 with ESP32-S3-PICO-1-N8R2,UM_TINYWATCHS3 @@ -188,6 +188,6 @@ W5500-EVB-Pico,W5500_EVB_PICO WeAct Studio RP2040,WEACTSTUDIO Wio Terminal D51R with SAMD51P19A,SEEED_WIO_TERMINAL WiPy with CC3200,WIPY -WT51822-S4AT with NRF51822,wt51822_s4at -XENON with NRF52840,particle_xenon -XIAO nRF52840 Sense with NRF52840,seeed_xiao_nrf52 +WT51822-S4AT with NRF51822,WT51822_S4AT +XENON with NRF52840,PARTICLE_XENON +XIAO nRF52840 Sense with NRF52840,SEEED_XIAO_NRF52 diff --git a/src/stubber/data/board_info.json b/src/stubber/data/board_info.json index e38cc5f28..9985acf6f 100644 --- a/src/stubber/data/board_info.json +++ b/src/stubber/data/board_info.json @@ -6,16 +6,16 @@ "board_name": "4MB/OTA module", "mcu_name": "ESP32", "path": "ports/esp32/boards/GENERIC_OTA/mpconfigboard.h", - "version": "v1.13" + "version": "v1.20.0" }, { "description": "Actinius Icarus with NRF9160", "port": "nrf", - "board": "actinius_icarus", + "board": "ACTINIUS_ICARUS", "board_name": "Actinius Icarus", "mcu_name": "NRF9160", - "path": "ports/nrf/boards/actinius_icarus/mpconfigboard.h", - "version": "v1.13" + "path": "ports/nrf/boards/ACTINIUS_ICARUS/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "Adafruit Feather RP2040", @@ -24,7 +24,7 @@ "board_name": "Adafruit Feather RP2040", "mcu_name": "-", "path": "ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h", - "version": "v1.15" + "version": "v1.22.0" }, { "description": "Adafruit Feather STM32F405 with STM32F405RG", @@ -33,7 +33,7 @@ "board_name": "Adafruit Feather STM32F405", "mcu_name": "STM32F405RG", "path": "ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "Adafruit ItsyBitsy RP2040", @@ -42,7 +42,7 @@ "board_name": "Adafruit ItsyBitsy RP2040", "mcu_name": "-", "path": "ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h", - "version": "v1.17" + "version": "v1.22.0" }, { "description": "Adafruit Metro M7 with MIMXRT1011DAE5A", @@ -51,7 +51,7 @@ "board_name": "Adafruit Metro M7", "mcu_name": "MIMXRT1011DAE5A", "path": "ports/mimxrt/boards/ADAFRUIT_METRO_M7/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "Adafruit QT Py RP2040", @@ -60,7 +60,7 @@ "board_name": "Adafruit QT Py RP2040", "mcu_name": "-", "path": "ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h", - "version": "v1.17" + "version": "v1.22.0" }, { "description": "Arduino GIGA R1 WiFi with STM32H747", @@ -74,11 +74,11 @@ { "description": "Arduino Nano 33 BLE Sense with NRF52840", "port": "nrf", - "board": "arduino_nano_33_ble_sense", + "board": "ARDUINO_NANO_33_BLE_SENSE", "board_name": "Arduino Nano 33 BLE Sense", "mcu_name": "NRF52840", - "path": "ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.h", - "version": "v1.20.0" + "path": "ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "Arduino Nano ESP32 with ESP32S3", @@ -87,7 +87,7 @@ "board_name": "Arduino Nano ESP32", "mcu_name": "ESP32S3", "path": "ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "Arduino Nano RP2040 Connect", @@ -96,7 +96,7 @@ "board_name": "Arduino Nano RP2040 Connect", "mcu_name": "-", "path": "ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h", - "version": "v1.18" + "version": "v1.22.0" }, { "description": "Arduino Nicla Vision with STM32H747", @@ -128,11 +128,11 @@ { "description": "Arduino Primo with NRF52832", "port": "nrf", - "board": "arduino_primo", + "board": "ARDUINO_PRIMO", "board_name": "Arduino Primo", "mcu_name": "NRF52832", - "path": "ports/nrf/boards/arduino_primo/mpconfigboard.h", - "version": "v1.10" + "path": "ports/nrf/boards/ARDUINO_PRIMO/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "B-L072Z-LRWAN1 with STM32L072CZ", @@ -141,7 +141,7 @@ "board_name": "B-L072Z-LRWAN1", "mcu_name": "STM32L072CZ", "path": "ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "B-L475E-IOT01A with STM32L475", @@ -150,25 +150,25 @@ "board_name": "B-L475E-IOT01A", "mcu_name": "STM32L475", "path": "ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "Bluefruit nRF52 Feather with NRF52832", "port": "nrf", - "board": "feather52", + "board": "FEATHER52", "board_name": "Bluefruit nRF52 Feather", "mcu_name": "NRF52832", - "path": "ports/nrf/boards/feather52/mpconfigboard.h", - "version": "v1.10" + "path": "ports/nrf/boards/FEATHER52/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "BLUEIO-TAG-EVIM with NRF52832", "port": "nrf", - "board": "blueio_tag_evim", + "board": "BLUEIO_TAG_EVIM", "board_name": "BLUEIO-TAG-EVIM", "mcu_name": "NRF52832", - "path": "ports/nrf/boards/blueio_tag_evim/mpconfigboard.h", - "version": "v1.11" + "path": "ports/nrf/boards/BLUEIO_TAG_EVIM/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "Cerb40 with STM32F405RG", @@ -177,7 +177,7 @@ "board_name": "Cerb40", "mcu_name": "STM32F405RG", "path": "ports/stm32/boards/CERB40/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "CustomPCB with STM32F439", @@ -186,16 +186,16 @@ "board_name": "CustomPCB", "mcu_name": "STM32F439", "path": "ports/stm32/boards/STM32F439/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "DVK-BL652 with NRF52832", "port": "nrf", - "board": "dvk_bl652", + "board": "DVK_BL652", "board_name": "DVK-BL652", "mcu_name": "NRF52832", - "path": "ports/nrf/boards/dvk_bl652/mpconfigboard.h", - "version": "v1.10" + "path": "ports/nrf/boards/DVK_BL652/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "EK-RA4M1 with RA4M1", @@ -204,7 +204,7 @@ "board_name": "EK-RA4M1", "mcu_name": "RA4M1", "path": "ports/renesas-ra/boards/EK_RA4M1/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "EK-RA4W1 with RA4W1", @@ -213,7 +213,7 @@ "board_name": "EK-RA4W1", "mcu_name": "RA4W1", "path": "ports/renesas-ra/boards/EK_RA4W1/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "EK-RA6M1 with RA6M1", @@ -222,7 +222,7 @@ "board_name": "EK-RA6M1", "mcu_name": "RA6M1", "path": "ports/renesas-ra/boards/EK_RA6M1/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "EK-RA6M2 with RA6M2", @@ -231,34 +231,34 @@ "board_name": "EK-RA6M2", "mcu_name": "RA6M2", "path": "ports/renesas-ra/boards/EK_RA6M2/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "ESP module (1M) with ESP8266", "port": "esp8266", - "board": "GENERIC_1M", + "board": "ESP8266_GENERIC", "board_name": "ESP module (1M)", "mcu_name": "ESP8266", - "path": "ports/esp8266/boards/GENERIC_1M/mpconfigboard.h", - "version": "v1.13" + "path": "ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "ESP module (512K) with ESP8266", "port": "esp8266", - "board": "GENERIC_512K", + "board": "ESP8266_GENERIC", "board_name": "ESP module (512K)", "mcu_name": "ESP8266", - "path": "ports/esp8266/boards/GENERIC_512K/mpconfigboard.h", - "version": "v1.12" + "path": "ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "ESP module with ESP8266", "port": "esp8266", - "board": "GENERIC", + "board": "ESP8266_GENERIC", "board_name": "ESP module", "mcu_name": "ESP8266", - "path": "ports/esp8266/boards/GENERIC/mpconfigboard.h", - "version": "v1.12" + "path": "ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "ESP32 module (spiram) with ESP32", @@ -267,7 +267,7 @@ "board_name": "ESP32 module (spiram)", "mcu_name": "ESP32", "path": "ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.h", - "version": "v1.12" + "version": "v1.20.0" }, { "description": "ESP32 module with ESP32", @@ -276,7 +276,7 @@ "board_name": "ESP32 module", "mcu_name": "ESP32", "path": "ports/esp32/boards/GENERIC/mpconfigboard.h", - "version": "v1.12" + "version": "v1.20.0" }, { "description": "ESP32 Unicore module with ESP32-UNICORE", @@ -294,7 +294,7 @@ "board_name": "-", "mcu_name": "-", "path": "ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "ESP32-S2-WROVER with ESP32-S2", @@ -303,7 +303,7 @@ "board_name": "ESP32-S2-WROVER", "mcu_name": "ESP32-S2", "path": "ports/esp32/boards/ESP32_S2_WROVER/mpconfigboard.h", - "version": "v1.18" + "version": "v1.20.0" }, { "description": "ESP32-UNICORE", @@ -312,16 +312,16 @@ "board_name": "-", "mcu_name": "-", "path": "ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "ESP32C3 module with ESP32C3", "port": "esp32", - "board": "GENERIC_C3", + "board": "ESP32_GENERIC_C3", "board_name": "ESP32C3 module", "mcu_name": "ESP32C3", - "path": "ports/esp32/boards/GENERIC_C3/mpconfigboard.h", - "version": "v1.17" + "path": "ports/esp32/boards/ESP32_GENERIC_C3/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "ESP32S2 module with ESP32S2", @@ -330,7 +330,7 @@ "board_name": "ESP32S2 module", "mcu_name": "ESP32S2", "path": "ports/esp32/boards/GENERIC_S2/mpconfigboard.h", - "version": "v1.15" + "version": "v1.20.0" }, { "description": "ESP32S3 module (spiram octal) with ESP32S3", @@ -348,7 +348,7 @@ "board_name": "ESP32S3 module (spiram)", "mcu_name": "ESP32S3", "path": "ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h", - "version": "v1.18" + "version": "v1.20.0" }, { "description": "ESP32S3 module with ESP32S3", @@ -357,7 +357,7 @@ "board_name": "ESP32S3 module", "mcu_name": "ESP32S3", "path": "ports/esp32/boards/GENERIC_S3/mpconfigboard.h", - "version": "v1.18" + "version": "v1.20.0" }, { "description": "Espruino Pico with STM32F401CD", @@ -366,25 +366,25 @@ "board_name": "Espruino Pico", "mcu_name": "STM32F401CD", "path": "ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "EVK_NINA_B1 with NRF52832", "port": "nrf", - "board": "evk_nina_b1", + "board": "EVK_NINA_B1", "board_name": "EVK_NINA_B1", "mcu_name": "NRF52832", - "path": "ports/nrf/boards/evk_nina_b1/mpconfigboard.h", - "version": "v1.12" + "path": "ports/nrf/boards/EVK_NINA_B1/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "EVK_NINA_B3 with NRF52840", "port": "nrf", - "board": "evk_nina_b3", + "board": "EVK_NINA_B3", "board_name": "EVK_NINA_B3", "mcu_name": "NRF52840", - "path": "ports/nrf/boards/evk_nina_b3/mpconfigboard.h", - "version": "v1.16" + "path": "ports/nrf/boards/EVK_NINA_B3/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "F411DISC with STM32F411", @@ -393,7 +393,7 @@ "board_name": "F411DISC", "mcu_name": "STM32F411", "path": "ports/stm32/boards/STM32F411DISC/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "F429I-DISCO with STM32F429", @@ -402,7 +402,7 @@ "board_name": "F429I-DISCO", "mcu_name": "STM32F429", "path": "ports/stm32/boards/STM32F429DISC/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "F4DISC with STM32F407", @@ -411,7 +411,7 @@ "board_name": "F4DISC", "mcu_name": "STM32F407", "path": "ports/stm32/boards/STM32F4DISC/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "F769DISC with STM32F769", @@ -420,7 +420,7 @@ "board_name": "F769DISC", "mcu_name": "STM32F769", "path": "ports/stm32/boards/STM32F769DISC/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "F7DISC with STM32F746", @@ -429,7 +429,7 @@ "board_name": "F7DISC", "mcu_name": "STM32F746", "path": "ports/stm32/boards/STM32F7DISC/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "Feather M0 Express with SAMD21G18A", @@ -438,7 +438,7 @@ "board_name": "Feather M0 Express", "mcu_name": "SAMD21G18A", "path": "ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "Feather M4 Express with SAMD51J19A", @@ -447,7 +447,7 @@ "board_name": "Feather M4 Express", "mcu_name": "SAMD51J19A", "path": "ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.22.0" }, { "description": "FeatherS2 Neo with ESP32-S2FN4R2", @@ -456,7 +456,7 @@ "board_name": "FeatherS2 Neo", "mcu_name": "ESP32-S2FN4R2", "path": "ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.h", - "version": "v1.18" + "version": "v1.22.0" }, { "description": "FeatherS2 with ESP32-S2", @@ -465,7 +465,7 @@ "board_name": "FeatherS2", "mcu_name": "ESP32-S2", "path": "ports/esp32/boards/UM_FEATHERS2/mpconfigboard.h", - "version": "v1.16" + "version": "v1.22.0" }, { "description": "FeatherS3 with ESP32-S3", @@ -474,7 +474,7 @@ "board_name": "FeatherS3", "mcu_name": "ESP32-S3", "path": "ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.22.0" }, { "description": "GARATRONIC_PYBSTICK26_RP2040", @@ -483,7 +483,7 @@ "board_name": "GARATRONIC_PYBSTICK26_RP2040", "mcu_name": "-", "path": "ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.h", - "version": "v1.18" + "version": "v1.22.0" }, { "description": "Generic ESP32 module with ESP32", @@ -492,7 +492,7 @@ "board_name": "Generic ESP32 module", "mcu_name": "ESP32", "path": "ports/esp32/boards/ESP32_GENERIC/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "Generic ESP32 module with OTA", @@ -501,7 +501,7 @@ "board_name": "-", "mcu_name": "-", "path": "ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "Generic ESP32 module with SPIRAM", @@ -510,7 +510,7 @@ "board_name": "-", "mcu_name": "-", "path": "ports/esp32/boards/ESP32_GENERIC/mpconfigboard.cmake", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "Generic ESP32-D2WD module with ESP32-D2WD", @@ -519,7 +519,7 @@ "board_name": "Generic ESP32-D2WD module", "mcu_name": "ESP32-D2WD", "path": "ports/esp32/boards/GENERIC_D2WD/mpconfigboard.h", - "version": "v1.12" + "version": "v1.20.0" }, { "description": "Generic ESP32S2 module with ESP32S2", @@ -528,7 +528,7 @@ "board_name": "Generic ESP32S2 module", "mcu_name": "ESP32S2", "path": "ports/esp32/boards/ESP32_GENERIC_S2/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "Generic ESP32S3 module with ESP32S3", @@ -537,7 +537,7 @@ "board_name": "Generic ESP32S3 module", "mcu_name": "ESP32S3", "path": "ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "Generic ESP32S3 module with Octal-SPIRAM", @@ -546,7 +546,7 @@ "board_name": "-", "mcu_name": "-", "path": "ports/esp32/boards/ESP32_GENERIC_S3/mpconfigboard.cmake", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "GIGA with STM32H747", @@ -555,7 +555,7 @@ "board_name": "GIGA", "mcu_name": "STM32H747", "path": "ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.21.0" }, { "description": "HydraBus1.0 with STM32F4", @@ -564,7 +564,7 @@ "board_name": "HydraBus1.0", "mcu_name": "STM32F4", "path": "ports/stm32/boards/HYDRABUS/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "i.MX RT1010 EVK with MIMXRT1011DAE5A", @@ -573,7 +573,7 @@ "board_name": "i.MX RT1010 EVK", "mcu_name": "MIMXRT1011DAE5A", "path": "ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h", - "version": "v1.13" + "version": "v1.22.0" }, { "description": "i.MX RT1015 EVK with MIMXRT1015DAF5A", @@ -582,7 +582,7 @@ "board_name": "i.MX RT1015 EVK", "mcu_name": "MIMXRT1015DAF5A", "path": "ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.22.0" }, { "description": "i.MX RT1020 EVK with MIMXRT1021DAG5A", @@ -591,7 +591,7 @@ "board_name": "i.MX RT1020 EVK", "mcu_name": "MIMXRT1021DAG5A", "path": "ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h", - "version": "v1.13" + "version": "v1.22.0" }, { "description": "i.MX RT1050 EVK with MIMXRT1052DVL6B", @@ -600,7 +600,7 @@ "board_name": "i.MX RT1050 EVK", "mcu_name": "MIMXRT1052DVL6B", "path": "ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h", - "version": "v1.15" + "version": "v1.17" }, { "description": "i.MX RT1050 EVKB with MIMXRT1052DVL6B", @@ -618,7 +618,7 @@ "board_name": "i.MX RT1050 EVKB-A1", "mcu_name": "MIMXRT1052DVL6B", "path": "ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h", - "version": "v1.18" + "version": "v1.22.0" }, { "description": "i.MX RT1060 EVK with MIMXRT1062DVJ6A", @@ -627,7 +627,7 @@ "board_name": "i.MX RT1060 EVK", "mcu_name": "MIMXRT1062DVJ6A", "path": "ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h", - "version": "v1.13" + "version": "v1.22.0" }, { "description": "i.MX RT1064 EVK with MIMXRT1064DVL6A", @@ -636,7 +636,7 @@ "board_name": "i.MX RT1064 EVK", "mcu_name": "MIMXRT1064DVL6A", "path": "ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h", - "version": "v1.14" + "version": "v1.22.0" }, { "description": "i.MX RT1170 EVK with MIMXRT1176DVMAA", @@ -645,25 +645,25 @@ "board_name": "i.MX RT1170 EVK", "mcu_name": "MIMXRT1176DVMAA", "path": "ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.22.0" }, { "description": "IBK-BLYST-NANO with NRF52832", "port": "nrf", - "board": "ibk_blyst_nano", + "board": "IBK_BLYST_NANO", "board_name": "IBK-BLYST-NANO", "mcu_name": "NRF52832", - "path": "ports/nrf/boards/ibk_blyst_nano/mpconfigboard.h", - "version": "v1.11" + "path": "ports/nrf/boards/IBK_BLYST_NANO/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "IDK-BLYST-NANO with NRF52832", "port": "nrf", - "board": "idk_blyst_nano", + "board": "IDK_BLYST_NANO", "board_name": "IDK-BLYST-NANO", "mcu_name": "NRF52832", - "path": "ports/nrf/boards/idk_blyst_nano/mpconfigboard.h", - "version": "v1.11" + "path": "ports/nrf/boards/IDK_BLYST_NANO/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "ItsyBitsy M0 Express with SAMD21G18A", @@ -672,7 +672,7 @@ "board_name": "ItsyBitsy M0 Express", "mcu_name": "SAMD21G18A", "path": "ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.22.0" }, { "description": "ItsyBitsy M4 Express with SAMD51G19A", @@ -681,7 +681,7 @@ "board_name": "ItsyBitsy M4 Express", "mcu_name": "SAMD51G19A", "path": "ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "L476-DISCO with STM32L476", @@ -690,7 +690,7 @@ "board_name": "L476-DISCO", "mcu_name": "STM32L476", "path": "ports/stm32/boards/STM32L476DISC/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "L496G-DISCO with STM32L496", @@ -699,7 +699,7 @@ "board_name": "L496G-DISCO", "mcu_name": "STM32L496", "path": "ports/stm32/boards/STM32L496GDISC/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "LaunchPad with CC3200", @@ -708,7 +708,7 @@ "board_name": "LaunchPad", "mcu_name": "CC3200", "path": "ports/cc3200/boards/LAUNCHXL/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "LEGO Technic Hub No.6 with STM32F413", @@ -717,7 +717,7 @@ "board_name": "LEGO Technic Hub No.6", "mcu_name": "STM32F413", "path": "ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h", - "version": "v1.17" + "version": "v1.22.0" }, { "description": "LEGO Technic Hub No.7 with STM32F413", @@ -726,7 +726,7 @@ "board_name": "LEGO Technic Hub No.7", "mcu_name": "STM32F413", "path": "ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.22.0" }, { "description": "LILYGO TTGO LoRa32 with ESP32", @@ -735,7 +735,7 @@ "board_name": "LILYGO TTGO LoRa32", "mcu_name": "ESP32", "path": "ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.22.0" }, { "description": "LIMIFROG with STM32L476", @@ -744,7 +744,7 @@ "board_name": "LIMIFROG", "mcu_name": "STM32L476", "path": "ports/stm32/boards/LIMIFROG/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "LOLIN_C3_MINI with ESP32-C3FH4", @@ -753,7 +753,7 @@ "board_name": "LOLIN_C3_MINI", "mcu_name": "ESP32-C3FH4", "path": "ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.22.0" }, { "description": "LOLIN_S2_MINI with ESP32-S2FN4R2", @@ -762,7 +762,7 @@ "board_name": "LOLIN_S2_MINI", "mcu_name": "ESP32-S2FN4R2", "path": "ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.h", - "version": "v1.18" + "version": "v1.22.0" }, { "description": "LOLIN_S2_PICO with ESP32-S2FN4R2", @@ -771,7 +771,7 @@ "board_name": "LOLIN_S2_PICO", "mcu_name": "ESP32-S2FN4R2", "path": "ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h", - "version": "v1.18" + "version": "v1.22.0" }, { "description": "M5Stack ATOM with ESP32-PICO-D4", @@ -780,16 +780,16 @@ "board_name": "M5Stack ATOM", "mcu_name": "ESP32-PICO-D4", "path": "ports/esp32/boards/M5STACK_ATOM/mpconfigboard.h", - "version": "v1.16" + "version": "v1.22.0" }, { "description": "MDK-USB-DONGLE with NRF52840", "port": "nrf", - "board": "nrf52840-mdk-usb-dongle", + "board": "NRF52840_MDK_USB_DONGLE", "board_name": "MDK-USB-DONGLE", "mcu_name": "NRF52840", - "path": "ports/nrf/boards/nrf52840-mdk-usb-dongle/mpconfigboard.h", - "version": "v1.13" + "path": "ports/nrf/boards/NRF52840_MDK_USB_DONGLE/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "Metro M4 Express Airlift with SAMD51J19A", @@ -798,16 +798,16 @@ "board_name": "Metro M4 Express Airlift", "mcu_name": "SAMD51J19A", "path": "ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "micro:bit with NRF51822", "port": "nrf", - "board": "microbit", + "board": "MICROBIT", "board_name": "micro:bit", "mcu_name": "NRF51822", - "path": "ports/nrf/boards/microbit/mpconfigboard.h", - "version": "v1.10" + "path": "ports/nrf/boards/MICROBIT/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "MikroE Quail with STM32F427VI", @@ -816,7 +816,7 @@ "board_name": "MikroE Quail", "mcu_name": "STM32F427VI", "path": "ports/stm32/boards/MIKROE_QUAIL/mpconfigboard.h", - "version": "v1.18" + "version": "v1.22.0" }, { "description": "MIKROE_CLICKER2_STM32 with STM32F407", @@ -825,7 +825,7 @@ "board_name": "MIKROE_CLICKER2_STM32", "mcu_name": "STM32F407", "path": "ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "Mini SAM M4 with SAMD51G19A", @@ -834,16 +834,16 @@ "board_name": "Mini SAM M4", "mcu_name": "SAMD51G19A", "path": "ports/samd/boards/MINISAM_M4/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "NADHAT_PYBF405 with STM32F405RG", "port": "stm32", - "board": "NADHAT_PYBF405", + "board": "GARATRONIC_NADHAT_F405", "board_name": "NADHAT_PYBF405", "mcu_name": "STM32F405RG", - "path": "ports/stm32/boards/NADHAT_PYBF405/mpconfigboard.h", - "version": "v1.12" + "path": "ports/stm32/boards/GARATRONIC_NADHAT_F405/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "NanoS3 with ESP32-S3-FN8", @@ -852,7 +852,7 @@ "board_name": "NanoS3", "mcu_name": "ESP32-S3-FN8", "path": "ports/esp32/boards/UM_NANOS3/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "NetduinoPlus2 with STM32F405RG", @@ -861,7 +861,7 @@ "board_name": "NetduinoPlus2", "mcu_name": "STM32F405RG", "path": "ports/stm32/boards/NETDUINO_PLUS_2/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "NICLAVISION with STM32H747", @@ -870,7 +870,7 @@ "board_name": "NICLAVISION", "mcu_name": "STM32H747", "path": "ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.21.0" }, { "description": "NUCLEO-F091RC with STM32F091RCT6", @@ -879,7 +879,7 @@ "board_name": "NUCLEO-F091RC", "mcu_name": "STM32F091RCT6", "path": "ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "NUCLEO-F401RE with STM32F401xE", @@ -888,7 +888,7 @@ "board_name": "NUCLEO-F401RE", "mcu_name": "STM32F401xE", "path": "ports/stm32/boards/NUCLEO_F401RE/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "NUCLEO-F411RE with STM32F411xE", @@ -897,7 +897,7 @@ "board_name": "NUCLEO-F411RE", "mcu_name": "STM32F411xE", "path": "ports/stm32/boards/NUCLEO_F411RE/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "NUCLEO-F412ZG with STM32F412Zx", @@ -906,7 +906,7 @@ "board_name": "NUCLEO-F412ZG", "mcu_name": "STM32F412Zx", "path": "ports/stm32/boards/NUCLEO_F412ZG/mpconfigboard.h", - "version": "v1.13" + "version": "v1.22.0" }, { "description": "NUCLEO-F413ZH with STM32F413", @@ -915,7 +915,7 @@ "board_name": "NUCLEO-F413ZH", "mcu_name": "STM32F413", "path": "ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.h", - "version": "v1.11" + "version": "v1.22.0" }, { "description": "NUCLEO-F429ZI with STM32F429", @@ -924,7 +924,7 @@ "board_name": "NUCLEO-F429ZI", "mcu_name": "STM32F429", "path": "ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "NUCLEO-F439ZI with STM32F439ZIT6", @@ -933,7 +933,7 @@ "board_name": "NUCLEO-F439ZI", "mcu_name": "STM32F439ZIT6", "path": "ports/stm32/boards/NUCLEO_F439ZI/mpconfigboard.h", - "version": "v1.17" + "version": "v1.22.0" }, { "description": "NUCLEO-F446RE with STM32F446xx", @@ -942,7 +942,7 @@ "board_name": "NUCLEO-F446RE", "mcu_name": "STM32F446xx", "path": "ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "NUCLEO-F722ZE with STM32F722", @@ -951,7 +951,7 @@ "board_name": "NUCLEO-F722ZE", "mcu_name": "STM32F722", "path": "ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "NUCLEO-F746ZG with STM32F746", @@ -960,7 +960,7 @@ "board_name": "NUCLEO-F746ZG", "mcu_name": "STM32F746", "path": "ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "NUCLEO-F756ZG with STM32F756", @@ -969,7 +969,7 @@ "board_name": "NUCLEO-F756ZG", "mcu_name": "STM32F756", "path": "ports/stm32/boards/NUCLEO_F756ZG/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.22.0" }, { "description": "NUCLEO-F767ZI with STM32F767", @@ -978,7 +978,7 @@ "board_name": "NUCLEO-F767ZI", "mcu_name": "STM32F767", "path": "ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "NUCLEO-G0B1RE with STM32G0B1xE", @@ -987,7 +987,7 @@ "board_name": "NUCLEO-G0B1RE", "mcu_name": "STM32G0B1xE", "path": "ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.22.0" }, { "description": "NUCLEO-L073RZ with STM32L073RZT6", @@ -996,7 +996,7 @@ "board_name": "NUCLEO-L073RZ", "mcu_name": "STM32L073RZT6", "path": "ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "NUCLEO-L152RE with STM32L152xE", @@ -1005,7 +1005,7 @@ "board_name": "NUCLEO-L152RE", "mcu_name": "STM32L152xE", "path": "ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.22.0" }, { "description": "NUCLEO-L432KC with STM32L432KC", @@ -1014,7 +1014,7 @@ "board_name": "NUCLEO-L432KC", "mcu_name": "STM32L432KC", "path": "ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "NUCLEO-L452RE with STM32L452RE", @@ -1023,7 +1023,7 @@ "board_name": "NUCLEO-L452RE", "mcu_name": "STM32L452RE", "path": "ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "NUCLEO-L476RG with STM32L476RG", @@ -1032,7 +1032,7 @@ "board_name": "NUCLEO-L476RG", "mcu_name": "STM32L476RG", "path": "ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "NUCLEO-L4A6ZG with STM32L4A6ZG", @@ -1041,7 +1041,7 @@ "board_name": "NUCLEO-L4A6ZG", "mcu_name": "STM32L4A6ZG", "path": "ports/stm32/boards/NUCLEO_L4A6ZG/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "NUCLEO-WB55 with STM32WB55RGV6", @@ -1050,7 +1050,7 @@ "board_name": "NUCLEO-WB55", "mcu_name": "STM32WB55RGV6", "path": "ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "NUCLEO-WL55 with STM32WL55JCI7", @@ -1059,7 +1059,7 @@ "board_name": "NUCLEO-WL55", "mcu_name": "STM32WL55JCI7", "path": "ports/stm32/boards/NUCLEO_WL55/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.22.0" }, { "description": "NUCLEO_G474RE with STM32G474", @@ -1068,7 +1068,7 @@ "board_name": "NUCLEO_G474RE", "mcu_name": "STM32G474", "path": "ports/stm32/boards/NUCLEO_G474RE/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.22.0" }, { "description": "NUCLEO_H563ZI with STM32H563ZI", @@ -1086,7 +1086,7 @@ "board_name": "NUCLEO_H723ZG", "mcu_name": "STM32H723ZGT6", "path": "ports/stm32/boards/NUCLEO_H723ZG/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.22.0" }, { "description": "NUCLEO_H743ZI with STM32H743", @@ -1095,7 +1095,7 @@ "board_name": "NUCLEO_H743ZI", "mcu_name": "STM32H743", "path": "ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "NUCLEO_H743ZI2", @@ -1104,7 +1104,7 @@ "board_name": "NUCLEO_H743ZI2", "mcu_name": "-", "path": "ports/stm32/boards/NUCLEO_H743ZI2/mpconfigboard.h", - "version": "v1.17" + "version": "v1.22.0" }, { "description": "nullbits Bit-C PRO", @@ -1113,7 +1113,7 @@ "board_name": "nullbits Bit-C PRO", "mcu_name": "-", "path": "ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.22.0" }, { "description": "Olimex ESP32 ETH with ESP32", @@ -1122,7 +1122,7 @@ "board_name": "Olimex ESP32 ETH", "mcu_name": "ESP32", "path": "ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.22.0" }, { "description": "OLIMEX STM32-E407 with STM32F407", @@ -1131,7 +1131,7 @@ "board_name": "OLIMEX STM32-E407", "mcu_name": "STM32F407", "path": "ports/stm32/boards/OLIMEX_E407/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "OLIMEX STM32-H407 with STM32F407", @@ -1140,79 +1140,79 @@ "board_name": "OLIMEX STM32-H407", "mcu_name": "STM32F407", "path": "ports/stm32/boards/OLIMEX_H407/mpconfigboard.h", - "version": "v1.18" + "version": "v1.22.0" }, { "description": "PCA10000 with NRF51822", "port": "nrf", - "board": "pca10000", + "board": "PCA10000", "board_name": "PCA10000", "mcu_name": "NRF51822", - "path": "ports/nrf/boards/pca10000/mpconfigboard.h", - "version": "v1.10" + "path": "ports/nrf/boards/PCA10000/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "PCA10001 with NRF51822", "port": "nrf", - "board": "pca10001", + "board": "PCA10001", "board_name": "PCA10001", "mcu_name": "NRF51822", - "path": "ports/nrf/boards/pca10001/mpconfigboard.h", - "version": "v1.10" + "path": "ports/nrf/boards/PCA10001/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "PCA10028 with NRF51822", "port": "nrf", - "board": "pca10028", + "board": "PCA10028", "board_name": "PCA10028", "mcu_name": "NRF51822", - "path": "ports/nrf/boards/pca10028/mpconfigboard.h", - "version": "v1.10" + "path": "ports/nrf/boards/PCA10028/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "PCA10031 with NRF51822", "port": "nrf", - "board": "pca10031", + "board": "PCA10031", "board_name": "PCA10031", "mcu_name": "NRF51822", - "path": "ports/nrf/boards/pca10031/mpconfigboard.h", - "version": "v1.10" + "path": "ports/nrf/boards/PCA10031/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "PCA10040 with NRF52832", "port": "nrf", - "board": "pca10040", + "board": "PCA10040", "board_name": "PCA10040", "mcu_name": "NRF52832", - "path": "ports/nrf/boards/pca10040/mpconfigboard.h", - "version": "v1.10" + "path": "ports/nrf/boards/PCA10040/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "PCA10056 with NRF52840", "port": "nrf", - "board": "pca10056", + "board": "PCA10056", "board_name": "PCA10056", "mcu_name": "NRF52840", - "path": "ports/nrf/boards/pca10056/mpconfigboard.h", - "version": "v1.10" + "path": "ports/nrf/boards/PCA10056/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "PCA10059 with NRF52840", "port": "nrf", - "board": "pca10059", + "board": "PCA10059", "board_name": "PCA10059", "mcu_name": "NRF52840", - "path": "ports/nrf/boards/pca10059/mpconfigboard.h", - "version": "v1.12" + "path": "ports/nrf/boards/PCA10059/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "PCA10090 with NRF9160", "port": "nrf", - "board": "pca10090", + "board": "PCA10090", "board_name": "PCA10090", "mcu_name": "NRF9160", - "path": "ports/nrf/boards/pca10090/mpconfigboard.h", - "version": "v1.12" + "path": "ports/nrf/boards/PCA10090/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "Pimoroni Pico LiPo 16MB", @@ -1221,7 +1221,7 @@ "board_name": "Pimoroni Pico LiPo 16MB", "mcu_name": "-", "path": "ports/rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h", - "version": "v1.17" + "version": "v1.22.0" }, { "description": "Pimoroni Pico LiPo 4MB", @@ -1230,7 +1230,7 @@ "board_name": "Pimoroni Pico LiPo 4MB", "mcu_name": "-", "path": "ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h", - "version": "v1.17" + "version": "v1.22.0" }, { "description": "Pimoroni Tiny 2040", @@ -1239,7 +1239,7 @@ "board_name": "Pimoroni Tiny 2040", "mcu_name": "-", "path": "ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h", - "version": "v1.17" + "version": "v1.22.0" }, { "description": "Pololu 3pi+ 2040 Robot", @@ -1275,7 +1275,7 @@ "board_name": "PORTENTA", "mcu_name": "STM32H747", "path": "ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.21.0" }, { "description": "ProS3 with ESP32-S3", @@ -1284,7 +1284,7 @@ "board_name": "ProS3", "mcu_name": "ESP32-S3", "path": "ports/esp32/boards/UM_PROS3/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.22.0" }, { "description": "PYBD-SF2W with STM32F722IEK", @@ -1293,7 +1293,7 @@ "board_name": "PYBD-SF2W", "mcu_name": "STM32F722IEK", "path": "ports/stm32/boards/PYBD_SF2/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "PYBD-SF3W with STM32F733IEK", @@ -1302,7 +1302,7 @@ "board_name": "PYBD-SF3W", "mcu_name": "STM32F733IEK", "path": "ports/stm32/boards/PYBD_SF3/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "PYBD-SF6W with STM32F767IIK", @@ -1311,7 +1311,7 @@ "board_name": "PYBD-SF6W", "mcu_name": "STM32F767IIK", "path": "ports/stm32/boards/PYBD_SF6/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "PYBLITEv1.0 with STM32F411RE", @@ -1320,7 +1320,7 @@ "board_name": "PYBLITEv1.0", "mcu_name": "STM32F411RE", "path": "ports/stm32/boards/PYBLITEV10/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "PYBSTICK26_STD with STM32F411RE", @@ -1329,7 +1329,7 @@ "board_name": "PYBSTICK26_STD", "mcu_name": "STM32F411RE", "path": "ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/mpconfigboard.h", - "version": "v1.18" + "version": "v1.22.0" }, { "description": "PYBv1.0 with STM32F405RG", @@ -1338,7 +1338,7 @@ "board_name": "PYBv1.0", "mcu_name": "STM32F405RG", "path": "ports/stm32/boards/PYBV10/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "PYBv1.1 with STM32F405RG", @@ -1347,7 +1347,7 @@ "board_name": "PYBv1.1", "mcu_name": "STM32F405RG", "path": "ports/stm32/boards/PYBV11/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "PYBv3 with STM32F405RG", @@ -1356,7 +1356,7 @@ "board_name": "PYBv3", "mcu_name": "STM32F405RG", "path": "ports/stm32/boards/PYBV3/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "PYBv4 with STM32F405RG", @@ -1365,7 +1365,7 @@ "board_name": "PYBv4", "mcu_name": "STM32F405RG", "path": "ports/stm32/boards/PYBV4/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "RA4M1 CLICKER with RA4M1", @@ -1374,7 +1374,7 @@ "board_name": "RA4M1 CLICKER", "mcu_name": "RA4M1", "path": "ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "RA4M1_CLICKER with RA4M1", @@ -1383,7 +1383,7 @@ "board_name": "RA4M1_CLICKER", "mcu_name": "RA4M1", "path": "ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.20.0" }, { "description": "RA4M1_EK with RA4M1", @@ -1392,7 +1392,7 @@ "board_name": "RA4M1_EK", "mcu_name": "RA4M1", "path": "ports/renesas-ra/boards/RA4M1_EK/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.20.0" }, { "description": "RA4W1_EK with RA4W1", @@ -1401,7 +1401,7 @@ "board_name": "RA4W1_EK", "mcu_name": "RA4W1", "path": "ports/renesas-ra/boards/RA4W1_EK/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.20.0" }, { "description": "RA6M1_EK with RA6M1", @@ -1410,7 +1410,7 @@ "board_name": "RA6M1_EK", "mcu_name": "RA6M1", "path": "ports/renesas-ra/boards/RA6M1_EK/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.20.0" }, { "description": "RA6M2_EK with RA6M2", @@ -1419,25 +1419,25 @@ "board_name": "RA6M2_EK", "mcu_name": "RA6M2", "path": "ports/renesas-ra/boards/RA6M2_EK/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.20.0" }, { "description": "Raspberry Pi Pico", "port": "rp2", - "board": "PICO", + "board": "RPI_PICO", "board_name": "Raspberry Pi Pico", "mcu_name": "-", - "path": "ports/rp2/boards/PICO/mpconfigboard.h", - "version": "v1.15" + "path": "ports/rp2/boards/RPI_PICO/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "Raspberry Pi Pico W", "port": "rp2", - "board": "PICO_W", + "board": "RPI_PICO_W", "board_name": "Raspberry Pi Pico W", "mcu_name": "-", - "path": "ports/rp2/boards/PICO_W/mpconfigboard.h", - "version": "v1.20.0" + "path": "ports/rp2/boards/RPI_PICO_W/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "RT1010-Py-DevKIT with MIMXRT1011DAE5A", @@ -1446,7 +1446,7 @@ "board_name": "RT1010-Py-DevKIT", "mcu_name": "MIMXRT1011DAE5A", "path": "ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.22.0" }, { "description": "SAMD21-XPLAINED-PRO with SAMD21J18A", @@ -1455,7 +1455,7 @@ "board_name": "SAMD21-XPLAINED-PRO", "mcu_name": "SAMD21J18A", "path": "ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "Seeed ARCH MIX with MIMXRT1052DVL5B", @@ -1464,16 +1464,16 @@ "board_name": "Seeed ARCH MIX", "mcu_name": "MIMXRT1052DVL5B", "path": "ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h", - "version": "v1.18" + "version": "v1.22.0" }, { "description": "Seeed Xiao with SAMD21G18A", "port": "samd", - "board": "SEEED_XIAO", + "board": "SEEED_XIAO_SAMD21", "board_name": "Seeed Xiao", "mcu_name": "SAMD21G18A", - "path": "ports/samd/boards/SEEED_XIAO/mpconfigboard.h", - "version": "v1.18" + "path": "ports/samd/boards/SEEED_XIAO_SAMD21/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "Silicognition RP2040-Shim", @@ -1491,7 +1491,7 @@ "board_name": "Silicognition wESP32", "mcu_name": "ESP32", "path": "ports/esp32/boards/SIL_WESP32/mpconfigboard.h", - "version": "v1.17" + "version": "v1.22.0" }, { "description": "SparkFun Pro Micro RP2040", @@ -1500,7 +1500,7 @@ "board_name": "SparkFun Pro Micro RP2040", "mcu_name": "-", "path": "ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h", - "version": "v1.16" + "version": "v1.22.0" }, { "description": "Sparkfun SAMD51 Thing Plus with SAMD51J20A", @@ -1509,7 +1509,7 @@ "board_name": "Sparkfun SAMD51 Thing Plus", "mcu_name": "SAMD51J20A", "path": "ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.22.0" }, { "description": "SparkFun STM32 MicroMod Processor with STM32F405RG", @@ -1518,7 +1518,7 @@ "board_name": "SparkFun STM32 MicroMod Processor", "mcu_name": "STM32F405RG", "path": "ports/stm32/boards/SPARKFUN_MICROMOD_STM32/mpconfigboard.h", - "version": "v1.17" + "version": "v1.22.0" }, { "description": "SparkFun Thing Plus RP2040", @@ -1527,7 +1527,7 @@ "board_name": "SparkFun Thing Plus RP2040", "mcu_name": "-", "path": "ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h", - "version": "v1.16" + "version": "v1.22.0" }, { "description": "STM32H573I-DK with STM32H573IIK3Q", @@ -1536,7 +1536,7 @@ "board_name": "STM32H573I-DK", "mcu_name": "STM32H573IIK3Q", "path": "ports/stm32/boards/STM32H573I_DK/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "STM32H7B3I-DK with STM32H7B3LIH6Q", @@ -1545,7 +1545,7 @@ "board_name": "STM32H7B3I-DK", "mcu_name": "STM32H7B3LIH6Q", "path": "ports/stm32/boards/STM32H7B3I_DK/mpconfigboard.h", - "version": "v1.18" + "version": "v1.22.0" }, { "description": "Teensy 4.0 with MIMXRT1062DVJ6A", @@ -1554,7 +1554,7 @@ "board_name": "Teensy 4.0", "mcu_name": "MIMXRT1062DVJ6A", "path": "ports/mimxrt/boards/TEENSY40/mpconfigboard.h", - "version": "v1.13" + "version": "v1.22.0" }, { "description": "Teensy 4.1 with MIMXRT1062DVJ6A", @@ -1563,16 +1563,16 @@ "board_name": "Teensy 4.1", "mcu_name": "MIMXRT1062DVJ6A", "path": "ports/mimxrt/boards/TEENSY41/mpconfigboard.h", - "version": "v1.16" + "version": "v1.22.0" }, { "description": "TinyPICO with ESP32-PICO-D4", "port": "esp32", - "board": "TINYPICO", + "board": "UM_TINYPICO", "board_name": "TinyPICO", "mcu_name": "ESP32-PICO-D4", - "path": "ports/esp32/boards/TINYPICO/mpconfigboard.h", - "version": "v1.12" + "path": "ports/esp32/boards/UM_TINYPICO/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "TinyS2 with ESP32-S2FN4R2", @@ -1581,7 +1581,7 @@ "board_name": "TinyS2", "mcu_name": "ESP32-S2FN4R2", "path": "ports/esp32/boards/UM_TINYS2/mpconfigboard.h", - "version": "v1.16" + "version": "v1.22.0" }, { "description": "TinyS3 with ESP32-S3-FN8", @@ -1590,7 +1590,7 @@ "board_name": "TinyS3", "mcu_name": "ESP32-S3-FN8", "path": "ports/esp32/boards/UM_TINYS3/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.22.0" }, { "description": "TinyWATCH S3 with ESP32-S3-PICO-1-N8R2", @@ -1608,7 +1608,7 @@ "board_name": "Trinket M0", "mcu_name": "SAMD21E18A", "path": "ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "USBDongle-WB55 with STM32WB55CGU6", @@ -1617,7 +1617,7 @@ "board_name": "USBDongle-WB55", "mcu_name": "STM32WB55CGU6", "path": "ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h", - "version": "v1.12" + "version": "v1.22.0" }, { "description": "VCC-GND STM32F407VE with STM32F407VE", @@ -1626,7 +1626,7 @@ "board_name": "VCC-GND STM32F407VE", "mcu_name": "STM32F407VE", "path": "ports/stm32/boards/VCC_GND_F407VE/mpconfigboard.h", - "version": "v1.16" + "version": "v1.22.0" }, { "description": "VCC-GND STM32F407ZG with STM32F407ZG", @@ -1635,7 +1635,7 @@ "board_name": "VCC-GND STM32F407ZG", "mcu_name": "STM32F407ZG", "path": "ports/stm32/boards/VCC_GND_F407ZG/mpconfigboard.h", - "version": "v1.16" + "version": "v1.22.0" }, { "description": "VCC-GND STM32H743VI with STM32H743VI", @@ -1644,7 +1644,7 @@ "board_name": "VCC-GND STM32H743VI", "mcu_name": "STM32H743VI", "path": "ports/stm32/boards/VCC_GND_H743VI/mpconfigboard.h", - "version": "v1.18" + "version": "v1.22.0" }, { "description": "VK-RA6M5 with RA6M5", @@ -1653,7 +1653,7 @@ "board_name": "VK-RA6M5", "mcu_name": "RA6M5", "path": "ports/renesas-ra/boards/VK_RA6M5/mpconfigboard.h", - "version": "v1.21.0" + "version": "v1.22.0" }, { "description": "W5100S-EVB-Pico", @@ -1662,7 +1662,7 @@ "board_name": "W5100S-EVB-Pico", "mcu_name": "-", "path": "ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.h", - "version": "v1.19.1" + "version": "v1.22.0" }, { "description": "W5500-EVB-Pico", @@ -1671,7 +1671,7 @@ "board_name": "W5500-EVB-Pico", "mcu_name": "-", "path": "ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.22.0" }, { "description": "WeAct Studio RP2040", @@ -1680,7 +1680,7 @@ "board_name": "WeAct Studio RP2040", "mcu_name": "-", "path": "ports/rp2/boards/WEACTSTUDIO/mpconfigboard.h", - "version": "v1.20.0" + "version": "v1.22.0" }, { "description": "Wio Terminal D51R with SAMD51P19A", @@ -1689,7 +1689,7 @@ "board_name": "Wio Terminal D51R", "mcu_name": "SAMD51P19A", "path": "ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h", - "version": "v1.18" + "version": "v1.22.0" }, { "description": "WiPy with CC3200", @@ -1698,33 +1698,33 @@ "board_name": "WiPy", "mcu_name": "CC3200", "path": "ports/cc3200/boards/WIPY/mpconfigboard.h", - "version": "v1.10" + "version": "v1.22.0" }, { "description": "WT51822-S4AT with NRF51822", "port": "nrf", - "board": "wt51822_s4at", + "board": "WT51822_S4AT", "board_name": "WT51822-S4AT", "mcu_name": "NRF51822", - "path": "ports/nrf/boards/wt51822_s4at/mpconfigboard.h", - "version": "v1.10" + "path": "ports/nrf/boards/WT51822_S4AT/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "XENON with NRF52840", "port": "nrf", - "board": "particle_xenon", + "board": "PARTICLE_XENON", "board_name": "XENON", "mcu_name": "NRF52840", - "path": "ports/nrf/boards/particle_xenon/mpconfigboard.h", - "version": "v1.12" + "path": "ports/nrf/boards/PARTICLE_XENON/mpconfigboard.h", + "version": "v1.22.0" }, { "description": "XIAO nRF52840 Sense with NRF52840", "port": "nrf", - "board": "seeed_xiao_nrf52", + "board": "SEEED_XIAO_NRF52", "board_name": "XIAO nRF52840 Sense", "mcu_name": "NRF52840", - "path": "ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.h", - "version": "v1.20.0" + "path": "ports/nrf/boards/SEEED_XIAO_NRF52/mpconfigboard.h", + "version": "v1.22.0" } ] \ No newline at end of file From 24ca8ab29d15702089ce88f8af462f7bea6c1612 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Wed, 3 Jan 2024 12:36:21 +0100 Subject: [PATCH 21/68] Add notebook to flash most MCUs in bulk Signed-off-by: Jos Verlinde --- scripts/flash.ipynb | 352 +++++++++++++++++--------------------------- 1 file changed, 139 insertions(+), 213 deletions(-) diff --git a/scripts/flash.ipynb b/scripts/flash.ipynb index e0ca14264..a0814ed6f 100644 --- a/scripts/flash.ipynb +++ b/scripts/flash.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 44, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -11,48 +11,7 @@ }, { "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[{'port': 'esp32',\n", - " 'build': '',\n", - " 'arch': 'xtensawin',\n", - " 'family': 'micropython',\n", - " 'board': 'Generic ESP32S3 module with ESP32S3',\n", - " 'cpu': 'ESP32S3',\n", - " 'version': '1.22.0.',\n", - " 'mpy': 'v6.2',\n", - " 'ver': 'v1.22.0.',\n", - " 'serial_port': 'COM8'}]" - ] - }, - "execution_count": 45, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "devs = %mpy --list\n", - "ports = devs.fields(0) # list of ports\n", - "# build a list of dicts with info for each port and attached board \n", - "dev_info = []\n", - "for p in ports:\n", - " info = %mpy --select {p} --info\n", - " if info:\n", - " dev_info.append(info)\n", - "\n", - "target_version = \"1.22.0\"\n", - "# filter \n", - "# dev_info = [d for d in dev_info if d[\"version\"].rstrip(\".\") != target_version]\n", - "dev_info" - ] - }, - { - "cell_type": "code", - "execution_count": 46, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -73,6 +32,11 @@ " return None\n", " v_str = f\"v{version}\"\n", " ext = PORT_FWTYPES[port]\n", + " if port == \"rp2\":\n", + " # PICO boards were renamed to RPI_PICO starting @v1.22.0 for all versions on the download page\n", + " if board.startswith(\"PICO\"):\n", + " board = f\"RPI_{board}\"\n", + "\n", " fw_files = list(fw_folder.glob(f\"{board}-{v_str}{ext}\"))\n", " if not fw_files:\n", " print(f\"No firmware files found for {v_str}\")\n", @@ -89,7 +53,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -164,79 +128,19 @@ " return False\n", " finally:\n", " del lines\n", - " gc.collect()\n", - "\n", - "\n", - "def find_board_old(info: dict, descr: str, filename: str, short_descr: str):\n", - " \"Find the board in the provided board_info.csv file\"\n", - " short_hit = \"\"\n", - " with open(filename, \"r\") as file:\n", - " # ugly code to make testable in python and micropython\n", - " # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file)\n", - " while 1:\n", - " line = file.readline()\n", - " if not line:\n", - " break\n", - " descr_, board_ = line.split(\",\")[0].strip(), line.split(\",\")[1].strip()\n", - " if descr_ == descr:\n", - " info[\"board\"] = board_\n", - " return True\n", - " elif short_descr and descr_ == short_descr:\n", - " if \"with\" in short_descr:\n", - " # Good enough - no need to trawl the entire file\n", - " info[\"board\"] = board_\n", - " return True\n", - " # good enough if not found in the rest of the file (but slow)\n", - " short_hit = board_\n", - " if short_hit:\n", - " info[\"board\"] = short_hit\n", - " return True\n", - " return False" + " gc.collect()" ] }, { "cell_type": "code", - "execution_count": 48, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "searching info file: ../src/stubber/data/board_info.csv for: 'Generic ESP32S3 module with ESP32S3' \n" - ] - }, - { - "data": { - "text/plain": [ - "(WindowsPath('c:/develop/MyPython/micropython-stubber/scripts/firmware/esp32/ESP32_GENERIC_S3-v1.22.0.bin'),\n", - " {'port': 'esp32',\n", - " 'build': '',\n", - " 'arch': 'xtensawin',\n", - " 'family': 'micropython',\n", - " 'board': 'ESP32_GENERIC_S3',\n", - " 'cpu': 'ESP32S3',\n", - " 'version': '1.22.0.',\n", - " 'mpy': 'v6.2',\n", - " 'ver': 'v1.22.0.',\n", - " 'serial_port': 'COM8'})" - ] - }, - "execution_count": 48, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "mcu = dev_info.pop()\n", - "read_boardname(mcu)\n", - "fw_file = find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"]).__next__()\n", - "fw_file, mcu" - ] + "outputs": [], + "source": [] }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -279,7 +183,7 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ @@ -308,125 +212,147 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "{'port': 'esp32', 'build': '', 'arch': 'xtensawin', 'family': 'micropython', 'board': 'ESP32_GENERIC_S3', 'cpu': 'ESP32S3', 'version': '1.22.0.', 'mpy': 'v6.2', 'ver': 'v1.22.0.', 'serial_port': 'COM8'}\n", - "Flashing c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\esp32\\ESP32_GENERIC_S3-v1.22.0.bin on ESP32_GENERIC_S3 on COM8\n", - "esptool.py v4.6.2\n", - "Serial port COM8\n", - "Connecting....\n", - "Chip is ESP32-S3 (revision v0.1)\n", - "Features: WiFi, BLE\n", - "Crystal is 40MHz\n", - "MAC: f4:12:fa:81:3b:8c\n", - "Uploading stub...\n", - "Running stub...\n", - "Stub running...\n", - "Changing baud rate to 2000000\n", - "Changed.\n", - "Configuring flash size...\n", - "Flash will be erased from 0x00000000 to 0x0018dfff...\n", - "Compressed 1628240 bytes to 1066966...\n", - "Writing at 0x00000000... (1 %)\n", - "Writing at 0x0001248d... (3 %)\n", - "Writing at 0x0001a1cd... (4 %)\n", - "Writing at 0x00021df4... (6 %)\n", - "Writing at 0x000283d4... (7 %)\n", - "Writing at 0x00032609... (9 %)\n", - "Writing at 0x00041899... (10 %)\n", - "Writing at 0x000476af... (12 %)\n", - "Writing at 0x00051717... (13 %)\n", - "Writing at 0x0005973a... (15 %)\n", - "Writing at 0x0005efe8... (16 %)\n", - "Writing at 0x000645b0... (18 %)\n", - "Writing at 0x00069dcf... (19 %)\n", - "Writing at 0x0006eea8... (21 %)\n", - "Writing at 0x000740f2... (22 %)\n", - "Writing at 0x000791ec... (24 %)\n", - "Writing at 0x0007e1ae... (25 %)\n", - "Writing at 0x00083403... (27 %)\n", - "Writing at 0x00088073... (28 %)\n", - "Writing at 0x0008cce9... (30 %)\n", - "Writing at 0x000933e6... (31 %)\n", - "Writing at 0x00098b29... (33 %)\n", - "Writing at 0x0009e6b2... (34 %)\n", - "Writing at 0x000a3f27... (36 %)\n", - "Writing at 0x000a92ac... (37 %)\n", - "Writing at 0x000af11a... (39 %)\n", - "Writing at 0x000b47d1... (40 %)\n", - "Writing at 0x000b9c29... (42 %)\n", - "Writing at 0x000bf40f... (43 %)\n", - "Writing at 0x000c4bbc... (45 %)\n", - "Writing at 0x000ca15b... (46 %)\n", - "Writing at 0x000cf23f... (48 %)\n", - "Writing at 0x000d4db4... (50 %)\n", - "Writing at 0x000da894... (51 %)\n", - "Writing at 0x000e0416... (53 %)\n", - "Writing at 0x000e6797... (54 %)\n", - "Writing at 0x000ebcef... (56 %)\n", - "Writing at 0x000f0c28... (57 %)\n", - "Writing at 0x000f5f2f... (59 %)\n", - "Writing at 0x000fae99... (60 %)\n", - "Writing at 0x00100475... (62 %)\n", - "Writing at 0x00105738... (63 %)\n", - "Writing at 0x0010ac09... (65 %)\n", - "Writing at 0x0010fcea... (66 %)\n", - "Writing at 0x00115378... (68 %)\n", - "Writing at 0x0011b934... (69 %)\n", - "Writing at 0x001208ba... (71 %)\n", - "Writing at 0x00125ba2... (72 %)\n", - "Writing at 0x0012b207... (74 %)\n", - "Writing at 0x00130579... (75 %)\n", - "Writing at 0x00135c0a... (77 %)\n", - "Writing at 0x0013afcf... (78 %)\n", - "Writing at 0x0013ff1a... (80 %)\n", - "Writing at 0x00144fca... (81 %)\n", - "Writing at 0x0014a084... (83 %)\n", - "Writing at 0x0014f380... (84 %)\n", - "Writing at 0x00154754... (86 %)\n", - "Writing at 0x0015a0e8... (87 %)\n", - "Writing at 0x0015f7bc... (89 %)\n", - "Writing at 0x001655b4... (90 %)\n", - "Writing at 0x0016e1f4... (92 %)\n", - "Writing at 0x0017614c... (93 %)\n", - "Writing at 0x0017ba83... (95 %)\n", - "Writing at 0x001810e8... (96 %)\n", - "Writing at 0x00186b0a... (98 %)\n", - "Writing at 0x0018caf6... (100 %)\n", - "Wrote 1628240 bytes (1066966 compressed) at 0x00000000 in 17.3 seconds (effective 751.2 kbit/s)...\n", - "Hash of data verified.\n", - "\n", - "Leaving...\n", - "Hard resetting via RTS pin...\n", - "Done flashing, resetting the board and wait for it to restart\n", - "searching info file: ../src/stubber/data/board_info.csv for: 'Generic ESP32S3 module with ESP32S3' \n", - "{'port': 'esp32', 'build': '', 'arch': 'xtensawin', 'family': 'micropython', 'board': 'ESP32_GENERIC_S3', 'cpu': 'ESP32S3', 'version': '1.22.0.', 'mpy': 'v6.2', 'ver': 'v1.22.0.', 'serial_port': 'COM8'}\n" + "searching info file: ../src/stubber/data/board_info.csv for: 'Raspberry Pi Pico W with RP2040' \n", + "searching info file: ../src/stubber/data/board_info.csv for: 'Raspberry Pi Pico with RP2040' \n", + "| ver | version | port | mpy | build | cpu | family | board | arch | serial_port |\n", + "|----------|-----------|--------|-------|---------|--------|-------------|------------|--------|---------------|\n", + "| v1.22.0. | 1.22.0 | rp2 | v6.2 | | RP2040 | micropython | RPI_PICO_W | armv6m | COM4 |\n", + "| v1.22.0. | 1.22.0 | rp2 | v6.2 | | RP2040 | micropython | RPI_PICO | armv6m | COM15 |\n" ] } ], "source": [ + "def get_dev_info():\n", + " devs = %mpy --list\n", + " ports = devs.fields(0) # list of ports\n", + " # build a list of dicts with info for each port and attached board \n", + " dev_info = []\n", + " for p in ports:\n", + " info = %mpy --select {p} --info\n", + " if info:\n", + " try:\n", + " info[\"version\"] = info[\"version\"].rstrip(\".\")\n", + " read_boardname(info)\n", + " finally:\n", + " dev_info.append(info)\n", + " return dev_info\n", + "\n", + "dev_info = get_dev_info()\n", + "from tabulate import tabulate\n", + "print(tabulate(dev_info, headers=\"keys\", tablefmt=\"github\"))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'ver': 'v1.22.0.', 'version': '1.22.0', 'port': 'rp2', 'mpy': 'v6.2', 'build': '', 'cpu': 'RP2040', 'family': 'micropython', 'board': 'RPI_PICO', 'arch': 'armv6m', 'serial_port': 'COM15'}\n", + "No firmware files found for v1.14.0\n" + ] + }, + { + "ename": "StopIteration", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mStopIteration\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[23], line 4\u001b[0m\n\u001b[0;32m 2\u001b[0m mcu \u001b[38;5;241m=\u001b[39m dev_info[\u001b[38;5;241m1\u001b[39m]\n\u001b[0;32m 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(mcu)\n\u001b[1;32m----> 4\u001b[0m \u001b[43mfind_firmware\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtarget_version\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mport\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmcu\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mport\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mboard\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmcu\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mboard\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;21;43m__next__\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[1;31mStopIteration\u001b[0m: " + ] + } + ], + "source": [ + "target_version = \"1.14.0\"\n", + "mcu = dev_info[1]\n", "print(mcu)\n", - "new = None\n", - "if mcu[\"port\"] in [\"samd\",\"rp2\"]:\n", - " new = flash_uf2(mcu)\n", - "elif mcu[\"port\"] in [\"esp32\"]:\n", - " new = flash_esp32(mcu, erase_flash=False)\n", - "if new:\n", - " read_boardname(new)\n", - " print(new)\n", - " mcu = new\n" + "find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"]).__next__()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\rp2\\RPI_PICO_W-v1.22.0.uf2 {'ver': 'v1.22.0.', 'version': '1.22.0', 'port': 'rp2', 'mpy': 'v6.2', 'build': '', 'cpu': 'RP2040', 'family': 'micropython', 'board': 'RPI_PICO_W', 'arch': 'armv6m', 'serial_port': 'COM4'}\n", + "Entering bootloader on RPI_PICO_W on COM4\n", + "Waiting for mcu to mount as a drive : 5 seconds left\n", + "Waiting for mcu to mount as a drive : 4 seconds left\n", + "Board is in bootloader mode\n", + "Copying c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\rp2\\RPI_PICO_W-v1.22.0.uf2 to E:\\\n", + "Done copying, resetting the board and wait for it to restart\n", + "searching info file: ../src/stubber/data/board_info.csv for: 'Raspberry Pi Pico W with RP2040' \n", + "c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\rp2\\RPI_PICO-v1.22.0.uf2 {'ver': 'v1.22.0.', 'version': '1.22.0', 'port': 'rp2', 'mpy': 'v6.2', 'build': '', 'cpu': 'RP2040', 'family': 'micropython', 'board': 'RPI_PICO', 'arch': 'armv6m', 'serial_port': 'COM15'}\n", + "Entering bootloader on RPI_PICO on COM15\n", + "Waiting for mcu to mount as a drive : 5 seconds left\n", + "Waiting for mcu to mount as a drive : 4 seconds left\n", + "Board is in bootloader mode\n", + "Copying c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\rp2\\RPI_PICO-v1.22.0.uf2 to E:\\\n", + "Done copying, resetting the board and wait for it to restart\n", + "searching info file: ../src/stubber/data/board_info.csv for: 'Raspberry Pi Pico with RP2040' \n", + "| ver | version | port | mpy | build | cpu | family | board | arch | serial_port |\n", + "|----------|-----------|--------|-------|---------|--------|-------------|------------|--------|---------------|\n", + "| v1.22.0. | 1.22.0. | rp2 | v6.2 | | RP2040 | micropython | RPI_PICO_W | armv6m | COM4 |\n", + "| v1.22.0. | 1.22.0. | rp2 | v6.2 | | RP2040 | micropython | RPI_PICO | armv6m | COM15 |\n" + ] + } + ], + "source": [ + "target_version = \"1.22.0\"\n", + "updated = []\n", + "for mcu in dev_info:\n", + " fw_file = find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"]).__next__()\n", + " print(fw_file, mcu)\n", + "\n", + "\n", + " new = None\n", + "\n", + " if mcu[\"port\"] in [\"samd\", \"rp2\"]:\n", + " new = flash_uf2(mcu)\n", + "\n", + " elif mcu[\"port\"] in [\"esp32\"]:\n", + " new = flash_esp32(mcu, erase_flash=False)\n", + "\n", + " if new:\n", + " read_boardname(new)\n", + " updated.append(new)\n", + "\n", + "\n", + "print(tabulate(updated, headers=\"keys\", tablefmt=\"github\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'.uf2'" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "PORT_FWTYPES[mcu[\"port\"]]" ] From 831b9061944ec36365ca111943f9771d257cc03f Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Wed, 3 Jan 2024 12:49:44 +0100 Subject: [PATCH 22/68] Add MicroPython v1.22.0 for Raspberry Pi Pico W and module list readme Signed-off-by: Jos Verlinde --- data/micropython_v1_22_0_rpi_pico_w.txt | 18 ++++++++++++++++++ data/readme.md | 14 ++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 data/micropython_v1_22_0_rpi_pico_w.txt create mode 100644 data/readme.md diff --git a/data/micropython_v1_22_0_rpi_pico_w.txt b/data/micropython_v1_22_0_rpi_pico_w.txt new file mode 100644 index 000000000..0ba8abd4d --- /dev/null +++ b/data/micropython_v1_22_0_rpi_pico_w.txt @@ -0,0 +1,18 @@ +# MicroPython v1.22.0 on 2023-12-27; Raspberry Pi Pico W with RP2040 +__main__ array framebuf random +_asyncio asyncio/__init__ gc re +_boot asyncio/core hashlib requests/__init__ +_boot_fat asyncio/event heapq rp2 +_onewire asyncio/funcs io select +_rp2 asyncio/lock json socket +_thread asyncio/stream lwip ssl +_webrepl binascii machine struct +aioble/__init__ bluetooth math sys +aioble/central builtins micropython time +aioble/client cmath mip/__init__ uasyncio +aioble/core collections neopixel uctypes +aioble/device cryptolib network urequests +aioble/l2cap deflate ntptime webrepl +aioble/peripheral dht onewire webrepl_setup +aioble/security ds18x20 os websocket +aioble/server errno platform \ No newline at end of file diff --git a/data/readme.md b/data/readme.md new file mode 100644 index 000000000..612cce1d0 --- /dev/null +++ b/data/readme.md @@ -0,0 +1,14 @@ +# Overview of modules avaialble on different ports and boards +These files are used to compile a list of modules that createstubs.py and its variants will attempt to create stubs for. + +This can be generated by running the following command in micropython on the board: `help('modules')` +or via mpremote by running the following command: `mpremote exec "help('modules')"` + +Store the ouput in a file called `micropython--[-].txt` in this directory. +place a comment `#` before all lines that do not not contain module names. + +After adding or changing any file update the list of modules using from the root of the repository. +``` +stubber update-module-list +stubber make-variants +``` From 8ed52d85316ebbdbad4446ac9d71708f9577a3ee Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Wed, 3 Jan 2024 16:32:35 +0100 Subject: [PATCH 23/68] Add chime and bincopy dependencies Signed-off-by: Jos Verlinde --- poetry.lock | 78 ++++++++++++++++++++++++++++++++++++++++++++++++-- pyproject.toml | 2 ++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 94e27dac6..d9aaa49c3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "alabaster" @@ -58,6 +58,17 @@ files = [ [package.extras] test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] +[[package]] +name = "argparse-addons" +version = "0.12.0" +description = "Additional argparse types and actions." +optional = false +python-versions = ">=3.6" +files = [ + {file = "argparse_addons-0.12.0-py3-none-any.whl", hash = "sha256:48b70ecd719054fcb0d7e6f25a1fecc13607aac61d446e83f47d211b4ead0d61"}, + {file = "argparse_addons-0.12.0.tar.gz", hash = "sha256:6322a0dcd706887e76308d23136d5b86da0eab75a282dc6496701d1210b460af"}, +] + [[package]] name = "astroid" version = "3.0.2" @@ -155,6 +166,22 @@ soupsieve = ">1.2" html5lib = ["html5lib"] lxml = ["lxml"] +[[package]] +name = "bincopy" +version = "20.0.0" +description = "Mangling of various file formats that conveys binary information (Motorola S-Record, Intel HEX and binary files)." +optional = false +python-versions = ">=3.6" +files = [ + {file = "bincopy-20.0.0-py3-none-any.whl", hash = "sha256:c9cde5234e3699aa9eaaab4a4e7f32f175d2111549ae4423ee19012840714426"}, + {file = "bincopy-20.0.0.tar.gz", hash = "sha256:14cfb4cf97227bf2b1f5b85623df4c767ad219afdc9fe0732dd2cfdff446afdf"}, +] + +[package.dependencies] +argparse-addons = ">=0.4.0" +humanfriendly = "*" +pyelftools = "*" + [[package]] name = "bitarray" version = "2.9.1" @@ -520,6 +547,17 @@ files = [ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] +[[package]] +name = "chime" +version = "0.7.0" +description = "Python sound notifications made easy." +optional = false +python-versions = ">=3.6,<4.0" +files = [ + {file = "chime-0.7.0-py3-none-any.whl", hash = "sha256:9626f8151cb008b1e0ffb7de6d1834b7013ba5fc4c4e3c9ba6e29dc9bf5feac6"}, + {file = "chime-0.7.0.tar.gz", hash = "sha256:ba4af8934ec8bd9a89a340b4433b2e500097b979823386432be7128e0b201f0d"}, +] + [[package]] name = "click" version = "8.1.7" @@ -828,6 +866,20 @@ files = [ {file = "fasteners-0.19.tar.gz", hash = "sha256:b4f37c3ac52d8a445af3a66bce57b33b5e90b97c696b7b984f530cf8f0ded09c"}, ] +[[package]] +name = "humanfriendly" +version = "10.0" +description = "Human friendly output for text interfaces using Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"}, + {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"}, +] + +[package.dependencies] +pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""} + [[package]] name = "idna" version = "3.6" @@ -1758,6 +1810,17 @@ snowballstemmer = ">=2.2.0" [package.extras] toml = ["tomli (>=1.2.3)"] +[[package]] +name = "pyelftools" +version = "0.30" +description = "Library for analyzing ELF files and DWARF debugging information" +optional = false +python-versions = "*" +files = [ + {file = "pyelftools-0.30-py2.py3-none-any.whl", hash = "sha256:544c3440eddb9a0dce70b6611de0b28163d71def759d2ed57a0d00118fc5da86"}, + {file = "pyelftools-0.30.tar.gz", hash = "sha256:2fc92b0d534f8b081f58c7c370967379123d8e00984deb53c209364efd575b40"}, +] + [[package]] name = "pyflakes" version = "3.1.0" @@ -1871,6 +1934,17 @@ requests = ">=2.20,<3.0" [package.extras] tqdm = ["tqdm"] +[[package]] +name = "pyreadline3" +version = "3.4.1" +description = "A python implementation of GNU readline." +optional = false +python-versions = "*" +files = [ + {file = "pyreadline3-3.4.1-py3-none-any.whl", hash = "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb"}, + {file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"}, +] + [[package]] name = "pyright" version = "1.1.343" @@ -2845,4 +2919,4 @@ tools = ["esptool"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "a31b36234b8a35054e09185e806ce687a537776fefbc5c3d6edd29d0f8a941c2" +content-hash = "2a91438425ed433330988080b8e4829e990e986e768de1f009de4760103ff3fe" diff --git a/pyproject.toml b/pyproject.toml index 7a06a1faf..f972d6d24 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,6 +102,8 @@ ipykernel = "^6.23.1" fasteners = "^0.19" python-dotenv = "^1.0.0" pydocstyle = "^6.3.0" +chime = "^0.7.0" +bincopy = "^20.0.0" From f5dad250a5529dbb6ff89b343c123951b0a5fa49 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Wed, 3 Jan 2024 16:33:19 +0100 Subject: [PATCH 24/68] board_stubber.py: Switch from uname to sys.implementation as primary source of info. Add Build ditribution package step Signed-off-by: Jos Verlinde --- scripts/board_stubber.py | 64 ++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 42 deletions(-) diff --git a/scripts/board_stubber.py b/scripts/board_stubber.py index 0ccc2e3c4..041b84b46 100644 --- a/scripts/board_stubber.py +++ b/scripts/board_stubber.py @@ -21,6 +21,7 @@ from stubber import utils from stubber.publish.merge_docstubs import get_board_path, merge_all_docstubs +from stubber.publish.publish import build_multiple from stubber.utils.config import CONFIG OK = 0 @@ -142,13 +143,11 @@ def timed_out(): timer.cancel() proc.wait(timeout=1) - return proc.returncode, output + return proc.returncode or 0, output ############################################################################################### -UName = NamedTuple("UName", sysname=str, nodename=str, release=str, version=str, machine=str) - class Variant(str, Enum): """Variants of generatings stubs on a MCU""" @@ -173,7 +172,7 @@ def __init__(self, serialport: str = ""): self.serialport = serialport # self.board = "" self.firmware = {} - self.uname: Optional[UName] = None + self.connected = False self.path: Optional[Path] = None self.description = "" @@ -187,7 +186,7 @@ def connected_boards(): @retry(stop=stop_after_attempt(RETRIES), wait=wait_fixed(1)) def get_mcu_info(self): - # TODO: switch from uname to sys.implementation os the primary source of info + # switched from uname to sys.implementation as the primary source of info rc, result = self.run_command( [ "exec", @@ -195,7 +194,7 @@ def get_mcu_info(self): ], no_info=True, ) - if rc == 0: + if rc == OK: s = result[0] if "name=" in s: implementation = eval(f"dict{s}") @@ -203,36 +202,8 @@ def get_mcu_info(self): self.description = implementation["_machine"] if len(result) > 1: self.port = result[1].strip() - - @retry(stop=stop_after_attempt(RETRIES), wait=wait_fixed(1)) - def get_uname(self): - # TODO: switch from uname to sys.implementation os the primary source of info - rc, result = self.run_command( - [ - "exec", - "import sys;print(repr(sys.implementation) if 'implementation' in dir(sys) else 'no.implementation')", - ], - no_info=True, - ) - s = result[0] - if "name=" in s: - implementation = eval(f"dict{s}") - version = ".".join([str(n) for n in implementation["version"]]) - UName("implementation", implementation.name, version, version, "?") - - rc, result = self.run_command( - ["exec", "import os;print(os.uname() if 'uname' in dir(os) else 'no.uname')"], - no_info=True, - ) - s = result[0] - if "sysname=" in s: - self.uname = eval(f"UName{s}") - elif s.strip() == "no.uname": - self.uname = UName("no.uname", "?", "?", "?", "?") - else: - self.uname = UName(*s[1:-1].split(", ")) - self.connected = True - return rc, self.uname + else: + self.port = "unknown" def disconnect(self) -> bool: """Disconnect from a board""" @@ -381,12 +352,12 @@ def run_createstubs(dest: Path, board: MPRemoteBoard, variant: Variant = Variant board.run_command(cmd_path, timeout=5) if reset_before: - log.info(f"Resetting {board.serialport} {board.uname[4] if board.uname else ''}") + log.info(f"Resetting {board.serialport} {board.description}") board.run_command("reset", timeout=5) time.sleep(2) log.info( - f"Running createstubs {variant} on {board.serialport} {board.uname[4] if board.uname else ''} using temp path: {dest}" + f"Running createstubs {variant} on {board.serialport} {board.description} using temp path: {dest}" ) cmd = build_cmd(dest, variant) @@ -601,7 +572,7 @@ def copy_to_repo(source: Path, fw: dict) -> Optional[Path]: # scan boards and generate stubs for board in connected_boards: - log.info(f"Connecting to {board.serialport} {board.uname[4] if board.uname else ''}") + log.info(f"Connecting to {board.serialport} {board.description} {board.version}") rc, my_stubs = generate_board_stubs(dest, board, variant, form) if rc == OK and my_stubs: log.success(f'Stubs generated for {board.firmware["port"]}-{board.firmware["board"]}') @@ -610,16 +581,25 @@ def copy_to_repo(source: Path, fw: dict) -> Optional[Path]: # Also merge the stubs with the docstubs log.info(f"Merging stubs with docstubs : {board.firmware}") - _ = merge_all_docstubs( + merged = merge_all_docstubs( versions=board.firmware["version"], family=board.firmware["family"], boards=board.firmware["board"], ports=board.firmware["port"], mpy_path=CONFIG.mpy_path, ) - log.success("Done") - + if not merged: + log.error(f"Failed to merge stubs for {board.serialport}") + continue # Then Build the package + log.info(f"Building package for {board.firmware}") + built = build_multiple( + versions=board.firmware["version"], + family=board.firmware["family"], + boards=board.firmware["board"], + ports=board.firmware["port"], + ) + log.success("Done") else: log.error(f"Failed to generate stubs for {board.serialport}") From 455bb3ad9c48015ac543f34a1eea52eca8a39d64 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Wed, 3 Jan 2024 16:34:20 +0100 Subject: [PATCH 25/68] flash: Add support for STM32 Signed-off-by: Jos Verlinde --- scripts/flash.ipynb | 345 +++++++++++++++++++++++++++++++------------- 1 file changed, 243 insertions(+), 102 deletions(-) diff --git a/scripts/flash.ipynb b/scripts/flash.ipynb index a0814ed6f..8ee85996c 100644 --- a/scripts/flash.ipynb +++ b/scripts/flash.ipynb @@ -2,20 +2,25 @@ "cells": [ { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "import shutil, time" + "import shutil, time\n", + "from pathlib import Path" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "from pathlib import Path\n", + "# Find firmware files for a given version port and board\n", + "# firmwares downloaded via get_firmware.ipynb are stored in firmware//-v[-preview.].\n", + "# NOTE: The build dates have been removed from the filenames as they mostly get in the way\n", + "\n", + "\n", "\n", "PORT_FWTYPES = {\n", " \"stm32\": \".hex\",\n", @@ -25,6 +30,7 @@ "}\n", "\n", "\n", + "\n", "def find_firmware(version: str, *, board: str = \"*\", port: str):\n", " fw_folder = Path.cwd() / \"firmware\" / port\n", " if not fw_folder.exists():\n", @@ -38,96 +44,167 @@ " board = f\"RPI_{board}\"\n", "\n", " fw_files = list(fw_folder.glob(f\"{board}-{v_str}{ext}\"))\n", + "\n", " if not fw_files:\n", " print(f\"No firmware files found for {v_str}\")\n", " return None\n", " fw_files.sort()\n", - " yield from fw_files\n", - "\n", - "\n", - "# for fw in find_firmware(\"1.22.0\", port=\"samd\", board=\"SEEED_WIO_*\"):\n", - "# print(fw)\n", - "# for fw in find_firmware(\"1.22.0\", port=\"esp32\", board=\"ESP32_GENERIC-SPIRAM\"):\n", - "# print(fw)" + " yield from fw_files" ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ + "# resolve board descriptions to BOARD_NAMES\n", "import gc\n", + "\n", + "\n", "import os\n", "\n", "\n", + "\n", "LIBS = [\"../src/stubber/data\"]\n", "\n", "\n", + "\n", "def file_exists(filename: str):\n", " try:\n", " if os.stat(filename)[0] >> 14:\n", " return True\n", + "\n", + "\n", " return False\n", + "\n", + "\n", " except OSError:\n", " return False\n", "\n", "\n", + "\n", "def read_boardname(info, desc: str = \"\"):\n", " found = False\n", + "\n", + "\n", " for filename in [d + \"/board_info.csv\" for d in LIBS]:\n", " # print(\"look up the board name in the file\", filename)\n", + "\n", + "\n", " if file_exists(filename):\n", " descr = desc or info[\"board\"].strip()\n", + "\n", + "\n", " print(\"searching info file: {} for: '{}' \".format(filename, descr))\n", + "\n", + "\n", " if find_board(info, descr, filename):\n", " found = True\n", + "\n", + "\n", " break\n", " if not found:\n", + "\n", " print(\"Board not found, guessing board name\")\n", + "\n", + "\n", " descr = desc or info[\"board\"].strip()\n", + "\n", + "\n", " if \"with \" + info[\"cpu\"].upper() in descr:\n", " # remove the with cpu part\n", + "\n", + "\n", " descr = descr.split(\"with \" + info[\"cpu\"].upper())[0].strip()\n", + "\n", + "\n", " info[\"board\"] = descr\n", + "\n", + "\n", " info[\"board\"] = info[\"board\"].replace(\" \", \"_\")\n", + "\n", + "\n", " gc.collect()\n", "\n", "\n", + "\n", "def find_board(info: dict, descr: str, filename: str):\n", " # find a board based on its description\n", + "\n", + "\n", " short_hit = \"\"\n", + "\n", + "\n", " lines = []\n", + "\n", + "\n", " pos = descr.rfind(\" with\")\n", + "\n", + "\n", " if pos != -1:\n", " short_descr = descr[:pos].strip()\n", " else:\n", + "\n", " short_descr = \"\"\n", + "\n", + "\n", " try:\n", " with open(filename, \"r\") as file:\n", " lines = file.readlines()\n", " for line in lines:\n", + "\n", " line = line.strip()\n", + "\n", + "\n", " if line.startswith(\"#\"):\n", " continue\n", + "\n", + "\n", " _descr = line.split(\",\")[0].strip()\n", + "\n", + "\n", " _board = line.split(\",\")[1].strip()\n", + "\n", + "\n", " if _descr == descr:\n", " info[\"board\"] = _board\n", + "\n", + "\n", " return True\n", + "\n", + "\n", " elif short_descr and _descr == short_descr:\n", " if \"with\" in short_descr:\n", " # Good enough - no need to trawl the entire file\n", + "\n", + "\n", " info[\"board\"] = _board\n", + "\n", + "\n", " return True\n", + "\n", + "\n", " # good enough if not found in the rest of the file (but slow)\n", + "\n", + "\n", " short_hit = _board\n", + "\n", + "\n", " if short_hit:\n", " info[\"board\"] = short_hit\n", + "\n", + "\n", " return True\n", + "\n", + "\n", " return False\n", + "\n", + "\n", " finally:\n", " del lines\n", + "\n", + "\n", " gc.collect()" ] }, @@ -136,14 +213,8 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], "source": [ + "# flash .UF2 devices via bootloader and filecopy\n", "from typing import Dict, Optional\n", "import psutil\n", "MCUInfo = Dict[str,str]\n", @@ -183,10 +254,11 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ + "# Flash ESP32 via esptool\n", "def flash_esp32(mcu:MCUInfo, fw_file:Optional[Path]= None,*, erase_flash:bool=True) -> Optional[MCUInfo]:\n", " if not mcu[\"port\"] in [\"esp32\"]:\n", " print(f\"ESP32 not supported on {mcu['board']} on {mcu['serial_port']}\")\n", @@ -212,22 +284,62 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "searching info file: ../src/stubber/data/board_info.csv for: 'Raspberry Pi Pico W with RP2040' \n", - "searching info file: ../src/stubber/data/board_info.csv for: 'Raspberry Pi Pico with RP2040' \n", - "| ver | version | port | mpy | build | cpu | family | board | arch | serial_port |\n", - "|----------|-----------|--------|-------|---------|--------|-------------|------------|--------|---------------|\n", - "| v1.22.0. | 1.22.0 | rp2 | v6.2 | | RP2040 | micropython | RPI_PICO_W | armv6m | COM4 |\n", - "| v1.22.0. | 1.22.0 | rp2 | v6.2 | | RP2040 | micropython | RPI_PICO | armv6m | COM15 |\n" - ] - } - ], + "outputs": [], + "source": [ + "# flash STM32 using STM32CubeProgrammer\n", + "import bincopy \n", + "\n", + "def get_stm32_start_address(fw_file):\n", + " \"\"\"\n", + " Get the start address of the firmware file indoer to allow automatic restart after flashing\n", + " \"\"\"\n", + " try:\n", + " hex = bincopy.BinFile(str(fw_file))\n", + " return f\"0x{hex.execution_start_address:08X}\"\n", + " except:\n", + " return \"\"\n", + "\n", + "def flash_stm32(mcu:MCUInfo, fw_file:Optional[Path]= None,*, erase_flash:bool=True) -> Optional[MCUInfo]:\n", + " print(f\"Entering bootloader on {mcu['board']} on {mcu['serial_port']}\")\n", + " %mpy --select {mcu['serial_port']}\n", + " %mpy --bootloader # TODO: add this to micropython-magic\n", + "\n", + " time.sleep(2)\n", + " results = !\"C:\\Program Files\\STMicroelectronics\\STM32Cube\\STM32CubeProgrammer\\bin\\STM32_Programmer_CLI.exe\" --list\n", + " if \"Product ID : STM32 BOOTLOADER\" in results:\n", + " print(\"No STM32 BOOTLOADER detected\")\n", + " return None\n", + " echo = False\n", + " for line in results:\n", + " if line.startswith(\"===== DFU Interface\"):\n", + " echo = True\n", + " if line.startswith(\"===== STLink\"):\n", + " echo = False\n", + " if echo:\n", + " print(line)\n", + "\n", + " # !\"C:\\Program Files\\STMicroelectronics\\STM32Cube\\STM32CubeProgrammer\\bin\\STM32_Programmer_CLI.exe\" --connect port=USB1\n", + " if erase_flash:\n", + " print(\"Erasing flash\")\n", + " !\"C:\\Program Files\\STMicroelectronics\\STM32Cube\\STM32CubeProgrammer\\bin\\STM32_Programmer_CLI.exe\" --connect port=USB1 --erase all\n", + " \n", + " print(\"Flashing\")\n", + " fw_file = fw_file or find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"]).__next__()\n", + " start_address = get_stm32_start_address(fw_file)\n", + "\n", + " print(f\"STM32_Programmer_CLI.exe --connect port=USB1 --write {str(fw_file)} --go {start_address}\")\n", + " !\"C:\\Program Files\\STMicroelectronics\\STM32Cube\\STM32CubeProgrammer\\bin\\STM32_Programmer_CLI.exe\" --connect port=USB1 --write \"{str(fw_file)}\" --go {start_address}\n", + " print(\"Done flashing, resetting the board and wait for it to restart\")\n", + " time.sleep(5)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "def get_dev_info():\n", " devs = %mpy --list\n", @@ -251,68 +363,9 @@ }, { "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'ver': 'v1.22.0.', 'version': '1.22.0', 'port': 'rp2', 'mpy': 'v6.2', 'build': '', 'cpu': 'RP2040', 'family': 'micropython', 'board': 'RPI_PICO', 'arch': 'armv6m', 'serial_port': 'COM15'}\n", - "No firmware files found for v1.14.0\n" - ] - }, - { - "ename": "StopIteration", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mStopIteration\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[23], line 4\u001b[0m\n\u001b[0;32m 2\u001b[0m mcu \u001b[38;5;241m=\u001b[39m dev_info[\u001b[38;5;241m1\u001b[39m]\n\u001b[0;32m 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(mcu)\n\u001b[1;32m----> 4\u001b[0m \u001b[43mfind_firmware\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtarget_version\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mport\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmcu\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mport\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mboard\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmcu\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mboard\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;21;43m__next__\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", - "\u001b[1;31mStopIteration\u001b[0m: " - ] - } - ], - "source": [ - "target_version = \"1.14.0\"\n", - "mcu = dev_info[1]\n", - "print(mcu)\n", - "find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"]).__next__()" - ] - }, - { - "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\rp2\\RPI_PICO_W-v1.22.0.uf2 {'ver': 'v1.22.0.', 'version': '1.22.0', 'port': 'rp2', 'mpy': 'v6.2', 'build': '', 'cpu': 'RP2040', 'family': 'micropython', 'board': 'RPI_PICO_W', 'arch': 'armv6m', 'serial_port': 'COM4'}\n", - "Entering bootloader on RPI_PICO_W on COM4\n", - "Waiting for mcu to mount as a drive : 5 seconds left\n", - "Waiting for mcu to mount as a drive : 4 seconds left\n", - "Board is in bootloader mode\n", - "Copying c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\rp2\\RPI_PICO_W-v1.22.0.uf2 to E:\\\n", - "Done copying, resetting the board and wait for it to restart\n", - "searching info file: ../src/stubber/data/board_info.csv for: 'Raspberry Pi Pico W with RP2040' \n", - "c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\rp2\\RPI_PICO-v1.22.0.uf2 {'ver': 'v1.22.0.', 'version': '1.22.0', 'port': 'rp2', 'mpy': 'v6.2', 'build': '', 'cpu': 'RP2040', 'family': 'micropython', 'board': 'RPI_PICO', 'arch': 'armv6m', 'serial_port': 'COM15'}\n", - "Entering bootloader on RPI_PICO on COM15\n", - "Waiting for mcu to mount as a drive : 5 seconds left\n", - "Waiting for mcu to mount as a drive : 4 seconds left\n", - "Board is in bootloader mode\n", - "Copying c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\rp2\\RPI_PICO-v1.22.0.uf2 to E:\\\n", - "Done copying, resetting the board and wait for it to restart\n", - "searching info file: ../src/stubber/data/board_info.csv for: 'Raspberry Pi Pico with RP2040' \n", - "| ver | version | port | mpy | build | cpu | family | board | arch | serial_port |\n", - "|----------|-----------|--------|-------|---------|--------|-------------|------------|--------|---------------|\n", - "| v1.22.0. | 1.22.0. | rp2 | v6.2 | | RP2040 | micropython | RPI_PICO_W | armv6m | COM4 |\n", - "| v1.22.0. | 1.22.0. | rp2 | v6.2 | | RP2040 | micropython | RPI_PICO | armv6m | COM15 |\n" - ] - } - ], + "outputs": [], "source": [ "target_version = \"1.22.0\"\n", "updated = []\n", @@ -320,17 +373,18 @@ " fw_file = find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"]).__next__()\n", " print(fw_file, mcu)\n", "\n", - "\n", " new = None\n", "\n", " if mcu[\"port\"] in [\"samd\", \"rp2\"]:\n", " new = flash_uf2(mcu)\n", - "\n", " elif mcu[\"port\"] in [\"esp32\"]:\n", " new = flash_esp32(mcu, erase_flash=False)\n", + " elif mcu[\"port\"] in [\"stm32\"]:\n", + " new = flash_stm32(mcu, erase_flash=False)\n", "\n", " if new:\n", " read_boardname(new)\n", + " new[\"version\"] = new[\"version\"].rstrip(\".\") # todo: update micropython-magic to do this\n", " updated.append(new)\n", "\n", "\n", @@ -339,22 +393,109 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Entering bootloader on PYBV11 on COM17\n", + "===== DFU Interface =====\n", + "\n", + "Total number of available STM32 device in DFU mode: 1\n", + "\n", + " Device Index : USB1\n", + " USB Bus Number : 001\n", + " USB Address Number : 002\n", + " Product ID : STM32 BOOTLOADER\n", + " Serial number : 206437A1304E\n", + " Firmware version : 0x011a\n", + " Device ID : 0x0413\n", + "\n", + "Flashing\n", + "STM32_Programmer_CLI.exe --connect port=USB1 --write c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\stm32\\PYBV11-v1.22.0.hex --go 0x08020161\n", + " -------------------------------------------------------------------\n", + " STM32CubeProgrammer v2.13.0 \n", + " -------------------------------------------------------------------\n", + "\n", + "\n", + "\n", + "USB speed : Full Speed (12MBit/s)\n", + "Manuf. ID : STMicroelectronics\n", + "Product ID : STM32 BOOTLOADER\n", + "SN : 206437A1304E\n", + "DFU protocol: 1.1\n", + "Board : --\n", + "Device ID : 0x0413\n", + "Device name : STM32F405xx/F407xx/F415xx/F417xx\n", + "Flash size : 1 MBytes (default)\n", + "Device type : MCU\n", + "Revision ID : -- \n", + "Device CPU : Cortex-M4\n", + "\n", + "\n", + "Memory Programming ...\n", + "Opening and parsing file: PYBV11-v1.22.0.hex\n", + " File : PYBV11-v1.22.0.hex\n", + " Size : 355.81 KB \n", + " Address : 0x08000000 \n", + "\n", + "\n", + "Erasing memory corresponding to segment 0:\n", + "Erasing internal memory sector 0\n", + "erasing sector 0000 @: 0x08000000 done\n", + "Erasing memory corresponding to segment 1:\n", + "Erasing internal memory sectors [5 7]\n", + "erasing sector 0005 @: 0x08020000 done\n", + "erasing sector 0006 @: 0x08040000 done\n", + "erasing sector 0007 @: 0x08060000 done\n", + "Download in Progress:\n", + "�������������������������������������������������� 0%\n", + "� 2%� 4%� 2%� 4%� 6%� 8%� 10%� 12%� 14%� 16%� 18%� 20%� 22%� 24%� 26%� 28%� 30%� 32%� 34%� 36%� 38%� 40%� 42%� 44%� 46%� 48%� 50%� 52%� 54%� 56%� 58%� 60%� 62%� 64%� 66%� 68%� 70%� 72%� 74%� 76%� 78%� 80%� 82%� 84%� 86%� 88%� 90%� 92%� 94%� 96%� 98%� 100%\n", + "\n", + "File download complete\n", + "Time elapsed during download operation: 00:00:13.463\n", + "\n", + "RUNNING Program ... \n", + " Address: : 0x8020161\n", + "Start operation achieved successfully\n" + ] + } + ], + "source": [ + "# mcu = dev_info[0]\n", + "# flash_stm32(mcu, erase_flash=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "'.uf2'" + "{'port': 'stm32',\n", + " 'build': '',\n", + " 'arch': 'armv7emsp',\n", + " 'family': 'micropython',\n", + " 'board': 'PYBv1.1 with STM32F405RG',\n", + " 'cpu': 'STM32F405RG',\n", + " 'version': '1.22.0.',\n", + " 'mpy': 'v6.2',\n", + " 'ver': 'v1.22.0.',\n", + " 'serial_port': 'COM17'}" ] }, - "execution_count": 9, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "PORT_FWTYPES[mcu[\"port\"]]" + "\n", + "%mpy --info" ] }, { From 57dd756fb037680aebbe8f53a3df740ddba2cb3f Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Wed, 3 Jan 2024 16:34:49 +0100 Subject: [PATCH 26/68] Reverse the order of versions in get_boardnames.py to get most recent boardnames Signed-off-by: Jos Verlinde --- scripts/get_boardnames.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/get_boardnames.py b/scripts/get_boardnames.py index 0cc99647b..ce1272268 100644 --- a/scripts/get_boardnames.py +++ b/scripts/get_boardnames.py @@ -203,7 +203,7 @@ def main(): "v1.11", "v1.10", ] - versions.reverse() + # versions.reverse() board_list = get_board_list(versions, mpy_path) print(tabulate(board_list, headers="keys")) # type: ignore From da4cd7953e75bdbd63ce8890f2e6f4ce1aeb9258 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Wed, 3 Jan 2024 16:35:21 +0100 Subject: [PATCH 27/68] chore Signed-off-by: Jos Verlinde --- scripts/get_firmwares.ipynb | 298 ++++++++++++------------------------ 1 file changed, 94 insertions(+), 204 deletions(-) diff --git a/scripts/get_firmwares.ipynb b/scripts/get_firmwares.ipynb index bdcf53ca9..d97be2bdb 100644 --- a/scripts/get_firmwares.ipynb +++ b/scripts/get_firmwares.ipynb @@ -86,13 +86,13 @@ " )\n", " if \"?\" in base_url:\n", " base_url = base_url.split(\"?\")[0]\n", - " links = [urljoin(base_url, tag.get(\"href\")) for tag in tags]\n", + " links: List = [urljoin(base_url, tag.get(\"href\")) for tag in tags]\n", " return links" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 5, "metadata": { "tags": [] }, @@ -166,22 +166,19 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Found 85 relevant firmwares\n" + "Found 102 relevant firmwares\n" ] } ], "source": [ - "relevant = [\n", - " board\n", - " for board in board_urls\n", - " if board[\"board\"] in RELEVANT_BOARDS and (board[\"version\"] in [\"1.22.0\"] or board[\"preview\"])\n", + "relevant = [3````````````````\n", " # and b[\"port\"] in [\"esp32\", \"rp2\"]\n", "]\n", "# relevant\n", @@ -190,101 +187,9 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 13, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " firmware\\stm32\\PYBV11-v1.22.0.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-v1.22.0-preview.289.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-v1.22.0-preview.283.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-v1.22.0-preview.281.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-v1.22.0-preview.278.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-DP-v1.22.0.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-DP-v1.22.0-preview.289.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-DP-v1.22.0-preview.283.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-DP-v1.22.0-preview.281.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-DP-v1.22.0-preview.278.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-NETWORK-v1.22.0.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-NETWORK-v1.22.0-preview.289.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-NETWORK-v1.22.0-preview.283.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-NETWORK-v1.22.0-preview.281.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-NETWORK-v1.22.0-preview.278.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-THREAD-v1.22.0.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-THREAD-v1.22.0-preview.289.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-THREAD-v1.22.0-preview.283.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-THREAD-v1.22.0-preview.281.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-THREAD-v1.22.0-preview.278.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0-preview.289.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0-preview.283.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0-preview.281.hex already exists, skip download\n", - " firmware\\stm32\\PYBV11-DP_THREAD-v1.22.0-preview.278.hex already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-v1.22.0.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-v1.22.0-preview.289.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-v1.22.0-preview.283.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-v1.22.0-preview.281.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-v1.22.0-preview.278.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0-preview.289.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0-preview.283.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0-preview.281.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.0-preview.278.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0-preview.289.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0-preview.283.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0-preview.281.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.0-preview.278.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0-preview.289.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0-preview.283.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0-preview.281.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.0-preview.278.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.289.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.283.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.281.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.278.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC_S3-v1.22.0.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC_S3-v1.22.0-preview.289.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC_S3-v1.22.0-preview.283.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC_S3-v1.22.0-preview.281.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC_S3-v1.22.0-preview.278.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.289.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.283.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.281.bin already exists, skip download\n", - " firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.278.bin already exists, skip download\n", - " firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0.uf2 already exists, skip download\n", - " firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0-preview.289.uf2 already exists, skip download\n", - " firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0-preview.283.uf2 already exists, skip download\n", - " firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0-preview.281.uf2 already exists, skip download\n", - " firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.0-preview.278.uf2 already exists, skip download\n", - " firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0.uf2 already exists, skip download\n", - " firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0-preview.289.uf2 already exists, skip download\n", - " firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0-preview.283.uf2 already exists, skip download\n", - " firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0-preview.281.uf2 already exists, skip download\n", - " firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.0-preview.278.uf2 already exists, skip download\n", - " firmware\\rp2\\RPI_PICO-v1.22.0.uf2 already exists, skip download\n", - " firmware\\rp2\\RPI_PICO-v1.22.0-preview.289.uf2 already exists, skip download\n", - " firmware\\rp2\\RPI_PICO-v1.22.0-preview.283.uf2 already exists, skip download\n", - " firmware\\rp2\\RPI_PICO-v1.22.0-preview.281.uf2 already exists, skip download\n", - " firmware\\rp2\\RPI_PICO-v1.22.0-preview.278.uf2 already exists, skip download\n", - " firmware\\rp2\\RPI_PICO_W-v1.22.0.uf2 already exists, skip download\n", - " firmware\\rp2\\RPI_PICO_W-v1.22.0-preview.289.uf2 already exists, skip download\n", - " firmware\\rp2\\RPI_PICO_W-v1.22.0-preview.283.uf2 already exists, skip download\n", - " firmware\\rp2\\RPI_PICO_W-v1.22.0-preview.281.uf2 already exists, skip download\n", - " firmware\\rp2\\RPI_PICO_W-v1.22.0-preview.278.uf2 already exists, skip download\n", - " firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0.uf2 already exists, skip download\n", - " firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0-preview.289.uf2 already exists, skip download\n", - " firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0-preview.283.uf2 already exists, skip download\n", - " firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0-preview.281.uf2 already exists, skip download\n", - " firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.0-preview.278.uf2 already exists, skip download\n" - ] - } - ], + "outputs": [], "source": [ "# download the relevant files to the firmware folder\n", "import requests\n", @@ -303,7 +208,7 @@ " filename = firmware_folder / board[\"port\"] / fname\n", " filename.parent.mkdir(exist_ok=True)\n", " if filename.exists():\n", - " print(f\" {filename} already exists, skip download\")\n", + " # print(f\" {filename} already exists, skip download\")\n", " continue\n", " print(f\"Downloading {board['firmware']} to {filename}\")\n", " r = requests.get(board[\"firmware\"], allow_redirects=True)\n", @@ -314,121 +219,106 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "COM4 017154B9 10c4:ea60 Silicon Labs None\n" + " Volume in drive C has no label.\n", + " Volume Serial Number is 30ED-D319\n", + "\n", + " Directory of c:\\develop\\MyPython\\micropython-stubber\\scripts\n", + "\n", + "\n", + " Directory of c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\esp32\n", + "\n", + "03-01-2024 11:55 .\n", + "19-10-2023 14:24 ..\n", + "19-10-2023 14:45 1.494.672 ESP32_GENERIC-D2WD-v1.21.0.bin\n", + "19-10-2023 14:45 1.494.832 ESP32_GENERIC-D2WD-v1.22.0-preview.27.bin\n", + "30-12-2023 00:28 1.493.840 ESP32_GENERIC-D2WD-v1.22.0-preview.278.bin\n", + "30-12-2023 00:28 1.494.112 ESP32_GENERIC-D2WD-v1.22.0-preview.281.bin\n", + "30-12-2023 00:28 1.494.176 ESP32_GENERIC-D2WD-v1.22.0-preview.283.bin\n", + "30-12-2023 00:28 1.494.144 ESP32_GENERIC-D2WD-v1.22.0-preview.289.bin\n", + "19-10-2023 14:45 1.494.832 ESP32_GENERIC-D2WD-v1.22.0-preview.30.bin\n", + "19-10-2023 14:45 1.494.832 ESP32_GENERIC-D2WD-v1.22.0-preview.31.bin\n", + "19-10-2023 14:45 1.494.832 ESP32_GENERIC-D2WD-v1.22.0-preview.32.bin\n", + "30-12-2023 00:28 1.494.112 ESP32_GENERIC-D2WD-v1.22.0.bin\n", + "03-01-2024 11:55 1.494.144 ESP32_GENERIC-D2WD-v1.23.0-preview.6.bin\n", + "19-10-2023 14:45 1.621.792 ESP32_GENERIC-OTA-v1.21.0.bin\n", + "19-10-2023 14:45 1.621.936 ESP32_GENERIC-OTA-v1.22.0-preview.27.bin\n", + "30-12-2023 00:28 1.544.848 ESP32_GENERIC-OTA-v1.22.0-preview.278.bin\n", + "30-12-2023 00:28 1.545.104 ESP32_GENERIC-OTA-v1.22.0-preview.281.bin\n", + "30-12-2023 00:28 1.545.152 ESP32_GENERIC-OTA-v1.22.0-preview.283.bin\n", + "30-12-2023 00:28 1.545.120 ESP32_GENERIC-OTA-v1.22.0-preview.289.bin\n", + "19-10-2023 14:45 1.621.936 ESP32_GENERIC-OTA-v1.22.0-preview.30.bin\n", + "19-10-2023 14:45 1.621.952 ESP32_GENERIC-OTA-v1.22.0-preview.31.bin\n", + "19-10-2023 14:45 1.621.952 ESP32_GENERIC-OTA-v1.22.0-preview.32.bin\n", + "30-12-2023 00:28 1.545.088 ESP32_GENERIC-OTA-v1.22.0.bin\n", + "03-01-2024 11:55 1.545.120 ESP32_GENERIC-OTA-v1.23.0-preview.6.bin\n", + "19-10-2023 14:45 1.601.072 ESP32_GENERIC-SPIRAM-v1.21.0.bin\n", + "19-10-2023 14:45 1.601.200 ESP32_GENERIC-SPIRAM-v1.22.0-preview.27.bin\n", + "30-12-2023 00:28 1.614.304 ESP32_GENERIC-SPIRAM-v1.22.0-preview.278.bin\n", + "30-12-2023 00:28 1.614.576 ESP32_GENERIC-SPIRAM-v1.22.0-preview.281.bin\n", + "30-12-2023 00:28 1.614.640 ESP32_GENERIC-SPIRAM-v1.22.0-preview.283.bin\n", + "30-12-2023 00:28 1.614.624 ESP32_GENERIC-SPIRAM-v1.22.0-preview.289.bin\n", + "19-10-2023 14:45 1.601.200 ESP32_GENERIC-SPIRAM-v1.22.0-preview.30.bin\n", + "19-10-2023 14:45 1.601.200 ESP32_GENERIC-SPIRAM-v1.22.0-preview.31.bin\n", + "19-10-2023 14:45 1.601.200 ESP32_GENERIC-SPIRAM-v1.22.0-preview.32.bin\n", + "30-12-2023 00:28 1.614.576 ESP32_GENERIC-SPIRAM-v1.22.0.bin\n", + "03-01-2024 11:55 1.614.624 ESP32_GENERIC-SPIRAM-v1.23.0-preview.6.bin\n", + "19-10-2023 14:45 1.653.872 ESP32_GENERIC-UNICORE-v1.21.0.bin\n", + "19-10-2023 14:45 1.654.032 ESP32_GENERIC-UNICORE-v1.22.0-preview.27.bin\n", + "30-12-2023 00:28 1.728.880 ESP32_GENERIC-UNICORE-v1.22.0-preview.278.bin\n", + "30-12-2023 00:28 1.729.200 ESP32_GENERIC-UNICORE-v1.22.0-preview.281.bin\n", + "30-12-2023 00:28 1.729.248 ESP32_GENERIC-UNICORE-v1.22.0-preview.283.bin\n", + "30-12-2023 00:28 1.729.232 ESP32_GENERIC-UNICORE-v1.22.0-preview.289.bin\n", + "19-10-2023 14:45 1.654.032 ESP32_GENERIC-UNICORE-v1.22.0-preview.30.bin\n", + "19-10-2023 14:45 1.654.032 ESP32_GENERIC-UNICORE-v1.22.0-preview.31.bin\n", + "19-10-2023 14:45 1.654.032 ESP32_GENERIC-UNICORE-v1.22.0-preview.32.bin\n", + "30-12-2023 00:28 1.729.152 ESP32_GENERIC-UNICORE-v1.22.0.bin\n", + "03-01-2024 11:55 1.729.232 ESP32_GENERIC-UNICORE-v1.23.0-preview.6.bin\n", + "19-10-2023 14:45 1.661.872 ESP32_GENERIC-v1.21.0.bin\n", + "19-10-2023 14:45 1.662.032 ESP32_GENERIC-v1.22.0-preview.27.bin\n", + "30-12-2023 00:28 1.737.408 ESP32_GENERIC-v1.22.0-preview.278.bin\n", + "30-12-2023 00:28 1.737.696 ESP32_GENERIC-v1.22.0-preview.281.bin\n", + "30-12-2023 00:28 1.737.760 ESP32_GENERIC-v1.22.0-preview.283.bin\n", + "30-12-2023 00:28 1.737.728 ESP32_GENERIC-v1.22.0-preview.289.bin\n", + "19-10-2023 14:45 1.662.032 ESP32_GENERIC-v1.22.0-preview.30.bin\n", + "19-10-2023 14:45 1.662.032 ESP32_GENERIC-v1.22.0-preview.31.bin\n", + "19-10-2023 14:45 1.662.032 ESP32_GENERIC-v1.22.0-preview.32.bin\n", + "30-12-2023 00:28 1.737.664 ESP32_GENERIC-v1.22.0.bin\n", + "03-01-2024 11:55 1.737.728 ESP32_GENERIC-v1.23.0-preview.6.bin\n", + "03-01-2024 11:55 1.561.184 ESP32_GENERIC_S3-SPIRAM_OCT-v1.21.0.bin\n", + "30-12-2023 00:29 1.631.216 ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.278.bin\n", + "30-12-2023 00:29 1.631.536 ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.281.bin\n", + "30-12-2023 00:29 1.631.600 ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.283.bin\n", + "30-12-2023 00:29 1.631.584 ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.289.bin\n", + "30-12-2023 00:29 1.631.504 ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0.bin\n", + "03-01-2024 11:55 1.631.584 ESP32_GENERIC_S3-SPIRAM_OCT-v1.23.0-preview.6.bin\n", + "03-01-2024 11:55 1.559.472 ESP32_GENERIC_S3-v1.21.0.bin\n", + "30-12-2023 00:29 1.627.952 ESP32_GENERIC_S3-v1.22.0-preview.278.bin\n", + "30-12-2023 00:29 1.628.272 ESP32_GENERIC_S3-v1.22.0-preview.281.bin\n", + "30-12-2023 00:29 1.628.320 ESP32_GENERIC_S3-v1.22.0-preview.283.bin\n", + "30-12-2023 00:28 1.628.320 ESP32_GENERIC_S3-v1.22.0-preview.289.bin\n", + "30-12-2023 00:28 1.628.240 ESP32_GENERIC_S3-v1.22.0.bin\n", + "03-01-2024 11:55 1.628.304 ESP32_GENERIC_S3-v1.23.0-preview.6.bin\n", + " 69 File(s) 111.571.760 bytes\n", + " 2 Dir(s) 348.284.379.136 bytes free\n" ] - } - ], - "source": [ - "!mpremote devs" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ + }, { - "name": "stdout", + "name": "stderr", "output_type": "stream", "text": [ - "esptool.py v4.6.2\n", - "Serial port COM6\n", - "Connecting......\n", - "Chip is ESP32-D0WD (revision v1.0)\n", - "Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None\n", - "Crystal is 40MHz\n", - "MAC: b4:e6:2d:df:40:8d\n", - "Uploading stub...\n", - "Running stub...\n", - "Stub running...\n", - "Configuring flash size...\n", - "Flash will be erased from 0x00001000 to 0x0018bfff...\n", - "Compressed 1614624 bytes to 1055696...\n", - "Writing at 0x00001000... (1 %)\n", - "Writing at 0x00010a5e... (3 %)\n", - "Writing at 0x00018790... (4 %)\n", - "Writing at 0x000205a9... (6 %)\n", - "Writing at 0x0002684e... (7 %)\n", - "Writing at 0x0002fbb1... (9 %)\n", - "Writing at 0x00039936... (10 %)\n", - "Writing at 0x0003f7ce... (12 %)\n", - "Writing at 0x0004bc0d... (13 %)\n", - "Writing at 0x000515d9... (15 %)\n", - "Writing at 0x00056c57... (16 %)\n", - "Writing at 0x0005bf86... (18 %)\n", - "Writing at 0x00061230... (20 %)\n", - "Writing at 0x00066429... (21 %)\n", - "Writing at 0x0006b602... (23 %)\n", - "Writing at 0x00070ab8... (24 %)\n", - "Writing at 0x00075967... (26 %)\n", - "Writing at 0x0007aa31... (27 %)\n", - "Writing at 0x00081627... (29 %)\n", - "Writing at 0x00086ead... (30 %)\n", - "Writing at 0x0008c367... (32 %)\n", - "Writing at 0x00091e5a... (33 %)\n", - "Writing at 0x00097de4... (35 %)\n", - "Writing at 0x0009d681... (36 %)\n", - "Writing at 0x000a3295... (38 %)\n", - "Writing at 0x000a91fb... (40 %)\n", - "Writing at 0x000af5bb... (41 %)\n", - "Writing at 0x000b5347... (43 %)\n", - "Writing at 0x000ba99a... (44 %)\n", - "Writing at 0x000c0140... (46 %)\n", - "Writing at 0x000c5c8e... (47 %)\n", - "Writing at 0x000cbc50... (49 %)\n", - "Writing at 0x000d171c... (50 %)\n", - "Writing at 0x000d68a2... (52 %)\n", - "Writing at 0x000dbe93... (53 %)\n", - "Writing at 0x000e1181... (55 %)\n", - "Writing at 0x000e69fb... (56 %)\n", - "Writing at 0x000ec3eb... (58 %)\n", - "Writing at 0x000f18e5... (60 %)\n", - "Writing at 0x000f6a94... (61 %)\n", - "Writing at 0x000fc862... (63 %)\n", - "Writing at 0x001019dd... (64 %)\n", - "Writing at 0x00106fef... (66 %)\n", - "Writing at 0x0010c8ab... (67 %)\n", - "Writing at 0x00111ff1... (69 %)\n", - "Writing at 0x00117970... (70 %)\n", - "Writing at 0x0011cded... (72 %)\n", - "Writing at 0x00122154... (73 %)\n", - "Writing at 0x00127538... (75 %)\n", - "Writing at 0x0012c8d3... (76 %)\n", - "Writing at 0x00131f88... (78 %)\n", - "Writing at 0x001376a8... (80 %)\n", - "Writing at 0x0013d61b... (81 %)\n", - "Writing at 0x00143168... (83 %)\n", - "Writing at 0x00148c86... (84 %)\n", - "Writing at 0x0014fc61... (86 %)\n", - "Writing at 0x00158bb6... (87 %)\n", - "Writing at 0x00160b5e... (89 %)\n", - "Writing at 0x00166caa... (90 %)\n", - "Writing at 0x0016be53... (92 %)\n", - "Writing at 0x00172329... (93 %)\n", - "Writing at 0x00177896... (95 %)\n", - "Writing at 0x0017d43b... (96 %)\n", - "Writing at 0x00182bf6... (98 %)\n", - "Writing at 0x00188b28... (100 %)\n", - "Wrote 1614624 bytes (1055696 compressed) at 0x00001000 in 93.1 seconds (effective 138.7 kbit/s)...\n", - "Hash of data verified.\n", - "\n", - "Leaving...\n", - "Hard resetting via RTS pin...\n" + "File Not Found\n" ] } ], "source": [ - "serialport = \"COM6\"\n", - "# !esptool --chip esp32 --port {serialport} erase_flash\n", - "# !esptool --chip esp32 --port {serialport} write_flash -z 0x1000 \"firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0.bin\"\n", - "!esptool --chip esp32 --port {serialport} write_flash -z 0x1000 \"firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.0-preview.289.bin\"" + "!dir -l firmware\\esp32" ] }, { From 91394e70a168cfea954f0137faf38d769ae372e8 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Wed, 3 Jan 2024 16:36:06 +0100 Subject: [PATCH 28/68] chore:cleanup Signed-off-by: Jos Verlinde --- scripts/Docstrings_check.ipynb | 71 +- scripts/docstrings.csv | 185 +-- scripts/docstrings.json | 1869 ++++++++++++++++++++----------- scripts/quick_check_array.ipynb | 198 ---- scripts/requirements.ps1 | 31 - 5 files changed, 1349 insertions(+), 1005 deletions(-) delete mode 100644 scripts/quick_check_array.ipynb delete mode 100644 scripts/requirements.ps1 diff --git a/scripts/Docstrings_check.ipynb b/scripts/Docstrings_check.ipynb index 5468b3186..4df60bb83 100644 --- a/scripts/Docstrings_check.ipynb +++ b/scripts/Docstrings_check.ipynb @@ -18,7 +18,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -31,7 +31,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -58,7 +58,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -109,7 +109,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -674,7 +674,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "168\n" + "197\n" ] } ], @@ -732,7 +732,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -753,7 +753,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ @@ -769,7 +769,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -782,7 +782,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -839,20 +839,20 @@ " 1.00\n", " 0.96\n", " 0.97\n", - " {'def': 911, 'class': 116, 'module': 55}\n", + " {'def': 919, 'class': 120, 'module': 55}\n", " {'module': 0, 'class': 5, 'def': 24}\n", " \n", " \n", " 2\n", - " micropython-latest-esp32--OLD\n", + " micropython-latest-esp32-ESP32_GENERIC-merged\n", " ..\\repos\\micropython-stubs\\stubs\\micropython-l...\n", " 99.99.99\n", " esp32\n", - " 0.52\n", - " 0.29\n", - " 0.11\n", - " {'def': 2100, 'class': 331, 'module': 170}\n", - " {'module': 81, 'class': 234, 'def': 1874}\n", + " 0.84\n", + " 0.71\n", + " 0.59\n", + " {'def': 2248, 'class': 385, 'module': 174}\n", + " {'module': 28, 'class': 110, 'def': 918}\n", " \n", " \n", " 3\n", @@ -883,12 +883,12 @@ "" ], "text/plain": [ - " folder \\\n", - "0 micropython-core \n", - "1 micropython-latest-docstubs \n", - "2 micropython-latest-esp32--OLD \n", - "3 micropython-latest-esp32-merged \n", - "4 micropython-latest-esp8266-merged \n", + " folder \\\n", + "0 micropython-core \n", + "1 micropython-latest-docstubs \n", + "2 micropython-latest-esp32-ESP32_GENERIC-merged \n", + "3 micropython-latest-esp32-merged \n", + "4 micropython-latest-esp8266-merged \n", "\n", " path version port \\\n", "0 ..\\repos\\micropython-stubs\\stubs\\micropython-core core unknown \n", @@ -899,20 +899,20 @@ "\n", " module class def counts \\\n", "0 1.00 1.00 1.00 {'def': 14, 'class': 1, 'module': 2} \n", - "1 1.00 0.96 0.97 {'def': 911, 'class': 116, 'module': 55} \n", - "2 0.52 0.29 0.11 {'def': 2100, 'class': 331, 'module': 170} \n", + "1 1.00 0.96 0.97 {'def': 919, 'class': 120, 'module': 55} \n", + "2 0.84 0.71 0.59 {'def': 2248, 'class': 385, 'module': 174} \n", "3 0.83 0.70 0.58 {'def': 2236, 'class': 377, 'module': 174} \n", "4 0.89 0.80 0.62 {'def': 1322, 'class': 166, 'module': 116} \n", "\n", - " missing \n", - "0 {'module': 0, 'class': 0, 'def': 0} \n", - "1 {'module': 0, 'class': 5, 'def': 24} \n", - "2 {'module': 81, 'class': 234, 'def': 1874} \n", - "3 {'module': 30, 'class': 112, 'def': 950} \n", - "4 {'module': 13, 'class': 34, 'def': 498} " + " missing \n", + "0 {'module': 0, 'class': 0, 'def': 0} \n", + "1 {'module': 0, 'class': 5, 'def': 24} \n", + "2 {'module': 28, 'class': 110, 'def': 918} \n", + "3 {'module': 30, 'class': 112, 'def': 950} \n", + "4 {'module': 13, 'class': 34, 'def': 498} " ] }, - "execution_count": 8, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -920,13 +920,6 @@ "source": [ "df.head()" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -945,7 +938,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.7" } }, "nbformat": 4, diff --git a/scripts/docstrings.csv b/scripts/docstrings.csv index 9de98802a..d9c464e7c 100644 --- a/scripts/docstrings.csv +++ b/scripts/docstrings.csv @@ -1,18 +1,21 @@ folder,path,version,port,module,class,def,counts,missing micropython-core,..\repos\micropython-stubs\stubs\micropython-core,core,unknown,1.0,1.0,1.0,"{'def': 14, 'class': 1, 'module': 2}","{'module': 0, 'class': 0, 'def': 0}" -micropython-latest-docstubs,..\repos\micropython-stubs\stubs\micropython-latest-docstubs,99.99.99,docstubs,1.0,0.96,0.97,"{'def': 911, 'class': 116, 'module': 55}","{'module': 0, 'class': 5, 'def': 24}" -micropython-latest-esp32--OLD,..\repos\micropython-stubs\stubs\micropython-latest-esp32--OLD,99.99.99,esp32,0.52,0.29,0.11,"{'def': 2100, 'class': 331, 'module': 170}","{'module': 81, 'class': 234, 'def': 1874}" +micropython-latest-docstubs,..\repos\micropython-stubs\stubs\micropython-latest-docstubs,99.99.99,docstubs,1.0,0.96,0.97,"{'def': 919, 'class': 120, 'module': 55}","{'module': 0, 'class': 5, 'def': 24}" +micropython-latest-esp32-ESP32_GENERIC-merged,..\repos\micropython-stubs\stubs\micropython-latest-esp32-ESP32_GENERIC-merged,99.99.99,esp32,0.84,0.71,0.59,"{'def': 2248, 'class': 385, 'module': 174}","{'module': 28, 'class': 110, 'def': 918}" micropython-latest-esp32-merged,..\repos\micropython-stubs\stubs\micropython-latest-esp32-merged,99.99.99,esp32,0.83,0.7,0.58,"{'def': 2236, 'class': 377, 'module': 174}","{'module': 30, 'class': 112, 'def': 950}" micropython-latest-esp8266-merged,..\repos\micropython-stubs\stubs\micropython-latest-esp8266-merged,99.99.99,esp8266,0.89,0.8,0.62,"{'def': 1322, 'class': 166, 'module': 116}","{'module': 13, 'class': 34, 'def': 498}" -micropython-latest-frozen,..\repos\micropython-stubs\stubs\micropython-latest-frozen,99.99.99,frozen,0.14,0.12,0.33,"{'def': 19581, 'class': 2971, 'module': 2327}","{'module': 2004, 'class': 2626, 'def': 13158}" +micropython-latest-frozen,..\repos\micropython-stubs\stubs\micropython-latest-frozen,99.99.99,frozen,0.26,0.17,0.37,"{'def': 20461, 'class': 3084, 'module': 2394}","{'module': 1778, 'class': 2555, 'def': 12977}" micropython-latest-rp2-merged,..\repos\micropython-stubs\stubs\micropython-latest-rp2-merged,99.99.99,rp2,0.91,0.8,0.57,"{'def': 1546, 'class': 359, 'module': 116}","{'module': 11, 'class': 73, 'def': 660}" micropython-latest-rp2-PIMORONI_PICOLIPO_16MB-merged,..\repos\micropython-stubs\stubs\micropython-latest-rp2-PIMORONI_PICOLIPO_16MB-merged,99.99.99,rp2,0.91,0.76,0.57,"{'def': 1546, 'class': 305, 'module': 116}","{'module': 11, 'class': 73, 'def': 660}" +micropython-latest-rp2-RPI_PICO-merged,..\repos\micropython-stubs\stubs\micropython-latest-rp2-RPI_PICO-merged,99.99.99,rp2,0.89,0.82,0.62,"{'def': 1688, 'class': 432, 'module': 128}","{'module': 14, 'class': 79, 'def': 644}" +micropython-latest-rp2-RPI_PICO_W-merged,..\repos\micropython-stubs\stubs\micropython-latest-rp2-RPI_PICO_W-merged,99.99.99,rp2,0.83,0.75,0.57,"{'def': 2288, 'class': 636, 'module': 174}","{'module': 30, 'class': 159, 'def': 978}" micropython-latest-samd-ADAFRUIT_FEATHER_M4_EXPRESS-merged,..\repos\micropython-stubs\stubs\micropython-latest-samd-ADAFRUIT_FEATHER_M4_EXPRESS-merged,99.99.99,samd,0.88,0.84,0.56,"{'def': 1454, 'class': 397, 'module': 102}","{'module': 12, 'class': 64, 'def': 646}" micropython-latest-samd-ADAFRUIT_ITSYBITSY_M4_EXPRESS-merged,..\repos\micropython-stubs\stubs\micropython-latest-samd-ADAFRUIT_ITSYBITSY_M4_EXPRESS-merged,99.99.99,samd,0.88,0.83,0.56,"{'def': 1454, 'class': 371, 'module': 102}","{'module': 12, 'class': 64, 'def': 646}" micropython-latest-samd-MINISAM_M4-merged,..\repos\micropython-stubs\stubs\micropython-latest-samd-MINISAM_M4-merged,99.99.99,samd,0.88,0.82,0.56,"{'def': 1454, 'class': 353, 'module': 102}","{'module': 12, 'class': 64, 'def': 646}" -micropython-latest-samd-SEEED_WIO_TERMINAL-merged,..\repos\micropython-stubs\stubs\micropython-latest-samd-SEEED_WIO_TERMINAL-merged,99.99.99,samd,0.88,0.88,0.56,"{'def': 1454, 'class': 539, 'module': 102}","{'module': 12, 'class': 64, 'def': 646}" +micropython-latest-samd-SEEED_WIO_TERMINAL-merged,..\repos\micropython-stubs\stubs\micropython-latest-samd-SEEED_WIO_TERMINAL-merged,99.99.99,samd,0.87,0.88,0.61,"{'def': 1546, 'class': 624, 'module': 114}","{'module': 15, 'class': 76, 'def': 608}" micropython-latest-stm32-merged,..\repos\micropython-stubs\stubs\micropython-latest-stm32-merged,99.99.99,stm32,0.92,0.89,0.66,"{'def': 2066, 'class': 559, 'module': 118}","{'module': 10, 'class': 62, 'def': 708}" -micropython-latest-stm32-PYBV11-merged,..\repos\micropython-stubs\stubs\micropython-latest-stm32-PYBV11-merged,99.99.99,stm32,0.92,0.89,0.66,"{'def': 2066, 'class': 559, 'module': 118}","{'module': 10, 'class': 62, 'def': 708}" +micropython-latest-stm32-PYBV11-merged,..\repos\micropython-stubs\stubs\micropython-latest-stm32-PYBV11-merged,99.99.99,stm32,0.9,0.89,0.67,"{'def': 2190, 'class': 630, 'module': 124}","{'module': 13, 'class': 72, 'def': 726}" +micropython-latest-webassembly-GENERIC-merged,..\repos\micropython-stubs\stubs\micropython-latest-webassembly-GENERIC-merged,99.99.99,webassembly,0.97,0.77,0.64,"{'def': 688, 'class': 70, 'module': 80}","{'module': 2, 'class': 16, 'def': 246}" micropython-pico-go,..\repos\micropython-stubs\stubs\micropython-pico-go,pico,go,0.81,0.95,0.95,"{'def': 1657, 'class': 404, 'module': 58}","{'module': 11, 'class': 20, 'def': 85}" micropython-ulab,..\repos\micropython-stubs\stubs\micropython-ulab,ulab,unknown,0.5,0.5,0.63,"{'def': 222, 'class': 2, 'module': 18}","{'module': 9, 'class': 1, 'def': 83}" micropython-v1_10-esp32,..\repos\micropython-stubs\stubs\micropython-v1_10-esp32,1.10,esp32,0.52,0.53,0.11,"{'def': 1514, 'class': 229, 'module': 128}","{'module': 62, 'class': 107, 'def': 1350}" @@ -36,7 +39,6 @@ micropython-v1_15-esp32,..\repos\micropython-stubs\stubs\micropython-v1_15-esp32 micropython-v1_15-esp8266,..\repos\micropython-stubs\stubs\micropython-v1_15-esp8266,1.15,esp8266,0.51,0.6,0.11,"{'def': 2015, 'class': 355, 'module': 149}","{'module': 73, 'class': 141, 'def': 1793}" micropython-v1_15-frozen,..\repos\micropython-stubs\stubs\micropython-v1_15-frozen,1.15,frozen,0.16,0.17,0.31,"{'def': 2146, 'class': 328, 'module': 242}","{'module': 204, 'class': 273, 'def': 1489}" micropython-v1_15-pyboard,..\repos\micropython-stubs\stubs\micropython-v1_15-pyboard,1.15,pyboard,0.52,0.77,0.11,"{'def': 2448, 'class': 684, 'module': 116}","{'module': 56, 'class': 155, 'def': 2184}" -micropython-v1_16-docstubs,..\repos\micropython-stubs\stubs\micropython-v1_16-docstubs,1.16,docstubs,1.0,1.0,1.0,"{'def': 0, 'class': 0, 'module': 0}","{'module': 0, 'class': 0, 'def': 0}" micropython-v1_16-esp32,..\repos\micropython-stubs\stubs\micropython-v1_16-esp32,1.16,esp32,0.52,0.6,0.11,"{'def': 2094, 'class': 379, 'module': 150}","{'module': 72, 'class': 150, 'def': 1854}" micropython-v1_16-esp8266,..\repos\micropython-stubs\stubs\micropython-v1_16-esp8266,1.16,esp8266,0.51,0.61,0.11,"{'def': 2021, 'class': 360, 'module': 149}","{'module': 73, 'class': 141, 'def': 1799}" micropython-v1_16-frozen,..\repos\micropython-stubs\stubs\micropython-v1_16-frozen,1.16,frozen,0.17,0.17,0.32,"{'def': 3692, 'class': 580, 'module': 440}","{'module': 365, 'class': 479, 'def': 2502}" @@ -63,77 +65,96 @@ micropython-v1_18-stm32,..\repos\micropython-stubs\stubs\micropython-v1_18-stm32 micropython-v1_18-stm32-merged,..\repos\micropython-stubs\stubs\micropython-v1_18-stm32-merged,1.18,stm32,0.89,0.94,0.65,"{'def': 2028, 'class': 599, 'module': 114}","{'module': 13, 'class': 38, 'def': 712}" micropython-v1_19-docstubs,..\repos\micropython-stubs\stubs\micropython-v1_19-docstubs,1.19,docstubs,1.0,0.95,0.97,"{'def': 813, 'class': 109, 'module': 50}","{'module': 0, 'class': 5, 'def': 25}" micropython-v1_19-frozen,..\repos\micropython-stubs\stubs\micropython-v1_19-frozen,1.19,frozen,0.31,0.35,0.45,"{'def': 4146, 'class': 721, 'module': 473}","{'module': 325, 'class': 468, 'def': 2299}" -micropython-v1_19_1-docstubs,..\repos\micropython-stubs\stubs\micropython-v1_19_1-docstubs,1.19.1,docstubs,1.0,0.95,0.97,"{'def': 813, 'class': 109, 'module': 50}","{'module': 0, 'class': 5, 'def': 25}" -micropython-v1_19_1-esp32,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32,1.19.1,esp32,0.51,0.21,0.1,"{'def': 1890, 'class': 260, 'module': 152}","{'module': 74, 'class': 205, 'def': 1694}" -micropython-v1_19_1-esp32-merged,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32-merged,1.19.1,esp32,0.84,0.73,0.58,"{'def': 1934, 'class': 305, 'module': 150}","{'module': 24, 'class': 82, 'def': 806}" -micropython-v1_19_1-esp32-s3,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32-s3,1.19.1,esp32,1.0,0.33,0.11,"{'def': 1027, 'class': 167, 'module': 75}","{'module': 0, 'class': 112, 'def': 919}" -micropython-v1_19_1-esp32-S3-merged,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32-S3-merged,1.19.1,esp32,1.0,0.79,0.59,"{'def': 974, 'class': 178, 'module': 74}","{'module': 0, 'class': 37, 'def': 396}" -micropython-v1_19_1-esp32-UM_TINYPICO,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32-UM_TINYPICO,1.19.1,esp32,0.91,0.87,0.12,"{'def': 1021, 'class': 213, 'module': 79}","{'module': 7, 'class': 28, 'def': 898}" -micropython-v1_19_1-esp32-UM_TINYPICO-merged,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32-UM_TINYPICO-merged,1.19.1,esp32,0.91,0.88,0.56,"{'def': 1049, 'class': 232, 'module': 79}","{'module': 7, 'class': 28, 'def': 464}" +micropython-v1_19_1-docstubs,..\repos\micropython-stubs\stubs\micropython-v1_19_1-docstubs,1.19.1,docstubs,1.0,0.96,0.97,"{'def': 813, 'class': 113, 'module': 50}","{'module': 0, 'class': 5, 'def': 25}" +micropython-v1_19_1-esp32-GENERIC,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32-GENERIC,1.19.1,esp32,0.51,0.21,0.1,"{'def': 1890, 'class': 260, 'module': 152}","{'module': 74, 'class': 205, 'def': 1694}" +micropython-v1_19_1-esp32-GENERIC-merged,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32-GENERIC-merged,1.19.1,esp32,0.84,0.74,0.58,"{'def': 1934, 'class': 313, 'module': 150}","{'module': 24, 'class': 82, 'def': 806}" +micropython-v1_19_1-esp32-GENERIC_S3,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32-GENERIC_S3,1.19.1,esp32,0.52,0.21,0.1,"{'def': 1977, 'class': 268, 'module': 149}","{'module': 71, 'class': 213, 'def': 1771}" +micropython-v1_19_1-esp32-GENERIC_S3-merged,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32-GENERIC_S3-merged,1.19.1,esp32,0.86,0.76,0.59,"{'def': 1948, 'class': 311, 'module': 148}","{'module': 20, 'class': 74, 'def': 792}" +micropython-v1_19_1-esp32-GENERIC_SPIRAM,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32-GENERIC_SPIRAM,1.19.1,esp32,0.51,0.21,0.1,"{'def': 1890, 'class': 260, 'module': 152}","{'module': 74, 'class': 205, 'def': 1694}" +micropython-v1_19_1-esp32-GENERIC_SPIRAM-merged,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32-GENERIC_SPIRAM-merged,1.19.1,esp32,0.84,0.74,0.58,"{'def': 1934, 'class': 313, 'module': 150}","{'module': 24, 'class': 82, 'def': 806}" +micropython-v1_19_1-esp32-UM_TINYPICO,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32-UM_TINYPICO,1.19.1,esp32,0.52,0.61,0.11,"{'def': 1862, 'class': 302, 'module': 147}","{'module': 71, 'class': 117, 'def': 1654}" +micropython-v1_19_1-esp32-UM_TINYPICO-merged,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp32-UM_TINYPICO-merged,1.19.1,esp32,0.84,0.85,0.6,"{'def': 1866, 'class': 328, 'module': 146}","{'module': 24, 'class': 50, 'def': 744}" micropython-v1_19_1-esp8266,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp8266,1.19.1,esp8266,0.51,0.09,0.1,"{'def': 1368, 'class': 148, 'module': 118}","{'module': 58, 'class': 134, 'def': 1236}" -micropython-v1_19_1-esp8266-merged,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp8266-merged,1.19.1,esp8266,0.89,0.78,0.59,"{'def': 1412, 'class': 178, 'module': 118}","{'module': 13, 'class': 40, 'def': 572}" -micropython-v1_19_1-frozen,..\repos\micropython-stubs\stubs\micropython-v1_19_1-frozen,1.19.1,frozen,0.31,0.35,0.45,"{'def': 4146, 'class': 721, 'module': 473}","{'module': 325, 'class': 468, 'def': 2299}" +micropython-v1_19_1-esp8266-merged,..\repos\micropython-stubs\stubs\micropython-v1_19_1-esp8266-merged,1.19.1,esp8266,0.89,0.78,0.59,"{'def': 1412, 'class': 186, 'module': 118}","{'module': 13, 'class': 40, 'def': 572}" +micropython-v1_19_1-frozen,..\repos\micropython-stubs\stubs\micropython-v1_19_1-frozen,1.19.1,frozen,0.23,0.25,0.41,"{'def': 8120, 'class': 1319, 'module': 935}","{'module': 720, 'class': 991, 'def': 4753}" micropython-v1_19_1-rp2,..\repos\micropython-stubs\stubs\micropython-v1_19_1-rp2,1.19.1,rp2,0.52,0.32,0.12,"{'def': 1992, 'class': 373, 'module': 142}","{'module': 68, 'class': 254, 'def': 1758}" -micropython-v1_19_1-rp2-merged,..\repos\micropython-stubs\stubs\micropython-v1_19_1-rp2-merged,1.19.1,rp2,0.84,0.65,0.54,"{'def': 1974, 'class': 395, 'module': 140}","{'module': 22, 'class': 137, 'def': 902}" +micropython-v1_19_1-rp2-merged,..\repos\micropython-stubs\stubs\micropython-v1_19_1-rp2-merged,1.19.1,rp2,0.84,0.67,0.56,"{'def': 1974, 'class': 403, 'module': 140}","{'module': 22, 'class': 131, 'def': 874}" micropython-v1_19_1-rp2_simple,..\repos\micropython-stubs\stubs\micropython-v1_19_1-rp2_simple,1.19.1,rp2_simple,0.53,0.26,0.1,"{'def': 1357, 'class': 195, 'module': 105}","{'module': 49, 'class': 144, 'def': 1222}" micropython-v1_19_1-stm32,..\repos\micropython-stubs\stubs\micropython-v1_19_1-stm32,1.19.1,stm32,0.51,0.65,0.1,"{'def': 2087, 'class': 549, 'module': 115}","{'module': 56, 'class': 194, 'def': 1888}" -micropython-v1_19_1-stm32-merged,..\repos\micropython-stubs\stubs\micropython-v1_19_1-stm32-merged,1.19.1,stm32,0.89,0.9,0.64,"{'def': 2088, 'class': 573, 'module': 114}","{'module': 12, 'class': 60, 'def': 754}" -micropython-v1_20_0-docstubs,..\repos\micropython-stubs\stubs\micropython-v1_20_0-docstubs,1.20.0,docstubs,1.0,0.95,0.97,"{'def': 823, 'class': 108, 'module': 50}","{'module': 0, 'class': 5, 'def': 24}" -micropython-v1_20_0-esp32,..\repos\micropython-stubs\stubs\micropython-v1_20_0-esp32,1.20.0,esp32,0.52,0.21,0.1,"{'def': 1908, 'class': 262, 'module': 158}","{'module': 76, 'class': 206, 'def': 1710}" -micropython-v1_20_0-esp32-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-esp32-merged,1.20.0,esp32,0.84,0.73,0.61,"{'def': 1966, 'class': 306, 'module': 158}","{'module': 25, 'class': 84, 'def': 764}" -micropython-v1_20_0-esp32-OTA,..\repos\micropython-stubs\stubs\micropython-v1_20_0-esp32-OTA,1.20.0,esp32,0.52,0.21,0.1,"{'def': 1908, 'class': 262, 'module': 158}","{'module': 76, 'class': 206, 'def': 1710}" -micropython-v1_20_0-esp32-OTA-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-esp32-OTA-merged,1.20.0,esp32,0.84,0.73,0.61,"{'def': 1966, 'class': 306, 'module': 158}","{'module': 25, 'class': 84, 'def': 764}" -micropython-v1_20_0-esp32-S3,..\repos\micropython-stubs\stubs\micropython-v1_20_0-esp32-S3,1.20.0,esp32,0.52,0.22,0.1,"{'def': 1896, 'class': 263, 'module': 156}","{'module': 75, 'class': 204, 'def': 1700}" -micropython-v1_20_0-esp32-S3-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-esp32-S3-merged,1.20.0,esp32,0.85,0.72,0.61,"{'def': 1944, 'class': 303, 'module': 156}","{'module': 24, 'class': 84, 'def': 766}" -micropython-v1_20_0-frozen,..\repos\micropython-stubs\stubs\micropython-v1_20_0-frozen,1.20.0,frozen,0.15,0.15,0.32,"{'def': 18676, 'class': 2959, 'module': 2019}","{'module': 1711, 'class': 2517, 'def': 12774}" -micropython-v1_20_0-rp2,..\repos\micropython-stubs\stubs\micropython-v1_20_0-rp2,1.20.0,rp2,0.54,0.52,0.11,"{'def': 1518, 'class': 339, 'module': 116}","{'module': 53, 'class': 164, 'def': 1354}" -micropython-v1_20_0-rp2-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-rp2-merged,1.20.0,rp2,0.91,0.81,0.57,"{'def': 1546, 'class': 363, 'module': 116}","{'module': 11, 'class': 69, 'def': 660}" +micropython-v1_19_1-stm32-merged,..\repos\micropython-stubs\stubs\micropython-v1_19_1-stm32-merged,1.19.1,stm32,0.89,0.9,0.64,"{'def': 2088, 'class': 581, 'module': 114}","{'module': 12, 'class': 60, 'def': 754}" +micropython-v1_20_0-docstubs,..\repos\micropython-stubs\stubs\micropython-v1_20_0-docstubs,1.20.0,docstubs,1.0,0.96,0.97,"{'def': 823, 'class': 112, 'module': 50}","{'module': 0, 'class': 5, 'def': 24}" +micropython-v1_20_0-esp32,..\repos\micropython-stubs\stubs\micropython-v1_20_0-esp32,1.20.0,esp32,0.68,0.49,0.36,"{'def': 3874, 'class': 568, 'module': 316}","{'module': 101, 'class': 290, 'def': 2474}" +micropython-v1_20_0-esp32-GENERIC,..\repos\micropython-stubs\stubs\micropython-v1_20_0-esp32-GENERIC,1.20.0,esp32,0.52,0.21,0.1,"{'def': 1908, 'class': 262, 'module': 158}","{'module': 76, 'class': 206, 'def': 1710}" +micropython-v1_20_0-esp32-GENERIC-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-esp32-GENERIC-merged,1.20.0,esp32,0.84,0.73,0.61,"{'def': 1966, 'class': 314, 'module': 158}","{'module': 25, 'class': 84, 'def': 764}" +micropython-v1_20_0-esp32-GENERIC_OTA,..\repos\micropython-stubs\stubs\micropython-v1_20_0-esp32-GENERIC_OTA,1.20.0,esp32,0.52,0.21,0.1,"{'def': 1908, 'class': 262, 'module': 158}","{'module': 76, 'class': 206, 'def': 1710}" +micropython-v1_20_0-esp32-GENERIC_OTA-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-esp32-GENERIC_OTA-merged,1.20.0,esp32,0.84,0.73,0.61,"{'def': 1966, 'class': 314, 'module': 158}","{'module': 25, 'class': 84, 'def': 764}" +micropython-v1_20_0-esp32-GENERIC_S3,..\repos\micropython-stubs\stubs\micropython-v1_20_0-esp32-GENERIC_S3,1.20.0,esp32,0.52,0.22,0.1,"{'def': 1896, 'class': 263, 'module': 156}","{'module': 75, 'class': 204, 'def': 1700}" +micropython-v1_20_0-esp32-GENERIC_S3-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-esp32-GENERIC_S3-merged,1.20.0,esp32,0.85,0.73,0.61,"{'def': 1944, 'class': 311, 'module': 156}","{'module': 24, 'class': 84, 'def': 766}" +micropython-v1_20_0-frozen,..\repos\micropython-stubs\stubs\micropython-v1_20_0-frozen,1.20.0,frozen,0.15,0.16,0.32,"{'def': 18676, 'class': 2964, 'module': 2019}","{'module': 1711, 'class': 2475, 'def': 12639}" micropython-v1_20_0-rp2-PICO,..\repos\micropython-stubs\stubs\micropython-v1_20_0-rp2-PICO,1.20.0,rp2,0.54,0.52,0.11,"{'def': 1518, 'class': 339, 'module': 116}","{'module': 53, 'class': 164, 'def': 1354}" -micropython-v1_20_0-rp2-PICO-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-rp2-PICO-merged,1.20.0,rp2,0.91,0.81,0.57,"{'def': 1546, 'class': 363, 'module': 116}","{'module': 11, 'class': 69, 'def': 660}" +micropython-v1_20_0-rp2-PICO-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-rp2-PICO-merged,1.20.0,rp2,0.91,0.83,0.59,"{'def': 1546, 'class': 371, 'module': 116}","{'module': 11, 'class': 63, 'def': 630}" micropython-v1_20_0-rp2-PICO_W,..\repos\micropython-stubs\stubs\micropython-v1_20_0-rp2-PICO_W,1.20.0,rp2,0.54,0.51,0.1,"{'def': 1748, 'class': 365, 'module': 138}","{'module': 64, 'class': 178, 'def': 1570}" -micropython-v1_20_0-rp2-PICO_W-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-rp2-PICO_W-merged,1.20.0,rp2,0.88,0.8,0.56,"{'def': 1776, 'class': 389, 'module': 138}","{'module': 17, 'class': 77, 'def': 780}" +micropython-v1_20_0-rp2-PICO_W-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-rp2-PICO_W-merged,1.20.0,rp2,0.88,0.82,0.58,"{'def': 1776, 'class': 397, 'module': 138}","{'module': 17, 'class': 71, 'def': 750}" micropython-v1_20_0-rp2-PIMORONI_PICOLIPO_16MB,..\repos\micropython-stubs\stubs\micropython-v1_20_0-rp2-PIMORONI_PICOLIPO_16MB,1.20.0,rp2,0.54,0.42,0.11,"{'def': 1518, 'class': 285, 'module': 116}","{'module': 53, 'class': 164, 'def': 1354}" -micropython-v1_20_0-rp2-PIMORONI_PICOLIPO_16MB-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-rp2-PIMORONI_PICOLIPO_16MB-merged,1.20.0,rp2,0.91,0.78,0.57,"{'def': 1546, 'class': 309, 'module': 116}","{'module': 11, 'class': 69, 'def': 660}" +micropython-v1_20_0-rp2-PIMORONI_PICOLIPO_16MB-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-rp2-PIMORONI_PICOLIPO_16MB-merged,1.20.0,rp2,0.91,0.8,0.59,"{'def': 1546, 'class': 317, 'module': 116}","{'module': 11, 'class': 63, 'def': 630}" micropython-v1_20_0-samd-ADAFRUIT_FEATHER_M4_EXPRESS,..\repos\micropython-stubs\stubs\micropython-v1_20_0-samd-ADAFRUIT_FEATHER_M4_EXPRESS,1.20.0,samd,0.52,0.61,0.11,"{'def': 1426, 'class': 377, 'module': 102}","{'module': 49, 'class': 148, 'def': 1276}" -micropython-v1_20_0-samd-ADAFRUIT_FEATHER_M4_EXPRESS-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-samd-ADAFRUIT_FEATHER_M4_EXPRESS-merged,1.20.0,samd,0.88,0.85,0.56,"{'def': 1454, 'class': 401, 'module': 102}","{'module': 12, 'class': 60, 'def': 646}" +micropython-v1_20_0-samd-ADAFRUIT_FEATHER_M4_EXPRESS-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-samd-ADAFRUIT_FEATHER_M4_EXPRESS-merged,1.20.0,samd,0.88,0.85,0.56,"{'def': 1454, 'class': 409, 'module': 102}","{'module': 12, 'class': 60, 'def': 646}" micropython-v1_20_0-samd-ADAFRUIT_ITSYBITSY_M4_EXPRESS,..\repos\micropython-stubs\stubs\micropython-v1_20_0-samd-ADAFRUIT_ITSYBITSY_M4_EXPRESS,1.20.0,samd,0.52,0.58,0.11,"{'def': 1426, 'class': 351, 'module': 102}","{'module': 49, 'class': 148, 'def': 1276}" -micropython-v1_20_0-samd-ADAFRUIT_ITSYBITSY_M4_EXPRESS-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-samd-ADAFRUIT_ITSYBITSY_M4_EXPRESS-merged,1.20.0,samd,0.88,0.84,0.56,"{'def': 1454, 'class': 375, 'module': 102}","{'module': 12, 'class': 60, 'def': 646}" +micropython-v1_20_0-samd-ADAFRUIT_ITSYBITSY_M4_EXPRESS-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-samd-ADAFRUIT_ITSYBITSY_M4_EXPRESS-merged,1.20.0,samd,0.88,0.84,0.56,"{'def': 1454, 'class': 383, 'module': 102}","{'module': 12, 'class': 60, 'def': 646}" micropython-v1_20_0-samd-MINISAM_M4,..\repos\micropython-stubs\stubs\micropython-v1_20_0-samd-MINISAM_M4,1.20.0,samd,0.52,0.56,0.11,"{'def': 1426, 'class': 333, 'module': 102}","{'module': 49, 'class': 148, 'def': 1276}" -micropython-v1_20_0-samd-MINISAM_M4-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-samd-MINISAM_M4-merged,1.20.0,samd,0.88,0.83,0.56,"{'def': 1454, 'class': 357, 'module': 102}","{'module': 12, 'class': 60, 'def': 646}" +micropython-v1_20_0-samd-MINISAM_M4-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-samd-MINISAM_M4-merged,1.20.0,samd,0.88,0.84,0.56,"{'def': 1454, 'class': 365, 'module': 102}","{'module': 12, 'class': 60, 'def': 646}" micropython-v1_20_0-samd-SEEED_WIO_TERMINAL,..\repos\micropython-stubs\stubs\micropython-v1_20_0-samd-SEEED_WIO_TERMINAL,1.20.0,samd,0.52,0.71,0.11,"{'def': 1426, 'class': 519, 'module': 102}","{'module': 49, 'class': 148, 'def': 1276}" -micropython-v1_20_0-samd-SEEED_WIO_TERMINAL-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-samd-SEEED_WIO_TERMINAL-merged,1.20.0,samd,0.88,0.89,0.56,"{'def': 1454, 'class': 543, 'module': 102}","{'module': 12, 'class': 60, 'def': 646}" +micropython-v1_20_0-samd-SEEED_WIO_TERMINAL-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-samd-SEEED_WIO_TERMINAL-merged,1.20.0,samd,0.88,0.89,0.56,"{'def': 1454, 'class': 551, 'module': 102}","{'module': 12, 'class': 60, 'def': 646}" micropython-v1_20_0-stm32,..\repos\micropython-stubs\stubs\micropython-v1_20_0-stm32,1.20.0,stm32,0.53,0.66,0.09,"{'def': 2034, 'class': 539, 'module': 118}","{'module': 56, 'class': 184, 'def': 1844}" -micropython-v1_20_0-stm32-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-stm32-merged,1.20.0,stm32,0.9,0.9,0.65,"{'def': 2066, 'class': 563, 'module': 118}","{'module': 12, 'class': 58, 'def': 720}" micropython-v1_20_0-stm32-PYBV11,..\repos\micropython-stubs\stubs\micropython-v1_20_0-stm32-PYBV11,1.20.0,stm32,0.53,0.66,0.09,"{'def': 2034, 'class': 539, 'module': 118}","{'module': 56, 'class': 184, 'def': 1844}" -micropython-v1_20_0-stm32-PYBV11-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-stm32-PYBV11-merged,1.20.0,stm32,0.9,0.9,0.65,"{'def': 2066, 'class': 563, 'module': 118}","{'module': 12, 'class': 58, 'def': 720}" -micropython-v1_21_0-docstubs,..\repos\micropython-stubs\stubs\micropython-v1_21_0-docstubs,1.21.0,docstubs,1.0,0.96,0.97,"{'def': 915, 'class': 124, 'module': 55}","{'module': 0, 'class': 5, 'def': 24}" -micropython-v1_21_0-esp32,..\repos\micropython-stubs\stubs\micropython-v1_21_0-esp32,1.21.0,esp32,0.51,0.29,0.1,"{'def': 2220, 'class': 339, 'module': 179}","{'module': 87, 'class': 242, 'def': 1988}" +micropython-v1_20_0-stm32-PYBV11-merged,..\repos\micropython-stubs\stubs\micropython-v1_20_0-stm32-PYBV11-merged,1.20.0,stm32,0.9,0.9,0.65,"{'def': 2066, 'class': 571, 'module': 118}","{'module': 12, 'class': 58, 'def': 720}" +micropython-v1_21_0-docstubs,..\repos\micropython-stubs\stubs\micropython-v1_21_0-docstubs,1.21.0,docstubs,1.0,0.96,0.97,"{'def': 915, 'class': 128, 'module': 55}","{'module': 0, 'class': 5, 'def': 24}" micropython-v1_21_0-esp32-ESP32_GENERIC,..\repos\micropython-stubs\stubs\micropython-v1_21_0-esp32-ESP32_GENERIC,1.21.0,esp32,0.51,0.29,0.1,"{'def': 2220, 'class': 339, 'module': 179}","{'module': 87, 'class': 242, 'def': 1988}" -micropython-v1_21_0-esp32-ESP32_GENERIC-merged,..\repos\micropython-stubs\stubs\micropython-v1_21_0-esp32-ESP32_GENERIC-merged,1.21.0,esp32,0.83,0.7,0.58,"{'def': 2236, 'class': 377, 'module': 174}","{'module': 30, 'class': 112, 'def': 950}" -micropython-v1_21_0-esp32-merged,..\repos\micropython-stubs\stubs\micropython-v1_21_0-esp32-merged,1.21.0,esp32,0.83,0.7,0.58,"{'def': 2236, 'class': 377, 'module': 174}","{'module': 30, 'class': 112, 'def': 950}" -micropython-v1_21_0-frozen,..\repos\micropython-stubs\stubs\micropython-v1_21_0-frozen,1.21.0,frozen,0.23,0.15,0.36,"{'def': 19937, 'class': 2989, 'module': 2338}","{'module': 1795, 'class': 2554, 'def': 12856}" +micropython-v1_21_0-esp32-ESP32_GENERIC-merged,..\repos\micropython-stubs\stubs\micropython-v1_21_0-esp32-ESP32_GENERIC-merged,1.21.0,esp32,0.84,0.71,0.59,"{'def': 2248, 'class': 385, 'module': 174}","{'module': 28, 'class': 110, 'def': 918}" +micropython-v1_21_0-frozen,..\repos\micropython-stubs\stubs\micropython-v1_21_0-frozen,1.21.0,frozen,0.23,0.17,0.36,"{'def': 19937, 'class': 2996, 'module': 2338}","{'module': 1795, 'class': 2494, 'def': 12679}" micropython-v1_21_0-rp2-RPI_PICO,..\repos\micropython-stubs\stubs\micropython-v1_21_0-rp2-RPI_PICO,1.21.0,rp2,0.54,0.53,0.11,"{'def': 1648, 'class': 402, 'module': 128}","{'module': 59, 'class': 188, 'def': 1464}" -micropython-v1_21_0-rp2-RPI_PICO-merged,..\repos\micropython-stubs\stubs\micropython-v1_21_0-rp2-RPI_PICO-merged,1.21.0,rp2,0.88,0.78,0.55,"{'def': 1676, 'class': 424, 'module': 128}","{'module': 16, 'class': 95, 'def': 754}" +micropython-v1_21_0-rp2-RPI_PICO-merged,..\repos\micropython-stubs\stubs\micropython-v1_21_0-rp2-RPI_PICO-merged,1.21.0,rp2,0.89,0.82,0.62,"{'def': 1688, 'class': 432, 'module': 128}","{'module': 14, 'class': 79, 'def': 644}" micropython-v1_21_0-rp2-RPI_PICO_W,..\repos\micropython-stubs\stubs\micropython-v1_21_0-rp2-RPI_PICO_W,1.21.0,rp2,0.53,0.52,0.12,"{'def': 2248, 'class': 602, 'module': 176}","{'module': 83, 'class': 286, 'def': 1978}" -micropython-v1_21_0-rp2-RPI_PICO_W-merged,..\repos\micropython-stubs\stubs\micropython-v1_21_0-rp2-RPI_PICO_W-merged,1.21.0,rp2,0.82,0.72,0.52,"{'def': 2276, 'class': 628, 'module': 174}","{'module': 32, 'class': 175, 'def': 1088}" -micropython-v1_21_0-samd-SEEED_WIO_TERMINAL,..\repos\micropython-stubs\stubs\micropython-v1_21_0-samd-SEEED_WIO_TERMINAL,1.21.0,samd,0.52,0.72,0.11,"{'def': 1506, 'class': 594, 'module': 114}","{'module': 55, 'class': 168, 'def': 1340}" -micropython-v1_21_0-samd-SEEED_WIO_TERMINAL-merged,..\repos\micropython-stubs\stubs\micropython-v1_21_0-samd-SEEED_WIO_TERMINAL-merged,1.21.0,samd,0.85,0.86,0.55,"{'def': 1534, 'class': 616, 'module': 114}","{'module': 17, 'class': 86, 'def': 688}" +micropython-v1_21_0-rp2-RPI_PICO_W-merged,..\repos\micropython-stubs\stubs\micropython-v1_21_0-rp2-RPI_PICO_W-merged,1.21.0,rp2,0.83,0.75,0.57,"{'def': 2288, 'class': 636, 'module': 174}","{'module': 30, 'class': 159, 'def': 978}" +micropython-v1_21_0-samd-SEEED_WIO_TERMINAL,..\repos\micropython-stubs\stubs\micropython-v1_21_0-samd-SEEED_WIO_TERMINAL,1.21.0,samd,0.52,0.71,0.11,"{'def': 1534, 'class': 596, 'module': 116}","{'module': 56, 'class': 170, 'def': 1366}" +micropython-v1_21_0-samd-SEEED_WIO_TERMINAL-merged,..\repos\micropython-stubs\stubs\micropython-v1_21_0-samd-SEEED_WIO_TERMINAL-merged,1.21.0,samd,0.86,0.88,0.6,"{'def': 1574, 'class': 626, 'module': 116}","{'module': 16, 'class': 78, 'def': 634}" micropython-v1_21_0-stm32-PYBV11,..\repos\micropython-stubs\stubs\micropython-v1_21_0-stm32-PYBV11,1.21.0,stm32,0.52,0.66,0.1,"{'def': 2146, 'class': 600, 'module': 124}","{'module': 60, 'class': 206, 'def': 1938}" -micropython-v1_21_0-stm32-PYBV11-merged,..\repos\micropython-stubs\stubs\micropython-v1_21_0-stm32-PYBV11-merged,1.21.0,stm32,0.88,0.87,0.63,"{'def': 2178, 'class': 622, 'module': 124}","{'module': 15, 'class': 82, 'def': 806}" +micropython-v1_21_0-stm32-PYBV11-merged,..\repos\micropython-stubs\stubs\micropython-v1_21_0-stm32-PYBV11-merged,1.21.0,stm32,0.9,0.89,0.67,"{'def': 2190, 'class': 630, 'module': 124}","{'module': 13, 'class': 72, 'def': 726}" +micropython-v1_21_0-webassembly-GENERIC,..\repos\micropython-stubs\stubs\micropython-v1_21_0-webassembly-GENERIC,1.21.0,webassembly,0.51,0.0,0.07,"{'def': 664, 'class': 44, 'module': 80}","{'module': 39, 'class': 44, 'def': 620}" +micropython-v1_21_0-webassembly-GENERIC-merged,..\repos\micropython-stubs\stubs\micropython-v1_21_0-webassembly-GENERIC-merged,1.21.0,webassembly,0.97,0.77,0.64,"{'def': 688, 'class': 70, 'module': 80}","{'module': 2, 'class': 16, 'def': 246}" +micropython-v1_22_0-docstubs,..\repos\micropython-stubs\stubs\micropython-v1_22_0-docstubs,1.22.0,docstubs,1.0,0.96,0.97,"{'def': 919, 'class': 120, 'module': 55}","{'module': 0, 'class': 5, 'def': 24}" +micropython-v1_22_0-esp32-ESP32_GENERIC,..\repos\micropython-stubs\stubs\micropython-v1_22_0-esp32-ESP32_GENERIC,1.22.0,esp32,0.52,0.3,0.11,"{'def': 2242, 'class': 353, 'module': 178}","{'module': 85, 'class': 248, 'def': 2002}" +micropython-v1_22_0-esp32-ESP32_GENERIC-merged,..\repos\micropython-stubs\stubs\micropython-v1_22_0-esp32-ESP32_GENERIC-merged,1.22.0,esp32,0.84,0.72,0.59,"{'def': 2274, 'class': 397, 'module': 174}","{'module': 28, 'class': 112, 'def': 922}" +micropython-v1_22_0-esp32-ESP32_GENERIC_S3,..\repos\micropython-stubs\stubs\micropython-v1_22_0-esp32-ESP32_GENERIC_S3,1.22.0,esp32,0.52,0.3,0.11,"{'def': 2232, 'class': 349, 'module': 178}","{'module': 85, 'class': 244, 'def': 1996}" +micropython-v1_22_0-esp32-ESP32_GENERIC_S3-merged,..\repos\micropython-stubs\stubs\micropython-v1_22_0-esp32-ESP32_GENERIC_S3-merged,1.22.0,esp32,0.84,0.73,0.59,"{'def': 2264, 'class': 393, 'module': 174}","{'module': 28, 'class': 108, 'def': 918}" +micropython-v1_22_0-esp32-Generic_ESP32S3_module,..\repos\micropython-stubs\stubs\micropython-v1_22_0-esp32-Generic_ESP32S3_module,1.22.0,esp32,0.52,0.3,0.11,"{'def': 2232, 'class': 349, 'module': 178}","{'module': 85, 'class': 244, 'def': 1996}" +micropython-v1_22_0-rp2-ARDUINO_NANO_RP2040_CONNECT,..\repos\micropython-stubs\stubs\micropython-v1_22_0-rp2-ARDUINO_NANO_RP2040_CONNECT,1.22.0,rp2,0.53,0.52,0.12,"{'def': 2292, 'class': 616, 'module': 180}","{'module': 85, 'class': 298, 'def': 2010}" +micropython-v1_22_0-rp2-ARDUINO_NANO_RP2040_CONNECT-merged,..\repos\micropython-stubs\stubs\micropython-v1_22_0-rp2-ARDUINO_NANO_RP2040_CONNECT-merged,1.22.0,rp2,0.82,0.75,0.58,"{'def': 2312, 'class': 646, 'module': 176}","{'module': 31, 'class': 161, 'def': 976}" +micropython-v1_22_0-rp2-RPI_PICO,..\repos\micropython-stubs\stubs\micropython-v1_22_0-rp2-RPI_PICO,1.22.0,rp2,0.54,0.53,0.12,"{'def': 1612, 'class': 408, 'module': 130}","{'module': 60, 'class': 192, 'def': 1424}" +micropython-v1_22_0-rp2-RPI_PICO-merged,..\repos\micropython-stubs\stubs\micropython-v1_22_0-rp2-RPI_PICO-merged,1.22.0,rp2,0.88,0.82,0.62,"{'def': 1652, 'class': 438, 'module': 130}","{'module': 15, 'class': 79, 'def': 632}" +micropython-v1_22_0-rp2-RPI_PICO_W,..\repos\micropython-stubs\stubs\micropython-v1_22_0-rp2-RPI_PICO_W,1.22.0,rp2,0.53,0.52,0.12,"{'def': 2228, 'class': 590, 'module': 180}","{'module': 85, 'class': 284, 'def': 1960}" +micropython-v1_22_0-rp2-RPI_PICO_W-merged,..\repos\micropython-stubs\stubs\micropython-v1_22_0-rp2-RPI_PICO_W-merged,1.22.0,rp2,0.82,0.76,0.58,"{'def': 2248, 'class': 620, 'module': 176}","{'module': 31, 'class': 151, 'def': 954}" +micropython-v1_22_0-samd-SEEED_WIO_TERMINAL,..\repos\micropython-stubs\stubs\micropython-v1_22_0-samd-SEEED_WIO_TERMINAL,1.22.0,samd,0.52,0.72,0.11,"{'def': 1488, 'class': 604, 'module': 116}","{'module': 56, 'class': 172, 'def': 1318}" +micropython-v1_22_0-samd-SEEED_WIO_TERMINAL-merged,..\repos\micropython-stubs\stubs\micropython-v1_22_0-samd-SEEED_WIO_TERMINAL-merged,1.22.0,samd,0.86,0.88,0.6,"{'def': 1528, 'class': 634, 'module': 116}","{'module': 16, 'class': 76, 'def': 614}" micropython-v1_9_3-esp8266,..\repos\micropython-stubs\stubs\micropython-v1_9_3-esp8266,1.9.3,esp8266,0.51,0.58,0.01,"{'def': 1112, 'class': 182, 'module': 117}","{'module': 57, 'class': 76, 'def': 1100}" micropython-v1_9_3-frozen,..\repos\micropython-stubs\stubs\micropython-v1_9_3-frozen,1.9.3,frozen,0.05,0.0,0.16,"{'def': 363, 'class': 40, 'module': 40}","{'module': 38, 'class': 40, 'def': 306}" micropython-v1_9_4-esp8266,..\repos\micropython-stubs\stubs\micropython-v1_9_4-esp8266,1.9.4,esp8266,0.52,0.5,0.02,"{'def': 642, 'class': 104, 'module': 119}","{'module': 57, 'class': 52, 'def': 630}" micropython-v1_9_4-frozen,..\repos\micropython-stubs\stubs\micropython-v1_9_4-frozen,1.9.4,frozen,0.05,0.0,0.17,"{'def': 571, 'class': 82, 'module': 74}","{'module': 70, 'class': 82, 'def': 474}" -micropython-latest-esp32-stubs,..\repos\micropython-stubs\publish\micropython-latest-esp32-stubs,99.99.99,esp32,0.61,0.59,0.59,"{'def': 1148, 'class': 145, 'module': 94}","{'module': 37, 'class': 59, 'def': 475}" -micropython-latest-rp2-pimoroni_picolipo_16mb-stubs,..\repos\micropython-stubs\publish\micropython-latest-rp2-pimoroni_picolipo_16mb-stubs,99.99.99,rp2,0.7,0.55,0.55,"{'def': 844, 'class': 107, 'module': 66}","{'module': 20, 'class': 48, 'def': 377}" -micropython-latest-rp2-stubs,..\repos\micropython-stubs\publish\micropython-latest-rp2-stubs,99.99.99,rp2,0.7,0.55,0.55,"{'def': 844, 'class': 107, 'module': 66}","{'module': 20, 'class': 48, 'def': 377}" -micropython-latest-samd-adafruit_feather_m4_express-stubs,..\repos\micropython-stubs\publish\micropython-latest-samd-adafruit_feather_m4_express-stubs,99.99.99,samd,0.68,0.58,0.54,"{'def': 798, 'class': 99, 'module': 59}","{'module': 19, 'class': 42, 'def': 368}" -micropython-latest-samd-adafruit_itsybitsy_m4_express-stubs,..\repos\micropython-stubs\publish\micropython-latest-samd-adafruit_itsybitsy_m4_express-stubs,99.99.99,samd,0.68,0.58,0.54,"{'def': 798, 'class': 99, 'module': 59}","{'module': 19, 'class': 42, 'def': 368}" -micropython-latest-samd-minisam_m4-stubs,..\repos\micropython-stubs\publish\micropython-latest-samd-minisam_m4-stubs,99.99.99,samd,0.68,0.58,0.54,"{'def': 798, 'class': 99, 'module': 59}","{'module': 19, 'class': 42, 'def': 368}" -micropython-latest-samd-seeed_wio_terminal-stubs,..\repos\micropython-stubs\publish\micropython-latest-samd-seeed_wio_terminal-stubs,99.99.99,samd,0.68,0.58,0.54,"{'def': 798, 'class': 99, 'module': 59}","{'module': 19, 'class': 42, 'def': 368}" -micropython-latest-stm32-pybv11-stubs,..\repos\micropython-stubs\publish\micropython-latest-stm32-pybv11-stubs,99.99.99,stm32,0.74,0.66,0.64,"{'def': 1104, 'class': 119, 'module': 66}","{'module': 17, 'class': 41, 'def': 400}" -micropython-latest-stm32-stubs,..\repos\micropython-stubs\publish\micropython-latest-stm32-stubs,99.99.99,stm32,0.74,0.66,0.64,"{'def': 1104, 'class': 119, 'module': 66}","{'module': 17, 'class': 41, 'def': 400}" -micropython-stdlib-stubs,..\repos\micropython-stubs\publish\micropython-stdlib-stubs,1.0,stdlib,1.0,1.0,1.0,"{'def': 3625, 'class': 658, 'module': 63}","{'module': 0, 'class': 0, 'def': 0}" +micropython-latest-esp32-esp32_generic-stubs,..\repos\micropython-stubs\publish\micropython-latest-esp32-esp32_generic-stubs,99.99.99,esp32,0.68,0.6,0.6,"{'def': 1096, 'class': 138, 'module': 87}","{'module': 28, 'class': 55, 'def': 435}" +micropython-latest-esp32-stubs,..\repos\micropython-stubs\publish\micropython-latest-esp32-stubs,99.99.99,esp32,0.68,0.6,0.6,"{'def': 1096, 'class': 138, 'module': 87}","{'module': 28, 'class': 55, 'def': 435}" +micropython-latest-rp2-pimoroni_picolipo_16mb-stubs,..\repos\micropython-stubs\publish\micropython-latest-rp2-pimoroni_picolipo_16mb-stubs,99.99.99,rp2,0.81,0.58,0.59,"{'def': 745, 'class': 88, 'module': 58}","{'module': 11, 'class': 37, 'def': 306}" +micropython-latest-rp2-rpi_pico-stubs,..\repos\micropython-stubs\publish\micropython-latest-rp2-rpi_pico-stubs,99.99.99,rp2,0.78,0.62,0.63,"{'def': 816, 'class': 105, 'module': 64}","{'module': 14, 'class': 40, 'def': 298}" +micropython-latest-rp2-rpi_pico_w-stubs,..\repos\micropython-stubs\publish\micropython-latest-rp2-rpi_pico_w-stubs,99.99.99,rp2,0.64,0.54,0.62,"{'def': 1142, 'class': 138, 'module': 92}","{'module': 33, 'class': 63, 'def': 435}" +micropython-latest-rp2-stubs,..\repos\micropython-stubs\publish\micropython-latest-rp2-stubs,99.99.99,rp2,0.78,0.62,0.63,"{'def': 816, 'class': 105, 'module': 64}","{'module': 14, 'class': 40, 'def': 298}" +micropython-latest-samd-adafruit_feather_m4_express-stubs,..\repos\micropython-stubs\publish\micropython-latest-samd-adafruit_feather_m4_express-stubs,99.99.99,samd,0.76,0.6,0.57,"{'def': 700, 'class': 80, 'module': 51}","{'module': 12, 'class': 32, 'def': 299}" +micropython-latest-samd-adafruit_itsybitsy_m4_express-stubs,..\repos\micropython-stubs\publish\micropython-latest-samd-adafruit_itsybitsy_m4_express-stubs,99.99.99,samd,0.76,0.6,0.57,"{'def': 700, 'class': 80, 'module': 51}","{'module': 12, 'class': 32, 'def': 299}" +micropython-latest-samd-minisam_m4-stubs,..\repos\micropython-stubs\publish\micropython-latest-samd-minisam_m4-stubs,99.99.99,samd,0.76,0.6,0.57,"{'def': 700, 'class': 80, 'module': 51}","{'module': 12, 'class': 32, 'def': 299}" +micropython-latest-samd-seeed_wio_terminal-stubs,..\repos\micropython-stubs\publish\micropython-latest-samd-seeed_wio_terminal-stubs,99.99.99,samd,0.74,0.6,0.62,"{'def': 745, 'class': 95, 'module': 57}","{'module': 15, 'class': 38, 'def': 280}" +micropython-latest-samd-stubs,..\repos\micropython-stubs\publish\micropython-latest-samd-stubs,99.99.99,samd,0.74,0.6,0.62,"{'def': 745, 'class': 95, 'module': 57}","{'module': 15, 'class': 38, 'def': 280}" +micropython-latest-stm32-pybv11-stubs,..\repos\micropython-stubs\publish\micropython-latest-stm32-pybv11-stubs,99.99.99,stm32,0.79,0.69,0.68,"{'def': 1067, 'class': 116, 'module': 62}","{'module': 13, 'class': 36, 'def': 339}" +micropython-latest-stm32-stubs,..\repos\micropython-stubs\publish\micropython-latest-stm32-stubs,99.99.99,stm32,0.79,0.69,0.68,"{'def': 1067, 'class': 116, 'module': 62}","{'module': 13, 'class': 36, 'def': 339}" +micropython-latest-webassembly-stubs,..\repos\micropython-stubs\publish\micropython-latest-webassembly-stubs,99.99.99,webassembly,0.95,0.7,0.69,"{'def': 316, 'class': 27, 'module': 40}","{'module': 2, 'class': 8, 'def': 98}" +micropython-stdlib-stubs,..\repos\micropython-stubs\publish\micropython-stdlib-stubs,1.0,stdlib,1.0,1.0,1.0,"{'def': 3566, 'class': 649, 'module': 57}","{'module': 0, 'class': 0, 'def': 0}" micropython-v1_17-esp32-stubs,..\repos\micropython-stubs\publish\micropython-v1_17-esp32-stubs,1.17,esp32,0.62,0.55,0.5,"{'def': 953, 'class': 132, 'module': 80}","{'module': 30, 'class': 60, 'def': 481}" micropython-v1_17-esp8266-stubs,..\repos\micropython-stubs\publish\micropython-v1_17-esp8266-stubs,1.17,esp8266,0.56,0.5,0.43,"{'def': 899, 'class': 113, 'module': 80}","{'module': 35, 'class': 57, 'def': 512}" micropython-v1_17-rp2-stubs,..\repos\micropython-stubs\publish\micropython-v1_17-rp2-stubs,1.17,rp2,0.7,0.55,0.42,"{'def': 661, 'class': 95, 'module': 53}","{'module': 16, 'class': 43, 'def': 385}" @@ -142,28 +163,36 @@ micropython-v1_18-esp32-stubs,..\repos\micropython-stubs\publish\micropython-v1_ micropython-v1_18-esp8266-stubs,..\repos\micropython-stubs\publish\micropython-v1_18-esp8266-stubs,1.18,esp8266,0.59,0.5,0.44,"{'def': 900, 'class': 113, 'module': 80}","{'module': 33, 'class': 57, 'def': 508}" micropython-v1_18-rp2-stubs,..\repos\micropython-stubs\publish\micropython-v1_18-rp2-stubs,1.18,rp2,0.79,0.58,0.54,"{'def': 839, 'class': 113, 'module': 61}","{'module': 13, 'class': 47, 'def': 388}" micropython-v1_18-stm32-stubs,..\repos\micropython-stubs\publish\micropython-v1_18-stm32-stubs,1.18,stm32,0.75,0.67,0.64,"{'def': 1037, 'class': 121, 'module': 59}","{'module': 15, 'class': 40, 'def': 371}" +micropython-v1_19_1-esp32-generic_s3-stubs,..\repos\micropython-stubs\publish\micropython-v1_19_1-esp32-generic_s3-stubs,1.19.1,esp32,0.64,0.62,0.58,"{'def': 1048, 'class': 136, 'module': 86}","{'module': 31, 'class': 51, 'def': 443}" +micropython-v1_19_1-esp32-generic_spiram-stubs,..\repos\micropython-stubs\publish\micropython-v1_19_1-esp32-generic_spiram-stubs,1.19.1,esp32,0.65,0.66,0.59,"{'def': 1003, 'class': 129, 'module': 82}","{'module': 29, 'class': 44, 'def': 416}" micropython-v1_19_1-esp32-s3-stubs,..\repos\micropython-stubs\publish\micropython-v1_19_1-esp32-s3-stubs,1.19.1,esp32,0.81,0.77,0.62,"{'def': 1007, 'class': 142, 'module': 80}","{'module': 15, 'class': 33, 'def': 381}" -micropython-v1_19_1-esp32-stubs,..\repos\micropython-stubs\publish\micropython-v1_19_1-esp32-stubs,1.19.1,esp32,0.64,0.65,0.57,"{'def': 1020, 'class': 133, 'module': 81}","{'module': 29, 'class': 47, 'def': 443}" -micropython-v1_19_1-esp32-um_tinypico-stubs,..\repos\micropython-stubs\publish\micropython-v1_19_1-esp32-um_tinypico-stubs,1.19.1,esp32,0.63,0.65,0.57,"{'def': 1038, 'class': 134, 'module': 83}","{'module': 31, 'class': 47, 'def': 443}" -micropython-v1_19_1-esp8266-stubs,..\repos\micropython-stubs\publish\micropython-v1_19_1-esp8266-stubs,1.19.1,esp8266,0.71,0.72,0.58,"{'def': 739, 'class': 85, 'module': 65}","{'module': 19, 'class': 24, 'def': 311}" -micropython-v1_19_1-rp2-stubs,..\repos\micropython-stubs\publish\micropython-v1_19_1-rp2-stubs,1.19.1,rp2,0.68,0.5,0.54,"{'def': 1003, 'class': 142, 'module': 73}","{'module': 23, 'class': 71, 'def': 460}" -micropython-v1_19_1-stm32-stubs,..\repos\micropython-stubs\publish\micropython-v1_19_1-stm32-stubs,1.19.1,stm32,0.76,0.73,0.63,"{'def': 1066, 'class': 119, 'module': 59}","{'module': 14, 'class': 32, 'def': 391}" +micropython-v1_19_1-esp32-stubs,..\repos\micropython-stubs\publish\micropython-v1_19_1-esp32-stubs,1.19.1,esp32,0.65,0.66,0.59,"{'def': 1003, 'class': 129, 'module': 82}","{'module': 29, 'class': 44, 'def': 416}" +micropython-v1_19_1-esp32-um_tinypico-stubs,..\repos\micropython-stubs\publish\micropython-v1_19_1-esp32-um_tinypico-stubs,1.19.1,esp32,0.62,0.65,0.63,"{'def': 931, 'class': 110, 'module': 82}","{'module': 31, 'class': 38, 'def': 342}" +micropython-v1_19_1-esp8266-stubs,..\repos\micropython-stubs\publish\micropython-v1_19_1-esp8266-stubs,1.19.1,esp8266,0.73,0.73,0.59,"{'def': 724, 'class': 85, 'module': 66}","{'module': 18, 'class': 23, 'def': 296}" +micropython-v1_19_1-rp2-stubs,..\repos\micropython-stubs\publish\micropython-v1_19_1-rp2-stubs,1.19.1,rp2,0.69,0.53,0.58,"{'def': 981, 'class': 137, 'module': 74}","{'module': 23, 'class': 64, 'def': 413}" +micropython-v1_19_1-stm32-stubs,..\repos\micropython-stubs\publish\micropython-v1_19_1-stm32-stubs,1.19.1,stm32,0.77,0.75,0.66,"{'def': 1043, 'class': 114, 'module': 60}","{'module': 14, 'class': 28, 'def': 358}" +micropython-v1_20_0-esp32-generic_ota-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-esp32-generic_ota-stubs,1.20.0,esp32,0.65,0.63,0.62,"{'def': 1010, 'class': 126, 'module': 85}","{'module': 30, 'class': 46, 'def': 384}" +micropython-v1_20_0-esp32-generic_s3-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-esp32-generic_s3-stubs,1.20.0,esp32,0.65,0.64,0.62,"{'def': 980, 'class': 120, 'module': 84}","{'module': 29, 'class': 43, 'def': 369}" micropython-v1_20_0-esp32-ota-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-esp32-ota-stubs,1.20.0,esp32,0.64,0.64,0.61,"{'def': 1041, 'class': 130, 'module': 85}","{'module': 31, 'class': 47, 'def': 410}" micropython-v1_20_0-esp32-s3-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-esp32-s3-stubs,1.20.0,esp32,0.64,0.65,0.61,"{'def': 1011, 'class': 124, 'module': 84}","{'module': 30, 'class': 44, 'def': 395}" -micropython-v1_20_0-esp32-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-esp32-stubs,1.20.0,esp32,0.64,0.64,0.61,"{'def': 1041, 'class': 130, 'module': 85}","{'module': 31, 'class': 47, 'def': 410}" -micropython-v1_20_0-rp2-pico-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-rp2-pico-stubs,1.20.0,rp2,0.77,0.65,0.59,"{'def': 782, 'class': 97, 'module': 60}","{'module': 14, 'class': 34, 'def': 324}" -micropython-v1_20_0-rp2-pico_w-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-rp2-pico_w-stubs,1.20.0,rp2,0.72,0.63,0.57,"{'def': 896, 'class': 104, 'module': 71}","{'module': 20, 'class': 38, 'def': 383}" -micropython-v1_20_0-rp2-pimoroni_picolipo_16mb-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-rp2-pimoroni_picolipo_16mb-stubs,1.20.0,rp2,0.77,0.65,0.59,"{'def': 782, 'class': 97, 'module': 60}","{'module': 14, 'class': 34, 'def': 324}" -micropython-v1_20_0-rp2-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-rp2-stubs,1.20.0,rp2,0.77,0.65,0.59,"{'def': 782, 'class': 97, 'module': 60}","{'module': 14, 'class': 34, 'def': 324}" -micropython-v1_20_0-samd-adafruit_feather_m4_express-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-samd-adafruit_feather_m4_express-stubs,1.20.0,samd,0.75,0.69,0.57,"{'def': 736, 'class': 89, 'module': 53}","{'module': 13, 'class': 28, 'def': 315}" -micropython-v1_20_0-samd-adafruit_itsybitsy_m4_express-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-samd-adafruit_itsybitsy_m4_express-stubs,1.20.0,samd,0.75,0.69,0.57,"{'def': 736, 'class': 89, 'module': 53}","{'module': 13, 'class': 28, 'def': 315}" -micropython-v1_20_0-samd-minisam_m4-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-samd-minisam_m4-stubs,1.20.0,samd,0.75,0.69,0.57,"{'def': 736, 'class': 89, 'module': 53}","{'module': 13, 'class': 28, 'def': 315}" -micropython-v1_20_0-samd-seeed_wio_terminal-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-samd-seeed_wio_terminal-stubs,1.20.0,samd,0.75,0.69,0.57,"{'def': 736, 'class': 89, 'module': 53}","{'module': 13, 'class': 28, 'def': 315}" -micropython-v1_20_0-stm32-pybv11-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-stm32-pybv11-stubs,1.20.0,stm32,0.77,0.75,0.66,"{'def': 1043, 'class': 109, 'module': 61}","{'module': 14, 'class': 27, 'def': 353}" -micropython-v1_20_0-stm32-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-stm32-stubs,1.20.0,stm32,0.77,0.75,0.66,"{'def': 1043, 'class': 109, 'module': 61}","{'module': 14, 'class': 27, 'def': 353}" -micropython-v1_21_0-esp32-esp32_generic-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-esp32-esp32_generic-stubs,1.21.0,esp32,0.64,0.6,0.59,"{'def': 1150, 'class': 145, 'module': 94}","{'module': 34, 'class': 58, 'def': 471}" -micropython-v1_21_0-esp32-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-esp32-stubs,1.21.0,esp32,0.64,0.6,0.59,"{'def': 1150, 'class': 145, 'module': 94}","{'module': 34, 'class': 58, 'def': 471}" -micropython-v1_21_0-rp2-rpi_pico-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-rp2-rpi_pico-stubs,1.21.0,rp2,0.76,0.58,0.58,"{'def': 838, 'class': 106, 'module': 67}","{'module': 16, 'class': 44, 'def': 356}" -micropython-v1_21_0-rp2-rpi_pico_w-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-rp2-rpi_pico_w-stubs,1.21.0,rp2,0.62,0.51,0.58,"{'def': 1170, 'class': 142, 'module': 93}","{'module': 35, 'class': 69, 'def': 492}" -micropython-v1_21_0-samd-seeed_wio_terminal-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-samd-seeed_wio_terminal-stubs,1.21.0,samd,0.72,0.59,0.58,"{'def': 766, 'class': 96, 'module': 60}","{'module': 17, 'class': 39, 'def': 325}" -micropython-v1_21_0-stm32-pybv11-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-stm32-pybv11-stubs,1.21.0,stm32,0.77,0.68,0.65,"{'def': 1089, 'class': 117, 'module': 64}","{'module': 15, 'class': 37, 'def': 385}" +micropython-v1_20_0-esp32-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-esp32-stubs,1.20.0,esp32,0.65,0.63,0.62,"{'def': 1010, 'class': 126, 'module': 85}","{'module': 30, 'class': 46, 'def': 384}" +micropython-v1_20_0-rp2-pico-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-rp2-pico-stubs,1.20.0,rp2,0.8,0.68,0.63,"{'def': 751, 'class': 93, 'module': 60}","{'module': 12, 'class': 30, 'def': 281}" +micropython-v1_20_0-rp2-pico_w-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-rp2-pico_w-stubs,1.20.0,rp2,0.75,0.66,0.61,"{'def': 865, 'class': 100, 'module': 71}","{'module': 18, 'class': 34, 'def': 340}" +micropython-v1_20_0-rp2-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-rp2-stubs,1.20.0,rp2,0.8,0.68,0.63,"{'def': 751, 'class': 93, 'module': 60}","{'module': 12, 'class': 30, 'def': 281}" +micropython-v1_20_0-samd-adafruit_feather_m4_express-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-samd-adafruit_feather_m4_express-stubs,1.20.0,samd,0.75,0.67,0.59,"{'def': 705, 'class': 85, 'module': 53}","{'module': 13, 'class': 28, 'def': 291}" +micropython-v1_20_0-samd-adafruit_itsybitsy_m4_express-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-samd-adafruit_itsybitsy_m4_express-stubs,1.20.0,samd,0.75,0.67,0.59,"{'def': 705, 'class': 85, 'module': 53}","{'module': 13, 'class': 28, 'def': 291}" +micropython-v1_20_0-samd-minisam_m4-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-samd-minisam_m4-stubs,1.20.0,samd,0.75,0.67,0.59,"{'def': 705, 'class': 85, 'module': 53}","{'module': 13, 'class': 28, 'def': 291}" +micropython-v1_20_0-samd-seeed_wio_terminal-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-samd-seeed_wio_terminal-stubs,1.20.0,samd,0.75,0.67,0.59,"{'def': 705, 'class': 85, 'module': 53}","{'module': 13, 'class': 28, 'def': 291}" +micropython-v1_20_0-samd-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-samd-stubs,1.20.0,samd,0.75,0.67,0.59,"{'def': 705, 'class': 85, 'module': 53}","{'module': 13, 'class': 28, 'def': 291}" +micropython-v1_20_0-stm32-pybv11-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-stm32-pybv11-stubs,1.20.0,stm32,0.78,0.74,0.67,"{'def': 1011, 'class': 105, 'module': 60}","{'module': 13, 'class': 27, 'def': 329}" +micropython-v1_20_0-stm32-stubs,..\repos\micropython-stubs\publish\micropython-v1_20_0-stm32-stubs,1.20.0,stm32,0.78,0.74,0.67,"{'def': 1011, 'class': 105, 'module': 60}","{'module': 13, 'class': 27, 'def': 329}" +micropython-v1_21_0-esp32-esp32_generic-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-esp32-esp32_generic-stubs,1.21.0,esp32,0.65,0.6,0.61,"{'def': 1122, 'class': 141, 'module': 93}","{'module': 33, 'class': 57, 'def': 441}" +micropython-v1_21_0-esp32-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-esp32-stubs,1.21.0,esp32,0.65,0.6,0.61,"{'def': 1122, 'class': 141, 'module': 93}","{'module': 33, 'class': 57, 'def': 441}" +micropython-v1_21_0-rp2-rpi_pico-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-rp2-rpi_pico-stubs,1.21.0,rp2,0.77,0.63,0.63,"{'def': 810, 'class': 102, 'module': 66}","{'module': 15, 'class': 38, 'def': 299}" +micropython-v1_21_0-rp2-rpi_pico_w-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-rp2-rpi_pico_w-stubs,1.21.0,rp2,0.63,0.54,0.62,"{'def': 1142, 'class': 138, 'module': 92}","{'module': 34, 'class': 63, 'def': 435}" +micropython-v1_21_0-rp2-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-rp2-stubs,1.21.0,rp2,0.77,0.63,0.63,"{'def': 810, 'class': 102, 'module': 66}","{'module': 15, 'class': 38, 'def': 299}" +micropython-v1_21_0-samd-seeed_wio_terminal-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-samd-seeed_wio_terminal-stubs,1.21.0,samd,0.73,0.61,0.62,"{'def': 738, 'class': 92, 'module': 59}","{'module': 16, 'class': 36, 'def': 283}" +micropython-v1_21_0-samd-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-samd-stubs,1.21.0,samd,0.73,0.61,0.62,"{'def': 738, 'class': 92, 'module': 59}","{'module': 16, 'class': 36, 'def': 283}" +micropython-v1_21_0-stm32-pybv11-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-stm32-pybv11-stubs,1.21.0,stm32,0.78,0.7,0.68,"{'def': 1061, 'class': 113, 'module': 63}","{'module': 14, 'class': 34, 'def': 343}" +micropython-v1_21_0-stm32-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-stm32-stubs,1.21.0,stm32,0.78,0.7,0.68,"{'def': 1061, 'class': 113, 'module': 63}","{'module': 14, 'class': 34, 'def': 343}" +micropython-v1_21_0-webassembly-stubs,..\repos\micropython-stubs\publish\micropython-v1_21_0-webassembly-stubs,1.21.0,webassembly,0.95,0.7,0.69,"{'def': 316, 'class': 27, 'module': 40}","{'module': 2, 'class': 8, 'def': 98}" diff --git a/scripts/docstrings.json b/scripts/docstrings.json index 3d575660e..b238735e7 100644 --- a/scripts/docstrings.json +++ b/scripts/docstrings.json @@ -27,8 +27,8 @@ "class": 0.96, "def": 0.97, "counts": { - "def": 911, - "class": 116, + "def": 919, + "class": 120, "module": 55 }, "missing": { @@ -38,22 +38,22 @@ } }, { - "folder": "micropython-latest-esp32--OLD", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-latest-esp32--OLD", + "folder": "micropython-latest-esp32-ESP32_GENERIC-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-latest-esp32-ESP32_GENERIC-merged", "version": "99.99.99", "port": "esp32", - "module": 0.52, - "class": 0.29, - "def": 0.11, + "module": 0.84, + "class": 0.71, + "def": 0.59, "counts": { - "def": 2100, - "class": 331, - "module": 170 + "def": 2248, + "class": 385, + "module": 174 }, "missing": { - "module": 81, - "class": 234, - "def": 1874 + "module": 28, + "class": 110, + "def": 918 } }, { @@ -99,18 +99,18 @@ "path": "..\\repos\\micropython-stubs\\stubs\\micropython-latest-frozen", "version": "99.99.99", "port": "frozen", - "module": 0.14, - "class": 0.12, - "def": 0.33, + "module": 0.26, + "class": 0.17, + "def": 0.37, "counts": { - "def": 19581, - "class": 2971, - "module": 2327 + "def": 20461, + "class": 3084, + "module": 2394 }, "missing": { - "module": 2004, - "class": 2626, - "def": 13158 + "module": 1778, + "class": 2555, + "def": 12977 } }, { @@ -151,6 +151,44 @@ "def": 660 } }, + { + "folder": "micropython-latest-rp2-RPI_PICO-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-latest-rp2-RPI_PICO-merged", + "version": "99.99.99", + "port": "rp2", + "module": 0.89, + "class": 0.82, + "def": 0.62, + "counts": { + "def": 1688, + "class": 432, + "module": 128 + }, + "missing": { + "module": 14, + "class": 79, + "def": 644 + } + }, + { + "folder": "micropython-latest-rp2-RPI_PICO_W-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-latest-rp2-RPI_PICO_W-merged", + "version": "99.99.99", + "port": "rp2", + "module": 0.83, + "class": 0.75, + "def": 0.57, + "counts": { + "def": 2288, + "class": 636, + "module": 174 + }, + "missing": { + "module": 30, + "class": 159, + "def": 978 + } + }, { "folder": "micropython-latest-samd-ADAFRUIT_FEATHER_M4_EXPRESS-merged", "path": "..\\repos\\micropython-stubs\\stubs\\micropython-latest-samd-ADAFRUIT_FEATHER_M4_EXPRESS-merged", @@ -213,18 +251,18 @@ "path": "..\\repos\\micropython-stubs\\stubs\\micropython-latest-samd-SEEED_WIO_TERMINAL-merged", "version": "99.99.99", "port": "samd", - "module": 0.88, + "module": 0.87, "class": 0.88, - "def": 0.56, + "def": 0.61, "counts": { - "def": 1454, - "class": 539, - "module": 102 + "def": 1546, + "class": 624, + "module": 114 }, "missing": { - "module": 12, - "class": 64, - "def": 646 + "module": 15, + "class": 76, + "def": 608 } }, { @@ -251,18 +289,37 @@ "path": "..\\repos\\micropython-stubs\\stubs\\micropython-latest-stm32-PYBV11-merged", "version": "99.99.99", "port": "stm32", - "module": 0.92, + "module": 0.9, "class": 0.89, - "def": 0.66, + "def": 0.67, "counts": { - "def": 2066, - "class": 559, - "module": 118 + "def": 2190, + "class": 630, + "module": 124 }, "missing": { - "module": 10, - "class": 62, - "def": 708 + "module": 13, + "class": 72, + "def": 726 + } + }, + { + "folder": "micropython-latest-webassembly-GENERIC-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-latest-webassembly-GENERIC-merged", + "version": "99.99.99", + "port": "webassembly", + "module": 0.97, + "class": 0.77, + "def": 0.64, + "counts": { + "def": 688, + "class": 70, + "module": 80 + }, + "missing": { + "module": 2, + "class": 16, + "def": 246 } }, { @@ -702,25 +759,6 @@ "def": 2184 } }, - { - "folder": "micropython-v1_16-docstubs", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_16-docstubs", - "version": "1.16", - "port": "docstubs", - "module": 1.0, - "class": 1.0, - "def": 1.0, - "counts": { - "def": 0, - "class": 0, - "module": 0 - }, - "missing": { - "module": 0, - "class": 0, - "def": 0 - } - }, { "folder": "micropython-v1_16-esp32", "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_16-esp32", @@ -1221,11 +1259,11 @@ "version": "1.19.1", "port": "docstubs", "module": 1.0, - "class": 0.95, + "class": 0.96, "def": 0.97, "counts": { "def": 813, - "class": 109, + "class": 113, "module": 50 }, "missing": { @@ -1235,8 +1273,8 @@ } }, { - "folder": "micropython-v1_19_1-esp32", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_19_1-esp32", + "folder": "micropython-v1_19_1-esp32-GENERIC", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_19_1-esp32-GENERIC", "version": "1.19.1", "port": "esp32", "module": 0.51, @@ -1254,16 +1292,16 @@ } }, { - "folder": "micropython-v1_19_1-esp32-merged", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_19_1-esp32-merged", + "folder": "micropython-v1_19_1-esp32-GENERIC-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_19_1-esp32-GENERIC-merged", "version": "1.19.1", "port": "esp32", "module": 0.84, - "class": 0.73, + "class": 0.74, "def": 0.58, "counts": { "def": 1934, - "class": 305, + "class": 313, "module": 150 }, "missing": { @@ -1273,41 +1311,79 @@ } }, { - "folder": "micropython-v1_19_1-esp32-s3", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_19_1-esp32-s3", + "folder": "micropython-v1_19_1-esp32-GENERIC_S3", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_19_1-esp32-GENERIC_S3", "version": "1.19.1", "port": "esp32", - "module": 1.0, - "class": 0.33, - "def": 0.11, + "module": 0.52, + "class": 0.21, + "def": 0.1, "counts": { - "def": 1027, - "class": 167, - "module": 75 + "def": 1977, + "class": 268, + "module": 149 }, "missing": { - "module": 0, - "class": 112, - "def": 919 + "module": 71, + "class": 213, + "def": 1771 } }, { - "folder": "micropython-v1_19_1-esp32-S3-merged", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_19_1-esp32-S3-merged", + "folder": "micropython-v1_19_1-esp32-GENERIC_S3-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_19_1-esp32-GENERIC_S3-merged", "version": "1.19.1", "port": "esp32", - "module": 1.0, - "class": 0.79, + "module": 0.86, + "class": 0.76, "def": 0.59, "counts": { - "def": 974, - "class": 178, - "module": 74 + "def": 1948, + "class": 311, + "module": 148 }, "missing": { - "module": 0, - "class": 37, - "def": 396 + "module": 20, + "class": 74, + "def": 792 + } + }, + { + "folder": "micropython-v1_19_1-esp32-GENERIC_SPIRAM", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_19_1-esp32-GENERIC_SPIRAM", + "version": "1.19.1", + "port": "esp32", + "module": 0.51, + "class": 0.21, + "def": 0.1, + "counts": { + "def": 1890, + "class": 260, + "module": 152 + }, + "missing": { + "module": 74, + "class": 205, + "def": 1694 + } + }, + { + "folder": "micropython-v1_19_1-esp32-GENERIC_SPIRAM-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_19_1-esp32-GENERIC_SPIRAM-merged", + "version": "1.19.1", + "port": "esp32", + "module": 0.84, + "class": 0.74, + "def": 0.58, + "counts": { + "def": 1934, + "class": 313, + "module": 150 + }, + "missing": { + "module": 24, + "class": 82, + "def": 806 } }, { @@ -1315,18 +1391,18 @@ "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_19_1-esp32-UM_TINYPICO", "version": "1.19.1", "port": "esp32", - "module": 0.91, - "class": 0.87, - "def": 0.12, + "module": 0.52, + "class": 0.61, + "def": 0.11, "counts": { - "def": 1021, - "class": 213, - "module": 79 + "def": 1862, + "class": 302, + "module": 147 }, "missing": { - "module": 7, - "class": 28, - "def": 898 + "module": 71, + "class": 117, + "def": 1654 } }, { @@ -1334,18 +1410,18 @@ "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_19_1-esp32-UM_TINYPICO-merged", "version": "1.19.1", "port": "esp32", - "module": 0.91, - "class": 0.88, - "def": 0.56, + "module": 0.84, + "class": 0.85, + "def": 0.6, "counts": { - "def": 1049, - "class": 232, - "module": 79 + "def": 1866, + "class": 328, + "module": 146 }, "missing": { - "module": 7, - "class": 28, - "def": 464 + "module": 24, + "class": 50, + "def": 744 } }, { @@ -1377,7 +1453,7 @@ "def": 0.59, "counts": { "def": 1412, - "class": 178, + "class": 186, "module": 118 }, "missing": { @@ -1391,18 +1467,18 @@ "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_19_1-frozen", "version": "1.19.1", "port": "frozen", - "module": 0.31, - "class": 0.35, - "def": 0.45, + "module": 0.23, + "class": 0.25, + "def": 0.41, "counts": { - "def": 4146, - "class": 721, - "module": 473 + "def": 8120, + "class": 1319, + "module": 935 }, "missing": { - "module": 325, - "class": 468, - "def": 2299 + "module": 720, + "class": 991, + "def": 4753 } }, { @@ -1430,17 +1506,17 @@ "version": "1.19.1", "port": "rp2", "module": 0.84, - "class": 0.65, - "def": 0.54, + "class": 0.67, + "def": 0.56, "counts": { "def": 1974, - "class": 395, + "class": 403, "module": 140 }, "missing": { "module": 22, - "class": 137, - "def": 902 + "class": 131, + "def": 874 } }, { @@ -1491,7 +1567,7 @@ "def": 0.64, "counts": { "def": 2088, - "class": 573, + "class": 581, "module": 114 }, "missing": { @@ -1506,11 +1582,11 @@ "version": "1.20.0", "port": "docstubs", "module": 1.0, - "class": 0.95, + "class": 0.96, "def": 0.97, "counts": { "def": 823, - "class": 108, + "class": 112, "module": 50 }, "missing": { @@ -1524,6 +1600,25 @@ "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-esp32", "version": "1.20.0", "port": "esp32", + "module": 0.68, + "class": 0.49, + "def": 0.36, + "counts": { + "def": 3874, + "class": 568, + "module": 316 + }, + "missing": { + "module": 101, + "class": 290, + "def": 2474 + } + }, + { + "folder": "micropython-v1_20_0-esp32-GENERIC", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-esp32-GENERIC", + "version": "1.20.0", + "port": "esp32", "module": 0.52, "class": 0.21, "def": 0.1, @@ -1539,8 +1634,8 @@ } }, { - "folder": "micropython-v1_20_0-esp32-merged", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-esp32-merged", + "folder": "micropython-v1_20_0-esp32-GENERIC-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-esp32-GENERIC-merged", "version": "1.20.0", "port": "esp32", "module": 0.84, @@ -1548,7 +1643,7 @@ "def": 0.61, "counts": { "def": 1966, - "class": 306, + "class": 314, "module": 158 }, "missing": { @@ -1558,8 +1653,8 @@ } }, { - "folder": "micropython-v1_20_0-esp32-OTA", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-esp32-OTA", + "folder": "micropython-v1_20_0-esp32-GENERIC_OTA", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-esp32-GENERIC_OTA", "version": "1.20.0", "port": "esp32", "module": 0.52, @@ -1577,8 +1672,8 @@ } }, { - "folder": "micropython-v1_20_0-esp32-OTA-merged", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-esp32-OTA-merged", + "folder": "micropython-v1_20_0-esp32-GENERIC_OTA-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-esp32-GENERIC_OTA-merged", "version": "1.20.0", "port": "esp32", "module": 0.84, @@ -1586,7 +1681,7 @@ "def": 0.61, "counts": { "def": 1966, - "class": 306, + "class": 314, "module": 158 }, "missing": { @@ -1596,8 +1691,8 @@ } }, { - "folder": "micropython-v1_20_0-esp32-S3", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-esp32-S3", + "folder": "micropython-v1_20_0-esp32-GENERIC_S3", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-esp32-GENERIC_S3", "version": "1.20.0", "port": "esp32", "module": 0.52, @@ -1615,16 +1710,16 @@ } }, { - "folder": "micropython-v1_20_0-esp32-S3-merged", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-esp32-S3-merged", + "folder": "micropython-v1_20_0-esp32-GENERIC_S3-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-esp32-GENERIC_S3-merged", "version": "1.20.0", "port": "esp32", "module": 0.85, - "class": 0.72, + "class": 0.73, "def": 0.61, "counts": { "def": 1944, - "class": 303, + "class": 311, "module": 156 }, "missing": { @@ -1639,55 +1734,17 @@ "version": "1.20.0", "port": "frozen", "module": 0.15, - "class": 0.15, + "class": 0.16, "def": 0.32, "counts": { "def": 18676, - "class": 2959, + "class": 2964, "module": 2019 }, "missing": { "module": 1711, - "class": 2517, - "def": 12774 - } - }, - { - "folder": "micropython-v1_20_0-rp2", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-rp2", - "version": "1.20.0", - "port": "rp2", - "module": 0.54, - "class": 0.52, - "def": 0.11, - "counts": { - "def": 1518, - "class": 339, - "module": 116 - }, - "missing": { - "module": 53, - "class": 164, - "def": 1354 - } - }, - { - "folder": "micropython-v1_20_0-rp2-merged", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-rp2-merged", - "version": "1.20.0", - "port": "rp2", - "module": 0.91, - "class": 0.81, - "def": 0.57, - "counts": { - "def": 1546, - "class": 363, - "module": 116 - }, - "missing": { - "module": 11, - "class": 69, - "def": 660 + "class": 2475, + "def": 12639 } }, { @@ -1715,17 +1772,17 @@ "version": "1.20.0", "port": "rp2", "module": 0.91, - "class": 0.81, - "def": 0.57, + "class": 0.83, + "def": 0.59, "counts": { "def": 1546, - "class": 363, + "class": 371, "module": 116 }, "missing": { "module": 11, - "class": 69, - "def": 660 + "class": 63, + "def": 630 } }, { @@ -1753,17 +1810,17 @@ "version": "1.20.0", "port": "rp2", "module": 0.88, - "class": 0.8, - "def": 0.56, + "class": 0.82, + "def": 0.58, "counts": { "def": 1776, - "class": 389, + "class": 397, "module": 138 }, "missing": { "module": 17, - "class": 77, - "def": 780 + "class": 71, + "def": 750 } }, { @@ -1791,17 +1848,17 @@ "version": "1.20.0", "port": "rp2", "module": 0.91, - "class": 0.78, - "def": 0.57, + "class": 0.8, + "def": 0.59, "counts": { "def": 1546, - "class": 309, + "class": 317, "module": 116 }, "missing": { "module": 11, - "class": 69, - "def": 660 + "class": 63, + "def": 630 } }, { @@ -1833,7 +1890,7 @@ "def": 0.56, "counts": { "def": 1454, - "class": 401, + "class": 409, "module": 102 }, "missing": { @@ -1871,7 +1928,7 @@ "def": 0.56, "counts": { "def": 1454, - "class": 375, + "class": 383, "module": 102 }, "missing": { @@ -1905,11 +1962,11 @@ "version": "1.20.0", "port": "samd", "module": 0.88, - "class": 0.83, + "class": 0.84, "def": 0.56, "counts": { "def": 1454, - "class": 357, + "class": 365, "module": 102 }, "missing": { @@ -1947,7 +2004,7 @@ "def": 0.56, "counts": { "def": 1454, - "class": 543, + "class": 551, "module": 102 }, "missing": { @@ -1976,32 +2033,13 @@ } }, { - "folder": "micropython-v1_20_0-stm32-merged", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-stm32-merged", + "folder": "micropython-v1_20_0-stm32-PYBV11", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-stm32-PYBV11", "version": "1.20.0", "port": "stm32", - "module": 0.9, - "class": 0.9, - "def": 0.65, - "counts": { - "def": 2066, - "class": 563, - "module": 118 - }, - "missing": { - "module": 12, - "class": 58, - "def": 720 - } - }, - { - "folder": "micropython-v1_20_0-stm32-PYBV11", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_20_0-stm32-PYBV11", - "version": "1.20.0", - "port": "stm32", - "module": 0.53, - "class": 0.66, - "def": 0.09, + "module": 0.53, + "class": 0.66, + "def": 0.09, "counts": { "def": 2034, "class": 539, @@ -2023,7 +2061,7 @@ "def": 0.65, "counts": { "def": 2066, - "class": 563, + "class": 571, "module": 118 }, "missing": { @@ -2042,7 +2080,7 @@ "def": 0.97, "counts": { "def": 915, - "class": 124, + "class": 128, "module": 55 }, "missing": { @@ -2051,25 +2089,6 @@ "def": 24 } }, - { - "folder": "micropython-v1_21_0-esp32", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_21_0-esp32", - "version": "1.21.0", - "port": "esp32", - "module": 0.51, - "class": 0.29, - "def": 0.1, - "counts": { - "def": 2220, - "class": 339, - "module": 179 - }, - "missing": { - "module": 87, - "class": 242, - "def": 1988 - } - }, { "folder": "micropython-v1_21_0-esp32-ESP32_GENERIC", "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_21_0-esp32-ESP32_GENERIC", @@ -2094,37 +2113,18 @@ "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_21_0-esp32-ESP32_GENERIC-merged", "version": "1.21.0", "port": "esp32", - "module": 0.83, - "class": 0.7, - "def": 0.58, - "counts": { - "def": 2236, - "class": 377, - "module": 174 - }, - "missing": { - "module": 30, - "class": 112, - "def": 950 - } - }, - { - "folder": "micropython-v1_21_0-esp32-merged", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_21_0-esp32-merged", - "version": "1.21.0", - "port": "esp32", - "module": 0.83, - "class": 0.7, - "def": 0.58, + "module": 0.84, + "class": 0.71, + "def": 0.59, "counts": { - "def": 2236, - "class": 377, + "def": 2248, + "class": 385, "module": 174 }, "missing": { - "module": 30, - "class": 112, - "def": 950 + "module": 28, + "class": 110, + "def": 918 } }, { @@ -2133,17 +2133,17 @@ "version": "1.21.0", "port": "frozen", "module": 0.23, - "class": 0.15, + "class": 0.17, "def": 0.36, "counts": { "def": 19937, - "class": 2989, + "class": 2996, "module": 2338 }, "missing": { "module": 1795, - "class": 2554, - "def": 12856 + "class": 2494, + "def": 12679 } }, { @@ -2170,18 +2170,18 @@ "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_21_0-rp2-RPI_PICO-merged", "version": "1.21.0", "port": "rp2", - "module": 0.88, - "class": 0.78, - "def": 0.55, + "module": 0.89, + "class": 0.82, + "def": 0.62, "counts": { - "def": 1676, - "class": 424, + "def": 1688, + "class": 432, "module": 128 }, "missing": { - "module": 16, - "class": 95, - "def": 754 + "module": 14, + "class": 79, + "def": 644 } }, { @@ -2208,18 +2208,18 @@ "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_21_0-rp2-RPI_PICO_W-merged", "version": "1.21.0", "port": "rp2", - "module": 0.82, - "class": 0.72, - "def": 0.52, + "module": 0.83, + "class": 0.75, + "def": 0.57, "counts": { - "def": 2276, - "class": 628, + "def": 2288, + "class": 636, "module": 174 }, "missing": { - "module": 32, - "class": 175, - "def": 1088 + "module": 30, + "class": 159, + "def": 978 } }, { @@ -2228,17 +2228,17 @@ "version": "1.21.0", "port": "samd", "module": 0.52, - "class": 0.72, + "class": 0.71, "def": 0.11, "counts": { - "def": 1506, - "class": 594, - "module": 114 + "def": 1534, + "class": 596, + "module": 116 }, "missing": { - "module": 55, - "class": 168, - "def": 1340 + "module": 56, + "class": 170, + "def": 1366 } }, { @@ -2246,18 +2246,18 @@ "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_21_0-samd-SEEED_WIO_TERMINAL-merged", "version": "1.21.0", "port": "samd", - "module": 0.85, - "class": 0.86, - "def": 0.55, + "module": 0.86, + "class": 0.88, + "def": 0.6, "counts": { - "def": 1534, - "class": 616, - "module": 114 + "def": 1574, + "class": 626, + "module": 116 }, "missing": { - "module": 17, - "class": 86, - "def": 688 + "module": 16, + "class": 78, + "def": 634 } }, { @@ -2284,227 +2284,607 @@ "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_21_0-stm32-PYBV11-merged", "version": "1.21.0", "port": "stm32", - "module": 0.88, - "class": 0.87, - "def": 0.63, + "module": 0.9, + "class": 0.89, + "def": 0.67, "counts": { - "def": 2178, - "class": 622, + "def": 2190, + "class": 630, "module": 124 }, "missing": { - "module": 15, - "class": 82, - "def": 806 + "module": 13, + "class": 72, + "def": 726 } }, { - "folder": "micropython-v1_9_3-esp8266", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_9_3-esp8266", - "version": "1.9.3", - "port": "esp8266", + "folder": "micropython-v1_21_0-webassembly-GENERIC", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_21_0-webassembly-GENERIC", + "version": "1.21.0", + "port": "webassembly", "module": 0.51, - "class": 0.58, - "def": 0.01, + "class": 0.0, + "def": 0.07, "counts": { - "def": 1112, - "class": 182, - "module": 117 + "def": 664, + "class": 44, + "module": 80 }, "missing": { - "module": 57, - "class": 76, - "def": 1100 + "module": 39, + "class": 44, + "def": 620 } }, { - "folder": "micropython-v1_9_3-frozen", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_9_3-frozen", - "version": "1.9.3", - "port": "frozen", - "module": 0.05, - "class": 0.0, - "def": 0.16, + "folder": "micropython-v1_21_0-webassembly-GENERIC-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_21_0-webassembly-GENERIC-merged", + "version": "1.21.0", + "port": "webassembly", + "module": 0.97, + "class": 0.77, + "def": 0.64, "counts": { - "def": 363, - "class": 40, - "module": 40 + "def": 688, + "class": 70, + "module": 80 }, "missing": { - "module": 38, - "class": 40, - "def": 306 + "module": 2, + "class": 16, + "def": 246 } }, { - "folder": "micropython-v1_9_4-esp8266", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_9_4-esp8266", - "version": "1.9.4", - "port": "esp8266", - "module": 0.52, - "class": 0.5, - "def": 0.02, + "folder": "micropython-v1_22_0-docstubs", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-docstubs", + "version": "1.22.0", + "port": "docstubs", + "module": 1.0, + "class": 0.96, + "def": 0.97, "counts": { - "def": 642, - "class": 104, - "module": 119 + "def": 919, + "class": 120, + "module": 55 }, "missing": { - "module": 57, - "class": 52, - "def": 630 + "module": 0, + "class": 5, + "def": 24 } }, { - "folder": "micropython-v1_9_4-frozen", - "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_9_4-frozen", - "version": "1.9.4", - "port": "frozen", - "module": 0.05, - "class": 0.0, - "def": 0.17, + "folder": "micropython-v1_22_0-esp32-ESP32_GENERIC", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-esp32-ESP32_GENERIC", + "version": "1.22.0", + "port": "esp32", + "module": 0.52, + "class": 0.3, + "def": 0.11, "counts": { - "def": 571, - "class": 82, - "module": 74 + "def": 2242, + "class": 353, + "module": 178 }, "missing": { - "module": 70, - "class": 82, - "def": 474 + "module": 85, + "class": 248, + "def": 2002 } }, { - "folder": "micropython-latest-esp32-stubs", - "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-esp32-stubs", - "version": "99.99.99", + "folder": "micropython-v1_22_0-esp32-ESP32_GENERIC-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-esp32-ESP32_GENERIC-merged", + "version": "1.22.0", "port": "esp32", - "module": 0.61, - "class": 0.59, + "module": 0.84, + "class": 0.72, "def": 0.59, "counts": { - "def": 1148, - "class": 145, - "module": 94 + "def": 2274, + "class": 397, + "module": 174 }, "missing": { - "module": 37, - "class": 59, - "def": 475 + "module": 28, + "class": 112, + "def": 922 } }, { - "folder": "micropython-latest-rp2-pimoroni_picolipo_16mb-stubs", - "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-rp2-pimoroni_picolipo_16mb-stubs", - "version": "99.99.99", - "port": "rp2", - "module": 0.7, - "class": 0.55, - "def": 0.55, + "folder": "micropython-v1_22_0-esp32-ESP32_GENERIC_S3", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-esp32-ESP32_GENERIC_S3", + "version": "1.22.0", + "port": "esp32", + "module": 0.52, + "class": 0.3, + "def": 0.11, "counts": { - "def": 844, - "class": 107, - "module": 66 + "def": 2232, + "class": 349, + "module": 178 }, "missing": { - "module": 20, - "class": 48, - "def": 377 + "module": 85, + "class": 244, + "def": 1996 } }, { - "folder": "micropython-latest-rp2-stubs", - "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-rp2-stubs", - "version": "99.99.99", - "port": "rp2", - "module": 0.7, - "class": 0.55, - "def": 0.55, + "folder": "micropython-v1_22_0-esp32-ESP32_GENERIC_S3-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-esp32-ESP32_GENERIC_S3-merged", + "version": "1.22.0", + "port": "esp32", + "module": 0.84, + "class": 0.73, + "def": 0.59, "counts": { - "def": 844, - "class": 107, - "module": 66 + "def": 2264, + "class": 393, + "module": 174 }, "missing": { - "module": 20, - "class": 48, - "def": 377 + "module": 28, + "class": 108, + "def": 918 } }, { - "folder": "micropython-latest-samd-adafruit_feather_m4_express-stubs", - "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-samd-adafruit_feather_m4_express-stubs", - "version": "99.99.99", - "port": "samd", - "module": 0.68, - "class": 0.58, - "def": 0.54, + "folder": "micropython-v1_22_0-esp32-Generic_ESP32S3_module", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-esp32-Generic_ESP32S3_module", + "version": "1.22.0", + "port": "esp32", + "module": 0.52, + "class": 0.3, + "def": 0.11, "counts": { - "def": 798, - "class": 99, - "module": 59 + "def": 2232, + "class": 349, + "module": 178 }, "missing": { - "module": 19, - "class": 42, - "def": 368 + "module": 85, + "class": 244, + "def": 1996 } }, { - "folder": "micropython-latest-samd-adafruit_itsybitsy_m4_express-stubs", - "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-samd-adafruit_itsybitsy_m4_express-stubs", - "version": "99.99.99", - "port": "samd", - "module": 0.68, - "class": 0.58, - "def": 0.54, + "folder": "micropython-v1_22_0-rp2-ARDUINO_NANO_RP2040_CONNECT", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-rp2-ARDUINO_NANO_RP2040_CONNECT", + "version": "1.22.0", + "port": "rp2", + "module": 0.53, + "class": 0.52, + "def": 0.12, "counts": { - "def": 798, - "class": 99, - "module": 59 + "def": 2292, + "class": 616, + "module": 180 }, "missing": { - "module": 19, - "class": 42, - "def": 368 + "module": 85, + "class": 298, + "def": 2010 } }, { - "folder": "micropython-latest-samd-minisam_m4-stubs", - "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-samd-minisam_m4-stubs", - "version": "99.99.99", - "port": "samd", - "module": 0.68, - "class": 0.58, - "def": 0.54, + "folder": "micropython-v1_22_0-rp2-ARDUINO_NANO_RP2040_CONNECT-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-rp2-ARDUINO_NANO_RP2040_CONNECT-merged", + "version": "1.22.0", + "port": "rp2", + "module": 0.82, + "class": 0.75, + "def": 0.58, "counts": { - "def": 798, - "class": 99, - "module": 59 + "def": 2312, + "class": 646, + "module": 176 }, "missing": { - "module": 19, - "class": 42, - "def": 368 + "module": 31, + "class": 161, + "def": 976 } }, { - "folder": "micropython-latest-samd-seeed_wio_terminal-stubs", - "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-samd-seeed_wio_terminal-stubs", - "version": "99.99.99", + "folder": "micropython-v1_22_0-rp2-RPI_PICO", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-rp2-RPI_PICO", + "version": "1.22.0", + "port": "rp2", + "module": 0.54, + "class": 0.53, + "def": 0.12, + "counts": { + "def": 1612, + "class": 408, + "module": 130 + }, + "missing": { + "module": 60, + "class": 192, + "def": 1424 + } + }, + { + "folder": "micropython-v1_22_0-rp2-RPI_PICO-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-rp2-RPI_PICO-merged", + "version": "1.22.0", + "port": "rp2", + "module": 0.88, + "class": 0.82, + "def": 0.62, + "counts": { + "def": 1652, + "class": 438, + "module": 130 + }, + "missing": { + "module": 15, + "class": 79, + "def": 632 + } + }, + { + "folder": "micropython-v1_22_0-rp2-RPI_PICO_W", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-rp2-RPI_PICO_W", + "version": "1.22.0", + "port": "rp2", + "module": 0.53, + "class": 0.52, + "def": 0.12, + "counts": { + "def": 2228, + "class": 590, + "module": 180 + }, + "missing": { + "module": 85, + "class": 284, + "def": 1960 + } + }, + { + "folder": "micropython-v1_22_0-rp2-RPI_PICO_W-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-rp2-RPI_PICO_W-merged", + "version": "1.22.0", + "port": "rp2", + "module": 0.82, + "class": 0.76, + "def": 0.58, + "counts": { + "def": 2248, + "class": 620, + "module": 176 + }, + "missing": { + "module": 31, + "class": 151, + "def": 954 + } + }, + { + "folder": "micropython-v1_22_0-samd-SEEED_WIO_TERMINAL", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-samd-SEEED_WIO_TERMINAL", + "version": "1.22.0", "port": "samd", + "module": 0.52, + "class": 0.72, + "def": 0.11, + "counts": { + "def": 1488, + "class": 604, + "module": 116 + }, + "missing": { + "module": 56, + "class": 172, + "def": 1318 + } + }, + { + "folder": "micropython-v1_22_0-samd-SEEED_WIO_TERMINAL-merged", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_22_0-samd-SEEED_WIO_TERMINAL-merged", + "version": "1.22.0", + "port": "samd", + "module": 0.86, + "class": 0.88, + "def": 0.6, + "counts": { + "def": 1528, + "class": 634, + "module": 116 + }, + "missing": { + "module": 16, + "class": 76, + "def": 614 + } + }, + { + "folder": "micropython-v1_9_3-esp8266", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_9_3-esp8266", + "version": "1.9.3", + "port": "esp8266", + "module": 0.51, + "class": 0.58, + "def": 0.01, + "counts": { + "def": 1112, + "class": 182, + "module": 117 + }, + "missing": { + "module": 57, + "class": 76, + "def": 1100 + } + }, + { + "folder": "micropython-v1_9_3-frozen", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_9_3-frozen", + "version": "1.9.3", + "port": "frozen", + "module": 0.05, + "class": 0.0, + "def": 0.16, + "counts": { + "def": 363, + "class": 40, + "module": 40 + }, + "missing": { + "module": 38, + "class": 40, + "def": 306 + } + }, + { + "folder": "micropython-v1_9_4-esp8266", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_9_4-esp8266", + "version": "1.9.4", + "port": "esp8266", + "module": 0.52, + "class": 0.5, + "def": 0.02, + "counts": { + "def": 642, + "class": 104, + "module": 119 + }, + "missing": { + "module": 57, + "class": 52, + "def": 630 + } + }, + { + "folder": "micropython-v1_9_4-frozen", + "path": "..\\repos\\micropython-stubs\\stubs\\micropython-v1_9_4-frozen", + "version": "1.9.4", + "port": "frozen", + "module": 0.05, + "class": 0.0, + "def": 0.17, + "counts": { + "def": 571, + "class": 82, + "module": 74 + }, + "missing": { + "module": 70, + "class": 82, + "def": 474 + } + }, + { + "folder": "micropython-latest-esp32-esp32_generic-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-esp32-esp32_generic-stubs", + "version": "99.99.99", + "port": "esp32", "module": 0.68, + "class": 0.6, + "def": 0.6, + "counts": { + "def": 1096, + "class": 138, + "module": 87 + }, + "missing": { + "module": 28, + "class": 55, + "def": 435 + } + }, + { + "folder": "micropython-latest-esp32-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-esp32-stubs", + "version": "99.99.99", + "port": "esp32", + "module": 0.68, + "class": 0.6, + "def": 0.6, + "counts": { + "def": 1096, + "class": 138, + "module": 87 + }, + "missing": { + "module": 28, + "class": 55, + "def": 435 + } + }, + { + "folder": "micropython-latest-rp2-pimoroni_picolipo_16mb-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-rp2-pimoroni_picolipo_16mb-stubs", + "version": "99.99.99", + "port": "rp2", + "module": 0.81, "class": 0.58, - "def": 0.54, + "def": 0.59, "counts": { - "def": 798, - "class": 99, - "module": 59 + "def": 745, + "class": 88, + "module": 58 + }, + "missing": { + "module": 11, + "class": 37, + "def": 306 + } + }, + { + "folder": "micropython-latest-rp2-rpi_pico-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-rp2-rpi_pico-stubs", + "version": "99.99.99", + "port": "rp2", + "module": 0.78, + "class": 0.62, + "def": 0.63, + "counts": { + "def": 816, + "class": 105, + "module": 64 + }, + "missing": { + "module": 14, + "class": 40, + "def": 298 + } + }, + { + "folder": "micropython-latest-rp2-rpi_pico_w-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-rp2-rpi_pico_w-stubs", + "version": "99.99.99", + "port": "rp2", + "module": 0.64, + "class": 0.54, + "def": 0.62, + "counts": { + "def": 1142, + "class": 138, + "module": 92 + }, + "missing": { + "module": 33, + "class": 63, + "def": 435 + } + }, + { + "folder": "micropython-latest-rp2-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-rp2-stubs", + "version": "99.99.99", + "port": "rp2", + "module": 0.78, + "class": 0.62, + "def": 0.63, + "counts": { + "def": 816, + "class": 105, + "module": 64 + }, + "missing": { + "module": 14, + "class": 40, + "def": 298 + } + }, + { + "folder": "micropython-latest-samd-adafruit_feather_m4_express-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-samd-adafruit_feather_m4_express-stubs", + "version": "99.99.99", + "port": "samd", + "module": 0.76, + "class": 0.6, + "def": 0.57, + "counts": { + "def": 700, + "class": 80, + "module": 51 + }, + "missing": { + "module": 12, + "class": 32, + "def": 299 + } + }, + { + "folder": "micropython-latest-samd-adafruit_itsybitsy_m4_express-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-samd-adafruit_itsybitsy_m4_express-stubs", + "version": "99.99.99", + "port": "samd", + "module": 0.76, + "class": 0.6, + "def": 0.57, + "counts": { + "def": 700, + "class": 80, + "module": 51 }, "missing": { - "module": 19, - "class": 42, - "def": 368 + "module": 12, + "class": 32, + "def": 299 + } + }, + { + "folder": "micropython-latest-samd-minisam_m4-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-samd-minisam_m4-stubs", + "version": "99.99.99", + "port": "samd", + "module": 0.76, + "class": 0.6, + "def": 0.57, + "counts": { + "def": 700, + "class": 80, + "module": 51 + }, + "missing": { + "module": 12, + "class": 32, + "def": 299 + } + }, + { + "folder": "micropython-latest-samd-seeed_wio_terminal-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-samd-seeed_wio_terminal-stubs", + "version": "99.99.99", + "port": "samd", + "module": 0.74, + "class": 0.6, + "def": 0.62, + "counts": { + "def": 745, + "class": 95, + "module": 57 + }, + "missing": { + "module": 15, + "class": 38, + "def": 280 + } + }, + { + "folder": "micropython-latest-samd-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-samd-stubs", + "version": "99.99.99", + "port": "samd", + "module": 0.74, + "class": 0.6, + "def": 0.62, + "counts": { + "def": 745, + "class": 95, + "module": 57 + }, + "missing": { + "module": 15, + "class": 38, + "def": 280 } }, { @@ -2512,18 +2892,18 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-stm32-pybv11-stubs", "version": "99.99.99", "port": "stm32", - "module": 0.74, - "class": 0.66, - "def": 0.64, + "module": 0.79, + "class": 0.69, + "def": 0.68, "counts": { - "def": 1104, - "class": 119, - "module": 66 + "def": 1067, + "class": 116, + "module": 62 }, "missing": { - "module": 17, - "class": 41, - "def": 400 + "module": 13, + "class": 36, + "def": 339 } }, { @@ -2531,18 +2911,37 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-stm32-stubs", "version": "99.99.99", "port": "stm32", - "module": 0.74, - "class": 0.66, - "def": 0.64, + "module": 0.79, + "class": 0.69, + "def": 0.68, "counts": { - "def": 1104, - "class": 119, - "module": 66 + "def": 1067, + "class": 116, + "module": 62 }, "missing": { - "module": 17, - "class": 41, - "def": 400 + "module": 13, + "class": 36, + "def": 339 + } + }, + { + "folder": "micropython-latest-webassembly-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-latest-webassembly-stubs", + "version": "99.99.99", + "port": "webassembly", + "module": 0.95, + "class": 0.7, + "def": 0.69, + "counts": { + "def": 316, + "class": 27, + "module": 40 + }, + "missing": { + "module": 2, + "class": 8, + "def": 98 } }, { @@ -2554,9 +2953,9 @@ "class": 1.0, "def": 1.0, "counts": { - "def": 3625, - "class": 658, - "module": 63 + "def": 3566, + "class": 649, + "module": 57 }, "missing": { "module": 0, @@ -2716,6 +3115,44 @@ "def": 371 } }, + { + "folder": "micropython-v1_19_1-esp32-generic_s3-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_19_1-esp32-generic_s3-stubs", + "version": "1.19.1", + "port": "esp32", + "module": 0.64, + "class": 0.62, + "def": 0.58, + "counts": { + "def": 1048, + "class": 136, + "module": 86 + }, + "missing": { + "module": 31, + "class": 51, + "def": 443 + } + }, + { + "folder": "micropython-v1_19_1-esp32-generic_spiram-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_19_1-esp32-generic_spiram-stubs", + "version": "1.19.1", + "port": "esp32", + "module": 0.65, + "class": 0.66, + "def": 0.59, + "counts": { + "def": 1003, + "class": 129, + "module": 82 + }, + "missing": { + "module": 29, + "class": 44, + "def": 416 + } + }, { "folder": "micropython-v1_19_1-esp32-s3-stubs", "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_19_1-esp32-s3-stubs", @@ -2740,18 +3177,18 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_19_1-esp32-stubs", "version": "1.19.1", "port": "esp32", - "module": 0.64, - "class": 0.65, - "def": 0.57, + "module": 0.65, + "class": 0.66, + "def": 0.59, "counts": { - "def": 1020, - "class": 133, - "module": 81 + "def": 1003, + "class": 129, + "module": 82 }, "missing": { "module": 29, - "class": 47, - "def": 443 + "class": 44, + "def": 416 } }, { @@ -2759,18 +3196,18 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_19_1-esp32-um_tinypico-stubs", "version": "1.19.1", "port": "esp32", - "module": 0.63, + "module": 0.62, "class": 0.65, - "def": 0.57, + "def": 0.63, "counts": { - "def": 1038, - "class": 134, - "module": 83 + "def": 931, + "class": 110, + "module": 82 }, "missing": { "module": 31, - "class": 47, - "def": 443 + "class": 38, + "def": 342 } }, { @@ -2778,56 +3215,94 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_19_1-esp8266-stubs", "version": "1.19.1", "port": "esp8266", - "module": 0.71, - "class": 0.72, - "def": 0.58, + "module": 0.73, + "class": 0.73, + "def": 0.59, "counts": { - "def": 739, + "def": 724, "class": 85, - "module": 65 + "module": 66 }, "missing": { - "module": 19, - "class": 24, - "def": 311 + "module": 18, + "class": 23, + "def": 296 + } + }, + { + "folder": "micropython-v1_19_1-rp2-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_19_1-rp2-stubs", + "version": "1.19.1", + "port": "rp2", + "module": 0.69, + "class": 0.53, + "def": 0.58, + "counts": { + "def": 981, + "class": 137, + "module": 74 + }, + "missing": { + "module": 23, + "class": 64, + "def": 413 + } + }, + { + "folder": "micropython-v1_19_1-stm32-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_19_1-stm32-stubs", + "version": "1.19.1", + "port": "stm32", + "module": 0.77, + "class": 0.75, + "def": 0.66, + "counts": { + "def": 1043, + "class": 114, + "module": 60 + }, + "missing": { + "module": 14, + "class": 28, + "def": 358 } }, { - "folder": "micropython-v1_19_1-rp2-stubs", - "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_19_1-rp2-stubs", - "version": "1.19.1", - "port": "rp2", - "module": 0.68, - "class": 0.5, - "def": 0.54, + "folder": "micropython-v1_20_0-esp32-generic_ota-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_20_0-esp32-generic_ota-stubs", + "version": "1.20.0", + "port": "esp32", + "module": 0.65, + "class": 0.63, + "def": 0.62, "counts": { - "def": 1003, - "class": 142, - "module": 73 + "def": 1010, + "class": 126, + "module": 85 }, "missing": { - "module": 23, - "class": 71, - "def": 460 + "module": 30, + "class": 46, + "def": 384 } }, { - "folder": "micropython-v1_19_1-stm32-stubs", - "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_19_1-stm32-stubs", - "version": "1.19.1", - "port": "stm32", - "module": 0.76, - "class": 0.73, - "def": 0.63, + "folder": "micropython-v1_20_0-esp32-generic_s3-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_20_0-esp32-generic_s3-stubs", + "version": "1.20.0", + "port": "esp32", + "module": 0.65, + "class": 0.64, + "def": 0.62, "counts": { - "def": 1066, - "class": 119, - "module": 59 + "def": 980, + "class": 120, + "module": 84 }, "missing": { - "module": 14, - "class": 32, - "def": 391 + "module": 29, + "class": 43, + "def": 369 } }, { @@ -2873,18 +3348,18 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_20_0-esp32-stubs", "version": "1.20.0", "port": "esp32", - "module": 0.64, - "class": 0.64, - "def": 0.61, + "module": 0.65, + "class": 0.63, + "def": 0.62, "counts": { - "def": 1041, - "class": 130, + "def": 1010, + "class": 126, "module": 85 }, "missing": { - "module": 31, - "class": 47, - "def": 410 + "module": 30, + "class": 46, + "def": 384 } }, { @@ -2892,18 +3367,18 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_20_0-rp2-pico-stubs", "version": "1.20.0", "port": "rp2", - "module": 0.77, - "class": 0.65, - "def": 0.59, + "module": 0.8, + "class": 0.68, + "def": 0.63, "counts": { - "def": 782, - "class": 97, + "def": 751, + "class": 93, "module": 60 }, "missing": { - "module": 14, - "class": 34, - "def": 324 + "module": 12, + "class": 30, + "def": 281 } }, { @@ -2911,37 +3386,18 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_20_0-rp2-pico_w-stubs", "version": "1.20.0", "port": "rp2", - "module": 0.72, - "class": 0.63, - "def": 0.57, + "module": 0.75, + "class": 0.66, + "def": 0.61, "counts": { - "def": 896, - "class": 104, + "def": 865, + "class": 100, "module": 71 }, "missing": { - "module": 20, - "class": 38, - "def": 383 - } - }, - { - "folder": "micropython-v1_20_0-rp2-pimoroni_picolipo_16mb-stubs", - "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_20_0-rp2-pimoroni_picolipo_16mb-stubs", - "version": "1.20.0", - "port": "rp2", - "module": 0.77, - "class": 0.65, - "def": 0.59, - "counts": { - "def": 782, - "class": 97, - "module": 60 - }, - "missing": { - "module": 14, + "module": 18, "class": 34, - "def": 324 + "def": 340 } }, { @@ -2949,18 +3405,18 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_20_0-rp2-stubs", "version": "1.20.0", "port": "rp2", - "module": 0.77, - "class": 0.65, - "def": 0.59, + "module": 0.8, + "class": 0.68, + "def": 0.63, "counts": { - "def": 782, - "class": 97, + "def": 751, + "class": 93, "module": 60 }, "missing": { - "module": 14, - "class": 34, - "def": 324 + "module": 12, + "class": 30, + "def": 281 } }, { @@ -2969,17 +3425,17 @@ "version": "1.20.0", "port": "samd", "module": 0.75, - "class": 0.69, - "def": 0.57, + "class": 0.67, + "def": 0.59, "counts": { - "def": 736, - "class": 89, + "def": 705, + "class": 85, "module": 53 }, "missing": { "module": 13, "class": 28, - "def": 315 + "def": 291 } }, { @@ -2988,17 +3444,17 @@ "version": "1.20.0", "port": "samd", "module": 0.75, - "class": 0.69, - "def": 0.57, + "class": 0.67, + "def": 0.59, "counts": { - "def": 736, - "class": 89, + "def": 705, + "class": 85, "module": 53 }, "missing": { "module": 13, "class": 28, - "def": 315 + "def": 291 } }, { @@ -3007,17 +3463,17 @@ "version": "1.20.0", "port": "samd", "module": 0.75, - "class": 0.69, - "def": 0.57, + "class": 0.67, + "def": 0.59, "counts": { - "def": 736, - "class": 89, + "def": 705, + "class": 85, "module": 53 }, "missing": { "module": 13, "class": 28, - "def": 315 + "def": 291 } }, { @@ -3026,17 +3482,36 @@ "version": "1.20.0", "port": "samd", "module": 0.75, - "class": 0.69, - "def": 0.57, + "class": 0.67, + "def": 0.59, "counts": { - "def": 736, - "class": 89, + "def": 705, + "class": 85, + "module": 53 + }, + "missing": { + "module": 13, + "class": 28, + "def": 291 + } + }, + { + "folder": "micropython-v1_20_0-samd-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_20_0-samd-stubs", + "version": "1.20.0", + "port": "samd", + "module": 0.75, + "class": 0.67, + "def": 0.59, + "counts": { + "def": 705, + "class": 85, "module": 53 }, "missing": { "module": 13, "class": 28, - "def": 315 + "def": 291 } }, { @@ -3044,18 +3519,18 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_20_0-stm32-pybv11-stubs", "version": "1.20.0", "port": "stm32", - "module": 0.77, - "class": 0.75, - "def": 0.66, + "module": 0.78, + "class": 0.74, + "def": 0.67, "counts": { - "def": 1043, - "class": 109, - "module": 61 + "def": 1011, + "class": 105, + "module": 60 }, "missing": { - "module": 14, + "module": 13, "class": 27, - "def": 353 + "def": 329 } }, { @@ -3063,18 +3538,18 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_20_0-stm32-stubs", "version": "1.20.0", "port": "stm32", - "module": 0.77, - "class": 0.75, - "def": 0.66, + "module": 0.78, + "class": 0.74, + "def": 0.67, "counts": { - "def": 1043, - "class": 109, - "module": 61 + "def": 1011, + "class": 105, + "module": 60 }, "missing": { - "module": 14, + "module": 13, "class": 27, - "def": 353 + "def": 329 } }, { @@ -3082,18 +3557,18 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_21_0-esp32-esp32_generic-stubs", "version": "1.21.0", "port": "esp32", - "module": 0.64, + "module": 0.65, "class": 0.6, - "def": 0.59, + "def": 0.61, "counts": { - "def": 1150, - "class": 145, - "module": 94 + "def": 1122, + "class": 141, + "module": 93 }, "missing": { - "module": 34, - "class": 58, - "def": 471 + "module": 33, + "class": 57, + "def": 441 } }, { @@ -3101,18 +3576,18 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_21_0-esp32-stubs", "version": "1.21.0", "port": "esp32", - "module": 0.64, + "module": 0.65, "class": 0.6, - "def": 0.59, + "def": 0.61, "counts": { - "def": 1150, - "class": 145, - "module": 94 + "def": 1122, + "class": 141, + "module": 93 }, "missing": { - "module": 34, - "class": 58, - "def": 471 + "module": 33, + "class": 57, + "def": 441 } }, { @@ -3120,18 +3595,18 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_21_0-rp2-rpi_pico-stubs", "version": "1.21.0", "port": "rp2", - "module": 0.76, - "class": 0.58, - "def": 0.58, + "module": 0.77, + "class": 0.63, + "def": 0.63, "counts": { - "def": 838, - "class": 106, - "module": 67 + "def": 810, + "class": 102, + "module": 66 }, "missing": { - "module": 16, - "class": 44, - "def": 356 + "module": 15, + "class": 38, + "def": 299 } }, { @@ -3139,18 +3614,37 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_21_0-rp2-rpi_pico_w-stubs", "version": "1.21.0", "port": "rp2", - "module": 0.62, - "class": 0.51, - "def": 0.58, + "module": 0.63, + "class": 0.54, + "def": 0.62, "counts": { - "def": 1170, - "class": 142, - "module": 93 + "def": 1142, + "class": 138, + "module": 92 }, "missing": { - "module": 35, - "class": 69, - "def": 492 + "module": 34, + "class": 63, + "def": 435 + } + }, + { + "folder": "micropython-v1_21_0-rp2-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_21_0-rp2-stubs", + "version": "1.21.0", + "port": "rp2", + "module": 0.77, + "class": 0.63, + "def": 0.63, + "counts": { + "def": 810, + "class": 102, + "module": 66 + }, + "missing": { + "module": 15, + "class": 38, + "def": 299 } }, { @@ -3158,18 +3652,37 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_21_0-samd-seeed_wio_terminal-stubs", "version": "1.21.0", "port": "samd", - "module": 0.72, - "class": 0.59, - "def": 0.58, + "module": 0.73, + "class": 0.61, + "def": 0.62, "counts": { - "def": 766, - "class": 96, - "module": 60 + "def": 738, + "class": 92, + "module": 59 }, "missing": { - "module": 17, - "class": 39, - "def": 325 + "module": 16, + "class": 36, + "def": 283 + } + }, + { + "folder": "micropython-v1_21_0-samd-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_21_0-samd-stubs", + "version": "1.21.0", + "port": "samd", + "module": 0.73, + "class": 0.61, + "def": 0.62, + "counts": { + "def": 738, + "class": 92, + "module": 59 + }, + "missing": { + "module": 16, + "class": 36, + "def": 283 } }, { @@ -3177,18 +3690,56 @@ "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_21_0-stm32-pybv11-stubs", "version": "1.21.0", "port": "stm32", - "module": 0.77, - "class": 0.68, - "def": 0.65, + "module": 0.78, + "class": 0.7, + "def": 0.68, "counts": { - "def": 1089, - "class": 117, - "module": 64 + "def": 1061, + "class": 113, + "module": 63 }, "missing": { - "module": 15, - "class": 37, - "def": 385 + "module": 14, + "class": 34, + "def": 343 + } + }, + { + "folder": "micropython-v1_21_0-stm32-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_21_0-stm32-stubs", + "version": "1.21.0", + "port": "stm32", + "module": 0.78, + "class": 0.7, + "def": 0.68, + "counts": { + "def": 1061, + "class": 113, + "module": 63 + }, + "missing": { + "module": 14, + "class": 34, + "def": 343 + } + }, + { + "folder": "micropython-v1_21_0-webassembly-stubs", + "path": "..\\repos\\micropython-stubs\\publish\\micropython-v1_21_0-webassembly-stubs", + "version": "1.21.0", + "port": "webassembly", + "module": 0.95, + "class": 0.7, + "def": 0.69, + "counts": { + "def": 316, + "class": 27, + "module": 40 + }, + "missing": { + "module": 2, + "class": 8, + "def": 98 } } ] \ No newline at end of file diff --git a/scripts/quick_check_array.ipynb b/scripts/quick_check_array.ipynb deleted file mode 100644 index b1f66ddef..000000000 --- a/scripts/quick_check_array.ipynb +++ /dev/null @@ -1,198 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "quick check to help find if/where `class array(List)` is being properly generarated" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "from pathlib import Path" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "94\n" - ] - } - ], - "source": [ - "stub_path = Path(\"../repos/micropython-stubs/stubs\")\n", - "pub_path = Path(\"../repos/micropython-stubs/publish\")\n", - "\n", - "version = \"v1_19_1*\"\n", - "version = \"v1_20_0*\"\n", - "version = \"v1_*\"\n", - "files = list(stub_path.glob(f\"micropython-{version}-merged/array.py\"))\n", - "files += list(stub_path.glob(f\"micropython-{version}-merged/array.pyi\"))\n", - "files += list(stub_path.glob(f\"micropython-{version}-docstubs/array.pyi\"))\n", - "files += list(pub_path.glob(f\"micropython-{version}/array.pyi\"))\n", - "\n", - "files = sorted(files, key=lambda f: str(f.parent))\n", - "\n", - "print(len(files))\n", - "# files" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "publish/micropython-v1_17-esp32-stubs/array.pyi class array: \n", - "publish/micropython-v1_17-esp8266-stubs/array.pyi class array: \n", - "publish/micropython-v1_17-rp2-stubs/array.pyi class array: \n", - "publish/micropython-v1_17-stm32-stubs/array.pyi class array: \n", - "publish/micropython-v1_18-esp32-stubs/array.pyi class array: \n", - "publish/micropython-v1_18-esp8266-stubs/array.pyi class array: \n", - "publish/micropython-v1_18-rp2-stubs/array.pyi class array: \n", - "publish/micropython-v1_18-stm32-stubs/array.pyi class array: \n", - "publish/micropython-v1_19_1-esp32-generic_s3-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_19_1-esp32-generic_spiram-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_19_1-esp32-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_19_1-esp32-um_tinypico-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_19_1-esp8266-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_19_1-rp2-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_19_1-stm32-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_20_0-esp32-generic_ota-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_20_0-esp32-generic_s3-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_20_0-esp32-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_20_0-rp2-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_20_0-samd-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_20_0-stm32-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_21_0-esp32-esp32_generic-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_21_0-esp32-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_21_0-rp2-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_21_0-samd-stubs/array.pyi class array(List): \n", - "publish/micropython-v1_21_0-stm32-stubs/array.pyi class array(List): \n", - "stubs/micropython-v1_17-docstubs/array.pyi class array: \n", - "stubs/micropython-v1_17-esp32-merged/array.py class array: \n", - "stubs/micropython-v1_17-esp32-merged/array.pyi class array: \n", - "stubs/micropython-v1_17-esp8266-merged/array.py class array: \n", - "stubs/micropython-v1_17-esp8266-merged/array.pyi class array: \n", - "stubs/micropython-v1_17-rp2-merged/array.py class array: \n", - "stubs/micropython-v1_17-rp2-merged/array.pyi class array: \n", - "stubs/micropython-v1_17-stm32-merged/array.py class array: \n", - "stubs/micropython-v1_17-stm32-merged/array.pyi class array: \n", - "stubs/micropython-v1_18-docstubs/array.pyi class array: \n", - "stubs/micropython-v1_18-esp32-merged/array.py class array: \n", - "stubs/micropython-v1_18-esp32-merged/array.pyi class array: \n", - "stubs/micropython-v1_18-esp8266-merged/array.py class array: \n", - "stubs/micropython-v1_18-esp8266-merged/array.pyi class array: \n", - "stubs/micropython-v1_18-rp2-merged/array.py class array: \n", - "stubs/micropython-v1_18-rp2-merged/array.pyi class array: \n", - "stubs/micropython-v1_18-stm32-merged/array.py class array: \n", - "stubs/micropython-v1_18-stm32-merged/array.pyi class array: \n", - "stubs/micropython-v1_19-docstubs/array.pyi class array: \n", - "stubs/micropython-v1_19_1-docstubs/array.pyi class array(List): \n", - "stubs/micropython-v1_19_1-esp32-GENERIC-merged/array.py class array(List): \n", - "stubs/micropython-v1_19_1-esp32-GENERIC-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_19_1-esp32-GENERIC_S3-merged/array.py class array(List): \n", - "stubs/micropython-v1_19_1-esp32-GENERIC_S3-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_19_1-esp32-GENERIC_SPIRAM-merged/array.py class array(List): \n", - "stubs/micropython-v1_19_1-esp32-GENERIC_SPIRAM-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_19_1-esp32-UM_TINYPICO-merged/array.py class array(List): \n", - "stubs/micropython-v1_19_1-esp32-UM_TINYPICO-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_19_1-esp8266-merged/array.py class array(List): \n", - "stubs/micropython-v1_19_1-esp8266-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_19_1-rp2-merged/array.py class array(List): \n", - "stubs/micropython-v1_19_1-rp2-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_19_1-stm32-merged/array.py class array(List): \n", - "stubs/micropython-v1_19_1-stm32-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_20_0-docstubs/array.pyi class array(List): \n", - "stubs/micropython-v1_20_0-esp32-GENERIC-merged/array.py class array(List): \n", - "stubs/micropython-v1_20_0-esp32-GENERIC-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_20_0-esp32-GENERIC_OTA-merged/array.py class array(List): \n", - "stubs/micropython-v1_20_0-esp32-GENERIC_OTA-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_20_0-esp32-GENERIC_S3-merged/array.py class array(List): \n", - "stubs/micropython-v1_20_0-esp32-GENERIC_S3-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_20_0-rp2-PICO-merged/array.py class array(List): \n", - "stubs/micropython-v1_20_0-rp2-PICO-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_20_0-rp2-PICO_W-merged/array.py class array(List): \n", - "stubs/micropython-v1_20_0-rp2-PICO_W-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_20_0-rp2-PIMORONI_PICOLIPO_16MB-merged/array.py class array(List): \n", - "stubs/micropython-v1_20_0-rp2-PIMORONI_PICOLIPO_16MB-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_20_0-samd-ADAFRUIT_FEATHER_M4_EXPRESS-merged/array.py class array(List): \n", - "stubs/micropython-v1_20_0-samd-ADAFRUIT_FEATHER_M4_EXPRESS-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_20_0-samd-ADAFRUIT_ITSYBITSY_M4_EXPRESS-merged/array.py class array(List): \n", - "stubs/micropython-v1_20_0-samd-ADAFRUIT_ITSYBITSY_M4_EXPRESS-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_20_0-samd-MINISAM_M4-merged/array.py class array(List): \n", - "stubs/micropython-v1_20_0-samd-MINISAM_M4-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_20_0-samd-SEEED_WIO_TERMINAL-merged/array.py class array(List): \n", - "stubs/micropython-v1_20_0-samd-SEEED_WIO_TERMINAL-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_20_0-stm32-PYBV11-merged/array.py class array(List): \n", - "stubs/micropython-v1_20_0-stm32-PYBV11-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_21_0-docstubs/array.pyi class array(List): \n", - "stubs/micropython-v1_21_0-esp32-ESP32_GENERIC-merged/array.py class array(List): \n", - "stubs/micropython-v1_21_0-esp32-ESP32_GENERIC-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_21_0-rp2-RPI_PICO-merged/array.py class array(List): \n", - "stubs/micropython-v1_21_0-rp2-RPI_PICO-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_21_0-rp2-RPI_PICO_W-merged/array.py class array(List): \n", - "stubs/micropython-v1_21_0-rp2-RPI_PICO_W-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_21_0-samd-SEEED_WIO_TERMINAL-merged/array.py class array(List): \n", - "stubs/micropython-v1_21_0-samd-SEEED_WIO_TERMINAL-merged/array.pyi class array(List): \n", - "stubs/micropython-v1_21_0-stm32-PYBV11-merged/array.py class array(List): \n", - "stubs/micropython-v1_21_0-stm32-PYBV11-merged/array.pyi class array(List): \n" - ] - } - ], - "source": [ - "data = \"\"\n", - "for f in files:\n", - " with open(f, \"r\") as file:\n", - " data = file.read()\n", - " stat = \"?\"\n", - " if \"class array(List):\" in data:\n", - " stat = \"class array(List):\"\n", - " elif \"class array:\" in data:\n", - " stat = \"class array:\"\n", - " print(f\"{str(f.relative_to(stub_path.parent)):<80} {stat:<20}\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".venv", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.17" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/scripts/requirements.ps1 b/scripts/requirements.ps1 deleted file mode 100644 index ab2af19e3..000000000 --- a/scripts/requirements.ps1 +++ /dev/null @@ -1,31 +0,0 @@ -# script used to prepare for testing different setups - -pip install -U micropython-stdlib-minimal --target ./typings --no-user -# pip install micropython-esp32-stubs --target ./typings --no-user - -$PyPi = $False - -if ($PyPi) { - pip install -U micropython-stm32-stubs --target .snippets/stm32/typings --no-user - pip install -U micropython-esp32-stubs --target .snippets/esp32/typings --no-user - pip install -U micropython-esp8266-stubs --target .snippets/esp8266/typings --no-user - pip install -U micropython-rp2-stubs --target .snippets/rp2/typings --no-user -} else { - pip install -U C:\develop\MyPython\micropython-stubber\repos\micropython-stubs\publish\micropython-v1_19_1-stm32-stubs --target .snippets/stm32/typings --no-user - pip install -U C:\develop\MyPython\micropython-stubber\repos\micropython-stubs\publish\micropython-v1_19_1-esp32-stubs --target .snippets/esp32/typings --no-user - pip install -U C:\develop\MyPython\micropython-stubber\repos\micropython-stubs\publish\micropython-v1_19_1-esp8266-stubs --target .snippets/esp8266/typings --no-user - pip install -U C:\develop\MyPython\micropython-stubber\repos\micropython-stubs\publish\micropython-v1_19_1-rp2-stubs --target .snippets/rp2/typings --no-user -} - -if (0){ - pip install -U C:\develop\MyPython\micropython-stubber\repos\micropython-stubs\publish\m\micropython-stdlib-minimal --target ./typings --no-user - pip install -U C:\develop\MyPython\micropython-stubber\repos\micropython-stubs\publish\m\micropython-stdlib-minimal --target .snippets/stm32/typings --no-user - pip install -U C:\develop\MyPython\micropython-stubber\repos\micropython-stubs\publish\m\micropython-stdlib-minimal --target .snippets/esp32/typings --no-user - pip install -U C:\develop\MyPython\micropython-stubber\repos\micropython-stubs\publish\m\micropython-stdlib-minimal --target .snippets/esp8266/typings --no-user - pip install -U C:\develop\MyPython\micropython-stubber\repos\micropython-stubs\publish\m\micropython-stdlib-minimal --target .snippets/rp2/typings --no-user - - -} - - - From e73fdedce41a3ec9080217633d0be6f6bc1841ec Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Sun, 21 Jan 2024 20:21:12 +0100 Subject: [PATCH 29/68] createstubs: Refactor test_stubber_fwid. Signed-off-by: Jos Verlinde --- src/stubber/board/createstubs.py | 108 +++++----- tests/createstubs/createstubs_all_test.py | 91 ++++----- tests/createstubs/testcases.py | 237 ++++++++++++++++------ 3 files changed, 267 insertions(+), 169 deletions(-) diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index 85421cd2d..9f29cb4c9 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -8,7 +8,10 @@ import os import sys -from ujson import dumps +try: + from ujson import dumps +except: + from json import dumps try: from machine import reset # type: ignore @@ -46,9 +49,9 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-{ver}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) else: - self._fwid = "{family}-{ver}-{port}".format(**self.info) + self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore if path: @@ -109,11 +112,7 @@ def get_obj_attributes(self, item_instance: object): order = 4 _result.append((name, repr(val), repr(type(val)), val, order)) except AttributeError as e: - _errors.append( - "Couldn't get attribute '{}' from object '{}', Err: {}".format( - name, item_instance, e - ) - ) + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) except MemoryError as e: print("MemoryError: {}".format(e)) sleep(1) @@ -177,9 +176,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - self.log.info( - "Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1) - ) + self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) @@ -197,9 +194,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") - self._report.append( - '{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/")) - ) + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) if module_name not in {"os", "sys", "logging", "gc"}: # try to unload the module unless we use it @@ -214,9 +209,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: gc.collect() return True - def write_object_stub( - self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0 - ): + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: @@ -276,11 +269,7 @@ def write_object_stub( s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - self.log.debug( - "# def {1} function/method/closure, type = '{0}'".format( - item_type_txt, item_name - ) - ) + self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -291,13 +280,11 @@ def write_object_stub( first = "self, " # class method - add function decoration if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format( - indent - ) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) - else: - s = "{}def {}({}*args, **kwargs) -> {}:\n".format( - indent, item_name, first, ret + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format( + indent, item_name, ret ) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) self.log.debug("\n" + s) @@ -324,9 +311,7 @@ def write_object_stub( # https://docs.python.org/3/tutorial/classes.html#item_instance-objects t = "Incomplete" # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format( - indent, item_name, t, item_type_txt, item_repr - ) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -378,9 +363,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" self.log.info( - "Created stubs for {} modules on board {}\nPath: {}".format( - len(self._report), self._fwid, self.path - ) + "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) ) f_name = "{}/{}".format(self.path, filename) self.log.info("Report file: {}".format(f_name)) @@ -439,12 +422,15 @@ def ensure_folder(path: str): def _build(s): - # extract a build nr from a string + # extract build from sys.version or os.uname().version if available + # 'v1.13-103-gb137d064e' + # 'MicroPython v1.23.0-preview.6.g3d0b6276f' if not s: return "" - if " on " in s: - s = s.split(" on ", 1)[0] - return s.split("-")[1] if "-" in s else "" + s = s.split(" on ", 1)[0] if " on " in s else s + s = s.split("; ", 1)[1] if "; " in s else s + b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + return b def _info(): # type:() -> dict[str, str] @@ -469,14 +455,12 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") + info["version"] = version_str(sys.implementation.version) # type: ignore except AttributeError: pass try: _machine = ( - sys.implementation._machine - if "_machine" in dir(sys.implementation) - else os.uname().machine # type: ignore + sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore ) # info["board"] = "with".join(_machine.split("with")[:-1]).strip() info["board"] = _machine @@ -495,19 +479,20 @@ def _info(): # type:() -> dict[str, str] gc.collect() try: - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - if not info["build"] and ";" in sys.version: - # extract build from uname().release if available - info["build"] = _build(sys.version.split(";")[1]) - except (AttributeError, IndexError): + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): pass # avoid build hashes - if info["build"] and len(info["build"]) > 5: - info["build"] = "" + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" if info["version"] == "" and sys.platform not in ("unix", "win32"): try: @@ -533,14 +518,14 @@ def _info(): # type:() -> dict[str, str] info["release"] = "2.0.0" if info["family"] == "micropython": + info["version"] if ( info["version"] and info["version"].endswith(".0") - and info["version"] - >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 and info["version"] <= "1.19.9" ): - # drop the .0 for newer releases + # versions from 1.10.0 to 1.20.0 do not have a micro .0 info["version"] = info["version"][:-2] # spell-checker: disable @@ -564,12 +549,21 @@ def _info(): # type:() -> dict[str, str] info["arch"] = arch # .mpy version.minor info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" # simple to use version[-build] string - info["ver"] = f"v{info['version']}-{info['build']}" if info["build"] else f"v{info['version']}" + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" return info +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + def read_boardname(info, desc: str = ""): found = False for filename in [d + "/board_info.csv" for d in LIBS]: diff --git a/tests/createstubs/createstubs_all_test.py b/tests/createstubs/createstubs_all_test.py index c4454219c..5ba22d1b8 100644 --- a/tests/createstubs/createstubs_all_test.py +++ b/tests/createstubs/createstubs_all_test.py @@ -4,7 +4,7 @@ from collections import namedtuple from importlib import import_module from pathlib import Path -from typing import Any, Dict, Generator, List +from typing import Any, Dict, Generator, List, NamedTuple, Optional import pytest from mock import MagicMock @@ -74,9 +74,7 @@ def test_stubber_Class_available( @pytest.mark.parametrize("variant", VARIANTS) @pytest.mark.parametrize("location", LOCATIONS) -def test_stubber_info_basic( - location: Any, variant: str, mock_micropython_path: Generator[str, None, None] -): +def test_stubber_info_basic(location: Any, variant: str, mock_micropython_path: Generator[str, None, None]): createstubs = import_variant(location, variant) stubber = createstubs.Stubber() assert stubber is not None, "Can't create Stubber instance" @@ -114,26 +112,24 @@ def test_stubber_info_custom( ################################################# # test the fwid naming on the different platforms ################################################# -from testcases import fwid_test_cases +from testcases import MP_Implementation, fwid_test_cases # @pytest.mark.parametrize("variant", VARIANTS) # @pytest.mark.parametrize("location", LOCATIONS) @pytest.mark.parametrize( - "fwid, sys_imp_name, sys_imp_version, sys_platform, os_uname, mock_modules", + "fwid, sys_implementation, sys_platform, sys_version, os_uname, mock_modules", fwid_test_cases, ids=[e[0] for e in fwid_test_cases], ) @pytest.mark.mocked def test_stubber_fwid( mock_micropython_path: Generator[str, None, None], - # location: str, - # variant: str, mocker: MockerFixture, fwid: str, - sys_imp_name: str, - sys_imp_version: tuple, + sys_implementation: MP_Implementation, sys_platform: str, + sys_version: str, os_uname: Dict, mock_modules: List[str], ): @@ -141,19 +137,28 @@ def test_stubber_fwid( location = "board" createstubs = import_variant(location, variant) - # FIX-ME : This does not yet cover minified mod_name = f"stubber.board.{variant}" # class.property : just pass a value mocker.patch(f"{mod_name}.sys.platform", sys_platform) - mocker.patch(f"{mod_name}.sys.implementation.name", sys_imp_name) - mocker.patch(f"{mod_name}.sys.implementation.version", sys_imp_version) + # fatch sys.implementation + mocker.patch(f"{mod_name}.sys.implementation.name", sys_implementation.name) + mocker.patch(f"{mod_name}.sys.implementation.version", sys_implementation.version) + mocker.patch(f"{mod_name}.sys.version", sys_version) + if sys_implementation._machine: + mocker.patch(f"{mod_name}.sys.implementation._machine", sys_implementation._machine, create=True) + if sys_implementation._mpy: + mocker.patch(f"{mod_name}.sys.implementation._mpy", sys_implementation._mpy, create=True) # class.method--> mock using function - fake_uname = os_uname - def mock_uname(): - return fake_uname + if os_uname: + # only mock uname if there is something to mock + fake_uname = os_uname + + def mock_uname(): + return fake_uname + + mocker.patch(f"{mod_name}.os.uname", mock_uname, create=True) - mocker.patch(f"{mod_name}.os.uname", mock_uname, create=True) for mod in mock_modules: # mock that these modules can be imported without errors sys.modules[mod] = MagicMock() @@ -183,7 +188,7 @@ def mock_uname(): assert info["port"] != "", "stubber.info() - No port detected" assert info["board"] != "", "stubber.info() - No board detected" - + # TEST 2: check if the firmware id is correct new_fwid = stubber._fwid assert new_fwid != "none" @@ -192,30 +197,15 @@ def mock_uname(): assert c not in stubber.flat_fwid, "flat_fwid must not contain '{}'".format(c) # Does the firmware id match (at least the part before the last -) - assert new_fwid.startswith( - fwid.rsplit("-", 1)[0] - ), f"fwid: {new_fwid} does not start with {fwid.rsplit('-', 1)[0]}" + + short_fwid = "-".join(fwid.split("-", 2)[:2]) + assert new_fwid.startswith(short_fwid), f"fwid: {new_fwid} does not start with {short_fwid}" if not "esp8266" in fwid: # TODO: Fix FWID logic with esp8266 assert new_fwid == fwid, f"fwid: {new_fwid} does not match" -# # throws an error on the commandline -# @pytest.mark.skip(reason="test not working") -# @pytest.mark.parametrize("variant", VARIANTS) -# @pytest.mark.parametrize("location", LOCATIONS) -# def test_read_path( -# location, -# variant, -# mock_micropython_path, -# ): -# # import createstubs # type: ignore -# createstubs = import_module(f"{location}.{variant}") # type: ignore - -# assert createstubs.read_path() == "" - - @pytest.mark.parametrize("variant", VARIANTS) @pytest.mark.parametrize("location", LOCATIONS) def test_create_all_stubs( @@ -360,17 +350,18 @@ def test_unavailable_modules( assert len(stublist) == 0 -# def test_clean(tmp_path): -# import createstubs # type: ignore -# createstubs = import_module(f"{location}.{variant}") # type: ignore -# myid = "MyCustomID" -# test_path = str(tmp_path) -# stub_path = Path(test_path) /"stubs"/ myid.lower() -# stubber = Stubber(path = test_path, firmware_id=myid) -# stubber.clean() - -# #Create a file -# stubber.create_module_stub("json", PurePosixPath( stub_path / "json.py") ) -# stublist = list(Path(test_path).glob('**/*.py')) -# assert len(stublist) == 1 -# stubber.clean() +@pytest.mark.parametrize( + "input, expected", + [ + ("", ""), + ("v1.13-103-gb137d064e on 2020-10-09", "103"), + ("3.4.0; MicroPython v1.23.0-preview.6.g3d0b6276f on 2024-01-02", "6"), + ], +) +def test_build(input: str, expected: str): + variant = "createstubs" + location = "board" + createstubs = import_variant(location, variant) + + outcome = createstubs._build(input) + assert outcome == expected diff --git a/tests/createstubs/testcases.py b/tests/createstubs/testcases.py index 2d1f5130f..cffa25aa6 100644 --- a/tests/createstubs/testcases.py +++ b/tests/createstubs/testcases.py @@ -4,6 +4,7 @@ from collections import namedtuple +from typing import Any, Optional, Tuple ## os.uname() # import os; print(os.uname()) @@ -77,7 +78,13 @@ version="v1.17 on 2021-09-02", machine="ESP module with ESP8266", ) - +uname_mpy_v1_22_esp32_GEN = UName( + sysname="esp32", + nodename="esp32", + release="1.22.0", + version="v1.22.0 on 2023-12-27", + machine="Generic ESP32 module with SPIRAM with ESP32", +) pyb1_v1_13_PYB11 = UName( sysname="pyboard", @@ -98,104 +105,138 @@ # TODO: add support for -Latest # ('micropython-1.13-latest-esp32', 'micropython', 'esp32', mpy_v1_13_build), + + +class MP_Implementation: + """Mock sys.implementation for MicroPython""" + + name: str + version: Tuple + _machine: Optional[str] # newer MicroPython versions have this attribute + _mpy: Optional[int] # MicroPython >= 1.11 + + # Define __getattr__, as the documentation states: + # > sys.implementation may contain additional attributes specific to the Python implementation. + # > These non-standard attributes must start with an underscore, and are not described here. + def __getattr__(self, name: str) -> Any: + ... + + def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): + self.name = name + self.version = version + self._machine = _machine + self._mpy = _mpy + + fwid_test_cases = [ # - expected firmware id - # - patch input - sys.implementation.name - # - patch input - sys.implementation.version + # - patch input - sys.implementation( name, version, _machine, _mpy) # - patch input - sys.platform - # - patch input - sys.os.uname stucture + # - patch input - sys.version (str) + # - patch input - os.uname stucture # - patch input - array of modules to mock for firmware detection - # mpy esp32 - ("micropython-v1.9.4-esp32-GENERIC", "micropython", (1, 9, 4), "esp32", mpy_v1_9_4, []), - ("micropython-v1.10-esp32-GENERIC", "micropython", (1, 10, 0), "esp32", mpy_v1_10, []), - # ("micropython-v1.13-103-esp32-GENERIC_SPIRAM", "micropython", (1, 13, 0), "esp32", mpy_v1_13_build, []), - ( - "micropython-v1.13-103-esp32-GENERIC", - "micropython", - (1, 13, 0), + ( + "micropython-v1.9.4-esp32-GENERIC", + MP_Implementation(name="micropython", version=(1, 9, 4)), "esp32", + "", + mpy_v1_9_4, + [], + ), + ( + "micropython-v1.10-esp32-GENERIC", + MP_Implementation( + "micropython", + (1, 10, 0), + ), + "esp32", + "", + mpy_v1_10, + [], + ), + ( + "micropython-v1.13-preview-esp32-GENERIC_SPIRAM", + MP_Implementation( + "micropython", + (1, 13, 0), + ), + "esp32", + "3.4.0", mpy_v1_13_build, [], ), - # mpy esp8266 ( "micropython-v1.11-esp8266-GENERIC", - "micropython", - (1, 11, 0), + MP_Implementation( + "micropython", + (1, 11, 0), + ), "esp8266", + "", mpy_v1_11_esp8266, [], ), ( - "micropython-v1.11-8-esp8266-GENERIC", - "micropython", - (1, 11, 0), + "micropython-v1.11-preview-esp8266-GENERIC", + MP_Implementation( + "micropython", + (1, 11, 0), + ), "esp8266", + "", mpy_v1_11_8_esp8266, [], ), ( "micropython-v1.17-esp8266-GENERIC", - "micropython", - (1, 17, 0), + MP_Implementation( + "micropython", + (1, 17, 0), + ), "esp8266", + "", mpy_v1_17_esp8266_GEN, [], ), # mpy pyb1 - ("micropython-v1.13-95-stm32-PYBV11", "micropython", (1, 13, 0), "pyb1", pyb1_v1_13_PYB11, []), - # RP2 ( - "micropython-v1.18-rp2-RPI_PICO", - "micropython", - (1, 18, 0), - "rp2", - UName( - sysname="rp2", - nodename="rp2", - release="1.18.0", - version="v1.18-g0fff2e03f on 2020-10-03", - machine="Raspberry Pi Pico with RP2040", + "micropython-v1.13-preview-stm32-PYBV11", + MP_Implementation( + "micropython", + (1, 13, 0), ), + "pyb1", + "", + pyb1_v1_13_PYB11, [], ), + # RP2 ( - "micropython-v1.19.1-721-rp2-RPI_PICO_W", - "micropython", - (1, 19, 1), - "rp2", - UName( - sysname="rp2", - nodename="rp2", - release="1.19.1", - version="v1.19.1-721-gd5181034f on 2022-11-28", - machine="Raspberry Pi Pico W with RP2040", + "micropython-v1.18-preview-rp2-RPI_PICO", + MP_Implementation( + "micropython", + (1, 18, 0), ), - [], - ), - ( - "micropython-v1.19.1-rp2-PIMORONI_PICOLIPO_16MB", - "micropython", - (1, 19, 1), "rp2", + "", UName( sysname="rp2", nodename="rp2", - release="1.19.1", - version="67fac4e on 2023-02-16 (GNU 9.2.1 MinSizeRel)", - machine="Pimoroni Pico LiPo 16MB with RP2040", + release="1.18.0", + version="v1.18-g0fff2e03f on 2020-10-03", + machine="Raspberry Pi Pico with RP2040", ), [], ), - # lobo - # ("loboris-v3.2.24-esp32", "micropython", (3,2, 24), "esp32_LoBo", lobo, []), - # ("loboris-v3.2.24-esp32", "micropython", (3,2, 24), "esp32_LoBo", lobo_bt_ram, []), # ev3_pybricks_1_0_0 ( "ev3-pybricks-v2.0.0-unix", - "", - (2, 0, 0), + MP_Implementation( + "", + (2, 0, 0), + ), "linux", + "", UName( machine="ev3", nodename="ev3", @@ -217,10 +258,13 @@ # ), # pycopy ( - "pycopy-v1.2.3-beta0-stm32", - "pycopy", - (1, 2, 3), + "pycopy-v1.2.3-stm32", + MP_Implementation( + "pycopy", + (1, 2, 3), + ), "pyb1", + "", UName( sysname="stm32", nodename="stm32", @@ -232,10 +276,13 @@ ), # pycom ( - "pycom-v1.18.0-95-esp32", - "pycom", - (1, 18, 0), + "pycom-v1.18.0-preview-esp32", + MP_Implementation( + "pycom", + (1, 18, 0), + ), "esp32", + "", UName( sysname="esp32", nodename="esp32", @@ -245,4 +292,70 @@ ), ["pycom"], ), + # 1.19.1 + ( + "micropython-v1.19.1-preview-rp2-RPI_PICO_W", + MP_Implementation("micropython", (1, 19, 1)), + "rp2", + "", + UName( + sysname="rp2", + nodename="rp2", + release="1.19.1", + version="v1.19.1-721-gd5181034f on 2022-11-28", + machine="Raspberry Pi Pico W with RP2040", + ), + [], + ), + ( + "micropython-v1.19.1-rp2-PIMORONI_PICOLIPO_16MB", + MP_Implementation("micropython", (1, 19, 1)), + "rp2", + "", + UName( + sysname="rp2", + nodename="rp2", + release="1.19.1", + version="67fac4e on 2023-02-16 (GNU 9.2.1 MinSizeRel)", + machine="Pimoroni Pico LiPo 16MB with RP2040", + ), + [], + ), + # version 1.22 + ( + # using uname (old) + "micropython-v1.22.0-esp32-ESP32_GENERIC", + MP_Implementation("micropython", (1, 22, 0, "")), + "esp32", + "", + uname_mpy_v1_22_esp32_GEN, + [], + ), + ( + # using _machine and uname + "micropython-v1.22.0-esp32-ESP32_GENERIC", + MP_Implementation("micropython", (1, 22, 0, ""), _machine="Generic ESP32 module with SPIRAM with ESP32"), + "esp32", + "", + uname_mpy_v1_22_esp32_GEN, + [], + ), + ( + # using _machine only (new) + "micropython-v1.22.0-samd-SEEED_WIO_TERMINAL", + MP_Implementation("micropython", (1, 22, 0, ""), _machine="Wio Terminal D51R with SAMD51P19A"), + "samd", + "", + None, + [], + ), + ( + # using _machine only (new) + "micropython-v1.23.0-preview-samd-SEEED_WIO_TERMINAL", + MP_Implementation("micropython", (1, 23, 0, "preview"), _machine="Wio Terminal D51R with SAMD51P19A"), + "samd", + "3.4.0; MicroPython v1.23.0-preview.6.g3d0b6276f on 2024-01-02", # sys.version + None, + [], + ), ] From d77c9f060488fd4f7e5662857aef58e006ac3bd5 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Sun, 21 Jan 2024 20:21:43 +0100 Subject: [PATCH 30/68] variants Signed-off-by: Jos Verlinde --- src/stubber/board/createstubs_db.py | 59 +++-- src/stubber/board/createstubs_db_min.py | 240 +++++++++---------- src/stubber/board/createstubs_db_mpy.mpy | Bin 8590 -> 8775 bytes src/stubber/board/createstubs_lvgl.py | 59 +++-- src/stubber/board/createstubs_lvgl_min.py | 256 +++++++++++---------- src/stubber/board/createstubs_lvgl_mpy.mpy | Bin 8066 -> 8250 bytes src/stubber/board/createstubs_mem.py | 59 +++-- src/stubber/board/createstubs_mem_min.py | 228 +++++++++--------- src/stubber/board/createstubs_mem_mpy.mpy | Bin 8101 -> 8286 bytes src/stubber/board/createstubs_min.py | 254 ++++++++++---------- src/stubber/board/createstubs_mpy.mpy | Bin 11120 -> 11298 bytes 11 files changed, 619 insertions(+), 536 deletions(-) diff --git a/src/stubber/board/createstubs_db.py b/src/stubber/board/createstubs_db.py index 7a9761f7e..d176f3714 100644 --- a/src/stubber/board/createstubs_db.py +++ b/src/stubber/board/createstubs_db.py @@ -27,7 +27,10 @@ import os import sys -from ujson import dumps +try: + from ujson import dumps +except: + from json import dumps try: from machine import reset # type: ignore @@ -65,9 +68,9 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-{ver}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) else: - self._fwid = "{family}-{ver}-{port}".format(**self.info) + self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore if path: @@ -432,12 +435,15 @@ def ensure_folder(path: str): def _build(s): - # extract a build nr from a string + # extract build from sys.version or os.uname().version if available + # 'v1.13-103-gb137d064e' + # 'MicroPython v1.23.0-preview.6.g3d0b6276f' if not s: return "" - if " on " in s: - s = s.split(" on ", 1)[0] - return s.split("-")[1] if "-" in s else "" + s = s.split(" on ", 1)[0] if " on " in s else s + s = s.split("; ", 1)[1] if "; " in s else s + b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + return b def _info(): # type:() -> dict[str, str] @@ -462,7 +468,7 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") + info["version"] = version_str(sys.implementation.version) # type: ignore except AttributeError: pass try: @@ -484,19 +490,20 @@ def _info(): # type:() -> dict[str, str] gc.collect() try: - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - if not info["build"] and ";" in sys.version: - # extract build from uname().release if available - info["build"] = _build(sys.version.split(";")[1]) - except (AttributeError, IndexError): + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): pass # avoid build hashes - if info["build"] and len(info["build"]) > 5: - info["build"] = "" + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" if info["version"] == "" and sys.platform not in ("unix", "win32"): try: @@ -522,13 +529,14 @@ def _info(): # type:() -> dict[str, str] info["release"] = "2.0.0" if info["family"] == "micropython": + info["version"] if ( info["version"] and info["version"].endswith(".0") and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 and info["version"] <= "1.19.9" ): - # drop the .0 for newer releases + # versions from 1.10.0 to 1.20.0 do not have a micro .0 info["version"] = info["version"][:-2] # spell-checker: disable @@ -552,12 +560,21 @@ def _info(): # type:() -> dict[str, str] info["arch"] = arch # .mpy version.minor info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" # simple to use version[-build] string - info["ver"] = f"v{info['version']}-{info['build']}" if info["build"] else f"v{info['version']}" + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" return info +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + def read_boardname(info, desc: str = ""): found = False for filename in [d + "/board_info.csv" for d in LIBS]: diff --git a/src/stubber/board/createstubs_db_min.py b/src/stubber/board/createstubs_db_min.py index 751c0c400..adae0e729 100644 --- a/src/stubber/board/createstubs_db_min.py +++ b/src/stubber/board/createstubs_db_min.py @@ -1,16 +1,18 @@ -w='with' -v='stubber' -u='{}/{}' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' +x='with' +w='stubber' +v='{}/{}' +u='method' +t='function' +s='bool' +r='str' +q='float' +p='int' +o=TypeError n=NameError m=sorted l=MemoryError k=NotImplementedError +d='-' c=',\n' b='dict' a='list' @@ -22,11 +24,11 @@ T='_' S=KeyError R=IndexError -Q=dir -P=ImportError -O='family' -N=print -M=len +Q=ImportError +P='family' +O=print +N=len +M=dir L='.' K=open J=True @@ -34,19 +36,20 @@ H='board' G='/' F=None -E='version' -D=False +E=False A=OSError +D='version' C='' import gc as B,os,sys -from ujson import dumps as d +try:from ujson import dumps +except:from json import dumps try:from machine import reset -except P:pass +except Q:pass try:from collections import OrderedDict as e -except P:from ucollections import OrderedDict as e +except Q:from ucollections import OrderedDict as e __version__='v1.16.2' -x=2 y=2 +z=2 f=[L,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: @@ -57,26 +60,26 @@ def __init__(C,path=F,firmware_id=F): except I:pass C._report=[];C.info=_info();B.collect() if D:C._fwid=D.lower() - elif C.info[O]==Y:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) - else:C._fwid='{family}-{ver}-{port}'.format(**C.info) + elif C.info[P]==Y:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info) + else:C._fwid='{family}-v{version}-{port}'.format(**C.info) C._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) try:g(path+G) - except A:N('error creating stub folder {}'.format(path)) + except A:O('error creating stub folder {}'.format(path)) C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] def get_obj_attributes(L,item_instance): H=item_instance;D=[];J=[] - for A in Q(H): + for A in M(H): if A.startswith(T)and not A in L.modules:continue try: E=getattr(H,A) try:F=W(type(E)).split("'")[1] except R:F=C - if F in{o,p,q,r,Z,a,b}:G=1 - elif F in{s,t}:G=2 + if F in{p,q,r,s,Z,a,b}:G=1 + elif F in{t,u}:G=2 elif F in'class':G=3 else:G=4 D.append((A,W(E),W(type(E)),E,G)) @@ -88,45 +91,45 @@ def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) def create_one_stub(C,module_name): - E=module_name - if E in C.problematic:return D - if E in C.excluded:return D - H='{}/{}.py'.format(C.path,E.replace(L,G));B.collect();F=D - try:F=C.create_module_stub(E,H) - except A:return D + D=module_name + if D in C.problematic:return E + if D in C.excluded:return E + H='{}/{}.py'.format(C.path,D.replace(L,G));B.collect();F=E + try:F=C.create_module_stub(D,H) + except A:return E B.collect();return F def create_module_stub(I,module_name,file_name=F): - H=file_name;E=module_name - if H is F:O=E.replace(L,T)+'.py';H=I.path+G+O + H=file_name;D=module_name + if H is F:O=D.replace(L,T)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in E:E=E.replace(G,L) + if G in D:D=D.replace(G,L) M=F - try:M=__import__(E,F,F,'*');U=B.mem_free() - except P:return D + try:M=__import__(D,F,F,'*');U=B.mem_free() + except Q:return E g(H) - with K(H,'w')as N:Q=X(I.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(E,I._fwid,Q,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,E,C) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(E,H.replace('\\',G))) - if E not in{'os','sys','logging','gc'}: + with K(H,'w')as N:P=X(I.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,D,C) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) + if D not in{'os','sys','logging','gc'}: try:del M except(A,S):pass - try:del sys.modules[E] + try:del sys.modules[D] except S:pass B.collect();return J def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;M='Exception';H=fp;E=indent;B.collect() if P in K.problematic:return R,L=K.get_obj_attributes(P) - if L:N(L) + if L:O(L) for(F,J,G,T,f)in R: - if F in['classmethod','staticmethod','BaseException',O]:continue + if F in['classmethod','staticmethod','BaseException',M]:continue if F[0].isdigit():continue - if G==""and M(E)<=y*4: - U=C;V=F.endswith(O)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=O + if G==""and N(E)<=z*4: + U=C;V=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=M D='\n{}class {}({}):\n'.format(E,F,U) if V:D+=E+' ...\n';H.write(D);return H.write(D);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) - elif any(A in G for A in[t,s,'closure']): + elif any(A in G for A in[u,t,'closure']): W=Y;X=C if Q>0:X='self, ' if c in G or c in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) @@ -135,7 +138,7 @@ def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): elif G=="":0 elif G.startswith("5:A[D]=C - if A[E]==C and sys.platform not in(b,a): - try:g=os.uname();A[E]=g.release - except(R,I,TypeError):pass - for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(f,'pybricks.hubs','EV3Brick')]: - try:k=__import__(i,F,F,j);A[O]=h;del k;break - except(P,S):pass - if A[O]==f:A['release']='2.0.0' - if A[O]==Y: - if A[E]and A[E].endswith('.0')and A[E]>='1.10.0'and A[E]<='1.19.9':A[E]=A[E][:-2] + if'uname'in M(os): + A[E]=V(os.uname()[3]) + if not A[E]:A[E]=V(os.uname()[2]) + elif D in M(sys):A[E]=V(sys.version) + except(I,R,o):pass + if A[D]==C and sys.platform not in(X,W): + try:d=os.uname();A[D]=d.release + except(R,I,o):pass + for(f,g,h)in[(Z,Z,'const'),(a,a,'FAT'),(b,'pybricks.hubs','EV3Brick')]: + try:i=__import__(g,F,F,h);A[P]=f;del i;break + except(Q,S):pass + if A[P]==b:A['release']='2.0.0' + if A[P]==Y: + A[D] + if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if J in A and A[J]: - K=int(A[J]);T=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if T:A[Z]=T + K=int(A[J]);N=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if N:A[T]=N A[J]='v{}.{}'.format(K&255,K>>8&3) - A[W]=f"v{A[E]}-{A[D]}"if A[D]else f"v{A[E]}";return A -def z(info,desc=C): - L='with ';A=info;F=D + if A[E]and not A[D].endswith(c):A[D]=A[D]+c + A[O]=f"{A[D]}-{A[E]}"if A[E]else f"{A[D]}";return A +def A0(version): + A=version;B=L.join([X(A)for A in A[:3]]) + if N(A)>3 and A[3]:B+=d+A[3] + return B +def A1(info,desc=C): + L='with ';A=info;F=E for G in[A+'/board_info.csv'for A in f]: if h(G): - E=desc or A[H].strip();I=E.rfind(' with') - if I!=-1:K=E[:I].strip() + D=desc or A[H].strip();I=D.rfind(' with') + if I!=-1:K=D[:I].strip() else:K=C - if A0(A,E,G,K):F=J;break + if A2(A,D,G,K):F=J;break if not F: - E=desc or A[H].strip() - if L+A[U].upper()in E:E=E.split(L+A[U].upper())[0].strip() - A[H]=E + D=desc or A[H].strip() + if L+A[U].upper()in D:D=D.split(L+A[U].upper())[0].strip() + A[H]=D A[H]=A[H].replace(' ',T);B.collect() -def A0(info,descr,filename,short_descr): - B=short_descr;A=info;E=C +def A2(info,descr,filename,short_descr): + B=short_descr;A=info;D=C with K(filename,'r')as L: while 1: F=L.readline() @@ -243,10 +251,10 @@ def A0(info,descr,filename,short_descr): I,G=F.split(',')[0].strip(),F.split(',')[1].strip() if I==descr:A[H]=G;return J elif B and I==B: - if w in B:A[H]=G;return J - E=G - if E:A[H]=E;return J - return D + if x in B:A[H]=G;return J + D=G + if D:A[H]=D;return J + return E def get_root(): try:B=os.getcwd() except(A,I):B=L @@ -258,56 +266,56 @@ def get_root(): def h(filename): try: if os.stat(filename)[0]>>14:return J - return D - except A:return D + return E + except A:return E def i():sys.exit(1) def read_path(): path=C - if M(sys.argv)==3: + if N(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] else:i() - elif M(sys.argv)==2:i() + elif N(sys.argv)==2:i() return path def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return D + try:A=bytes('abc',encoding='utf8');B=j.__module__;return E except(k,I):return J def main(): L='failed';G='modulelist.done';import machine as O - try:C=K(G,'r+b');N=J - except A:C=K(G,'w+b');N=D + try:C=K(G,'r+b');M=J + except A:C=K(G,'w+b');M=E stubber=Stubber(path=read_path()) - if not N:stubber.clean() - A1(stubber);E={} + if not M:stubber.clean() + A3(stubber);D={} try: with K(G)as C: for F in C.read().split('\n'): F=F.strip();B.collect() - if M(F)>0:P,Q=F.split('=',1);E[P]=Q + if N(F)>0:P,Q=F.split('=',1);D[P]=Q except(A,SyntaxError):pass - B.collect();R=[A for A in stubber.modules if A not in E.keys()];B.collect() + B.collect();R=[A for A in stubber.modules if A not in D.keys()];B.collect() for H in R: - I=D + I=E try:I=stubber.create_one_stub(H) except l:O.reset() - B.collect();E[H]=X(stubber._report[-1]if I else L) + B.collect();D[H]=X(stubber._report[-1]if I else L) with K(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if I else L)) - if E:stubber._report=[A for(B,A)in E.items()if A!=L];stubber.report() -def A1(stubber): + if D:stubber._report=[A for(B,A)in D.items()if A!=L];stubber.report() +def A3(stubber): E='/modulelist.txt';stubber.modules=[] for D in f: try: with K(D+E)as F: - N('DEBUG: list of modules: '+D+E) + O('DEBUG: list of modules: '+D+E) for C in F.read().split('\n'): C=C.strip() - if M(C)>0 and C[0]!='#':stubber.modules.append(C) + if N(C)>0 and C[0]!='#':stubber.modules.append(C) B.collect();break except A:pass if not stubber.modules:stubber.modules=[Y];_log.warn('Could not find modulelist.txt, using default modules') B.collect() if __name__=='__main__'or j(): - try:A2=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + try:A4=logging.getLogger(w);logging.basicConfig(level=logging.INFO) except n:pass if not h('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() diff --git a/src/stubber/board/createstubs_db_mpy.mpy b/src/stubber/board/createstubs_db_mpy.mpy index 88b1e6cd73ab8d51080cdd566a931abbafac1545..54bc57f32ee8ba4dc934b45d9128a796293b31f0 100644 GIT binary patch delta 6026 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 diff --git a/src/stubber/board/createstubs_lvgl.py b/src/stubber/board/createstubs_lvgl.py index fe5417871..7e0fd913c 100644 --- a/src/stubber/board/createstubs_lvgl.py +++ b/src/stubber/board/createstubs_lvgl.py @@ -12,7 +12,10 @@ import os import sys -from ujson import dumps +try: + from ujson import dumps +except: + from json import dumps try: from machine import reset # type: ignore @@ -50,9 +53,9 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-{ver}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) else: - self._fwid = "{family}-{ver}-{port}".format(**self.info) + self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore if path: @@ -417,12 +420,15 @@ def ensure_folder(path: str): def _build(s): - # extract a build nr from a string + # extract build from sys.version or os.uname().version if available + # 'v1.13-103-gb137d064e' + # 'MicroPython v1.23.0-preview.6.g3d0b6276f' if not s: return "" - if " on " in s: - s = s.split(" on ", 1)[0] - return s.split("-")[1] if "-" in s else "" + s = s.split(" on ", 1)[0] if " on " in s else s + s = s.split("; ", 1)[1] if "; " in s else s + b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + return b def _info(): # type:() -> dict[str, str] @@ -447,7 +453,7 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") + info["version"] = version_str(sys.implementation.version) # type: ignore except AttributeError: pass try: @@ -469,19 +475,20 @@ def _info(): # type:() -> dict[str, str] gc.collect() try: - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - if not info["build"] and ";" in sys.version: - # extract build from uname().release if available - info["build"] = _build(sys.version.split(";")[1]) - except (AttributeError, IndexError): + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): pass # avoid build hashes - if info["build"] and len(info["build"]) > 5: - info["build"] = "" + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" if info["version"] == "" and sys.platform not in ("unix", "win32"): try: @@ -507,13 +514,14 @@ def _info(): # type:() -> dict[str, str] info["release"] = "2.0.0" if info["family"] == "micropython": + info["version"] if ( info["version"] and info["version"].endswith(".0") and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 and info["version"] <= "1.19.9" ): - # drop the .0 for newer releases + # versions from 1.10.0 to 1.20.0 do not have a micro .0 info["version"] = info["version"][:-2] # spell-checker: disable @@ -537,12 +545,21 @@ def _info(): # type:() -> dict[str, str] info["arch"] = arch # .mpy version.minor info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" # simple to use version[-build] string - info["ver"] = f"v{info['version']}-{info['build']}" if info["build"] else f"v{info['version']}" + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" return info +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + def read_boardname(info, desc: str = ""): found = False for filename in [d + "/board_info.csv" for d in LIBS]: diff --git a/src/stubber/board/createstubs_lvgl_min.py b/src/stubber/board/createstubs_lvgl_min.py index 24d22c1d8..5412c8895 100644 --- a/src/stubber/board/createstubs_lvgl_min.py +++ b/src/stubber/board/createstubs_lvgl_min.py @@ -1,17 +1,19 @@ -u='with' -t='stubber' -s='{}/{}' -r='method' -q='function' -p='bool' -o='str' -n='float' -m='int' -l='micropython' -k=Exception +v='with' +u='stubber' +t='{}/{}' +s='method' +r='function' +q='bool' +p='str' +o='float' +n='int' +m='micropython' +l=Exception +k=TypeError j=NameError i=sorted h=NotImplementedError +b='-' a=',\n' Z='dict' Y='list' @@ -23,10 +25,10 @@ R=len Q=KeyError P=IndexError -O=dir -N=print -M=ImportError -L='family' +O=print +N=ImportError +M='family' +L=dir K=True J='.' I=AttributeError @@ -34,19 +36,20 @@ A=False G='/' E=None -D='version' F=OSError +C='version' B='' -import gc as C,os,sys -from ujson import dumps as b +import gc as D,os,sys +try:from ujson import dumps +except:from json import dumps try:from machine import reset -except M:pass +except N:pass try:from collections import OrderedDict as c -except M:from ucollections import OrderedDict as c +except N:from ucollections import OrderedDict as c __version__='v1.16.2' -v=2 w=2 -x=[J,'/lib','/sd/lib','/flash/lib','lib'] +x=2 +y=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): @@ -54,93 +57,93 @@ def __init__(A,path=E,firmware_id=E): try: if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise h('MicroPython 1.13.0 cannot be stubbed') except I:pass - A._report=[];A.info=_info();C.collect() + A._report=[];A.info=_info();D.collect() if B:A._fwid=B.lower() - elif A.info[L]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-{ver}-{port}'.format(**A.info) - A._start_free=C.mem_free() + elif A.info[M]==m:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) + else:A._fwid='{family}-v{version}-{port}'.format(**A.info) + A._start_free=D.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) try:d(path+G) - except F:N('error creating stub folder {}'.format(path)) + except F:O('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] - def get_obj_attributes(L,item_instance): - H=item_instance;D=[];J=[] - for A in O(H): - if A.startswith(S)and not A in L.modules:continue + def get_obj_attributes(M,item_instance): + H=item_instance;C=[];J=[] + for A in L(H): + if A.startswith(S)and not A in M.modules:continue try: E=getattr(H,A) try:F=V(type(E)).split("'")[1] except P:F=B - if F in{m,n,o,p,X,Y,Z}:G=1 - elif F in{q,r}:G=2 + if F in{n,o,p,q,X,Y,Z}:G=1 + elif F in{r,s}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,V(E),V(type(E)),E,G)) + C.append((A,V(E),V(type(E)),E,G)) except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=i([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + C=i([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,J def add_modules(A,modules):A.modules=i(set(A.modules)|set(modules)) def create_all_stubs(A): - C.collect() + D.collect() for B in A.modules:A.create_one_stub(B) def create_one_stub(B,module_name): - D=module_name - if D in B.problematic:return A - if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A - try:E=B.create_module_stub(D,H) + C=module_name + if C in B.problematic:return A + if C in B.excluded:return A + H='{}/{}.py'.format(B.path,C.replace(J,G));D.collect();E=A + try:E=B.create_module_stub(C,H) except F:return A - C.collect();return E + D.collect();return E def create_module_stub(I,module_name,file_name=E): - H=file_name;D=module_name - if H is E:O=D.replace(J,S)+'.py';H=I.path+G+O + H=file_name;C=module_name + if H is E:O=C.replace(J,S)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,J) + if G in C:C=C.replace(G,J) L=E - try:L=__import__(D,E,E,'*');T=C.mem_free() - except M:return A + try:L=__import__(C,E,E,'*');T=D.mem_free() + except N:return A d(H) - with W(H,'w')as N:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,L,D,B) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: + with W(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,I._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,C,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + if C not in{'os','sys','logging','gc'}: try:del L except(F,Q):pass - try:del sys.modules[D] + try:del sys.modules[C] except Q:pass - C.collect();return K + D.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() - if O in K.problematic:return - S,L=K.get_obj_attributes(O) - if L:N(L) + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;C=indent;D.collect() + if N in K.problematic:return + S,L=K.get_obj_attributes(N) + if L:O(L) for(E,J,G,T,f)in S: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and R(D)<=w*4: + if G==""and R(C)<=x*4: U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=M - A='\n{}class {}({}):\n'.format(D,E,U) - if V:A+=D+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): + A='\n{}class {}({}):\n'.format(C,E,U) + if V:A+=C+' ...\n';H.write(A);return + H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),C+' ',P+1);A=C+' def __init__(self, *argv, **kwargs) -> None:\n';A+=C+' ...\n\n';H.write(A) + elif any(A in G for A in[s,r,'closure']): W=b;a=B if P>0:a='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,W) - A+=D+' ...\n\n';H.write(A) + if c in G or c in J:A='{}@classmethod\n'.format(C)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(C,E,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(C,E,a,W) + A+=C+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(Z,Y): - try:e=os.uname();A[D]=e.release - except(P,I,TypeError):pass - for(f,g,h)in[(a,a,'const'),(b,b,'FAT'),(d,'pybricks.hubs','EV3Brick')]: - try:i=__import__(g,E,E,h);A[L]=f;del i;break - except(M,Q):pass - if A[L]==d:A['release']='2.0.0' - if A[L]==l: - if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if K in A and A[K]: - N=int(A[K]);V=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] - if V:A[X]=V - A[K]='v{}.{}'.format(N&255,N>>8&3) - A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def y(info,desc=B): - L='with ';D=info;F=A - for G in[A+'/board_info.csv'for A in x]: + if'uname'in L(os): + A[F]=U(os.uname()[3]) + if not A[F]:A[F]=U(os.uname()[2]) + elif C in L(sys):A[F]=U(sys.version) + except(I,P,k):pass + if A[C]==B and sys.platform not in(X,W): + try:d=os.uname();A[C]=d.release + except(P,I,k):pass + for(e,f,g)in[(Y,Y,'const'),(Z,Z,'FAT'),(a,'pybricks.hubs','EV3Brick')]: + try:h=__import__(f,E,E,g);A[M]=e;del h;break + except(N,Q):pass + if A[M]==a:A['release']='2.0.0' + if A[M]==m: + A[C] + if A[C]and A[C].endswith('.0')and A[C]>='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if J in A and A[J]: + K=int(A[J]);R=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if R:A[V]=R + A[J]='v{}.{}'.format(K&255,K>>8&3) + if A[F]and not A[C].endswith(b):A[C]=A[C]+b + A[S]=f"{A[C]}-{A[F]}"if A[F]else f"{A[C]}";return A +def z(version): + A=version;B=J.join([str(A)for A in A[:3]]) + if R(A)>3 and A[3]:B+=b+A[3] + return B +def A0(info,desc=B): + L='with ';C=info;F=A + for G in[A+'/board_info.csv'for A in y]: if e(G): - E=desc or D[H].strip();I=E.rfind(' with') + E=desc or C[H].strip();I=E.rfind(' with') if I!=-1:J=E[:I].strip() else:J=B - if z(D,E,G,J):F=K;break + if A1(C,E,G,J):F=K;break if not F: - E=desc or D[H].strip() - if L+D[T].upper()in E:E=E.split(L+D[T].upper())[0].strip() - D[H]=E - D[H]=D[H].replace(' ',S);C.collect() -def z(info,descr,filename,short_descr): + E=desc or C[H].strip() + if L+C[T].upper()in E:E=E.split(L+C[T].upper())[0].strip() + C[H]=E + C[H]=C[H].replace(' ',S);D.collect() +def A1(info,descr,filename,short_descr): D=short_descr;C=info;E=B with W(filename,'r')as J: while 1: @@ -242,7 +250,7 @@ def z(info,descr,filename,short_descr): I,G=F.split(',')[0].strip(),F.split(',')[1].strip() if I==descr:C[H]=G;return K elif D and I==D: - if u in D:C[H]=G;return K + if v in D:C[H]=G;return K E=G if E:C[H]=E;return K return A @@ -272,18 +280,18 @@ def g(): try:B=bytes('abc',encoding='utf8');C=g.__module__;return A except(h,I):return K def main(): - D='lvgl' + C='lvgl' try:import lvgl as A - except k:return - B=D + except l:return + B=C try:B='lvgl-{0}_{1}_{2}-{3}-{4}'.format(A.version_major(),A.version_minor(),A.version_patch(),A.version_info(),sys.platform) - except k:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) + except l:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) finally:stubber=Stubber(firmware_id=B) - stubber.clean();stubber.modules=['io','lodepng','rtch',D];C.collect();stubber.create_all_stubs();stubber.report() + stubber.clean();stubber.modules=['io','lodepng','rtch',C];D.collect();stubber.create_all_stubs();stubber.report() if __name__=='__main__'or g(): - try:A0=logging.getLogger(t);logging.basicConfig(level=logging.INFO) + try:A2=logging.getLogger(u);logging.basicConfig(level=logging.INFO) except j:pass if not e('no_auto_stubber.txt'): - try:C.threshold(4*1024);C.enable() + try:D.threshold(4*1024);D.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_lvgl_mpy.mpy b/src/stubber/board/createstubs_lvgl_mpy.mpy index 3813ad3c6b8cd138c29a46101b894ccbff6d01de..9609c5be1cde717c99e531562a782df183520436 100644 GIT binary patch delta 5562 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 delta 5321 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 dict[str, str] @@ -453,7 +459,7 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") + info["version"] = version_str(sys.implementation.version) # type: ignore except AttributeError: pass try: @@ -475,19 +481,20 @@ def _info(): # type:() -> dict[str, str] gc.collect() try: - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - if not info["build"] and ";" in sys.version: - # extract build from uname().release if available - info["build"] = _build(sys.version.split(";")[1]) - except (AttributeError, IndexError): + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): pass # avoid build hashes - if info["build"] and len(info["build"]) > 5: - info["build"] = "" + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" if info["version"] == "" and sys.platform not in ("unix", "win32"): try: @@ -513,13 +520,14 @@ def _info(): # type:() -> dict[str, str] info["release"] = "2.0.0" if info["family"] == "micropython": + info["version"] if ( info["version"] and info["version"].endswith(".0") and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 and info["version"] <= "1.19.9" ): - # drop the .0 for newer releases + # versions from 1.10.0 to 1.20.0 do not have a micro .0 info["version"] = info["version"][:-2] # spell-checker: disable @@ -543,12 +551,21 @@ def _info(): # type:() -> dict[str, str] info["arch"] = arch # .mpy version.minor info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" # simple to use version[-build] string - info["ver"] = f"v{info['version']}-{info['build']}" if info["build"] else f"v{info['version']}" + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" return info +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + def read_boardname(info, desc: str = ""): found = False for filename in [d + "/board_info.csv" for d in LIBS]: diff --git a/src/stubber/board/createstubs_mem_min.py b/src/stubber/board/createstubs_mem_min.py index 139f88f81..ef72491b9 100644 --- a/src/stubber/board/createstubs_mem_min.py +++ b/src/stubber/board/createstubs_mem_min.py @@ -1,15 +1,17 @@ -v='with' -u='stubber' -t='{}/{}' -s='method' -r='function' -q='bool' -p='str' -o='float' -n='int' +w='with' +v='stubber' +u='{}/{}' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n=TypeError m=NameError l=sorted k=NotImplementedError +d='-' c=',\n' b='dict' a='list' @@ -22,10 +24,10 @@ S=KeyError R=open Q=IndexError -P=dir -O=ImportError -N='family' -M=len +P=ImportError +O='family' +N=len +M=dir L=print K=True J='.' @@ -34,31 +36,32 @@ A=False G='/' E=None -D='version' F=OSError -B='' -import gc as C,os,sys -from ujson import dumps as d +D='version' +C='' +import gc as B,os,sys +try:from ujson import dumps +except:from json import dumps try:from machine import reset -except O:pass +except P:pass try:from collections import OrderedDict as e -except O:from ucollections import OrderedDict as e +except P:from ucollections import OrderedDict as e __version__='v1.16.2' -w=2 x=2 +y=2 f=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): - B=firmware_id + C=firmware_id try: if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') except I:pass - A._report=[];A.info=_info();C.collect() - if B:A._fwid=B.lower() - elif A.info[N]==Y:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-{ver}-{port}'.format(**A.info) - A._start_free=C.mem_free() + A._report=[];A.info=_info();B.collect() + if C:A._fwid=C.lower() + elif A.info[O]==Y:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) + else:A._fwid='{family}-v{version}-{port}'.format(**A.info) + A._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() @@ -68,80 +71,80 @@ def __init__(A,path=E,firmware_id=E): A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): H=item_instance;D=[];J=[] - for A in P(H): + for A in M(H): if A.startswith(T)and not A in L.modules:continue try: E=getattr(H,A) try:F=W(type(E)).split("'")[1] - except Q:F=B - if F in{n,o,p,q,Z,a,b}:G=1 - elif F in{r,s}:G=2 + except Q:F=C + if F in{o,p,q,r,Z,a,b}:G=1 + elif F in{s,t}:G=2 elif F in'class':G=3 else:G=4 D.append((A,W(E),W(type(E)),E,G)) except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) def create_all_stubs(A): - C.collect() - for B in A.modules:A.create_one_stub(B) - def create_one_stub(B,module_name): + B.collect() + for C in A.modules:A.create_one_stub(C) + def create_one_stub(C,module_name): D=module_name - if D in B.problematic:return A - if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A - try:E=B.create_module_stub(D,H) + if D in C.problematic:return A + if D in C.excluded:return A + H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=A + try:E=C.create_module_stub(D,H) except F:return A - C.collect();return E + B.collect();return E def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name if H is E:N=D.replace(J,T)+'.py';H=I.path+G+N else:N=H.split(G)[-1] if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');U=C.mem_free() - except O:return A + try:L=__import__(D,E,E,'*');U=B.mem_free() + except P:return A g(H) - with R(H,'w')as M:P=X(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) + with R(H,'w')as M:O=X(I.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,O,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,C) I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del L except(F,S):pass try:del sys.modules[D] except S:pass - C.collect();return K + B.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;C.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() if P in K.problematic:return - R,N=K.get_obj_attributes(P) - if N:L(N) + R,M=K.get_obj_attributes(P) + if M:L(M) for(E,J,G,T,f)in R: if E in['classmethod','staticmethod','BaseException',O]:continue if E[0].isdigit():continue - if G==""and M(D)<=x*4: - U=B;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if G==""and N(D)<=y*4: + U=C;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[s,r,'closure']): - W=Y;X=B + elif any(A in G for A in[t,s,'closure']): + W=Y;X=C if Q>0:X='self, ' if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(b,a): - try:g=os.uname();A[D]=g.release - except(Q,I,TypeError):pass - for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(f,'pybricks.hubs','EV3Brick')]: - try:k=__import__(i,E,E,j);A[N]=h;del k;break - except(O,S):pass - if A[N]==f:A['release']='2.0.0' - if A[N]==Y: + if'uname'in M(os): + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + elif D in M(sys):A[F]=V(sys.version) + except(I,Q,n):pass + if A[D]==C and sys.platform not in(X,W): + try:d=os.uname();A[D]=d.release + except(Q,I,n):pass + for(f,g,h)in[(Z,Z,'const'),(a,a,'FAT'),(b,'pybricks.hubs','EV3Brick')]: + try:i=__import__(g,E,E,h);A[O]=f;del i;break + except(P,S):pass + if A[O]==b:A['release']='2.0.0' + if A[O]==Y: + A[D] if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if K in A and A[K]: - L=int(A[K]);T=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][L>>10] - if T:A[Z]=T - A[K]='v{}.{}'.format(L&255,L>>8&3) - A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def y(info,desc=B): + if J in A and A[J]: + K=int(A[J]);N=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if N:A[T]=N + A[J]='v{}.{}'.format(K&255,K>>8&3) + if A[F]and not A[D].endswith(c):A[D]=A[D]+c + A[R]=f"{A[D]}-{A[F]}"if A[F]else f"{A[D]}";return A +def z(version): + A=version;B=J.join([X(A)for A in A[:3]]) + if N(A)>3 and A[3]:B+=d+A[3] + return B +def A0(info,desc=C): L='with ';D=info;F=A for G in[A+'/board_info.csv'for A in f]: if h(G): E=desc or D[H].strip();I=E.rfind(' with') if I!=-1:J=E[:I].strip() - else:J=B - if z(D,E,G,J):F=K;break + else:J=C + if A1(D,E,G,J):F=K;break if not F: E=desc or D[H].strip() if L+D[U].upper()in E:E=E.split(L+D[U].upper())[0].strip() D[H]=E - D[H]=D[H].replace(' ',T);C.collect() -def z(info,descr,filename,short_descr): - D=short_descr;C=info;E=B + D[H]=D[H].replace(' ',T);B.collect() +def A1(info,descr,filename,short_descr): + D=short_descr;B=info;E=C with R(filename,'r')as J: while 1: F=J.readline() if not F:break I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:C[H]=G;return K + if I==descr:B[H]=G;return K elif D and I==D: - if v in D:C[H]=G;return K + if w in D:B[H]=G;return K E=G - if E:C[H]=E;return K + if E:B[H]=E;return K return A def get_root(): try:A=os.getcwd() @@ -261,35 +269,35 @@ def h(filename): except F:return A def i():sys.exit(1) def read_path(): - path=B - if M(sys.argv)==3: + path=C + if N(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] else:i() - elif M(sys.argv)==2:i() + elif N(sys.argv)==2:i() return path def j(): try:B=bytes('abc',encoding='utf8');C=j.__module__;return A except(k,I):return K def main(): E='/modulelist.txt';stubber=Stubber(path=read_path());stubber.clean();stubber.modules=[] - for B in f: + for C in f: try: - F=C.mem_free() - with R(B+E)as D: - L('Debug: List of modules: '+B+E);A=D.readline() + F=B.mem_free() + with R(C+E)as D: + L('Debug: List of modules: '+C+E);A=D.readline() while A: A=A.strip() - if M(A)>0 and A[0]!='#':stubber.modules.append(A) + if N(A)>0 and A[0]!='#':stubber.modules.append(A) A=D.readline() - C.collect();L('Debug: Used memory to load modulelist.txt: '+X(F-C.mem_free())+' bytes');break + B.collect();L('Debug: Used memory to load modulelist.txt: '+X(F-B.mem_free())+' bytes');break except Exception:pass if not stubber.modules:stubber.modules=[Y] - C.collect();stubber.create_all_stubs();stubber.report() + B.collect();stubber.create_all_stubs();stubber.report() if __name__=='__main__'or j(): - try:A0=logging.getLogger(u);logging.basicConfig(level=logging.INFO) + try:A2=logging.getLogger(v);logging.basicConfig(level=logging.INFO) except m:pass if not h('no_auto_stubber.txt'): - try:C.threshold(4*1024);C.enable() + try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mem_mpy.mpy b/src/stubber/board/createstubs_mem_mpy.mpy index 560e2f8f5a33db15d79df94d4726560329115eaa..32f83286302c5ecc5eddc2fcab92e4a0b1373e35 100644 GIT binary patch delta 5641 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 diff --git a/src/stubber/board/createstubs_min.py b/src/stubber/board/createstubs_min.py index cca13284d..e01b97706 100644 --- a/src/stubber/board/createstubs_min.py +++ b/src/stubber/board/createstubs_min.py @@ -1,19 +1,21 @@ -x='with' -w='pyb' -v='stubber' -u='{}/{}' -t='logging' -s='sys' -r='method' -q='function' -p='bool' -o='str' -n='float' -m='int' +y='with' +x='pyb' +w='stubber' +v='{}/{}' +u='logging' +t='sys' +s='method' +r='function' +q='bool' +p='str' +o='float' +n='int' +m=TypeError l=NameError k=sorted j=NotImplementedError -c='pycom' +d='pycom' +c='-' b=',\n' a='dict' Z='list' @@ -26,10 +28,10 @@ R=len Q=KeyError P=IndexError -O=dir -N=print -M=ImportError -L='family' +O=print +N=ImportError +M='family' +L=dir K=True J='.' I=AttributeError @@ -38,18 +40,19 @@ G='/' E=None F=OSError -D='version' +C='version' B='' -import gc as C,os,sys -from ujson import dumps as d +import gc as D,os,sys +try:from ujson import dumps +except:from json import dumps try:from machine import reset -except M:pass +except N:pass try:from collections import OrderedDict as e -except M:from ucollections import OrderedDict as e +except N:from ucollections import OrderedDict as e __version__='v1.16.2' -y=2 z=2 -A0=[J,'/lib','/sd/lib','/flash/lib','lib'] +A0=2 +A1=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): @@ -57,93 +60,93 @@ def __init__(A,path=E,firmware_id=E): try: if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') except I:pass - A._report=[];A.info=_info();C.collect() + A._report=[];A.info=_info();D.collect() if B:A._fwid=B.lower() - elif A.info[L]==X:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-{ver}-{port}'.format(**A.info) - A._start_free=C.mem_free() + elif A.info[M]==X:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) + else:A._fwid='{family}-v{version}-{port}'.format(**A.info) + A._start_free=D.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) try:f(path+G) - except F:N('error creating stub folder {}'.format(path)) + except F:O('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] - def get_obj_attributes(L,item_instance): - H=item_instance;D=[];J=[] - for A in O(H): - if A.startswith(S)and not A in L.modules:continue + def get_obj_attributes(M,item_instance): + H=item_instance;C=[];J=[] + for A in L(H): + if A.startswith(S)and not A in M.modules:continue try: E=getattr(H,A) try:F=V(type(E)).split("'")[1] except P:F=B - if F in{m,n,o,p,Y,Z,a}:G=1 - elif F in{q,r}:G=2 + if F in{n,o,p,q,Y,Z,a}:G=1 + elif F in{r,s}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,V(E),V(type(E)),E,G)) + C.append((A,V(E),V(type(E)),E,G)) except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + C=k([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,J def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) def create_all_stubs(A): - C.collect() + D.collect() for B in A.modules:A.create_one_stub(B) def create_one_stub(B,module_name): - D=module_name - if D in B.problematic:return A - if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A - try:E=B.create_module_stub(D,H) + C=module_name + if C in B.problematic:return A + if C in B.excluded:return A + H='{}/{}.py'.format(B.path,C.replace(J,G));D.collect();E=A + try:E=B.create_module_stub(C,H) except F:return A - C.collect();return E + D.collect();return E def create_module_stub(I,module_name,file_name=E): - H=file_name;D=module_name - if H is E:O=D.replace(J,S)+'.py';H=I.path+G+O + H=file_name;C=module_name + if H is E:O=C.replace(J,S)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,J) + if G in C:C=C.replace(G,J) L=E - try:L=__import__(D,E,E,'*');T=C.mem_free() - except M:return A + try:L=__import__(C,E,E,'*');T=D.mem_free() + except N:return A f(H) - with W(H,'w')as N:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,L,D,B) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os',s,t,'gc'}: + with W(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,I._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,C,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + if C not in{'os',t,u,'gc'}: try:del L except(F,Q):pass - try:del sys.modules[D] + try:del sys.modules[C] except Q:pass - C.collect();return K + D.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() - if O in K.problematic:return - S,L=K.get_obj_attributes(O) - if L:N(L) + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;C=indent;D.collect() + if N in K.problematic:return + S,L=K.get_obj_attributes(N) + if L:O(L) for(E,J,G,T,f)in S: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and R(D)<=z*4: + if G==""and R(C)<=A0*4: U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=M - A='\n{}class {}({}):\n'.format(D,E,U) - if V:A+=D+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): + A='\n{}class {}({}):\n'.format(C,E,U) + if V:A+=C+' ...\n';H.write(A);return + H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),C+' ',P+1);A=C+' def __init__(self, *argv, **kwargs) -> None:\n';A+=C+' ...\n\n';H.write(A) + elif any(A in G for A in[s,r,'closure']): W=b;X=B if P>0:X='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) - A+=D+' ...\n\n';H.write(A) + if c in G or c in J:A='{}@classmethod\n'.format(C)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(C,E,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(C,E,X,W) + A+=C+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(a,Z): - try:f=os.uname();A[D]=f.release - except(P,I,TypeError):pass - for(g,h,i)in[(b,b,'const'),(c,c,'FAT'),(d,'pybricks.hubs','EV3Brick')]: - try:j=__import__(h,E,E,i);A[L]=g;del j;break - except(M,Q):pass - if A[L]==d:A['release']='2.0.0' - if A[L]==X: - if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if K in A and A[K]: - N=int(A[K]);V=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] - if V:A[Y]=V - A[K]='v{}.{}'.format(N&255,N>>8&3) - A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def A1(info,desc=B): - L='with ';D=info;F=A - for G in[A+'/board_info.csv'for A in A0]: + if'uname'in L(os): + A[F]=U(os.uname()[3]) + if not A[F]:A[F]=U(os.uname()[2]) + elif C in L(sys):A[F]=U(sys.version) + except(I,P,m):pass + if A[C]==B and sys.platform not in(Y,W): + try:c=os.uname();A[C]=c.release + except(P,I,m):pass + for(f,g,h)in[(Z,Z,'const'),(d,d,'FAT'),(a,'pybricks.hubs','EV3Brick')]: + try:i=__import__(g,E,E,h);A[M]=f;del i;break + except(N,Q):pass + if A[M]==a:A['release']='2.0.0' + if A[M]==X: + A[C] + if A[C]and A[C].endswith('.0')and A[C]>='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if J in A and A[J]: + K=int(A[J]);R=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if R:A[V]=R + A[J]='v{}.{}'.format(K&255,K>>8&3) + if A[F]and not A[C].endswith(b):A[C]=A[C]+b + A[S]=f"{A[C]}-{A[F]}"if A[F]else f"{A[C]}";return A +def A2(version): + A=version;B=J.join([str(A)for A in A[:3]]) + if R(A)>3 and A[3]:B+=c+A[3] + return B +def A3(info,desc=B): + L='with ';C=info;F=A + for G in[A+'/board_info.csv'for A in A1]: if g(G): - E=desc or D[H].strip();I=E.rfind(' with') + E=desc or C[H].strip();I=E.rfind(' with') if I!=-1:J=E[:I].strip() else:J=B - if A2(D,E,G,J):F=K;break + if A4(C,E,G,J):F=K;break if not F: - E=desc or D[H].strip() - if L+D[T].upper()in E:E=E.split(L+D[T].upper())[0].strip() - D[H]=E - D[H]=D[H].replace(' ',S);C.collect() -def A2(info,descr,filename,short_descr): + E=desc or C[H].strip() + if L+C[T].upper()in E:E=E.split(L+C[T].upper())[0].strip() + C[H]=E + C[H]=C[H].replace(' ',S);D.collect() +def A4(info,descr,filename,short_descr): D=short_descr;C=info;E=B with W(filename,'r')as J: while 1: @@ -245,7 +253,7 @@ def A2(info,descr,filename,short_descr): I,G=F.split(',')[0].strip(),F.split(',')[1].strip() if I==descr:C[H]=G;return K elif D and I==D: - if x in D:C[H]=G;return K + if y in D:C[H]=G;return K E=G if E:C[H]=E;return K return A @@ -274,11 +282,11 @@ def read_path(): def i(): try:B=bytes('abc',encoding='utf8');C=i.__module__;return A except(j,I):return K -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',X,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,c,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',u,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',X,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',x,d,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',t,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];D.collect();stubber.create_all_stubs();stubber.report() if __name__=='__main__'or i(): - try:A3=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + try:A5=logging.getLogger(w);logging.basicConfig(level=logging.INFO) except l:pass if not g('no_auto_stubber.txt'): - try:C.threshold(4*1024);C.enable() + try:D.threshold(4*1024);D.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mpy.mpy b/src/stubber/board/createstubs_mpy.mpy index 69dd56b39ff91e89c180b5d820f2e407d16ec8af..00887e7b699f7a540f8a6dd0c27e1948e80b733a 100644 GIT binary patch delta 5916 zcmZ`dS#T6dcGacUeZ4A`N+)X3+1<3%Eg`j<;t+>aDnZjiKo7K_0gXV7nBf-Ukbq&T zGYi%;%*F;|*$#(4>^}3kW5nr!SnmIC@zqICuKO)iGiGw>IavQ~blG zf}6LRZr&2?{I4@0(1^XWO(+;WedS%`nqN@QA%S(WtbBWCaB^8ZBTn{a`|RWI<$uz2 zT@c3v@v0zR5yZ=acu5e41@WRFUJ%ZU=Y^xI6O3R z<+?EWvYT_{%-N@ z;@f#AJKT5jhTJWVb;P@afT*$)kfpLgu&b;Mveiz=QCS>vRdy2cR5k=z`RdsCi*k=C zv0;^6f)bUDK&i?u1E}l@NGiJuvdXSOnaV~%QQ4TpuB+^Z#BQqWJt$Y%El^eVzQjz` z5+uu}TB2lSsg_-`vQ;ZbvT{``4=PkEU$P2RtMDz=DuPPYDweDg)hdN5)q?%1WlB)3 zT5?3S$|Orst#YVQEfs22t0EDpS)*E&IMk_i_&-<84V5Io(P*owuXU)7SQuiN>DtWH z*3Z|SxK3)FsxuZYJS16pFO9BP7?(;D;KC($txL74V&Tfnnz`&;X6#^PygA65vPTrdq%1j~xsM&>R%i=73Gr0;0M#kfrJYyLv&gDjIDE z+OpN*K#n>Z$W?C!@>DaBuTmjUpi(hVsM72}kxC0B)2f5@OI;y}W(NghDG{oba+DT{ zwP|Qk2g0ookaEh}G$y3=Vdq!$kxU{4ZC&q%$|b8(2|9l&Xto#!H)t!A+gB-RK~RWA z;>8~v%xiA`X!B2`JK!F=llPJI;o381$43Qs^W8&|Rj1N?XjZLyiC;xoqj;cAP+0}) z#=NK;YeMZBC%s-HBY5Q#KxENRi>ietPk~Ohfr^J z7^V3m_$Fb~3Rs0D(L!roV#|1>QZ?(8gPKrw7+B?!(I;nSHNdLAF+wuCM2-e+LwK#S zRl1^_Pe@j>YFQ8Ru|`Jy525~(#-2%q+BJ@>)kl(Ld?`OFv#}-P06C_#AK<9OMwTIn zkp2~vxr*bQ*qSthx|DGsrS!{|tl5lRsfgJuM(6cz`DRdY~_#v+@aYx8eNU81?D8j$q6z@;^d^y%teU_Fc&a4 zFb^3br+nFnT9?*SiNwc?=HvkLTKSeY(c|?6iPzy=w`0A}>1cG2jj08n@W>}TmaW2x zplzV%d)t#~r9)=#qvYXflv7#m(sgg>u1&TYCZ>bpVyHr9@5xrnin{t;8gFe%b&B|jk8)_19%AV=H zv%ne=w4Uku?Prq;^G)M1c*Yxt&D?LyMwbnDWN!25^WD;vVlp3jM`@p)c%WtBVkGk1 zo8KR!@h!c?Oe7g^r! zBG%6Wi5S{(phuohC8A0Pu(vf^S8Hm$qWj~=r6M-K%)vw~c{>_s-bP?emc*3A5#%ki z{oHt5{{5+-?LUJyyc4_)=ItzD<(8B<=3PCI(+%_#&LmK5jkIu6Hh0&Km~o-Ct<6UtTDDo(qUCcf4P=^uv*k$ua= zq$WNN7iXNS8!t+VqnBnPU@HE{`~O1P!dk3S%WpL$-Wi{(sW!|0#ps{Pa7CXGfwjJR z!cXFkI{oUA-ZQCe=jYkX=o1{LmW@4Wav9~ovt+AmF@%xioI(hHfdzv0#nn)Gnid7~ z?W!mmUPw%4Hzt9#1;t%^o|$qXDq4e%c9pz~ew7KDAg~RZ_?(uNl*r_2SwwgTG*Z2PA^J8snLT!0?Sc4z`l zBzFxtzhwNiNo7m;9G%jtz5PGm8GnM)3XkFfrTyjSaE6`0bYNY+tYuHR ztK8`N)T59KO8e(7a4A}rM@3xJrG5^~c=f$U{S2+{Qqhu;_-l|~z-KNQShvzX=>jcV zMCzU6TkERK46Xix$yS@Ire4568Is3y%Nv@Wn;CgDr&B59&%Ly+Xrkvun6w`mC<$IQ$?<3PN;I% zxFjw64cqGd+_vPJ((bO&Y-nsg#S3{wMqlAf|K_H*#9JCF@Pb!rsPW3-vK9Z8+4;t- z6&H@gZM5k40;+wS1u(_k8Gq?eO@|ds{8>XQkEeNHZ!Js=^b|izDOV?XF%akV)>Qn1 z;k#vZw8*NUg^54+YwO(&(QR0=Fh_LroG>3M!}`04=P(@E0R$FS1E@3;K#_Pq^6h>k zcVbQB$tYCFNe@nGCMI@YCNafhp|Yexi>6i>MLCcTHY|zh)(oqQ{=kgHKj=V#u<5F> z+=)+um?$^-HgVQmnv^CktcFvl2b0P~CaE+(La*$b-*C(5LaI?jn#_y1nZnDnL5gM>L`45JaH;Tbzz!ul}NB$B{l3n{!8U`LPv zhh&G}h9}ib3Y&Wp22tFj|1UYY&P9u}mZZIs9kL{i zowhb4CYmO@!s+u~^PNc3QLnRv9Y(UmR7S94Y4nF<^qyF!;cd>iRMO~aJ>=6IYZHg& z7xdpIlFCNRj^l;Sx~+JrXo|<-J(>G?lz6gx^K{wfL{zqFmW=bE0=&a5+*skY8H(8A z?ow_YQE49^a=OhQd0R`ivZ2HRSqIzZlU-QCD&nc+veA=Nwx_5jCZc+0@*(U%)E-2^ z4#d$kE{WmUiP6c?GP}%M4gFvSMjA89%TF=KE=D~EyC`n5Pk+d&t`f99-2OORm#HGFW2VtLVL3)wh;=?TeH;otfV(vb63^E(U+Gy;8 z{d4#G^kaydTEba`&-UUB-dZwtPV!ktNRlt4kHc~|heu`V%WB&iItvG|N#g`T+cNgH zT(ARr2u;uXU-I)$aS!x;%B^&Qmt!TW33D>L)dzj%?``bU56}J{a<|@vvd_)-rGpkP z(EhsWtp<`jJjW~aO3M)Hg@c?+9hYcG-kOocilY1v`sN-)yY^*prY5iqQa^%OF%vr@zkM;o(zSpz+7Em>dx;+LUn>`lJN^d?^h?H>3Xx#jnH zq2mBWhIwyRe!Y;dMN@cTaBL0^_ob)l7s4$B)o3jJ-xy90SV^&0G~#?>Mq%KejLb3| z|IXN#rik!b!=b*}xn<+)#N2Guc$$!laSYl#67QByz#zooBn-hRcn98v({RRD=#uXK z5cS9|+30r3bJKl*?TkxuQu8-1>4P7v-)JIUAzI%^TPCXXCrxZx_oUBEzDgg+SNFp? zr9F+rnI`HzaDHX3+2&^Y=Hk}Y&Y}x7iC+gdC+9K76zrE%5esDwV&Pf9Mgsd<>sw=A z%8DA{35-nyUVV>YXrrOdO!NHfbn{$b&dY^Jj9qgu{^N6ZCC@Ocu}I?I8hqXj0oO*- zfFF3W9s z694P<)q6bK0`Atvrpd=i?3XJR({*VKd)*^XXO-)y#{DkrN)q=m2i{l}V`W0qG97vT z;sLr~cy5}D#=Ffa_N?^%kvPqRJSyA+ zIai@Jnl4Uv4p%BvyeGSwn_9dY+Ug;?9OeL;g>JWm>4t-76aHvNn`fiyX%ve-)OX5M z!1tbx_TgJhzK1Pg(#)Vcl5wlUD4^N*s<-3ogzW*E12h+C9zFyg$~3!-=A+AVDcPkJ zYj9DE;#lbaX6)Oaw&c-*d$n>i;6sRtK_SS5hrDCK4+%hvftCO*1qwhVpfbrZ3Gyxj zssJqqs**gQ6(pY&kU~;Kib)A6B|s!1lQM!Nl|ZY2Rs*d8S_^ayDJLqaAeE$wR1^GA zMb-eV1L^=;4|FY1Cs0D_h=bIVwZusXP!~`)aS=E15d6AF8pab1&T0?Pb>If-1=;|# z5vUKSA7~TVGXA8&Y0}L=w*YMipl<;^0Q4ZxD9}DY9S)IBf~*gt zR58*;44_9yH`xjFC}7KsZO{nNV?g_Xz72E$=y9@Z{Kt(oDEt|qXYsuT^c*w+JrDE( z36b3-OnS&3(o6ONy$Ey|JmY`gh}S;~bPUj1*U3JDqTC=6@)ki+ZUTLepggxol=P89 zK;H+7A2bAD_+0=WyIBOkE7^f%1Iq!H3oMVsfaL=#09FXB2$MIkVsZpn39wRN_-K-V c;d`gdN6+#He>zW;p<7@(S)LhG93t`m1LJj~F8}}l delta 5791 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 Date: Sun, 21 Jan 2024 19:23:30 +0000 Subject: [PATCH 31/68] Update mip packages --- mip/v5/createstubs.py | 108 +++++++------- mip/v5/createstubs_db.py | 59 +++++--- mip/v5/createstubs_db_min.py | 240 +++++++++++++++--------------- mip/v5/createstubs_db_mpy.mpy | Bin 8786 -> 8997 bytes mip/v5/createstubs_lvgl.py | 59 +++++--- mip/v5/createstubs_lvgl_min.py | 256 ++++++++++++++++---------------- mip/v5/createstubs_lvgl_mpy.mpy | Bin 8236 -> 8447 bytes mip/v5/createstubs_mem.py | 59 +++++--- mip/v5/createstubs_mem_min.py | 228 ++++++++++++++-------------- mip/v5/createstubs_mem_mpy.mpy | Bin 8275 -> 8486 bytes mip/v5/createstubs_min.py | 254 ++++++++++++++++--------------- mip/v5/createstubs_mpy.mpy | Bin 10848 -> 11057 bytes mip/v6/createstubs.py | 108 +++++++------- mip/v6/createstubs_db.py | 59 +++++--- mip/v6/createstubs_db_min.py | 240 +++++++++++++++--------------- mip/v6/createstubs_db_mpy.mpy | Bin 8613 -> 8799 bytes mip/v6/createstubs_lvgl.py | 59 +++++--- mip/v6/createstubs_lvgl_min.py | 256 ++++++++++++++++---------------- mip/v6/createstubs_lvgl_mpy.mpy | Bin 8090 -> 8275 bytes mip/v6/createstubs_mem.py | 59 +++++--- mip/v6/createstubs_mem_min.py | 228 ++++++++++++++-------------- mip/v6/createstubs_mem_mpy.mpy | Bin 8124 -> 8310 bytes mip/v6/createstubs_min.py | 254 ++++++++++++++++--------------- mip/v6/createstubs_mpy.mpy | Bin 11142 -> 11320 bytes 24 files changed, 1340 insertions(+), 1186 deletions(-) diff --git a/mip/v5/createstubs.py b/mip/v5/createstubs.py index 85421cd2d..9f29cb4c9 100644 --- a/mip/v5/createstubs.py +++ b/mip/v5/createstubs.py @@ -8,7 +8,10 @@ import os import sys -from ujson import dumps +try: + from ujson import dumps +except: + from json import dumps try: from machine import reset # type: ignore @@ -46,9 +49,9 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-{ver}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) else: - self._fwid = "{family}-{ver}-{port}".format(**self.info) + self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore if path: @@ -109,11 +112,7 @@ def get_obj_attributes(self, item_instance: object): order = 4 _result.append((name, repr(val), repr(type(val)), val, order)) except AttributeError as e: - _errors.append( - "Couldn't get attribute '{}' from object '{}', Err: {}".format( - name, item_instance, e - ) - ) + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) except MemoryError as e: print("MemoryError: {}".format(e)) sleep(1) @@ -177,9 +176,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - self.log.info( - "Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1) - ) + self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) @@ -197,9 +194,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") - self._report.append( - '{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/")) - ) + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) if module_name not in {"os", "sys", "logging", "gc"}: # try to unload the module unless we use it @@ -214,9 +209,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: gc.collect() return True - def write_object_stub( - self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0 - ): + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: @@ -276,11 +269,7 @@ def write_object_stub( s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - self.log.debug( - "# def {1} function/method/closure, type = '{0}'".format( - item_type_txt, item_name - ) - ) + self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -291,13 +280,11 @@ def write_object_stub( first = "self, " # class method - add function decoration if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format( - indent - ) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) - else: - s = "{}def {}({}*args, **kwargs) -> {}:\n".format( - indent, item_name, first, ret + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format( + indent, item_name, ret ) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) self.log.debug("\n" + s) @@ -324,9 +311,7 @@ def write_object_stub( # https://docs.python.org/3/tutorial/classes.html#item_instance-objects t = "Incomplete" # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format( - indent, item_name, t, item_type_txt, item_repr - ) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -378,9 +363,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" self.log.info( - "Created stubs for {} modules on board {}\nPath: {}".format( - len(self._report), self._fwid, self.path - ) + "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) ) f_name = "{}/{}".format(self.path, filename) self.log.info("Report file: {}".format(f_name)) @@ -439,12 +422,15 @@ def ensure_folder(path: str): def _build(s): - # extract a build nr from a string + # extract build from sys.version or os.uname().version if available + # 'v1.13-103-gb137d064e' + # 'MicroPython v1.23.0-preview.6.g3d0b6276f' if not s: return "" - if " on " in s: - s = s.split(" on ", 1)[0] - return s.split("-")[1] if "-" in s else "" + s = s.split(" on ", 1)[0] if " on " in s else s + s = s.split("; ", 1)[1] if "; " in s else s + b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + return b def _info(): # type:() -> dict[str, str] @@ -469,14 +455,12 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") + info["version"] = version_str(sys.implementation.version) # type: ignore except AttributeError: pass try: _machine = ( - sys.implementation._machine - if "_machine" in dir(sys.implementation) - else os.uname().machine # type: ignore + sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore ) # info["board"] = "with".join(_machine.split("with")[:-1]).strip() info["board"] = _machine @@ -495,19 +479,20 @@ def _info(): # type:() -> dict[str, str] gc.collect() try: - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - if not info["build"] and ";" in sys.version: - # extract build from uname().release if available - info["build"] = _build(sys.version.split(";")[1]) - except (AttributeError, IndexError): + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): pass # avoid build hashes - if info["build"] and len(info["build"]) > 5: - info["build"] = "" + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" if info["version"] == "" and sys.platform not in ("unix", "win32"): try: @@ -533,14 +518,14 @@ def _info(): # type:() -> dict[str, str] info["release"] = "2.0.0" if info["family"] == "micropython": + info["version"] if ( info["version"] and info["version"].endswith(".0") - and info["version"] - >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 and info["version"] <= "1.19.9" ): - # drop the .0 for newer releases + # versions from 1.10.0 to 1.20.0 do not have a micro .0 info["version"] = info["version"][:-2] # spell-checker: disable @@ -564,12 +549,21 @@ def _info(): # type:() -> dict[str, str] info["arch"] = arch # .mpy version.minor info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" # simple to use version[-build] string - info["ver"] = f"v{info['version']}-{info['build']}" if info["build"] else f"v{info['version']}" + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" return info +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + def read_boardname(info, desc: str = ""): found = False for filename in [d + "/board_info.csv" for d in LIBS]: diff --git a/mip/v5/createstubs_db.py b/mip/v5/createstubs_db.py index 7a9761f7e..d176f3714 100644 --- a/mip/v5/createstubs_db.py +++ b/mip/v5/createstubs_db.py @@ -27,7 +27,10 @@ import os import sys -from ujson import dumps +try: + from ujson import dumps +except: + from json import dumps try: from machine import reset # type: ignore @@ -65,9 +68,9 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-{ver}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) else: - self._fwid = "{family}-{ver}-{port}".format(**self.info) + self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore if path: @@ -432,12 +435,15 @@ def ensure_folder(path: str): def _build(s): - # extract a build nr from a string + # extract build from sys.version or os.uname().version if available + # 'v1.13-103-gb137d064e' + # 'MicroPython v1.23.0-preview.6.g3d0b6276f' if not s: return "" - if " on " in s: - s = s.split(" on ", 1)[0] - return s.split("-")[1] if "-" in s else "" + s = s.split(" on ", 1)[0] if " on " in s else s + s = s.split("; ", 1)[1] if "; " in s else s + b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + return b def _info(): # type:() -> dict[str, str] @@ -462,7 +468,7 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") + info["version"] = version_str(sys.implementation.version) # type: ignore except AttributeError: pass try: @@ -484,19 +490,20 @@ def _info(): # type:() -> dict[str, str] gc.collect() try: - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - if not info["build"] and ";" in sys.version: - # extract build from uname().release if available - info["build"] = _build(sys.version.split(";")[1]) - except (AttributeError, IndexError): + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): pass # avoid build hashes - if info["build"] and len(info["build"]) > 5: - info["build"] = "" + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" if info["version"] == "" and sys.platform not in ("unix", "win32"): try: @@ -522,13 +529,14 @@ def _info(): # type:() -> dict[str, str] info["release"] = "2.0.0" if info["family"] == "micropython": + info["version"] if ( info["version"] and info["version"].endswith(".0") and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 and info["version"] <= "1.19.9" ): - # drop the .0 for newer releases + # versions from 1.10.0 to 1.20.0 do not have a micro .0 info["version"] = info["version"][:-2] # spell-checker: disable @@ -552,12 +560,21 @@ def _info(): # type:() -> dict[str, str] info["arch"] = arch # .mpy version.minor info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" # simple to use version[-build] string - info["ver"] = f"v{info['version']}-{info['build']}" if info["build"] else f"v{info['version']}" + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" return info +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + def read_boardname(info, desc: str = ""): found = False for filename in [d + "/board_info.csv" for d in LIBS]: diff --git a/mip/v5/createstubs_db_min.py b/mip/v5/createstubs_db_min.py index 751c0c400..adae0e729 100644 --- a/mip/v5/createstubs_db_min.py +++ b/mip/v5/createstubs_db_min.py @@ -1,16 +1,18 @@ -w='with' -v='stubber' -u='{}/{}' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' +x='with' +w='stubber' +v='{}/{}' +u='method' +t='function' +s='bool' +r='str' +q='float' +p='int' +o=TypeError n=NameError m=sorted l=MemoryError k=NotImplementedError +d='-' c=',\n' b='dict' a='list' @@ -22,11 +24,11 @@ T='_' S=KeyError R=IndexError -Q=dir -P=ImportError -O='family' -N=print -M=len +Q=ImportError +P='family' +O=print +N=len +M=dir L='.' K=open J=True @@ -34,19 +36,20 @@ H='board' G='/' F=None -E='version' -D=False +E=False A=OSError +D='version' C='' import gc as B,os,sys -from ujson import dumps as d +try:from ujson import dumps +except:from json import dumps try:from machine import reset -except P:pass +except Q:pass try:from collections import OrderedDict as e -except P:from ucollections import OrderedDict as e +except Q:from ucollections import OrderedDict as e __version__='v1.16.2' -x=2 y=2 +z=2 f=[L,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: @@ -57,26 +60,26 @@ def __init__(C,path=F,firmware_id=F): except I:pass C._report=[];C.info=_info();B.collect() if D:C._fwid=D.lower() - elif C.info[O]==Y:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) - else:C._fwid='{family}-{ver}-{port}'.format(**C.info) + elif C.info[P]==Y:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info) + else:C._fwid='{family}-v{version}-{port}'.format(**C.info) C._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) try:g(path+G) - except A:N('error creating stub folder {}'.format(path)) + except A:O('error creating stub folder {}'.format(path)) C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] def get_obj_attributes(L,item_instance): H=item_instance;D=[];J=[] - for A in Q(H): + for A in M(H): if A.startswith(T)and not A in L.modules:continue try: E=getattr(H,A) try:F=W(type(E)).split("'")[1] except R:F=C - if F in{o,p,q,r,Z,a,b}:G=1 - elif F in{s,t}:G=2 + if F in{p,q,r,s,Z,a,b}:G=1 + elif F in{t,u}:G=2 elif F in'class':G=3 else:G=4 D.append((A,W(E),W(type(E)),E,G)) @@ -88,45 +91,45 @@ def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) def create_one_stub(C,module_name): - E=module_name - if E in C.problematic:return D - if E in C.excluded:return D - H='{}/{}.py'.format(C.path,E.replace(L,G));B.collect();F=D - try:F=C.create_module_stub(E,H) - except A:return D + D=module_name + if D in C.problematic:return E + if D in C.excluded:return E + H='{}/{}.py'.format(C.path,D.replace(L,G));B.collect();F=E + try:F=C.create_module_stub(D,H) + except A:return E B.collect();return F def create_module_stub(I,module_name,file_name=F): - H=file_name;E=module_name - if H is F:O=E.replace(L,T)+'.py';H=I.path+G+O + H=file_name;D=module_name + if H is F:O=D.replace(L,T)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in E:E=E.replace(G,L) + if G in D:D=D.replace(G,L) M=F - try:M=__import__(E,F,F,'*');U=B.mem_free() - except P:return D + try:M=__import__(D,F,F,'*');U=B.mem_free() + except Q:return E g(H) - with K(H,'w')as N:Q=X(I.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(E,I._fwid,Q,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,E,C) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(E,H.replace('\\',G))) - if E not in{'os','sys','logging','gc'}: + with K(H,'w')as N:P=X(I.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,D,C) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) + if D not in{'os','sys','logging','gc'}: try:del M except(A,S):pass - try:del sys.modules[E] + try:del sys.modules[D] except S:pass B.collect();return J def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;M='Exception';H=fp;E=indent;B.collect() if P in K.problematic:return R,L=K.get_obj_attributes(P) - if L:N(L) + if L:O(L) for(F,J,G,T,f)in R: - if F in['classmethod','staticmethod','BaseException',O]:continue + if F in['classmethod','staticmethod','BaseException',M]:continue if F[0].isdigit():continue - if G==""and M(E)<=y*4: - U=C;V=F.endswith(O)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=O + if G==""and N(E)<=z*4: + U=C;V=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=M D='\n{}class {}({}):\n'.format(E,F,U) if V:D+=E+' ...\n';H.write(D);return H.write(D);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) - elif any(A in G for A in[t,s,'closure']): + elif any(A in G for A in[u,t,'closure']): W=Y;X=C if Q>0:X='self, ' if c in G or c in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) @@ -135,7 +138,7 @@ def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): elif G=="":0 elif G.startswith("5:A[D]=C - if A[E]==C and sys.platform not in(b,a): - try:g=os.uname();A[E]=g.release - except(R,I,TypeError):pass - for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(f,'pybricks.hubs','EV3Brick')]: - try:k=__import__(i,F,F,j);A[O]=h;del k;break - except(P,S):pass - if A[O]==f:A['release']='2.0.0' - if A[O]==Y: - if A[E]and A[E].endswith('.0')and A[E]>='1.10.0'and A[E]<='1.19.9':A[E]=A[E][:-2] + if'uname'in M(os): + A[E]=V(os.uname()[3]) + if not A[E]:A[E]=V(os.uname()[2]) + elif D in M(sys):A[E]=V(sys.version) + except(I,R,o):pass + if A[D]==C and sys.platform not in(X,W): + try:d=os.uname();A[D]=d.release + except(R,I,o):pass + for(f,g,h)in[(Z,Z,'const'),(a,a,'FAT'),(b,'pybricks.hubs','EV3Brick')]: + try:i=__import__(g,F,F,h);A[P]=f;del i;break + except(Q,S):pass + if A[P]==b:A['release']='2.0.0' + if A[P]==Y: + A[D] + if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if J in A and A[J]: - K=int(A[J]);T=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if T:A[Z]=T + K=int(A[J]);N=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if N:A[T]=N A[J]='v{}.{}'.format(K&255,K>>8&3) - A[W]=f"v{A[E]}-{A[D]}"if A[D]else f"v{A[E]}";return A -def z(info,desc=C): - L='with ';A=info;F=D + if A[E]and not A[D].endswith(c):A[D]=A[D]+c + A[O]=f"{A[D]}-{A[E]}"if A[E]else f"{A[D]}";return A +def A0(version): + A=version;B=L.join([X(A)for A in A[:3]]) + if N(A)>3 and A[3]:B+=d+A[3] + return B +def A1(info,desc=C): + L='with ';A=info;F=E for G in[A+'/board_info.csv'for A in f]: if h(G): - E=desc or A[H].strip();I=E.rfind(' with') - if I!=-1:K=E[:I].strip() + D=desc or A[H].strip();I=D.rfind(' with') + if I!=-1:K=D[:I].strip() else:K=C - if A0(A,E,G,K):F=J;break + if A2(A,D,G,K):F=J;break if not F: - E=desc or A[H].strip() - if L+A[U].upper()in E:E=E.split(L+A[U].upper())[0].strip() - A[H]=E + D=desc or A[H].strip() + if L+A[U].upper()in D:D=D.split(L+A[U].upper())[0].strip() + A[H]=D A[H]=A[H].replace(' ',T);B.collect() -def A0(info,descr,filename,short_descr): - B=short_descr;A=info;E=C +def A2(info,descr,filename,short_descr): + B=short_descr;A=info;D=C with K(filename,'r')as L: while 1: F=L.readline() @@ -243,10 +251,10 @@ def A0(info,descr,filename,short_descr): I,G=F.split(',')[0].strip(),F.split(',')[1].strip() if I==descr:A[H]=G;return J elif B and I==B: - if w in B:A[H]=G;return J - E=G - if E:A[H]=E;return J - return D + if x in B:A[H]=G;return J + D=G + if D:A[H]=D;return J + return E def get_root(): try:B=os.getcwd() except(A,I):B=L @@ -258,56 +266,56 @@ def get_root(): def h(filename): try: if os.stat(filename)[0]>>14:return J - return D - except A:return D + return E + except A:return E def i():sys.exit(1) def read_path(): path=C - if M(sys.argv)==3: + if N(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] else:i() - elif M(sys.argv)==2:i() + elif N(sys.argv)==2:i() return path def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return D + try:A=bytes('abc',encoding='utf8');B=j.__module__;return E except(k,I):return J def main(): L='failed';G='modulelist.done';import machine as O - try:C=K(G,'r+b');N=J - except A:C=K(G,'w+b');N=D + try:C=K(G,'r+b');M=J + except A:C=K(G,'w+b');M=E stubber=Stubber(path=read_path()) - if not N:stubber.clean() - A1(stubber);E={} + if not M:stubber.clean() + A3(stubber);D={} try: with K(G)as C: for F in C.read().split('\n'): F=F.strip();B.collect() - if M(F)>0:P,Q=F.split('=',1);E[P]=Q + if N(F)>0:P,Q=F.split('=',1);D[P]=Q except(A,SyntaxError):pass - B.collect();R=[A for A in stubber.modules if A not in E.keys()];B.collect() + B.collect();R=[A for A in stubber.modules if A not in D.keys()];B.collect() for H in R: - I=D + I=E try:I=stubber.create_one_stub(H) except l:O.reset() - B.collect();E[H]=X(stubber._report[-1]if I else L) + B.collect();D[H]=X(stubber._report[-1]if I else L) with K(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if I else L)) - if E:stubber._report=[A for(B,A)in E.items()if A!=L];stubber.report() -def A1(stubber): + if D:stubber._report=[A for(B,A)in D.items()if A!=L];stubber.report() +def A3(stubber): E='/modulelist.txt';stubber.modules=[] for D in f: try: with K(D+E)as F: - N('DEBUG: list of modules: '+D+E) + O('DEBUG: list of modules: '+D+E) for C in F.read().split('\n'): C=C.strip() - if M(C)>0 and C[0]!='#':stubber.modules.append(C) + if N(C)>0 and C[0]!='#':stubber.modules.append(C) B.collect();break except A:pass if not stubber.modules:stubber.modules=[Y];_log.warn('Could not find modulelist.txt, using default modules') B.collect() if __name__=='__main__'or j(): - try:A2=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + try:A4=logging.getLogger(w);logging.basicConfig(level=logging.INFO) except n:pass if not h('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() diff --git a/mip/v5/createstubs_db_mpy.mpy b/mip/v5/createstubs_db_mpy.mpy index 0b759468c8f98656dc87f151bdd2fa2e234a1582..b991b8b5bb6732e7baf8233f758b544ca921a6d6 100644 GIT binary patch delta 2107 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 diff --git a/mip/v5/createstubs_lvgl.py b/mip/v5/createstubs_lvgl.py index fe5417871..7e0fd913c 100644 --- a/mip/v5/createstubs_lvgl.py +++ b/mip/v5/createstubs_lvgl.py @@ -12,7 +12,10 @@ import os import sys -from ujson import dumps +try: + from ujson import dumps +except: + from json import dumps try: from machine import reset # type: ignore @@ -50,9 +53,9 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-{ver}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) else: - self._fwid = "{family}-{ver}-{port}".format(**self.info) + self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore if path: @@ -417,12 +420,15 @@ def ensure_folder(path: str): def _build(s): - # extract a build nr from a string + # extract build from sys.version or os.uname().version if available + # 'v1.13-103-gb137d064e' + # 'MicroPython v1.23.0-preview.6.g3d0b6276f' if not s: return "" - if " on " in s: - s = s.split(" on ", 1)[0] - return s.split("-")[1] if "-" in s else "" + s = s.split(" on ", 1)[0] if " on " in s else s + s = s.split("; ", 1)[1] if "; " in s else s + b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + return b def _info(): # type:() -> dict[str, str] @@ -447,7 +453,7 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") + info["version"] = version_str(sys.implementation.version) # type: ignore except AttributeError: pass try: @@ -469,19 +475,20 @@ def _info(): # type:() -> dict[str, str] gc.collect() try: - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - if not info["build"] and ";" in sys.version: - # extract build from uname().release if available - info["build"] = _build(sys.version.split(";")[1]) - except (AttributeError, IndexError): + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): pass # avoid build hashes - if info["build"] and len(info["build"]) > 5: - info["build"] = "" + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" if info["version"] == "" and sys.platform not in ("unix", "win32"): try: @@ -507,13 +514,14 @@ def _info(): # type:() -> dict[str, str] info["release"] = "2.0.0" if info["family"] == "micropython": + info["version"] if ( info["version"] and info["version"].endswith(".0") and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 and info["version"] <= "1.19.9" ): - # drop the .0 for newer releases + # versions from 1.10.0 to 1.20.0 do not have a micro .0 info["version"] = info["version"][:-2] # spell-checker: disable @@ -537,12 +545,21 @@ def _info(): # type:() -> dict[str, str] info["arch"] = arch # .mpy version.minor info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" # simple to use version[-build] string - info["ver"] = f"v{info['version']}-{info['build']}" if info["build"] else f"v{info['version']}" + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" return info +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + def read_boardname(info, desc: str = ""): found = False for filename in [d + "/board_info.csv" for d in LIBS]: diff --git a/mip/v5/createstubs_lvgl_min.py b/mip/v5/createstubs_lvgl_min.py index 24d22c1d8..5412c8895 100644 --- a/mip/v5/createstubs_lvgl_min.py +++ b/mip/v5/createstubs_lvgl_min.py @@ -1,17 +1,19 @@ -u='with' -t='stubber' -s='{}/{}' -r='method' -q='function' -p='bool' -o='str' -n='float' -m='int' -l='micropython' -k=Exception +v='with' +u='stubber' +t='{}/{}' +s='method' +r='function' +q='bool' +p='str' +o='float' +n='int' +m='micropython' +l=Exception +k=TypeError j=NameError i=sorted h=NotImplementedError +b='-' a=',\n' Z='dict' Y='list' @@ -23,10 +25,10 @@ R=len Q=KeyError P=IndexError -O=dir -N=print -M=ImportError -L='family' +O=print +N=ImportError +M='family' +L=dir K=True J='.' I=AttributeError @@ -34,19 +36,20 @@ A=False G='/' E=None -D='version' F=OSError +C='version' B='' -import gc as C,os,sys -from ujson import dumps as b +import gc as D,os,sys +try:from ujson import dumps +except:from json import dumps try:from machine import reset -except M:pass +except N:pass try:from collections import OrderedDict as c -except M:from ucollections import OrderedDict as c +except N:from ucollections import OrderedDict as c __version__='v1.16.2' -v=2 w=2 -x=[J,'/lib','/sd/lib','/flash/lib','lib'] +x=2 +y=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): @@ -54,93 +57,93 @@ def __init__(A,path=E,firmware_id=E): try: if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise h('MicroPython 1.13.0 cannot be stubbed') except I:pass - A._report=[];A.info=_info();C.collect() + A._report=[];A.info=_info();D.collect() if B:A._fwid=B.lower() - elif A.info[L]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-{ver}-{port}'.format(**A.info) - A._start_free=C.mem_free() + elif A.info[M]==m:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) + else:A._fwid='{family}-v{version}-{port}'.format(**A.info) + A._start_free=D.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) try:d(path+G) - except F:N('error creating stub folder {}'.format(path)) + except F:O('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] - def get_obj_attributes(L,item_instance): - H=item_instance;D=[];J=[] - for A in O(H): - if A.startswith(S)and not A in L.modules:continue + def get_obj_attributes(M,item_instance): + H=item_instance;C=[];J=[] + for A in L(H): + if A.startswith(S)and not A in M.modules:continue try: E=getattr(H,A) try:F=V(type(E)).split("'")[1] except P:F=B - if F in{m,n,o,p,X,Y,Z}:G=1 - elif F in{q,r}:G=2 + if F in{n,o,p,q,X,Y,Z}:G=1 + elif F in{r,s}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,V(E),V(type(E)),E,G)) + C.append((A,V(E),V(type(E)),E,G)) except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=i([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + C=i([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,J def add_modules(A,modules):A.modules=i(set(A.modules)|set(modules)) def create_all_stubs(A): - C.collect() + D.collect() for B in A.modules:A.create_one_stub(B) def create_one_stub(B,module_name): - D=module_name - if D in B.problematic:return A - if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A - try:E=B.create_module_stub(D,H) + C=module_name + if C in B.problematic:return A + if C in B.excluded:return A + H='{}/{}.py'.format(B.path,C.replace(J,G));D.collect();E=A + try:E=B.create_module_stub(C,H) except F:return A - C.collect();return E + D.collect();return E def create_module_stub(I,module_name,file_name=E): - H=file_name;D=module_name - if H is E:O=D.replace(J,S)+'.py';H=I.path+G+O + H=file_name;C=module_name + if H is E:O=C.replace(J,S)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,J) + if G in C:C=C.replace(G,J) L=E - try:L=__import__(D,E,E,'*');T=C.mem_free() - except M:return A + try:L=__import__(C,E,E,'*');T=D.mem_free() + except N:return A d(H) - with W(H,'w')as N:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,L,D,B) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: + with W(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,I._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,C,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + if C not in{'os','sys','logging','gc'}: try:del L except(F,Q):pass - try:del sys.modules[D] + try:del sys.modules[C] except Q:pass - C.collect();return K + D.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() - if O in K.problematic:return - S,L=K.get_obj_attributes(O) - if L:N(L) + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;C=indent;D.collect() + if N in K.problematic:return + S,L=K.get_obj_attributes(N) + if L:O(L) for(E,J,G,T,f)in S: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and R(D)<=w*4: + if G==""and R(C)<=x*4: U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=M - A='\n{}class {}({}):\n'.format(D,E,U) - if V:A+=D+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): + A='\n{}class {}({}):\n'.format(C,E,U) + if V:A+=C+' ...\n';H.write(A);return + H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),C+' ',P+1);A=C+' def __init__(self, *argv, **kwargs) -> None:\n';A+=C+' ...\n\n';H.write(A) + elif any(A in G for A in[s,r,'closure']): W=b;a=B if P>0:a='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,W) - A+=D+' ...\n\n';H.write(A) + if c in G or c in J:A='{}@classmethod\n'.format(C)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(C,E,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(C,E,a,W) + A+=C+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(Z,Y): - try:e=os.uname();A[D]=e.release - except(P,I,TypeError):pass - for(f,g,h)in[(a,a,'const'),(b,b,'FAT'),(d,'pybricks.hubs','EV3Brick')]: - try:i=__import__(g,E,E,h);A[L]=f;del i;break - except(M,Q):pass - if A[L]==d:A['release']='2.0.0' - if A[L]==l: - if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if K in A and A[K]: - N=int(A[K]);V=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] - if V:A[X]=V - A[K]='v{}.{}'.format(N&255,N>>8&3) - A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def y(info,desc=B): - L='with ';D=info;F=A - for G in[A+'/board_info.csv'for A in x]: + if'uname'in L(os): + A[F]=U(os.uname()[3]) + if not A[F]:A[F]=U(os.uname()[2]) + elif C in L(sys):A[F]=U(sys.version) + except(I,P,k):pass + if A[C]==B and sys.platform not in(X,W): + try:d=os.uname();A[C]=d.release + except(P,I,k):pass + for(e,f,g)in[(Y,Y,'const'),(Z,Z,'FAT'),(a,'pybricks.hubs','EV3Brick')]: + try:h=__import__(f,E,E,g);A[M]=e;del h;break + except(N,Q):pass + if A[M]==a:A['release']='2.0.0' + if A[M]==m: + A[C] + if A[C]and A[C].endswith('.0')and A[C]>='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if J in A and A[J]: + K=int(A[J]);R=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if R:A[V]=R + A[J]='v{}.{}'.format(K&255,K>>8&3) + if A[F]and not A[C].endswith(b):A[C]=A[C]+b + A[S]=f"{A[C]}-{A[F]}"if A[F]else f"{A[C]}";return A +def z(version): + A=version;B=J.join([str(A)for A in A[:3]]) + if R(A)>3 and A[3]:B+=b+A[3] + return B +def A0(info,desc=B): + L='with ';C=info;F=A + for G in[A+'/board_info.csv'for A in y]: if e(G): - E=desc or D[H].strip();I=E.rfind(' with') + E=desc or C[H].strip();I=E.rfind(' with') if I!=-1:J=E[:I].strip() else:J=B - if z(D,E,G,J):F=K;break + if A1(C,E,G,J):F=K;break if not F: - E=desc or D[H].strip() - if L+D[T].upper()in E:E=E.split(L+D[T].upper())[0].strip() - D[H]=E - D[H]=D[H].replace(' ',S);C.collect() -def z(info,descr,filename,short_descr): + E=desc or C[H].strip() + if L+C[T].upper()in E:E=E.split(L+C[T].upper())[0].strip() + C[H]=E + C[H]=C[H].replace(' ',S);D.collect() +def A1(info,descr,filename,short_descr): D=short_descr;C=info;E=B with W(filename,'r')as J: while 1: @@ -242,7 +250,7 @@ def z(info,descr,filename,short_descr): I,G=F.split(',')[0].strip(),F.split(',')[1].strip() if I==descr:C[H]=G;return K elif D and I==D: - if u in D:C[H]=G;return K + if v in D:C[H]=G;return K E=G if E:C[H]=E;return K return A @@ -272,18 +280,18 @@ def g(): try:B=bytes('abc',encoding='utf8');C=g.__module__;return A except(h,I):return K def main(): - D='lvgl' + C='lvgl' try:import lvgl as A - except k:return - B=D + except l:return + B=C try:B='lvgl-{0}_{1}_{2}-{3}-{4}'.format(A.version_major(),A.version_minor(),A.version_patch(),A.version_info(),sys.platform) - except k:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) + except l:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) finally:stubber=Stubber(firmware_id=B) - stubber.clean();stubber.modules=['io','lodepng','rtch',D];C.collect();stubber.create_all_stubs();stubber.report() + stubber.clean();stubber.modules=['io','lodepng','rtch',C];D.collect();stubber.create_all_stubs();stubber.report() if __name__=='__main__'or g(): - try:A0=logging.getLogger(t);logging.basicConfig(level=logging.INFO) + try:A2=logging.getLogger(u);logging.basicConfig(level=logging.INFO) except j:pass if not e('no_auto_stubber.txt'): - try:C.threshold(4*1024);C.enable() + try:D.threshold(4*1024);D.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_lvgl_mpy.mpy b/mip/v5/createstubs_lvgl_mpy.mpy index 64b1c6821d1c9ee88c75e08d56a63556c67e8c39..b637b49e423ade08089956031558af36e715c191 100644 GIT binary patch delta 2184 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 dict[str, str] @@ -453,7 +459,7 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") + info["version"] = version_str(sys.implementation.version) # type: ignore except AttributeError: pass try: @@ -475,19 +481,20 @@ def _info(): # type:() -> dict[str, str] gc.collect() try: - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - if not info["build"] and ";" in sys.version: - # extract build from uname().release if available - info["build"] = _build(sys.version.split(";")[1]) - except (AttributeError, IndexError): + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): pass # avoid build hashes - if info["build"] and len(info["build"]) > 5: - info["build"] = "" + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" if info["version"] == "" and sys.platform not in ("unix", "win32"): try: @@ -513,13 +520,14 @@ def _info(): # type:() -> dict[str, str] info["release"] = "2.0.0" if info["family"] == "micropython": + info["version"] if ( info["version"] and info["version"].endswith(".0") and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 and info["version"] <= "1.19.9" ): - # drop the .0 for newer releases + # versions from 1.10.0 to 1.20.0 do not have a micro .0 info["version"] = info["version"][:-2] # spell-checker: disable @@ -543,12 +551,21 @@ def _info(): # type:() -> dict[str, str] info["arch"] = arch # .mpy version.minor info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" # simple to use version[-build] string - info["ver"] = f"v{info['version']}-{info['build']}" if info["build"] else f"v{info['version']}" + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" return info +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + def read_boardname(info, desc: str = ""): found = False for filename in [d + "/board_info.csv" for d in LIBS]: diff --git a/mip/v5/createstubs_mem_min.py b/mip/v5/createstubs_mem_min.py index 139f88f81..ef72491b9 100644 --- a/mip/v5/createstubs_mem_min.py +++ b/mip/v5/createstubs_mem_min.py @@ -1,15 +1,17 @@ -v='with' -u='stubber' -t='{}/{}' -s='method' -r='function' -q='bool' -p='str' -o='float' -n='int' +w='with' +v='stubber' +u='{}/{}' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n=TypeError m=NameError l=sorted k=NotImplementedError +d='-' c=',\n' b='dict' a='list' @@ -22,10 +24,10 @@ S=KeyError R=open Q=IndexError -P=dir -O=ImportError -N='family' -M=len +P=ImportError +O='family' +N=len +M=dir L=print K=True J='.' @@ -34,31 +36,32 @@ A=False G='/' E=None -D='version' F=OSError -B='' -import gc as C,os,sys -from ujson import dumps as d +D='version' +C='' +import gc as B,os,sys +try:from ujson import dumps +except:from json import dumps try:from machine import reset -except O:pass +except P:pass try:from collections import OrderedDict as e -except O:from ucollections import OrderedDict as e +except P:from ucollections import OrderedDict as e __version__='v1.16.2' -w=2 x=2 +y=2 f=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): - B=firmware_id + C=firmware_id try: if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') except I:pass - A._report=[];A.info=_info();C.collect() - if B:A._fwid=B.lower() - elif A.info[N]==Y:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-{ver}-{port}'.format(**A.info) - A._start_free=C.mem_free() + A._report=[];A.info=_info();B.collect() + if C:A._fwid=C.lower() + elif A.info[O]==Y:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) + else:A._fwid='{family}-v{version}-{port}'.format(**A.info) + A._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() @@ -68,80 +71,80 @@ def __init__(A,path=E,firmware_id=E): A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): H=item_instance;D=[];J=[] - for A in P(H): + for A in M(H): if A.startswith(T)and not A in L.modules:continue try: E=getattr(H,A) try:F=W(type(E)).split("'")[1] - except Q:F=B - if F in{n,o,p,q,Z,a,b}:G=1 - elif F in{r,s}:G=2 + except Q:F=C + if F in{o,p,q,r,Z,a,b}:G=1 + elif F in{s,t}:G=2 elif F in'class':G=3 else:G=4 D.append((A,W(E),W(type(E)),E,G)) except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) def create_all_stubs(A): - C.collect() - for B in A.modules:A.create_one_stub(B) - def create_one_stub(B,module_name): + B.collect() + for C in A.modules:A.create_one_stub(C) + def create_one_stub(C,module_name): D=module_name - if D in B.problematic:return A - if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A - try:E=B.create_module_stub(D,H) + if D in C.problematic:return A + if D in C.excluded:return A + H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=A + try:E=C.create_module_stub(D,H) except F:return A - C.collect();return E + B.collect();return E def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name if H is E:N=D.replace(J,T)+'.py';H=I.path+G+N else:N=H.split(G)[-1] if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');U=C.mem_free() - except O:return A + try:L=__import__(D,E,E,'*');U=B.mem_free() + except P:return A g(H) - with R(H,'w')as M:P=X(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) + with R(H,'w')as M:O=X(I.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,O,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,C) I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del L except(F,S):pass try:del sys.modules[D] except S:pass - C.collect();return K + B.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;C.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() if P in K.problematic:return - R,N=K.get_obj_attributes(P) - if N:L(N) + R,M=K.get_obj_attributes(P) + if M:L(M) for(E,J,G,T,f)in R: if E in['classmethod','staticmethod','BaseException',O]:continue if E[0].isdigit():continue - if G==""and M(D)<=x*4: - U=B;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if G==""and N(D)<=y*4: + U=C;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[s,r,'closure']): - W=Y;X=B + elif any(A in G for A in[t,s,'closure']): + W=Y;X=C if Q>0:X='self, ' if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(b,a): - try:g=os.uname();A[D]=g.release - except(Q,I,TypeError):pass - for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(f,'pybricks.hubs','EV3Brick')]: - try:k=__import__(i,E,E,j);A[N]=h;del k;break - except(O,S):pass - if A[N]==f:A['release']='2.0.0' - if A[N]==Y: + if'uname'in M(os): + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + elif D in M(sys):A[F]=V(sys.version) + except(I,Q,n):pass + if A[D]==C and sys.platform not in(X,W): + try:d=os.uname();A[D]=d.release + except(Q,I,n):pass + for(f,g,h)in[(Z,Z,'const'),(a,a,'FAT'),(b,'pybricks.hubs','EV3Brick')]: + try:i=__import__(g,E,E,h);A[O]=f;del i;break + except(P,S):pass + if A[O]==b:A['release']='2.0.0' + if A[O]==Y: + A[D] if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if K in A and A[K]: - L=int(A[K]);T=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][L>>10] - if T:A[Z]=T - A[K]='v{}.{}'.format(L&255,L>>8&3) - A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def y(info,desc=B): + if J in A and A[J]: + K=int(A[J]);N=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if N:A[T]=N + A[J]='v{}.{}'.format(K&255,K>>8&3) + if A[F]and not A[D].endswith(c):A[D]=A[D]+c + A[R]=f"{A[D]}-{A[F]}"if A[F]else f"{A[D]}";return A +def z(version): + A=version;B=J.join([X(A)for A in A[:3]]) + if N(A)>3 and A[3]:B+=d+A[3] + return B +def A0(info,desc=C): L='with ';D=info;F=A for G in[A+'/board_info.csv'for A in f]: if h(G): E=desc or D[H].strip();I=E.rfind(' with') if I!=-1:J=E[:I].strip() - else:J=B - if z(D,E,G,J):F=K;break + else:J=C + if A1(D,E,G,J):F=K;break if not F: E=desc or D[H].strip() if L+D[U].upper()in E:E=E.split(L+D[U].upper())[0].strip() D[H]=E - D[H]=D[H].replace(' ',T);C.collect() -def z(info,descr,filename,short_descr): - D=short_descr;C=info;E=B + D[H]=D[H].replace(' ',T);B.collect() +def A1(info,descr,filename,short_descr): + D=short_descr;B=info;E=C with R(filename,'r')as J: while 1: F=J.readline() if not F:break I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:C[H]=G;return K + if I==descr:B[H]=G;return K elif D and I==D: - if v in D:C[H]=G;return K + if w in D:B[H]=G;return K E=G - if E:C[H]=E;return K + if E:B[H]=E;return K return A def get_root(): try:A=os.getcwd() @@ -261,35 +269,35 @@ def h(filename): except F:return A def i():sys.exit(1) def read_path(): - path=B - if M(sys.argv)==3: + path=C + if N(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] else:i() - elif M(sys.argv)==2:i() + elif N(sys.argv)==2:i() return path def j(): try:B=bytes('abc',encoding='utf8');C=j.__module__;return A except(k,I):return K def main(): E='/modulelist.txt';stubber=Stubber(path=read_path());stubber.clean();stubber.modules=[] - for B in f: + for C in f: try: - F=C.mem_free() - with R(B+E)as D: - L('Debug: List of modules: '+B+E);A=D.readline() + F=B.mem_free() + with R(C+E)as D: + L('Debug: List of modules: '+C+E);A=D.readline() while A: A=A.strip() - if M(A)>0 and A[0]!='#':stubber.modules.append(A) + if N(A)>0 and A[0]!='#':stubber.modules.append(A) A=D.readline() - C.collect();L('Debug: Used memory to load modulelist.txt: '+X(F-C.mem_free())+' bytes');break + B.collect();L('Debug: Used memory to load modulelist.txt: '+X(F-B.mem_free())+' bytes');break except Exception:pass if not stubber.modules:stubber.modules=[Y] - C.collect();stubber.create_all_stubs();stubber.report() + B.collect();stubber.create_all_stubs();stubber.report() if __name__=='__main__'or j(): - try:A0=logging.getLogger(u);logging.basicConfig(level=logging.INFO) + try:A2=logging.getLogger(v);logging.basicConfig(level=logging.INFO) except m:pass if not h('no_auto_stubber.txt'): - try:C.threshold(4*1024);C.enable() + try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_mem_mpy.mpy b/mip/v5/createstubs_mem_mpy.mpy index 6ee7538f8331873daf140cc57c4c3c6a5f31a336..42b519779063d8c0909a812755acd995118cf9b9 100644 GIT binary patch delta 2240 zcmZWqeQaA-6~Fg7jz1D7*Y`OuOPthc;$~|aJGSe*%xl*+&TAFAHEC$=5@0j_YU9TC z^X%t*ECjzaR6-1umitGif!H4d{y+kfrd>bY*0mjF1qNeGnkXom#Do|UQq?i>9}?#! z>sEm*-*@ise7tjh_uTW|+xL^G?U0#xy3V`$FP^gvbocgpdyT)bK0XxQ>)jjf^?JjB z7Zy)9X1h*zWxLMBJh@rgR8gy`RJJUV8ERix99UQsNtHGhvg(wQ5s6Ca@oF)x=9HpH zDirMzNtvSaB6*J5kLQ)7Dv}aK&x%BGB1t4gC-RA;;6!Idl6Rs3kxWwpNaozThaTw_ z$zj@fJXy%)=S4E^MAIS}bE2oYgo9}(3W($YZJNoJD;qD9DZ(Nd(I(t=C(lwNR?`VYj_{vZ53_Od_5<*n%cCiUG8Kj$!l+U%_2?h`);!^V}(s z%=7&uu`gs6$@9*=efY@Eda-Ue5VF7;3|U2bBC96KilT;WBAE)=MUo3Oh^(AVW)h{O zIu&XZ$;ps|uM?kTM#A6~;!e{(9OYj$4fQ)JLQzR1tE!UtlwiL)r+#y{RT}6>Lku-* zz!iUK{yWmzB~t`LV)yFS@c7y*<}p0fy|78sqHkv5Q$`kj3nitj!Xu?5%bCSW`~TbU zEtWsxQGVaji4XB+>x6>%FebWkwW6N{l?mNSTo@Gm>N^<+H5IW^L(CbgKpi6-HEk z#`+56AF@s3IRBw7291FdAD7{U*(hbABZDjLCI9}*+el}$i9$y*(o{P zT81|?oWY0JUTXLk##MgC@xEp3^)O~Y^mNmWIu+i*2bx#xki=#-<+Xn_pCtGcKg#;> zd0u0C@b~$3b_|?FA=&!lp&noV6FZ(j%;`c$R|LzdL~bz~|E@3yWZf1{;;lU3Y9VBV zA8`4*e}Ow!FWI@7{hQv0zgn!Sq8_)1}Tt4vpkE;#;g15Hp@T{T@ z>w5b$i(o&IM#$kfeRSz8=_V&^+8R%`Jk16_kPmCOzaXPa0(w%5F*3)mxAfo$|7*+P z+Va|{y z6ib^5u;Vl+VYz8T#YjfNpb|HChG8uRp%^)6;I}S7rlj&Rt$jkL?1^0QxZ>2_^mshs zpgO&`oMD z&8L;ZE!t>2OY?71Yqgl0`z5u{=88K*x2ZK*PEY-c)AV?<6d)3p@Cms6}kprw3LJ+71sS5vepHulum_^~lYMpMkjNDK_G zfZ?mDF#fH66-wl^zBHc#B5ZKMD{5h9NWU77c59%#bk_izAfb#hTQOj#0aJTESFFz6 zl`Y!E4g*EnsE8POp0x;_!h@j_#yY>*+HF3>9D;*?)Vi(q_G>!piNChN>a2tfeqWT3 z&bGy=H30>(76{N1#_MvU#!P}qutYuD6=q=;!SWC~6g6pVyM85pkfCGD&B#O_`9QAI zCXL(2NYvGoR`U65T9wcwgCV1b@gy_5%r)4LCJ^<&d$tV8TGr24hT8=@w*W&uM z*a*{@*)W&TsZB82rLjkWJGbHE)K~-Lwtd4K3WxD`jJ3j#6#Gn{Wudd?7<1p1cWY35 zgpG{V>I&;J~qBxnrgolExtx+`EXS#5K)*l!? z+Gkqr!IbWg?~Imn>FGYx4pZW(CsDxk`*(Wjs0T4uB9SW?Lo1PZgOU9Vduh0?*LhuM zWIX|zf@!2z8~uqyaJ3#ub{sgr;RfUi~fa07)M^#y;QsBW#78Ld`}{9 z@^DUaJA`gCQdyDkNF!`;Y~^EEHblCXX`uBQpAG-hXZ z`f6|q3}P!4#{HmI79(S;VZ8h& znQE)cG1;zNfXM>V$A2?M2!3!m)Zr%A?tHGI!U!nsY0y4I+~e-7hi)}%f9J#QO#R3m z=-nXysk;CliAOrR@JBq-5x}4DlO5A|mcQR|gq+2EN9QSQ<3I0=V7OwP-lk@6z#rKj fL2T#-WWw9GBylVM`j&Cr&fnfLhNEk4&*S*N11*7G delta 1941 zcmZ8hYj9gf72e&emt|RA?Uk-=WLvH!n?#8eSyry2yd&SFZXU8taur-A5qddREa@tG zI8lwzwM%9?lwsm-JM>3~4z$w_oetP_QzthmB!SQpUNh~`!R=(i@P{81G97-wFu=+N zTKKc)?6+t4obT+n`%2{fgDofY$kq4U#P-*gT6Qe$ZY6;Oo&%vlk0%s(x_;S`Ie58u z>2cSYIczOgs>x)gB%mrb&)0X%*9BC;mVBl%qof5?#(26~NL8{*K|m!8_6z6&2Hz4; z5u2xTN}?hl1%tB!D%gNeKzSRuBA}cN>=4lG((g}n9v9Gr4Gaos99yOn`E0Hxpr{SZ z(nsOYW7s;EDU~;lmTVv(pd%PS0Y%hFr|w)zK%-4ZDGQKUL%G&;usL1L7t3DgG*{1; zl|nZsp!5{|2=>99^zTs7UtAQ>C0a!Bux+0go*dQ-s1`H`=!u|Fz~?fRcu7$zL6d-H zf-M5d2F(H~WfJLlF;STbwhHKc&_dfepRp=JL3b!XN4bM=lzxpHffjm`>mt7H6pOE9 znr$oli?weIul|7xLl~lu=vQHM^*8z`^!3bda;^L38ACP}l~RS7q>?D5>t)CPEYru0 z@4>^=XX=3y^q6UqkGyjff-`Fb6$nxYDiU;o{=n3sD-l$t_e?LbdI~MG@Fe}PWr&Ry zvlE`8Tg*FQjGi@%aEd->enE%`c_m%VW#WZIKJ#??MVr{>R1@^k)^Eb`)el<#0%3{X zYx}@>;_VP5tYfcQZ|TYemFR5yvYDma%za^X0G~&&L9Y-me3srI`{DESZ{#$r&@b?b z&hL)6ecN|$+YN}#4o)re#uX9WA!wA|<9EXFGxqZx?gx@Zog(PC8-?Ihlh3#+u<;e%atpQ8)DPER|wxxNop?BHc=FrTS2Qj;kF+S)FkTDXGx z(YY3NnSRG{+&26`no#dPCV{Iw*r&?m0R5-K4M(V3m}o5Ow%SpQS8sZ@3;}HFQwn{z zmq&Ff*_v8ezAv?^%XYA|vLGT=zJ-yGL6!{&LlG{>DZ;UgsQm5YALFDso-Ir(t?F%; z%M};|{6xmZgn`PTZ-Q1z5roMT{cUXt=XqKSA30cKYScfsUWw(1<&BgY}u9IT1EkDbI^Q zqc3#!Hr9xd7ay@4GK`s-%_Z zc|9u-v+@@l0hY1%`C(x6K-AFt1`}eR^RlZ`|nFW zb<6=shrL4tzqrX;OPO3IQO;Y%Y0QbvZ{d%ky5PLkH%{N67kN=RM!vy{)q#ML}Y`pp7`N z;nFUV4PpqJ6Q%qdef@Js&f32Ii9AR=MAEAsqFs$)%iMh3KVN5`iO1Hz(0J&vJ@v_x z4@Ja8v3Ug>5x$KGjW}fniYU^ivKRDkjFXuR-->A|1nI1^$5lCGweQVk%N6zxi~IlY z^H%TDht6I-s_E4Sl{eD?I=J diff --git a/mip/v5/createstubs_min.py b/mip/v5/createstubs_min.py index cca13284d..e01b97706 100644 --- a/mip/v5/createstubs_min.py +++ b/mip/v5/createstubs_min.py @@ -1,19 +1,21 @@ -x='with' -w='pyb' -v='stubber' -u='{}/{}' -t='logging' -s='sys' -r='method' -q='function' -p='bool' -o='str' -n='float' -m='int' +y='with' +x='pyb' +w='stubber' +v='{}/{}' +u='logging' +t='sys' +s='method' +r='function' +q='bool' +p='str' +o='float' +n='int' +m=TypeError l=NameError k=sorted j=NotImplementedError -c='pycom' +d='pycom' +c='-' b=',\n' a='dict' Z='list' @@ -26,10 +28,10 @@ R=len Q=KeyError P=IndexError -O=dir -N=print -M=ImportError -L='family' +O=print +N=ImportError +M='family' +L=dir K=True J='.' I=AttributeError @@ -38,18 +40,19 @@ G='/' E=None F=OSError -D='version' +C='version' B='' -import gc as C,os,sys -from ujson import dumps as d +import gc as D,os,sys +try:from ujson import dumps +except:from json import dumps try:from machine import reset -except M:pass +except N:pass try:from collections import OrderedDict as e -except M:from ucollections import OrderedDict as e +except N:from ucollections import OrderedDict as e __version__='v1.16.2' -y=2 z=2 -A0=[J,'/lib','/sd/lib','/flash/lib','lib'] +A0=2 +A1=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): @@ -57,93 +60,93 @@ def __init__(A,path=E,firmware_id=E): try: if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') except I:pass - A._report=[];A.info=_info();C.collect() + A._report=[];A.info=_info();D.collect() if B:A._fwid=B.lower() - elif A.info[L]==X:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-{ver}-{port}'.format(**A.info) - A._start_free=C.mem_free() + elif A.info[M]==X:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) + else:A._fwid='{family}-v{version}-{port}'.format(**A.info) + A._start_free=D.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) try:f(path+G) - except F:N('error creating stub folder {}'.format(path)) + except F:O('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] - def get_obj_attributes(L,item_instance): - H=item_instance;D=[];J=[] - for A in O(H): - if A.startswith(S)and not A in L.modules:continue + def get_obj_attributes(M,item_instance): + H=item_instance;C=[];J=[] + for A in L(H): + if A.startswith(S)and not A in M.modules:continue try: E=getattr(H,A) try:F=V(type(E)).split("'")[1] except P:F=B - if F in{m,n,o,p,Y,Z,a}:G=1 - elif F in{q,r}:G=2 + if F in{n,o,p,q,Y,Z,a}:G=1 + elif F in{r,s}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,V(E),V(type(E)),E,G)) + C.append((A,V(E),V(type(E)),E,G)) except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + C=k([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,J def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) def create_all_stubs(A): - C.collect() + D.collect() for B in A.modules:A.create_one_stub(B) def create_one_stub(B,module_name): - D=module_name - if D in B.problematic:return A - if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A - try:E=B.create_module_stub(D,H) + C=module_name + if C in B.problematic:return A + if C in B.excluded:return A + H='{}/{}.py'.format(B.path,C.replace(J,G));D.collect();E=A + try:E=B.create_module_stub(C,H) except F:return A - C.collect();return E + D.collect();return E def create_module_stub(I,module_name,file_name=E): - H=file_name;D=module_name - if H is E:O=D.replace(J,S)+'.py';H=I.path+G+O + H=file_name;C=module_name + if H is E:O=C.replace(J,S)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,J) + if G in C:C=C.replace(G,J) L=E - try:L=__import__(D,E,E,'*');T=C.mem_free() - except M:return A + try:L=__import__(C,E,E,'*');T=D.mem_free() + except N:return A f(H) - with W(H,'w')as N:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,L,D,B) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os',s,t,'gc'}: + with W(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,I._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,C,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + if C not in{'os',t,u,'gc'}: try:del L except(F,Q):pass - try:del sys.modules[D] + try:del sys.modules[C] except Q:pass - C.collect();return K + D.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() - if O in K.problematic:return - S,L=K.get_obj_attributes(O) - if L:N(L) + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;C=indent;D.collect() + if N in K.problematic:return + S,L=K.get_obj_attributes(N) + if L:O(L) for(E,J,G,T,f)in S: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and R(D)<=z*4: + if G==""and R(C)<=A0*4: U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=M - A='\n{}class {}({}):\n'.format(D,E,U) - if V:A+=D+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): + A='\n{}class {}({}):\n'.format(C,E,U) + if V:A+=C+' ...\n';H.write(A);return + H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),C+' ',P+1);A=C+' def __init__(self, *argv, **kwargs) -> None:\n';A+=C+' ...\n\n';H.write(A) + elif any(A in G for A in[s,r,'closure']): W=b;X=B if P>0:X='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) - A+=D+' ...\n\n';H.write(A) + if c in G or c in J:A='{}@classmethod\n'.format(C)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(C,E,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(C,E,X,W) + A+=C+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(a,Z): - try:f=os.uname();A[D]=f.release - except(P,I,TypeError):pass - for(g,h,i)in[(b,b,'const'),(c,c,'FAT'),(d,'pybricks.hubs','EV3Brick')]: - try:j=__import__(h,E,E,i);A[L]=g;del j;break - except(M,Q):pass - if A[L]==d:A['release']='2.0.0' - if A[L]==X: - if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if K in A and A[K]: - N=int(A[K]);V=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] - if V:A[Y]=V - A[K]='v{}.{}'.format(N&255,N>>8&3) - A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def A1(info,desc=B): - L='with ';D=info;F=A - for G in[A+'/board_info.csv'for A in A0]: + if'uname'in L(os): + A[F]=U(os.uname()[3]) + if not A[F]:A[F]=U(os.uname()[2]) + elif C in L(sys):A[F]=U(sys.version) + except(I,P,m):pass + if A[C]==B and sys.platform not in(Y,W): + try:c=os.uname();A[C]=c.release + except(P,I,m):pass + for(f,g,h)in[(Z,Z,'const'),(d,d,'FAT'),(a,'pybricks.hubs','EV3Brick')]: + try:i=__import__(g,E,E,h);A[M]=f;del i;break + except(N,Q):pass + if A[M]==a:A['release']='2.0.0' + if A[M]==X: + A[C] + if A[C]and A[C].endswith('.0')and A[C]>='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if J in A and A[J]: + K=int(A[J]);R=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if R:A[V]=R + A[J]='v{}.{}'.format(K&255,K>>8&3) + if A[F]and not A[C].endswith(b):A[C]=A[C]+b + A[S]=f"{A[C]}-{A[F]}"if A[F]else f"{A[C]}";return A +def A2(version): + A=version;B=J.join([str(A)for A in A[:3]]) + if R(A)>3 and A[3]:B+=c+A[3] + return B +def A3(info,desc=B): + L='with ';C=info;F=A + for G in[A+'/board_info.csv'for A in A1]: if g(G): - E=desc or D[H].strip();I=E.rfind(' with') + E=desc or C[H].strip();I=E.rfind(' with') if I!=-1:J=E[:I].strip() else:J=B - if A2(D,E,G,J):F=K;break + if A4(C,E,G,J):F=K;break if not F: - E=desc or D[H].strip() - if L+D[T].upper()in E:E=E.split(L+D[T].upper())[0].strip() - D[H]=E - D[H]=D[H].replace(' ',S);C.collect() -def A2(info,descr,filename,short_descr): + E=desc or C[H].strip() + if L+C[T].upper()in E:E=E.split(L+C[T].upper())[0].strip() + C[H]=E + C[H]=C[H].replace(' ',S);D.collect() +def A4(info,descr,filename,short_descr): D=short_descr;C=info;E=B with W(filename,'r')as J: while 1: @@ -245,7 +253,7 @@ def A2(info,descr,filename,short_descr): I,G=F.split(',')[0].strip(),F.split(',')[1].strip() if I==descr:C[H]=G;return K elif D and I==D: - if x in D:C[H]=G;return K + if y in D:C[H]=G;return K E=G if E:C[H]=E;return K return A @@ -274,11 +282,11 @@ def read_path(): def i(): try:B=bytes('abc',encoding='utf8');C=i.__module__;return A except(j,I):return K -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',X,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,c,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',u,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',X,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',x,d,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',t,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];D.collect();stubber.create_all_stubs();stubber.report() if __name__=='__main__'or i(): - try:A3=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + try:A5=logging.getLogger(w);logging.basicConfig(level=logging.INFO) except l:pass if not g('no_auto_stubber.txt'): - try:C.threshold(4*1024);C.enable() + try:D.threshold(4*1024);D.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_mpy.mpy b/mip/v5/createstubs_mpy.mpy index eceb28c7253b323608835bf4f8b2e58de5c6ea9e..8884012220b45698d21b07bdb7dc3ef4edd60f1b 100644 GIT binary patch delta 2278 zcmZWqZA@F&89wJ+8yjOg$H(T9V8CD;LQPD-7!yL21as5UB#_c#6S5_)KW@N@zv652 zQH%HziZpf87J7bUnx|?OfIZzsUB`VLE|;(8%S)?9v30do zY+XCoQd-0{*~KW27O+{$7ot%y$D?^{C@vi;F7ap%o0FNDnM8VqM+ICXElNDfV`ECp z&t~F0k}$qhNXPPtOqxeI436>WDh4-sl*NWi$xI~AqYMTYd6c#QKaWxt;Nely0&ei= ziUl0v(dD(LwVF6ap0&Tfw71Bkvlh_7qj7A!6iFqLi#!^$fHU+WJX#vT0P-jxPuMjx zF&+u3kdb)Eo;zW|Q7e$KAznyjB{#Gi3YVo!x{2fA^r?C%3;Tht8k_u$O)f9Uk^-8Q`@Xcf(iu zYM9vP)vLTXkQ61Ye4bhi z{qT$Q1%n@k=`}+I&d{E^uflQqUfn%So}fbYnz0+g1^PYHn=JJc=21><$Q$PS8i@r# z$M=*CEXv(*uU7T=GJ>mAB5wE%`W86`-=bS&3eM4fYh>>`1MQxJN4kyxVzGhAvQ<~{ zqfLSY`hDv=%=eV-sIv^%d?#|L`AAOOtk}SJFe>`tv?`I^Nuw3pVa-UCbkV=rUV!V= zU*FYo3+$-Y7%nU^Y5PQFb`^%vl4bgMpJT6wjXprBRWbaeu(Z_T7z zACyNlGC2^dl(z(vT(*I=%CaBH!2p!Y_pxTEmEn7Ka17bO^6mlCqZrNkp{aQuL!8?6VV!PejhKmVcCoD-8`L=qKZ3hj8Y5G%2M=0x?ezK+4Dny~+5(6z98RRNCD!(E_{RjDB=9|-rUU;- zA!sbriBIg4mroHEE@BOyaHD6e8`vxsI;5%jFD-tM069tGP&Dn`(`C&EctAmrcCdrE2xB`JQQi$<<6Lp6yST(i!)0+Um!7&TU)o-I z>PO0k+9;usdETdnQuf0U<4#=VPt`lrLo3Uq$T(TGRs&#|9|cS@);xp!P`MpaVhBh^ zajwtvroExGoF7(a^M5`E@+bX6p!|SswGGUAVP#^4CF6sB$XM**PQY?yB`6r= zbw&wH`t*Qy$;$3-cY95%PN$$z1fO+D}*bhYUUT%_Ag zub>+m`h4?sXrv!D4?;}278fM6vn351>CKjxU{m!^Ew>RY(6`$@)-13gqt~1{n6GX- TUxjdlzU+Dt3e|7A9%=s#N3x5( delta 1989 zcmZ8iYfxLq72Z8pLP7|!T8RsU$HhosDv*MNBEWCMbwV5-cEgoTT8BzPfNV)u(G_4y zsV;atlW97gxSL5j?X*Aom`SJ87DW#D+HK=tw{hQ-wm(WeOrL)`{ozUf^)>AZw~gCB zyJycmXZQQg{q}4r`kSfhaWhEmueSGo<63p-+R+-?ciekC+~xI#`(9eRYEPcH+IHkHDdZ?jQ+SR-%x~F~&HDPi;RE_Mg%>E~*#qmB#1Xe6p{CQxL?MEv z%h!F7zyM?H_39{&vVT?w`53e{<8y4>_5_}0S8NgdVRqA2!m})0^C>*e{#J9#q){l8 zZ`uPGFS0+@ewtJJm}3-prQdPfHs$$g?4`O*8;A1{SFU`DTm-zqHmMK4#_rQ&_;c(r z*Eyb@cf}gNGT`y|9_l%SsMC$6HeHrd1a>Hlus^w8=UczxK7zl_-gP$v%(6eb2hDPv z!V(MAKZU=^mg;-jN~q*UUnW(y3u_TPeKvtmZSB>m^_QUoTl6w}tNsFBVXb1JxMBK$ z8x)uRmbW{Ih_zkKw!ghOV$$isL}_zRuF*H$=vrw#0=jaWfS?T+OeJR><^+jP2-fht5BhcPmZ@M>DG~YZbS%;wH9qD!X`jSGMSH7~9>^ zVWf|CA_}M7Xdwi&-qq@IaL5|(1Yuq!H+qp;BG_P)jUDDmTIZ@`OO2h8AKWykCwh}t zm%`-;E^;8Bi6Db^Mu~NXbEWlsr}{9i6r2h!!DShi^ey&oV?)u{ik_zE9Brm>#s|Na zP5Sg{j4p6_JSt?$FSHTH)70!Xb6t;~=MWX@aeE@@iW0`gji_-$8KF8gKaALT-`S}X zI82*d{yn)-r!~~RhImm{A{Cu3UDptaG{^_-cLx+seHg#U6Yl?WR3 z2^10(7fIEVC#QVErUw&pD%wAsPbDt-gdSn$nM0^g_|cDlGTMr$duAq;si8IZ^D2zqB>rOQ3>-!X7oWj{hNDSX88q}<8?#fm!hfts|&}Wb)&cUouIKL|& z*A05US&;|$jQKB{B&I+g7tcYy78GI+27)~0zTEu&dMGgTE4gleefHx4P*S5f>ol%MiG68xEwH-A+klsJtQQ}6$&2q@ zc@P1vf`=vFkMQqD7_?d8&IkipjP+b1Yoes4yN1YpgcTx?P|$zJdRp4~>oL~yG!C&>TQa=wn_AoP?^$PS zAAZ21t(Wj+w$u77=znJoZ5!CcKHD~gt?UnbHcs_!$%sib> bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - self.log.info( - "Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1) - ) + self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) @@ -197,9 +194,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") - self._report.append( - '{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/")) - ) + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) if module_name not in {"os", "sys", "logging", "gc"}: # try to unload the module unless we use it @@ -214,9 +209,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: gc.collect() return True - def write_object_stub( - self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0 - ): + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: @@ -276,11 +269,7 @@ def write_object_stub( s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - self.log.debug( - "# def {1} function/method/closure, type = '{0}'".format( - item_type_txt, item_name - ) - ) + self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -291,13 +280,11 @@ def write_object_stub( first = "self, " # class method - add function decoration if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format( - indent - ) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) - else: - s = "{}def {}({}*args, **kwargs) -> {}:\n".format( - indent, item_name, first, ret + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format( + indent, item_name, ret ) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) self.log.debug("\n" + s) @@ -324,9 +311,7 @@ def write_object_stub( # https://docs.python.org/3/tutorial/classes.html#item_instance-objects t = "Incomplete" # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format( - indent, item_name, t, item_type_txt, item_repr - ) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -378,9 +363,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" self.log.info( - "Created stubs for {} modules on board {}\nPath: {}".format( - len(self._report), self._fwid, self.path - ) + "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) ) f_name = "{}/{}".format(self.path, filename) self.log.info("Report file: {}".format(f_name)) @@ -439,12 +422,15 @@ def ensure_folder(path: str): def _build(s): - # extract a build nr from a string + # extract build from sys.version or os.uname().version if available + # 'v1.13-103-gb137d064e' + # 'MicroPython v1.23.0-preview.6.g3d0b6276f' if not s: return "" - if " on " in s: - s = s.split(" on ", 1)[0] - return s.split("-")[1] if "-" in s else "" + s = s.split(" on ", 1)[0] if " on " in s else s + s = s.split("; ", 1)[1] if "; " in s else s + b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + return b def _info(): # type:() -> dict[str, str] @@ -469,14 +455,12 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") + info["version"] = version_str(sys.implementation.version) # type: ignore except AttributeError: pass try: _machine = ( - sys.implementation._machine - if "_machine" in dir(sys.implementation) - else os.uname().machine # type: ignore + sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore ) # info["board"] = "with".join(_machine.split("with")[:-1]).strip() info["board"] = _machine @@ -495,19 +479,20 @@ def _info(): # type:() -> dict[str, str] gc.collect() try: - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - if not info["build"] and ";" in sys.version: - # extract build from uname().release if available - info["build"] = _build(sys.version.split(";")[1]) - except (AttributeError, IndexError): + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): pass # avoid build hashes - if info["build"] and len(info["build"]) > 5: - info["build"] = "" + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" if info["version"] == "" and sys.platform not in ("unix", "win32"): try: @@ -533,14 +518,14 @@ def _info(): # type:() -> dict[str, str] info["release"] = "2.0.0" if info["family"] == "micropython": + info["version"] if ( info["version"] and info["version"].endswith(".0") - and info["version"] - >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 and info["version"] <= "1.19.9" ): - # drop the .0 for newer releases + # versions from 1.10.0 to 1.20.0 do not have a micro .0 info["version"] = info["version"][:-2] # spell-checker: disable @@ -564,12 +549,21 @@ def _info(): # type:() -> dict[str, str] info["arch"] = arch # .mpy version.minor info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" # simple to use version[-build] string - info["ver"] = f"v{info['version']}-{info['build']}" if info["build"] else f"v{info['version']}" + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" return info +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + def read_boardname(info, desc: str = ""): found = False for filename in [d + "/board_info.csv" for d in LIBS]: diff --git a/mip/v6/createstubs_db.py b/mip/v6/createstubs_db.py index 7a9761f7e..d176f3714 100644 --- a/mip/v6/createstubs_db.py +++ b/mip/v6/createstubs_db.py @@ -27,7 +27,10 @@ import os import sys -from ujson import dumps +try: + from ujson import dumps +except: + from json import dumps try: from machine import reset # type: ignore @@ -65,9 +68,9 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-{ver}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) else: - self._fwid = "{family}-{ver}-{port}".format(**self.info) + self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore if path: @@ -432,12 +435,15 @@ def ensure_folder(path: str): def _build(s): - # extract a build nr from a string + # extract build from sys.version or os.uname().version if available + # 'v1.13-103-gb137d064e' + # 'MicroPython v1.23.0-preview.6.g3d0b6276f' if not s: return "" - if " on " in s: - s = s.split(" on ", 1)[0] - return s.split("-")[1] if "-" in s else "" + s = s.split(" on ", 1)[0] if " on " in s else s + s = s.split("; ", 1)[1] if "; " in s else s + b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + return b def _info(): # type:() -> dict[str, str] @@ -462,7 +468,7 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") + info["version"] = version_str(sys.implementation.version) # type: ignore except AttributeError: pass try: @@ -484,19 +490,20 @@ def _info(): # type:() -> dict[str, str] gc.collect() try: - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - if not info["build"] and ";" in sys.version: - # extract build from uname().release if available - info["build"] = _build(sys.version.split(";")[1]) - except (AttributeError, IndexError): + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): pass # avoid build hashes - if info["build"] and len(info["build"]) > 5: - info["build"] = "" + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" if info["version"] == "" and sys.platform not in ("unix", "win32"): try: @@ -522,13 +529,14 @@ def _info(): # type:() -> dict[str, str] info["release"] = "2.0.0" if info["family"] == "micropython": + info["version"] if ( info["version"] and info["version"].endswith(".0") and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 and info["version"] <= "1.19.9" ): - # drop the .0 for newer releases + # versions from 1.10.0 to 1.20.0 do not have a micro .0 info["version"] = info["version"][:-2] # spell-checker: disable @@ -552,12 +560,21 @@ def _info(): # type:() -> dict[str, str] info["arch"] = arch # .mpy version.minor info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" # simple to use version[-build] string - info["ver"] = f"v{info['version']}-{info['build']}" if info["build"] else f"v{info['version']}" + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" return info +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + def read_boardname(info, desc: str = ""): found = False for filename in [d + "/board_info.csv" for d in LIBS]: diff --git a/mip/v6/createstubs_db_min.py b/mip/v6/createstubs_db_min.py index 751c0c400..adae0e729 100644 --- a/mip/v6/createstubs_db_min.py +++ b/mip/v6/createstubs_db_min.py @@ -1,16 +1,18 @@ -w='with' -v='stubber' -u='{}/{}' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' +x='with' +w='stubber' +v='{}/{}' +u='method' +t='function' +s='bool' +r='str' +q='float' +p='int' +o=TypeError n=NameError m=sorted l=MemoryError k=NotImplementedError +d='-' c=',\n' b='dict' a='list' @@ -22,11 +24,11 @@ T='_' S=KeyError R=IndexError -Q=dir -P=ImportError -O='family' -N=print -M=len +Q=ImportError +P='family' +O=print +N=len +M=dir L='.' K=open J=True @@ -34,19 +36,20 @@ H='board' G='/' F=None -E='version' -D=False +E=False A=OSError +D='version' C='' import gc as B,os,sys -from ujson import dumps as d +try:from ujson import dumps +except:from json import dumps try:from machine import reset -except P:pass +except Q:pass try:from collections import OrderedDict as e -except P:from ucollections import OrderedDict as e +except Q:from ucollections import OrderedDict as e __version__='v1.16.2' -x=2 y=2 +z=2 f=[L,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: @@ -57,26 +60,26 @@ def __init__(C,path=F,firmware_id=F): except I:pass C._report=[];C.info=_info();B.collect() if D:C._fwid=D.lower() - elif C.info[O]==Y:C._fwid='{family}-{ver}-{port}-{board}'.format(**C.info) - else:C._fwid='{family}-{ver}-{port}'.format(**C.info) + elif C.info[P]==Y:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info) + else:C._fwid='{family}-v{version}-{port}'.format(**C.info) C._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) try:g(path+G) - except A:N('error creating stub folder {}'.format(path)) + except A:O('error creating stub folder {}'.format(path)) C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] def get_obj_attributes(L,item_instance): H=item_instance;D=[];J=[] - for A in Q(H): + for A in M(H): if A.startswith(T)and not A in L.modules:continue try: E=getattr(H,A) try:F=W(type(E)).split("'")[1] except R:F=C - if F in{o,p,q,r,Z,a,b}:G=1 - elif F in{s,t}:G=2 + if F in{p,q,r,s,Z,a,b}:G=1 + elif F in{t,u}:G=2 elif F in'class':G=3 else:G=4 D.append((A,W(E),W(type(E)),E,G)) @@ -88,45 +91,45 @@ def create_all_stubs(A): B.collect() for C in A.modules:A.create_one_stub(C) def create_one_stub(C,module_name): - E=module_name - if E in C.problematic:return D - if E in C.excluded:return D - H='{}/{}.py'.format(C.path,E.replace(L,G));B.collect();F=D - try:F=C.create_module_stub(E,H) - except A:return D + D=module_name + if D in C.problematic:return E + if D in C.excluded:return E + H='{}/{}.py'.format(C.path,D.replace(L,G));B.collect();F=E + try:F=C.create_module_stub(D,H) + except A:return E B.collect();return F def create_module_stub(I,module_name,file_name=F): - H=file_name;E=module_name - if H is F:O=E.replace(L,T)+'.py';H=I.path+G+O + H=file_name;D=module_name + if H is F:O=D.replace(L,T)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in E:E=E.replace(G,L) + if G in D:D=D.replace(G,L) M=F - try:M=__import__(E,F,F,'*');U=B.mem_free() - except P:return D + try:M=__import__(D,F,F,'*');U=B.mem_free() + except Q:return E g(H) - with K(H,'w')as N:Q=X(I.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(E,I._fwid,Q,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,E,C) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(E,H.replace('\\',G))) - if E not in{'os','sys','logging','gc'}: + with K(H,'w')as N:P=X(I.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,D,C) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) + if D not in{'os','sys','logging','gc'}: try:del M except(A,S):pass - try:del sys.modules[E] + try:del sys.modules[D] except S:pass B.collect();return J def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;E=indent;B.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;M='Exception';H=fp;E=indent;B.collect() if P in K.problematic:return R,L=K.get_obj_attributes(P) - if L:N(L) + if L:O(L) for(F,J,G,T,f)in R: - if F in['classmethod','staticmethod','BaseException',O]:continue + if F in['classmethod','staticmethod','BaseException',M]:continue if F[0].isdigit():continue - if G==""and M(E)<=y*4: - U=C;V=F.endswith(O)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=O + if G==""and N(E)<=z*4: + U=C;V=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] + if V:U=M D='\n{}class {}({}):\n'.format(E,F,U) if V:D+=E+' ...\n';H.write(D);return H.write(D);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) - elif any(A in G for A in[t,s,'closure']): + elif any(A in G for A in[u,t,'closure']): W=Y;X=C if Q>0:X='self, ' if c in G or c in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) @@ -135,7 +138,7 @@ def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): elif G=="":0 elif G.startswith("5:A[D]=C - if A[E]==C and sys.platform not in(b,a): - try:g=os.uname();A[E]=g.release - except(R,I,TypeError):pass - for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(f,'pybricks.hubs','EV3Brick')]: - try:k=__import__(i,F,F,j);A[O]=h;del k;break - except(P,S):pass - if A[O]==f:A['release']='2.0.0' - if A[O]==Y: - if A[E]and A[E].endswith('.0')and A[E]>='1.10.0'and A[E]<='1.19.9':A[E]=A[E][:-2] + if'uname'in M(os): + A[E]=V(os.uname()[3]) + if not A[E]:A[E]=V(os.uname()[2]) + elif D in M(sys):A[E]=V(sys.version) + except(I,R,o):pass + if A[D]==C and sys.platform not in(X,W): + try:d=os.uname();A[D]=d.release + except(R,I,o):pass + for(f,g,h)in[(Z,Z,'const'),(a,a,'FAT'),(b,'pybricks.hubs','EV3Brick')]: + try:i=__import__(g,F,F,h);A[P]=f;del i;break + except(Q,S):pass + if A[P]==b:A['release']='2.0.0' + if A[P]==Y: + A[D] + if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if J in A and A[J]: - K=int(A[J]);T=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if T:A[Z]=T + K=int(A[J]);N=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if N:A[T]=N A[J]='v{}.{}'.format(K&255,K>>8&3) - A[W]=f"v{A[E]}-{A[D]}"if A[D]else f"v{A[E]}";return A -def z(info,desc=C): - L='with ';A=info;F=D + if A[E]and not A[D].endswith(c):A[D]=A[D]+c + A[O]=f"{A[D]}-{A[E]}"if A[E]else f"{A[D]}";return A +def A0(version): + A=version;B=L.join([X(A)for A in A[:3]]) + if N(A)>3 and A[3]:B+=d+A[3] + return B +def A1(info,desc=C): + L='with ';A=info;F=E for G in[A+'/board_info.csv'for A in f]: if h(G): - E=desc or A[H].strip();I=E.rfind(' with') - if I!=-1:K=E[:I].strip() + D=desc or A[H].strip();I=D.rfind(' with') + if I!=-1:K=D[:I].strip() else:K=C - if A0(A,E,G,K):F=J;break + if A2(A,D,G,K):F=J;break if not F: - E=desc or A[H].strip() - if L+A[U].upper()in E:E=E.split(L+A[U].upper())[0].strip() - A[H]=E + D=desc or A[H].strip() + if L+A[U].upper()in D:D=D.split(L+A[U].upper())[0].strip() + A[H]=D A[H]=A[H].replace(' ',T);B.collect() -def A0(info,descr,filename,short_descr): - B=short_descr;A=info;E=C +def A2(info,descr,filename,short_descr): + B=short_descr;A=info;D=C with K(filename,'r')as L: while 1: F=L.readline() @@ -243,10 +251,10 @@ def A0(info,descr,filename,short_descr): I,G=F.split(',')[0].strip(),F.split(',')[1].strip() if I==descr:A[H]=G;return J elif B and I==B: - if w in B:A[H]=G;return J - E=G - if E:A[H]=E;return J - return D + if x in B:A[H]=G;return J + D=G + if D:A[H]=D;return J + return E def get_root(): try:B=os.getcwd() except(A,I):B=L @@ -258,56 +266,56 @@ def get_root(): def h(filename): try: if os.stat(filename)[0]>>14:return J - return D - except A:return D + return E + except A:return E def i():sys.exit(1) def read_path(): path=C - if M(sys.argv)==3: + if N(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] else:i() - elif M(sys.argv)==2:i() + elif N(sys.argv)==2:i() return path def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return D + try:A=bytes('abc',encoding='utf8');B=j.__module__;return E except(k,I):return J def main(): L='failed';G='modulelist.done';import machine as O - try:C=K(G,'r+b');N=J - except A:C=K(G,'w+b');N=D + try:C=K(G,'r+b');M=J + except A:C=K(G,'w+b');M=E stubber=Stubber(path=read_path()) - if not N:stubber.clean() - A1(stubber);E={} + if not M:stubber.clean() + A3(stubber);D={} try: with K(G)as C: for F in C.read().split('\n'): F=F.strip();B.collect() - if M(F)>0:P,Q=F.split('=',1);E[P]=Q + if N(F)>0:P,Q=F.split('=',1);D[P]=Q except(A,SyntaxError):pass - B.collect();R=[A for A in stubber.modules if A not in E.keys()];B.collect() + B.collect();R=[A for A in stubber.modules if A not in D.keys()];B.collect() for H in R: - I=D + I=E try:I=stubber.create_one_stub(H) except l:O.reset() - B.collect();E[H]=X(stubber._report[-1]if I else L) + B.collect();D[H]=X(stubber._report[-1]if I else L) with K(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if I else L)) - if E:stubber._report=[A for(B,A)in E.items()if A!=L];stubber.report() -def A1(stubber): + if D:stubber._report=[A for(B,A)in D.items()if A!=L];stubber.report() +def A3(stubber): E='/modulelist.txt';stubber.modules=[] for D in f: try: with K(D+E)as F: - N('DEBUG: list of modules: '+D+E) + O('DEBUG: list of modules: '+D+E) for C in F.read().split('\n'): C=C.strip() - if M(C)>0 and C[0]!='#':stubber.modules.append(C) + if N(C)>0 and C[0]!='#':stubber.modules.append(C) B.collect();break except A:pass if not stubber.modules:stubber.modules=[Y];_log.warn('Could not find modulelist.txt, using default modules') B.collect() if __name__=='__main__'or j(): - try:A2=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + try:A4=logging.getLogger(w);logging.basicConfig(level=logging.INFO) except n:pass if not h('no_auto_stubber.txt'): try:B.threshold(4*1024);B.enable() diff --git a/mip/v6/createstubs_db_mpy.mpy b/mip/v6/createstubs_db_mpy.mpy index deb27e592e68ab067146ec731ba4880e9163f418..99bab72bda685bd3acdc692e67aaef17fb5a7cfa 100644 GIT binary patch delta 6090 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 delta 5877 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 diff --git a/mip/v6/createstubs_lvgl.py b/mip/v6/createstubs_lvgl.py index fe5417871..7e0fd913c 100644 --- a/mip/v6/createstubs_lvgl.py +++ b/mip/v6/createstubs_lvgl.py @@ -12,7 +12,10 @@ import os import sys -from ujson import dumps +try: + from ujson import dumps +except: + from json import dumps try: from machine import reset # type: ignore @@ -50,9 +53,9 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-{ver}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) else: - self._fwid = "{family}-{ver}-{port}".format(**self.info) + self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore if path: @@ -417,12 +420,15 @@ def ensure_folder(path: str): def _build(s): - # extract a build nr from a string + # extract build from sys.version or os.uname().version if available + # 'v1.13-103-gb137d064e' + # 'MicroPython v1.23.0-preview.6.g3d0b6276f' if not s: return "" - if " on " in s: - s = s.split(" on ", 1)[0] - return s.split("-")[1] if "-" in s else "" + s = s.split(" on ", 1)[0] if " on " in s else s + s = s.split("; ", 1)[1] if "; " in s else s + b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + return b def _info(): # type:() -> dict[str, str] @@ -447,7 +453,7 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") + info["version"] = version_str(sys.implementation.version) # type: ignore except AttributeError: pass try: @@ -469,19 +475,20 @@ def _info(): # type:() -> dict[str, str] gc.collect() try: - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - if not info["build"] and ";" in sys.version: - # extract build from uname().release if available - info["build"] = _build(sys.version.split(";")[1]) - except (AttributeError, IndexError): + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): pass # avoid build hashes - if info["build"] and len(info["build"]) > 5: - info["build"] = "" + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" if info["version"] == "" and sys.platform not in ("unix", "win32"): try: @@ -507,13 +514,14 @@ def _info(): # type:() -> dict[str, str] info["release"] = "2.0.0" if info["family"] == "micropython": + info["version"] if ( info["version"] and info["version"].endswith(".0") and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 and info["version"] <= "1.19.9" ): - # drop the .0 for newer releases + # versions from 1.10.0 to 1.20.0 do not have a micro .0 info["version"] = info["version"][:-2] # spell-checker: disable @@ -537,12 +545,21 @@ def _info(): # type:() -> dict[str, str] info["arch"] = arch # .mpy version.minor info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" # simple to use version[-build] string - info["ver"] = f"v{info['version']}-{info['build']}" if info["build"] else f"v{info['version']}" + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" return info +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + def read_boardname(info, desc: str = ""): found = False for filename in [d + "/board_info.csv" for d in LIBS]: diff --git a/mip/v6/createstubs_lvgl_min.py b/mip/v6/createstubs_lvgl_min.py index 24d22c1d8..5412c8895 100644 --- a/mip/v6/createstubs_lvgl_min.py +++ b/mip/v6/createstubs_lvgl_min.py @@ -1,17 +1,19 @@ -u='with' -t='stubber' -s='{}/{}' -r='method' -q='function' -p='bool' -o='str' -n='float' -m='int' -l='micropython' -k=Exception +v='with' +u='stubber' +t='{}/{}' +s='method' +r='function' +q='bool' +p='str' +o='float' +n='int' +m='micropython' +l=Exception +k=TypeError j=NameError i=sorted h=NotImplementedError +b='-' a=',\n' Z='dict' Y='list' @@ -23,10 +25,10 @@ R=len Q=KeyError P=IndexError -O=dir -N=print -M=ImportError -L='family' +O=print +N=ImportError +M='family' +L=dir K=True J='.' I=AttributeError @@ -34,19 +36,20 @@ A=False G='/' E=None -D='version' F=OSError +C='version' B='' -import gc as C,os,sys -from ujson import dumps as b +import gc as D,os,sys +try:from ujson import dumps +except:from json import dumps try:from machine import reset -except M:pass +except N:pass try:from collections import OrderedDict as c -except M:from ucollections import OrderedDict as c +except N:from ucollections import OrderedDict as c __version__='v1.16.2' -v=2 w=2 -x=[J,'/lib','/sd/lib','/flash/lib','lib'] +x=2 +y=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): @@ -54,93 +57,93 @@ def __init__(A,path=E,firmware_id=E): try: if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise h('MicroPython 1.13.0 cannot be stubbed') except I:pass - A._report=[];A.info=_info();C.collect() + A._report=[];A.info=_info();D.collect() if B:A._fwid=B.lower() - elif A.info[L]==l:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-{ver}-{port}'.format(**A.info) - A._start_free=C.mem_free() + elif A.info[M]==m:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) + else:A._fwid='{family}-v{version}-{port}'.format(**A.info) + A._start_free=D.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) try:d(path+G) - except F:N('error creating stub folder {}'.format(path)) + except F:O('error creating stub folder {}'.format(path)) A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] - def get_obj_attributes(L,item_instance): - H=item_instance;D=[];J=[] - for A in O(H): - if A.startswith(S)and not A in L.modules:continue + def get_obj_attributes(M,item_instance): + H=item_instance;C=[];J=[] + for A in L(H): + if A.startswith(S)and not A in M.modules:continue try: E=getattr(H,A) try:F=V(type(E)).split("'")[1] except P:F=B - if F in{m,n,o,p,X,Y,Z}:G=1 - elif F in{q,r}:G=2 + if F in{n,o,p,q,X,Y,Z}:G=1 + elif F in{r,s}:G=2 elif F in'class':G=3 else:G=4 - D.append((A,V(E),V(type(E)),E,G)) + C.append((A,V(E),V(type(E)),E,G)) except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=i([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + C=i([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,J def add_modules(A,modules):A.modules=i(set(A.modules)|set(modules)) def create_all_stubs(A): - C.collect() + D.collect() for B in A.modules:A.create_one_stub(B) def create_one_stub(B,module_name): - D=module_name - if D in B.problematic:return A - if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A - try:E=B.create_module_stub(D,H) + C=module_name + if C in B.problematic:return A + if C in B.excluded:return A + H='{}/{}.py'.format(B.path,C.replace(J,G));D.collect();E=A + try:E=B.create_module_stub(C,H) except F:return A - C.collect();return E + D.collect();return E def create_module_stub(I,module_name,file_name=E): - H=file_name;D=module_name - if H is E:O=D.replace(J,S)+'.py';H=I.path+G+O + H=file_name;C=module_name + if H is E:O=C.replace(J,S)+'.py';H=I.path+G+O else:O=H.split(G)[-1] - if G in D:D=D.replace(G,J) + if G in C:C=C.replace(G,J) L=E - try:L=__import__(D,E,E,'*');T=C.mem_free() - except M:return A + try:L=__import__(C,E,E,'*');T=D.mem_free() + except N:return A d(H) - with W(H,'w')as N:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,L,D,B) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: + with W(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,I._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,C,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + if C not in{'os','sys','logging','gc'}: try:del L except(F,Q):pass - try:del sys.modules[D] + try:del sys.modules[C] except Q:pass - C.collect();return K + D.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;O=object_expr;M='Exception';H=fp;D=indent;C.collect() - if O in K.problematic:return - S,L=K.get_obj_attributes(O) - if L:N(L) + d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;C=indent;D.collect() + if N in K.problematic:return + S,L=K.get_obj_attributes(N) + if L:O(L) for(E,J,G,T,f)in S: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():continue - if G==""and R(D)<=w*4: + if G==""and R(C)<=x*4: U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=M - A='\n{}class {}({}):\n'.format(D,E,U) - if V:A+=D+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): + A='\n{}class {}({}):\n'.format(C,E,U) + if V:A+=C+' ...\n';H.write(A);return + H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),C+' ',P+1);A=C+' def __init__(self, *argv, **kwargs) -> None:\n';A+=C+' ...\n\n';H.write(A) + elif any(A in G for A in[s,r,'closure']): W=b;a=B if P>0:a='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,a,W) - A+=D+' ...\n\n';H.write(A) + if c in G or c in J:A='{}@classmethod\n'.format(C)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(C,E,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(C,E,a,W) + A+=C+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(Z,Y): - try:e=os.uname();A[D]=e.release - except(P,I,TypeError):pass - for(f,g,h)in[(a,a,'const'),(b,b,'FAT'),(d,'pybricks.hubs','EV3Brick')]: - try:i=__import__(g,E,E,h);A[L]=f;del i;break - except(M,Q):pass - if A[L]==d:A['release']='2.0.0' - if A[L]==l: - if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if K in A and A[K]: - N=int(A[K]);V=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] - if V:A[X]=V - A[K]='v{}.{}'.format(N&255,N>>8&3) - A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def y(info,desc=B): - L='with ';D=info;F=A - for G in[A+'/board_info.csv'for A in x]: + if'uname'in L(os): + A[F]=U(os.uname()[3]) + if not A[F]:A[F]=U(os.uname()[2]) + elif C in L(sys):A[F]=U(sys.version) + except(I,P,k):pass + if A[C]==B and sys.platform not in(X,W): + try:d=os.uname();A[C]=d.release + except(P,I,k):pass + for(e,f,g)in[(Y,Y,'const'),(Z,Z,'FAT'),(a,'pybricks.hubs','EV3Brick')]: + try:h=__import__(f,E,E,g);A[M]=e;del h;break + except(N,Q):pass + if A[M]==a:A['release']='2.0.0' + if A[M]==m: + A[C] + if A[C]and A[C].endswith('.0')and A[C]>='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if J in A and A[J]: + K=int(A[J]);R=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if R:A[V]=R + A[J]='v{}.{}'.format(K&255,K>>8&3) + if A[F]and not A[C].endswith(b):A[C]=A[C]+b + A[S]=f"{A[C]}-{A[F]}"if A[F]else f"{A[C]}";return A +def z(version): + A=version;B=J.join([str(A)for A in A[:3]]) + if R(A)>3 and A[3]:B+=b+A[3] + return B +def A0(info,desc=B): + L='with ';C=info;F=A + for G in[A+'/board_info.csv'for A in y]: if e(G): - E=desc or D[H].strip();I=E.rfind(' with') + E=desc or C[H].strip();I=E.rfind(' with') if I!=-1:J=E[:I].strip() else:J=B - if z(D,E,G,J):F=K;break + if A1(C,E,G,J):F=K;break if not F: - E=desc or D[H].strip() - if L+D[T].upper()in E:E=E.split(L+D[T].upper())[0].strip() - D[H]=E - D[H]=D[H].replace(' ',S);C.collect() -def z(info,descr,filename,short_descr): + E=desc or C[H].strip() + if L+C[T].upper()in E:E=E.split(L+C[T].upper())[0].strip() + C[H]=E + C[H]=C[H].replace(' ',S);D.collect() +def A1(info,descr,filename,short_descr): D=short_descr;C=info;E=B with W(filename,'r')as J: while 1: @@ -242,7 +250,7 @@ def z(info,descr,filename,short_descr): I,G=F.split(',')[0].strip(),F.split(',')[1].strip() if I==descr:C[H]=G;return K elif D and I==D: - if u in D:C[H]=G;return K + if v in D:C[H]=G;return K E=G if E:C[H]=E;return K return A @@ -272,18 +280,18 @@ def g(): try:B=bytes('abc',encoding='utf8');C=g.__module__;return A except(h,I):return K def main(): - D='lvgl' + C='lvgl' try:import lvgl as A - except k:return - B=D + except l:return + B=C try:B='lvgl-{0}_{1}_{2}-{3}-{4}'.format(A.version_major(),A.version_minor(),A.version_patch(),A.version_info(),sys.platform) - except k:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) + except l:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) finally:stubber=Stubber(firmware_id=B) - stubber.clean();stubber.modules=['io','lodepng','rtch',D];C.collect();stubber.create_all_stubs();stubber.report() + stubber.clean();stubber.modules=['io','lodepng','rtch',C];D.collect();stubber.create_all_stubs();stubber.report() if __name__=='__main__'or g(): - try:A0=logging.getLogger(t);logging.basicConfig(level=logging.INFO) + try:A2=logging.getLogger(u);logging.basicConfig(level=logging.INFO) except j:pass if not e('no_auto_stubber.txt'): - try:C.threshold(4*1024);C.enable() + try:D.threshold(4*1024);D.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_lvgl_mpy.mpy b/mip/v6/createstubs_lvgl_mpy.mpy index cecb4fb0b5c3041df3d37a53dfc7496bc7c07a2a..e84a7d7d40a8b25390838d57be36781d5a8835af 100644 GIT binary patch delta 5546 zcmZuVTTmQVcHKS0Q-E&ww3>lI8br?wFarXHp@pm$G%aZ~NS4NEkVg{2WWIaLXsc5RdFR=oFz)tmMi;{a+&x$m2-Q* zt1X9uzW1JU?mf?Y&bj>M-Y?s759e}T+VVke)FIS!AG{pp^FR3DU(1|3D>+&%T;>XU z2QQr&;z<4Q$iU^nfwA!+K2?!Be5H>od~@_-bC@d`8@$v%H1;M}cwz9;TW@pY-}6=D zWx^lV6<)nofAt#Y#6RI34&u)CMy_ydaP%ymTu@laW*lv&jsjeDjEr94GPAjT zd~4O!Gp}D9yl~}O{pG7`J5c)Jp^;G>`i5Q~>A%M1l>eA0b0FXAF#qn|x_=OOpWp9i ze|~>}{jAN_R{@_tfM_4Wo0}S1)g6s~pRcj*y=ym%`YUf%_E+91zFB-TzrW3QD}Uft zL8CXQ*6dY@pzI+I1^S6ofdP`Ez!{ROjFCJA-XQr3oFxScn1iHHfpcVo0_R28qre3b zE-G+IgdqinMfiyVBO<)1z$htF;4MHik3=nO`^3k5o9j!BoNYgNIZ#cMB#Ft8wXH0_Y;(9R)TX93`%fTf;S|%BEj1d zjMe9@7zRAmPt8hW5}c_Qa7mx)hi6R!bvVEARM&4lMWfeGBOB!L0<)R9U=9XntS#%e zlg|!{Q%I=Fa_jWuJGySK~HQ8QUsqH-OmmdNwt7BlDsT(vq-*2|BLGqjD)#N zgeR~q%tt8y(EP#YQ$Zmm(ENi%@ESy{ZnRi$r?il^67p^WuWNiqQ@TOc>r$_YMbJkp ztnP`Mi4?5~5@^5>++-ccvn61Wv5AS_m5%WL9pTaVXm(oDUILh|tYpnPKStNvxxrkR zkf9Mhn$(-)sXwedy#*Snn})1YRdsbVVg~b5~<^LyJ23F#RYaQTacNo~bN13>ASu^Xg+J0gKe>)rWd#M&8Nf;LXHi z9H&-{LpHe!WQdaL=`O>%)b=Ks@2)l|Bbp(aA1QOjK zdC-$nT_?Nk#Nt?k|IQ1=sejz{vHv{mpvAPFZlevfkv3Ux?G1*4P0jV=%`U|}6=@22 zxBBWmYS|KjT~7$?emebZ@>2qPK1+W-^~L&O_fcSs1U;TYO@gReqwtGgeqtQJyzmLy z>EqtczjZd|1V})v_5`GW%SQ<8CD2BoeLm#GjrtZJ!GH!`<8UGRJ!<)~@pBU-%727G zODk@E|F!XFxO4|(ACXVZYy7@4HX+b~(-L-|L0}(&{UOInV3Ti?(J>#8Rgc{Ik&pOf z%@I%#mhdSb5je2=O+fh&ZSPaiobl8TQ|5*beG-AF+?w$bEk{7=gX4$fGBZo7e@Z19 z_IWBfyhvxHF#@rW<1|Y=#@E(dpp?nyzGwZ)KtVbK?peQQrDOlBPh2sMt6NYMjaR){ ziApucYCzGCsFm5Z+gGYNQAQ@;q2H5F|2Ob^Om*wB(V>5iQ+DeQV>bL7oZr5VIXh6s z*ebp%wN09+JTx(%0!EkUrV&f?uie6j9U`as)Gaw!R zc9UXO(q`+=Yn#}uS|E^Eob2r^ewda=Gptq!3wl#J^>bHL0f~mAM)M}s2BuZ<- z;`)_}c4Bs!%x0Hu5ApD1h8<3eA0efu*X$G@Bk)9KdP;L3SbC(_4<5i~Qbiq)oGK>!B0R9xU>y#Z z+04w62z7WlF>#jmNzmVi;-3Eh$&p$OFws)9al+|_6I3$c9F182T%YNP+5EESBH^S> z2Q^hCa1zO^bXKrl8+?a@yTX=cD6g_IJ~bF* zn&MIHaMlNptj7mmns#YcLV}iM%$bGgrtQpFv8pV^iKT;tSx1mt$H&|O^ABp8N_M~* z>l3w_ytFXUfmP0(N>8j9ofGoTG-!gA(Ay^-kX;BmgdnmDVPL~1@QUui8_K{Eyv5oP z{aAL6G-iU8q7nvOoJ>tMeov0=wH|uCUSD|Iww)?Y8XL4Kv#vqg9o`-Z@9}PJY6u0q zt##gDZOd-b_CR$kkoHBQKO`NGi1C>0TO#|PkONOi^cgw$sYJ``3NZD@T%Fh&_Mz0a zcc}Y5o6q(k>d?JDa#*6GjfCrLm}8$A^xbFk_gG)?GV8YvkR$W=y7f~CnqJ1$QMP&+ zS0uh{?4M$*wx}pww7Hc=_<7`%EjH_2Z1fy?MWRKFAi}R;tIOniMUSHKSvy?$`G>ei z?EVlff(Ap&9MiaY39fe&Gx4K+3H{Z%9{~^O9Vq$yT(?~T(StcZRKWF{Bn{28TD{gn zM-P)Oc1k%DXh7PL73D?(#lPP@e?QT2#Dw6R4NXm~ADW5PVxF1DO{MP33B@1jVzk)>LjuAc}vDWD|@;d1wDbh~{$QkkmIZFmZ8+_88?-E$|UB*72YksDioReF9 zQWcor`lQ?6-S}1$(1mDy?W}Jz40sKNcu*?h)v?<#L4P6cn^7q zwr3mc-`EYdS-2qOBQbW?k<=euxFZIJpn|H_f7OO+TEf2VYQ48QK!z75u&tFIg*l0C zX3v$*$I|s_>;^uu()$XqFBR>OUYe1ALPj+H$*lQnjWJacJ=vF*n=luNqy8$1J?I7p~^sDci7(;tj|1} zz~sT!zbed37js-$GFF56j}vFU$9Cs>ty1oJFop# za6`e}a$neA+?rsXWgDzY1oCDlB+^)^@pHm;+PtAt$0WQ1}Ld+;GGYFv^4HrXx$@1e_@Yb_cRZWZ9K+3Gah?vY!Bn+YgtUY4Z|1~1~Y~Myao?u`Tj60 zET7%=03FLpD^|Wlr~J9oDW^oyDe`#yh1m~mz`%Y+S}A+poI~!%DUou~X-WR%Pn3Ey zHp?op?0)sC>Q&XNSFfs`zit1kjrrU21ut9mQGWEJc=V%R{zH+}Boy}@JALHL&>b-) zvAUsu7pw9h&g7v2saBHK4+W*6vXYBeuQy%2F684VNSBAcmZ&6M$^5HyM{*!$=(O`u znRG(fFC7=y3h9{8CmkI!^FyT`X@>xpq_>3a(sp6!TE1tsWD19*&4OeIQimY*3sOp; zeSH@P2G1WmbGoljkS+?+dqQ*GrWT=%oE?X@7Q|)+VIb}<6@K6taD``2DM-e{Rkyhy64@=~@e87t4xb|!P^ z71jb?>?O67l{3mbj6zsu#Y7`M;wOQSlQL9SheCo?b+j(IJ1mg;h(zndB5e&zbamK4 z*UL<85W839(UV~(Js-}em%;_~YPgVI3m4HF;bID682y|tvr5u1*AbOLj0ooMZ7b@P zVT~G+A*G9yRq;t9X~Mz1QfESTGjM8QGxAkUh=?6Wqf2GBRBf*Pm7t4B4z}nEoNq32 zLViR@##1GCb{DR!|6tXJ@@?WDxLx>x{QipL?H?51E%FbbDR@*)Qcu}(nGyVLkh)h1 z6qe$~pbmEijkq;%hcSklI2kwSq|j`00K-X_S#`J|g3Nq9M`C2TG?7CXUMk=99=_|n zVT>ZQru66JJ6qIYDRY4rO6^E(?a;4Xs^wARy5R01K@Fk>mqWR-KEg+jf)3b?4#=3>GAalNj3Yp*T9Qs39rR5ljh<#mu6rYT#TNSv9Hpa%#B4xhA zFoMy$qQU|rV-aaKx=ew~3acBBpmKFBfuJrz;%Tf5jT2v(ThKW5DcUrlz%d1mD)5d1 zM-+HhfeQ+pZz`BKO?YM;K=Occp-I9iduD8(un5#6eDj%M+w5DJSCCO)!Wo%v{kgjJz%YYDs!t#&thtglO%PTL7}D}g>;>}X9lt43q$ zpj-k6@g8>%-%6xduz^4$2BBi_M%fC)x$n67@pMG|kBErQN4K-!CKtGw%kBv->f?NU zT}!O#VHKM2M3csCvJBWPco8g3_BuGP?9Qdr%lf{GePZJg6L>TS$(k{$lSh<#o`^N?1K> zun!F_Q7SC*&t~svPB2D=M4;v66RwO0<=D$dMps5%%TJ&z1 zqm>G)8AS+x3A9G?X1Pv&EplOlne|6&TJcnp3S7z%2uGwX*0yI#A?ovBu$|MEVsPo% zE3%3}M3LZ~j~JbTluR-xVVmOl}3N25GSXpj+_JM!Wa-@Eiix0{%yb z7o~n{e(FB~IxAu!*2tRJO4e)-4xM%{w|XP3A@2%bQ>EsaC9w7>fpyQuo{xM^VEq^A zFGs&xlrn{u;%OW46mFpo_tYYN{mp0Q7QFkPp@%;0>-w9#7H5D2>p*&n@RQm`9Eo{^UoXGx4tzypnjRgu^|AYr-_||`YZ~i5qX9B8^sQVx2VyA}# z1lkdFae(j`_e+-%_*VK|s|iRs9nm@u|8aKoOVl(N74NFaH>zAEVQK6df5) zy#l%aKlUjEI#oU6Bf3*U?#)9VsvaxHYka{J*5a$I5kv(u!~lUUA;;T1xtQPElYwR2 zzViF_@61jD(LnixzjD4~^Mp^HH}`1OXo@as-ke3tbjQm8HFjta{IRa z#6IIY@K;*eiaE2x_zFROvtyX?{u<#sH!v>;JX|gHd9vv%m&c9}=pwK!ls|9A$8#EF zpNDHO{$O*?^9oOK@1nEJlZ_4n+Y!}I;4MVsumef`fr^Ed6+VxZSXe#a^AOlcAWmQx zF8aL7f;Jm~>F`=0^$~#v;a(QgjLDwi2VbE*9eKFU(Xj>c;4CaU7@iWQn|JBQe{F zp&VnGxlJmjOU?du8|KS3p*30A+@iED%`D!jXcs1ykz8U~`3QyY$#CJU=rMAZ z_gP)?6GZOKjE(9JM7tgvO*l_-rd;Z%;*xmc`p?;%TVI%6$mrDkxkAh{cgzKQn0n3r zI|BP=(s(um_M-p}DU3FXsLC_a9}$5!0E+||M95m?ks7hwmMcu|S0L4o1|Rr;`8m55 z;Krp`%Wz&f>}9TNaFm7Z-!^4BVp(Zf!5kXN@SWQtSjo_tKckuEkPNCjx5qZ^!Mo*BP3UhGdBH}!DtK7<+Mid>( zJKE|m9^jhNo(EWTp`RCBb(bzoDR8BSbpM}q-NxRDpCBzR%`iG}BU2MS+0s^mZQHBT zws=vLlT*A3W3cl!IJ#L`ozs6a5fP{E_e|YSbnIBfu^({mkQf-6z+A^=F@a=ZBkr)+Ibg?#7+uxT`MA3FHH9kh&61()a)cftX)W-9;)mo-8pZ%v`s3s8D5caoP4NaNH!`QN_v)Q6> z0h`TzPbbuOaT}8z9mbdTB!=(BMKcyAkhN*w^Uv?6=gipD7&i?!nHn|s-Nyuwz)Oi8 z@N0yrS)<+fTMNs_xEULN#gC!jO5HwtSh-~XcjKzs*44pi5k~iWy6`Zj^3;h@&2J^| zi;Ev(p&OnaCYQ+-OvH!?Is3Y5rlX~}f|uHv_HKx|atU{HvfU^0!dRV7-K=RNSDAKC ztZiM1&o*Qp=G*!32mXeziZHL@1AxEVUVje6Q}2=dYxkT=g?b&b#o=~MxpL!Pfv>5t zxh{hKdWbg`@1+$HZ_b%KS6b*5{z^u#JLk=<9K#Y1@o9SvUtPxTSL_TkWDeIpoU(2n zHA_IeSLR(2U9P}30{FJTt|<>+W2ixNgL67-Ai4waUGvHvMZABAr|us7H>n)*?kg}aklfvVpDn?T7T3AHNq1WHFDOnB6bZ&VlNMgnC7uv3 dict[str, str] @@ -453,7 +459,7 @@ def _info(): # type:() -> dict[str, str] elif info["port"] == "linux": info["port"] = "unix" try: - info["version"] = ".".join([str(n) for n in sys.implementation.version]).rstrip(".") + info["version"] = version_str(sys.implementation.version) # type: ignore except AttributeError: pass try: @@ -475,19 +481,20 @@ def _info(): # type:() -> dict[str, str] gc.collect() try: - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - if not info["build"] and ";" in sys.version: - # extract build from uname().release if available - info["build"] = _build(sys.version.split(";")[1]) - except (AttributeError, IndexError): + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): pass # avoid build hashes - if info["build"] and len(info["build"]) > 5: - info["build"] = "" + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" if info["version"] == "" and sys.platform not in ("unix", "win32"): try: @@ -513,13 +520,14 @@ def _info(): # type:() -> dict[str, str] info["release"] = "2.0.0" if info["family"] == "micropython": + info["version"] if ( info["version"] and info["version"].endswith(".0") and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 and info["version"] <= "1.19.9" ): - # drop the .0 for newer releases + # versions from 1.10.0 to 1.20.0 do not have a micro .0 info["version"] = info["version"][:-2] # spell-checker: disable @@ -543,12 +551,21 @@ def _info(): # type:() -> dict[str, str] info["arch"] = arch # .mpy version.minor info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" # simple to use version[-build] string - info["ver"] = f"v{info['version']}-{info['build']}" if info["build"] else f"v{info['version']}" + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" return info +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + def read_boardname(info, desc: str = ""): found = False for filename in [d + "/board_info.csv" for d in LIBS]: diff --git a/mip/v6/createstubs_mem_min.py b/mip/v6/createstubs_mem_min.py index 139f88f81..ef72491b9 100644 --- a/mip/v6/createstubs_mem_min.py +++ b/mip/v6/createstubs_mem_min.py @@ -1,15 +1,17 @@ -v='with' -u='stubber' -t='{}/{}' -s='method' -r='function' -q='bool' -p='str' -o='float' -n='int' +w='with' +v='stubber' +u='{}/{}' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n=TypeError m=NameError l=sorted k=NotImplementedError +d='-' c=',\n' b='dict' a='list' @@ -22,10 +24,10 @@ S=KeyError R=open Q=IndexError -P=dir -O=ImportError -N='family' -M=len +P=ImportError +O='family' +N=len +M=dir L=print K=True J='.' @@ -34,31 +36,32 @@ A=False G='/' E=None -D='version' F=OSError -B='' -import gc as C,os,sys -from ujson import dumps as d +D='version' +C='' +import gc as B,os,sys +try:from ujson import dumps +except:from json import dumps try:from machine import reset -except O:pass +except P:pass try:from collections import OrderedDict as e -except O:from ucollections import OrderedDict as e +except P:from ucollections import OrderedDict as e __version__='v1.16.2' -w=2 x=2 +y=2 f=[J,'/lib','/sd/lib','/flash/lib','lib'] from time import sleep class Stubber: def __init__(A,path=E,firmware_id=E): - B=firmware_id + C=firmware_id try: if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') except I:pass - A._report=[];A.info=_info();C.collect() - if B:A._fwid=B.lower() - elif A.info[N]==Y:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-{ver}-{port}'.format(**A.info) - A._start_free=C.mem_free() + A._report=[];A.info=_info();B.collect() + if C:A._fwid=C.lower() + elif A.info[O]==Y:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) + else:A._fwid='{family}-v{version}-{port}'.format(**A.info) + A._start_free=B.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() @@ -68,80 +71,80 @@ def __init__(A,path=E,firmware_id=E): A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] def get_obj_attributes(L,item_instance): H=item_instance;D=[];J=[] - for A in P(H): + for A in M(H): if A.startswith(T)and not A in L.modules:continue try: E=getattr(H,A) try:F=W(type(E)).split("'")[1] - except Q:F=B - if F in{n,o,p,q,Z,a,b}:G=1 - elif F in{r,s}:G=2 + except Q:F=C + if F in{o,p,q,r,Z,a,b}:G=1 + elif F in{s,t}:G=2 elif F in'class':G=3 else:G=4 D.append((A,W(E),W(type(E)),E,G)) except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) except MemoryError as K:sleep(1);reset() - D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J + D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) def create_all_stubs(A): - C.collect() - for B in A.modules:A.create_one_stub(B) - def create_one_stub(B,module_name): + B.collect() + for C in A.modules:A.create_one_stub(C) + def create_one_stub(C,module_name): D=module_name - if D in B.problematic:return A - if D in B.excluded:return A - H='{}/{}.py'.format(B.path,D.replace(J,G));C.collect();E=A - try:E=B.create_module_stub(D,H) + if D in C.problematic:return A + if D in C.excluded:return A + H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=A + try:E=C.create_module_stub(D,H) except F:return A - C.collect();return E + B.collect();return E def create_module_stub(I,module_name,file_name=E): H=file_name;D=module_name if H is E:N=D.replace(J,T)+'.py';H=I.path+G+N else:N=H.split(G)[-1] if G in D:D=D.replace(G,J) L=E - try:L=__import__(D,E,E,'*');U=C.mem_free() - except O:return A + try:L=__import__(D,E,E,'*');U=B.mem_free() + except P:return A g(H) - with R(H,'w')as M:P=X(I.info).replace('OrderedDict(',B).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,B) + with R(H,'w')as M:O=X(I.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,O,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,C) I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del L except(F,S):pass try:del sys.modules[D] except S:pass - C.collect();return K + B.collect();return K def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;C.collect() + d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() if P in K.problematic:return - R,N=K.get_obj_attributes(P) - if N:L(N) + R,M=K.get_obj_attributes(P) + if M:L(M) for(E,J,G,T,f)in R: if E in['classmethod','staticmethod','BaseException',O]:continue if E[0].isdigit():continue - if G==""and M(D)<=x*4: - U=B;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if G==""and N(D)<=y*4: + U=C;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=O A='\n{}class {}({}):\n'.format(D,E,U) if V:A+=D+' ...\n';H.write(A);return H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[s,r,'closure']): - W=Y;X=B + elif any(A in G for A in[t,s,'closure']): + W=Y;X=C if Q>0:X='self, ' if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) A+=D+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(b,a): - try:g=os.uname();A[D]=g.release - except(Q,I,TypeError):pass - for(h,i,j)in[(c,c,'const'),(d,d,'FAT'),(f,'pybricks.hubs','EV3Brick')]: - try:k=__import__(i,E,E,j);A[N]=h;del k;break - except(O,S):pass - if A[N]==f:A['release']='2.0.0' - if A[N]==Y: + if'uname'in M(os): + A[F]=V(os.uname()[3]) + if not A[F]:A[F]=V(os.uname()[2]) + elif D in M(sys):A[F]=V(sys.version) + except(I,Q,n):pass + if A[D]==C and sys.platform not in(X,W): + try:d=os.uname();A[D]=d.release + except(Q,I,n):pass + for(f,g,h)in[(Z,Z,'const'),(a,a,'FAT'),(b,'pybricks.hubs','EV3Brick')]: + try:i=__import__(g,E,E,h);A[O]=f;del i;break + except(P,S):pass + if A[O]==b:A['release']='2.0.0' + if A[O]==Y: + A[D] if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if K in A and A[K]: - L=int(A[K]);T=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][L>>10] - if T:A[Z]=T - A[K]='v{}.{}'.format(L&255,L>>8&3) - A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def y(info,desc=B): + if J in A and A[J]: + K=int(A[J]);N=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if N:A[T]=N + A[J]='v{}.{}'.format(K&255,K>>8&3) + if A[F]and not A[D].endswith(c):A[D]=A[D]+c + A[R]=f"{A[D]}-{A[F]}"if A[F]else f"{A[D]}";return A +def z(version): + A=version;B=J.join([X(A)for A in A[:3]]) + if N(A)>3 and A[3]:B+=d+A[3] + return B +def A0(info,desc=C): L='with ';D=info;F=A for G in[A+'/board_info.csv'for A in f]: if h(G): E=desc or D[H].strip();I=E.rfind(' with') if I!=-1:J=E[:I].strip() - else:J=B - if z(D,E,G,J):F=K;break + else:J=C + if A1(D,E,G,J):F=K;break if not F: E=desc or D[H].strip() if L+D[U].upper()in E:E=E.split(L+D[U].upper())[0].strip() D[H]=E - D[H]=D[H].replace(' ',T);C.collect() -def z(info,descr,filename,short_descr): - D=short_descr;C=info;E=B + D[H]=D[H].replace(' ',T);B.collect() +def A1(info,descr,filename,short_descr): + D=short_descr;B=info;E=C with R(filename,'r')as J: while 1: F=J.readline() if not F:break I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:C[H]=G;return K + if I==descr:B[H]=G;return K elif D and I==D: - if v in D:C[H]=G;return K + if w in D:B[H]=G;return K E=G - if E:C[H]=E;return K + if E:B[H]=E;return K return A def get_root(): try:A=os.getcwd() @@ -261,35 +269,35 @@ def h(filename): except F:return A def i():sys.exit(1) def read_path(): - path=B - if M(sys.argv)==3: + path=C + if N(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] else:i() - elif M(sys.argv)==2:i() + elif N(sys.argv)==2:i() return path def j(): try:B=bytes('abc',encoding='utf8');C=j.__module__;return A except(k,I):return K def main(): E='/modulelist.txt';stubber=Stubber(path=read_path());stubber.clean();stubber.modules=[] - for B in f: + for C in f: try: - F=C.mem_free() - with R(B+E)as D: - L('Debug: List of modules: '+B+E);A=D.readline() + F=B.mem_free() + with R(C+E)as D: + L('Debug: List of modules: '+C+E);A=D.readline() while A: A=A.strip() - if M(A)>0 and A[0]!='#':stubber.modules.append(A) + if N(A)>0 and A[0]!='#':stubber.modules.append(A) A=D.readline() - C.collect();L('Debug: Used memory to load modulelist.txt: '+X(F-C.mem_free())+' bytes');break + B.collect();L('Debug: Used memory to load modulelist.txt: '+X(F-B.mem_free())+' bytes');break except Exception:pass if not stubber.modules:stubber.modules=[Y] - C.collect();stubber.create_all_stubs();stubber.report() + B.collect();stubber.create_all_stubs();stubber.report() if __name__=='__main__'or j(): - try:A0=logging.getLogger(u);logging.basicConfig(level=logging.INFO) + try:A2=logging.getLogger(v);logging.basicConfig(level=logging.INFO) except m:pass if not h('no_auto_stubber.txt'): - try:C.threshold(4*1024);C.enable() + try:B.threshold(4*1024);B.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_mem_mpy.mpy b/mip/v6/createstubs_mem_mpy.mpy index 72c6790b977ce0f74604ec76b3c96bad2166c99b..bee999ab59698d1bb2b50c1e594a53677a6f0684 100644 GIT binary patch delta 5683 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 delta 5477 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"and R(D)<=z*4: + if G==""and R(C)<=A0*4: U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if V:U=M - A='\n{}class {}({}):\n'.format(D,E,U) - if V:A+=D+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',P+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[r,q,'closure']): + A='\n{}class {}({}):\n'.format(C,E,U) + if V:A+=C+' ...\n';H.write(A);return + H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),C+' ',P+1);A=C+' def __init__(self, *argv, **kwargs) -> None:\n';A+=C+' ...\n\n';H.write(A) + elif any(A in G for A in[s,r,'closure']): W=b;X=B if P>0:X='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) - A+=D+' ...\n\n';H.write(A) + if c in G or c in J:A='{}@classmethod\n'.format(C)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(C,E,W) + else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(C,E,X,W) + A+=C+' ...\n\n';H.write(A) elif G=="":0 elif G.startswith("5:A[F]=B - if A[D]==B and sys.platform not in(a,Z): - try:f=os.uname();A[D]=f.release - except(P,I,TypeError):pass - for(g,h,i)in[(b,b,'const'),(c,c,'FAT'),(d,'pybricks.hubs','EV3Brick')]: - try:j=__import__(h,E,E,i);A[L]=g;del j;break - except(M,Q):pass - if A[L]==d:A['release']='2.0.0' - if A[L]==X: - if A[D]and A[D].endswith('.0')and A[D]>='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if K in A and A[K]: - N=int(A[K]);V=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][N>>10] - if V:A[Y]=V - A[K]='v{}.{}'.format(N&255,N>>8&3) - A[W]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A -def A1(info,desc=B): - L='with ';D=info;F=A - for G in[A+'/board_info.csv'for A in A0]: + if'uname'in L(os): + A[F]=U(os.uname()[3]) + if not A[F]:A[F]=U(os.uname()[2]) + elif C in L(sys):A[F]=U(sys.version) + except(I,P,m):pass + if A[C]==B and sys.platform not in(Y,W): + try:c=os.uname();A[C]=c.release + except(P,I,m):pass + for(f,g,h)in[(Z,Z,'const'),(d,d,'FAT'),(a,'pybricks.hubs','EV3Brick')]: + try:i=__import__(g,E,E,h);A[M]=f;del i;break + except(N,Q):pass + if A[M]==a:A['release']='2.0.0' + if A[M]==X: + A[C] + if A[C]and A[C].endswith('.0')and A[C]>='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if J in A and A[J]: + K=int(A[J]);R=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] + if R:A[V]=R + A[J]='v{}.{}'.format(K&255,K>>8&3) + if A[F]and not A[C].endswith(b):A[C]=A[C]+b + A[S]=f"{A[C]}-{A[F]}"if A[F]else f"{A[C]}";return A +def A2(version): + A=version;B=J.join([str(A)for A in A[:3]]) + if R(A)>3 and A[3]:B+=c+A[3] + return B +def A3(info,desc=B): + L='with ';C=info;F=A + for G in[A+'/board_info.csv'for A in A1]: if g(G): - E=desc or D[H].strip();I=E.rfind(' with') + E=desc or C[H].strip();I=E.rfind(' with') if I!=-1:J=E[:I].strip() else:J=B - if A2(D,E,G,J):F=K;break + if A4(C,E,G,J):F=K;break if not F: - E=desc or D[H].strip() - if L+D[T].upper()in E:E=E.split(L+D[T].upper())[0].strip() - D[H]=E - D[H]=D[H].replace(' ',S);C.collect() -def A2(info,descr,filename,short_descr): + E=desc or C[H].strip() + if L+C[T].upper()in E:E=E.split(L+C[T].upper())[0].strip() + C[H]=E + C[H]=C[H].replace(' ',S);D.collect() +def A4(info,descr,filename,short_descr): D=short_descr;C=info;E=B with W(filename,'r')as J: while 1: @@ -245,7 +253,7 @@ def A2(info,descr,filename,short_descr): I,G=F.split(',')[0].strip(),F.split(',')[1].strip() if I==descr:C[H]=G;return K elif D and I==D: - if x in D:C[H]=G;return K + if y in D:C[H]=G;return K E=G if E:C[H]=E;return K return A @@ -274,11 +282,11 @@ def read_path(): def i(): try:B=bytes('abc',encoding='utf8');C=i.__module__;return A except(j,I):return K -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',t,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',X,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',w,c,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',s,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',D,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];C.collect();stubber.create_all_stubs();stubber.report() +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',u,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',X,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',x,d,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',t,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];D.collect();stubber.create_all_stubs();stubber.report() if __name__=='__main__'or i(): - try:A3=logging.getLogger(v);logging.basicConfig(level=logging.INFO) + try:A5=logging.getLogger(w);logging.basicConfig(level=logging.INFO) except l:pass if not g('no_auto_stubber.txt'): - try:C.threshold(4*1024);C.enable() + try:D.threshold(4*1024);D.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_mpy.mpy b/mip/v6/createstubs_mpy.mpy index ed8c45959117acf6d67e8b86389380d30ea5c08c..4307abc5a4b28003a9be2e0a221147d403eee6b3 100644 GIT binary patch delta 5936 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 delta 5747 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 Nvtumapy3dS{SP9Vb2k70 From c2fac87deb0bb3a28eacdd481560e7d414266b1c Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Sun, 21 Jan 2024 21:48:09 +0100 Subject: [PATCH 32/68] Fix encoding issues in subprocess.run calls Signed-off-by: Jos Verlinde --- src/stubber/basicgit.py | 4 +-- src/stubber/minify.py | 56 ++++++++++++++---------------- src/stubber/publish/stubpackage.py | 1 + src/stubber/utils/post.py | 2 +- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/stubber/basicgit.py b/src/stubber/basicgit.py index 3d327dc35..58f7d92e9 100644 --- a/src/stubber/basicgit.py +++ b/src/stubber/basicgit.py @@ -36,10 +36,10 @@ def _run_local_git( if isinstance(repo, str): repo = Path(repo) result = subprocess.run( - cmd, capture_output=capture_output, check=True, cwd=repo.absolute().as_posix() + cmd, capture_output=capture_output, check=True, cwd=repo.absolute().as_posix(),encoding="utf-8" ) else: - result = subprocess.run(cmd, capture_output=capture_output, check=True) + result = subprocess.run(cmd, capture_output=capture_output, check=True,encoding="utf-8") except (NotADirectoryError, FileNotFoundError) as e: # pragma: no cover return None except subprocess.CalledProcessError as e: # pragma: no cover diff --git a/src/stubber/minify.py b/src/stubber/minify.py index 98922a939..7889dba52 100644 --- a/src/stubber/minify.py +++ b/src/stubber/minify.py @@ -198,9 +198,7 @@ def minify_script(source_script: StubSource, keep_report: bool = True, diff: boo elif isinstance(source_script, str): # type: ignore source_content = source_script else: - raise TypeError( - f"source_script must be str, Path, or file-like object, not {type(source_script)}" - ) + raise TypeError(f"source_script must be str, Path, or file-like object, not {type(source_script)}") if not source_content: raise ValueError("No source content") @@ -256,30 +254,31 @@ def minify_script(source_script: StubSource, keep_report: bool = True, diff: boo with open("tmp_minified.py", "w+") as f: f.write(content) - source = python_minifier.minify( - content, - filename=getattr(source_script, "name", None), - combine_imports=True, - remove_literal_statements=True, # no Docstrings - remove_annotations=True, # not used runtime anyways - hoist_literals=True, # remove redundant strings - rename_locals=True, # short names save memory - preserve_locals=["stubber", "path"], # names to keep - rename_globals=True, # short names save memory - # keep these globals to allow testing/mocking to work against the minified not compiled version - preserve_globals=[ - "main", - "Stubber", - "read_path", - "get_root", - "_info", - "os", - "sys", - "__version__", - ], - # remove_pass=True, # no dead code - # convert_posargs_to_args=True, # Does not save any space - ) + # source = python_minifier.minify( + # content, + # filename=getattr(source_script, "name", None), + # combine_imports=True, + # remove_literal_statements=True, # no Docstrings + # remove_annotations=True, # not used runtime anyways + # hoist_literals=True, # remove redundant strings + # rename_locals=True, # short names save memory + # preserve_locals=["stubber", "path"], # names to keep + # rename_globals=True, # short names save memory + # # keep these globals to allow testing/mocking to work against the minified not compiled version + # preserve_globals=[ + # "main", + # "Stubber", + # "read_path", + # "get_root", + # "_info", + # "os", + # "sys", + # "__version__", + # ], + # # remove_pass=True, # no dead code + # # convert_posargs_to_args=True, # Does not save any space + # ) + source = content log.debug(f"Original length : {len(content)}") log.info(f"Minified length : {len(source)}") log.info(f"Reduced by : {len(content)-len(source)} ") @@ -347,7 +346,6 @@ def cross_compile( else: # target must be a Path object _target = get_temp_file(suffix=".mpy") - result = pipx_mpy_cross(version, source_file, _target) if result.stderr and "No matching distribution found for mpy-cross==" in result.stderr: log.warning(f"mpy-cross=={version} not found, using latest") @@ -378,7 +376,7 @@ def pipx_mpy_cross(version, source_file, _target): # Add params cmd += ["-O2", str(source_file), "-o", str(_target), "-s", "createstubs.py"] log.trace(" ".join(cmd)) - result = subprocess.run(cmd, capture_output=True, text=True) + result = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8") # Specify the encoding return result diff --git a/src/stubber/publish/stubpackage.py b/src/stubber/publish/stubpackage.py index 4b6d47005..07f2f2687 100644 --- a/src/stubber/publish/stubpackage.py +++ b/src/stubber/publish/stubpackage.py @@ -654,6 +654,7 @@ def run_poetry(self, parameters: List[str]) -> bool: # stdout=subprocess.PIPE, stdout=subprocess.PIPE, # interestingly: errors on stdout , output on stderr ..... universal_newlines=True, + encoding="utf-8" ) log.trace(f"poetry {parameters} completed") except (NotADirectoryError, FileNotFoundError) as e: # pragma: no cover # InvalidVersion diff --git a/src/stubber/utils/post.py b/src/stubber/utils/post.py index a403e3dec..29e007996 100644 --- a/src/stubber/utils/post.py +++ b/src/stubber/utils/post.py @@ -35,7 +35,7 @@ def run_black(path: Path, capture_output: bool = False): "--line-length", "140", ] - result = subprocess.run(cmd, capture_output=True, text=True) + result = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8") return result.returncode From 0d4e2c8cfa88975539f28562cefdefb81e15a246 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Sun, 21 Jan 2024 22:15:07 +0100 Subject: [PATCH 33/68] Fix formatting issues in minify.py and basicgit.py Signed-off-by: Jos Verlinde --- src/stubber/basicgit.py | 34 +- src/stubber/minify.py | 2 +- tmp_minified_1.py | 954 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 970 insertions(+), 20 deletions(-) create mode 100644 tmp_minified_1.py diff --git a/src/stubber/basicgit.py b/src/stubber/basicgit.py index 58f7d92e9..d9ecf4fd8 100644 --- a/src/stubber/basicgit.py +++ b/src/stubber/basicgit.py @@ -15,9 +15,7 @@ # Token with no permissions PAT_NO_ACCESS = ( - "github_pat" - + "_11AAHPVFQ0IwtAmfc3cD5Z" - + "_xOVII22ErRzzZ7xwwxRcNotUu4krMMbjinQcsMxjnWkYFBIDRWFlZMaHSqq" + "github_pat" + "_11AAHPVFQ0IwtAmfc3cD5Z" + "_xOVII22ErRzzZ7xwwxRcNotUu4krMMbjinQcsMxjnWkYFBIDRWFlZMaHSqq" ) PAT = os.environ.get("GITHUB_TOKEN") or PAT_NO_ACCESS GH_CLIENT = Github(auth=Auth.Token(PAT)) @@ -36,10 +34,10 @@ def _run_local_git( if isinstance(repo, str): repo = Path(repo) result = subprocess.run( - cmd, capture_output=capture_output, check=True, cwd=repo.absolute().as_posix(),encoding="utf-8" + cmd, capture_output=capture_output, check=True, cwd=repo.absolute().as_posix(), encoding="utf-8" ) else: - result = subprocess.run(cmd, capture_output=capture_output, check=True,encoding="utf-8") + result = subprocess.run(cmd, capture_output=capture_output, check=True, encoding="utf-8") except (NotADirectoryError, FileNotFoundError) as e: # pragma: no cover return None except subprocess.CalledProcessError as e: # pragma: no cover @@ -47,7 +45,7 @@ def _run_local_git( log.error(f"{str(e)} : { e.stderr.decode('utf-8')}") return None if result.stderr and result.stderr != b"": - stderr = result.stderr.decode("utf-8") + stderr = result.stderr if "cloning into" in stderr.lower(): # log.info(stderr) expect_stderr = True @@ -59,8 +57,8 @@ def _run_local_git( if not expect_stderr: raise ChildProcessError(stderr) - if result.returncode < 0: - raise ChildProcessError(result.stderr.decode("utf-8")) + if result.returncode and result.returncode < 0: + raise ChildProcessError(result.stderr) return result @@ -78,9 +76,7 @@ def clone(remote_repo: str, path: Path, shallow: bool = False, tag: Optional[str return False -def get_local_tag( - repo: Optional[Union[str, Path]] = None, abbreviate: bool = True -) -> Union[str, None]: +def get_local_tag(repo: Optional[Union[str, Path]] = None, abbreviate: bool = True) -> Union[str, None]: """ get the most recent git version tag of a local repo repo Path should be in the form of : repo = "./repo/micropython" @@ -100,7 +96,7 @@ def get_local_tag( ) if not result: return None - tag: str = result.stdout.decode("utf-8") + tag: str = result.stdout tag = tag.replace("\r", "").replace("\n", "") if abbreviate and "-" in tag: if result := _run_local_git( @@ -108,7 +104,7 @@ def get_local_tag( repo=repo.as_posix(), expect_stderr=True, ): - lines = result.stdout.decode("utf-8").replace("\r", "").split("\n") + lines = result.stdout.replace("\r", "").split("\n") if lines[0].startswith("On branch") and lines[0].endswith("master"): tag = "latest" return tag @@ -124,7 +120,7 @@ def get_local_tags(repo: Optional[Path] = None, minver: Optional[str] = None) -> result = _run_local_git(["git", "tag", "-l"], repo=repo.as_posix(), expect_stderr=True) if not result or result.returncode != 0: return [] - tags = result.stdout.decode("utf-8").replace("\r", "").split("\n") + tags = result.stdout.replace("\r", "").split("\n") tags = [tag for tag in tags if tag.startswith("v")] if minver: tags = [tag for tag in tags if parse(tag) >= parse(minver)] @@ -159,7 +155,7 @@ def checkout_tag(tag: str, repo: Optional[Union[str, Path]] = None) -> bool: if not result: return False # actually a good result - msg = {result.stdout.decode("utf-8")} + msg = {result.stdout} if msg != {""}: log.warning(f"git message: {msg}") return True @@ -177,7 +173,7 @@ def sync_submodules(repo: Optional[Union[Path, str]] = None) -> bool: for cmd in cmds: if result := _run_local_git(cmd, repo=repo, expect_stderr=True): # actually a good result - log.debug(result.stderr.decode("utf-8")) + log.debug(result.stderr) else: return False return True @@ -192,7 +188,7 @@ def checkout_commit(commit_hash: str, repo: Optional[Union[Path, str]] = None) - if not result: return False # actually a good result - log.debug(result.stderr.decode("utf-8")) + log.debug(result.stderr) return True @@ -209,7 +205,7 @@ def switch_tag(tag: Union[str, Path], repo: Optional[Union[Path, str]] = None) - if not result: return False # actually a good result - log.debug(result.stderr.decode("utf-8")) + log.debug(result.stderr) return True @@ -225,7 +221,7 @@ def switch_branch(branch: str, repo: Optional[Union[Path, str]] = None) -> bool: if not result: return False # actually a good result - log.debug(result.stderr.decode("utf-8")) + log.debug(result.stderr) return True diff --git a/src/stubber/minify.py b/src/stubber/minify.py index 7889dba52..d0e14b8ae 100644 --- a/src/stubber/minify.py +++ b/src/stubber/minify.py @@ -365,7 +365,7 @@ def cross_compile( return result.returncode -def pipx_mpy_cross(version, source_file, _target): +def pipx_mpy_cross(version:str, source_file, _target): """Run mpy-cross using pipx""" if version == "latest": version = "" diff --git a/tmp_minified_1.py b/tmp_minified_1.py new file mode 100644 index 000000000..ad7e11574 --- /dev/null +++ b/tmp_minified_1.py @@ -0,0 +1,954 @@ +""" +Create stubs for (all) modules on a MicroPython board +""" +# Copyright (c) 2019-2023 Jos Verlinde + +import gc +# import logging +import os +import sys + +try: + from ujson import dumps +except: + from json import dumps + +try: + from machine import reset # type: ignore +except ImportError: + pass + +try: + from collections import OrderedDict +except ImportError: + from ucollections import OrderedDict # type: ignore + +__version__ = "v1.16.2" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] +from time import sleep + + +class Stubber: + "Generate stubs for modules in firmware" + + def __init__(self, path: str = None, firmware_id: str = None): # type: ignore + try: + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore + raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") + except AttributeError: + pass + # self.log = logging.getLogger("stubber") + self._report = [] # type: list[str] + self.info = _info() + # self.log.info("Port: {}".format(self.info["port"])) + # self.log.info("Board: {}".format(self.info["board"])) + gc.collect() + if firmware_id: + self._fwid = firmware_id.lower() + else: + if self.info["family"] == "micropython": + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + else: + self._fwid = "{family}-v{version}-{port}".format(**self.info) + self._start_free = gc.mem_free() # type: ignore + + if path: + if path.endswith("/"): + path = path[:-1] + else: + path = get_root() + + self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") + # self.log.debug(self.path) + try: + ensure_folder(path + "/") + except OSError: + print("error creating stub folder {}".format(path)) + self.problematic = [ + "upip", + "upysh", + "webrepl_setup", + "http_client", + "http_client_ssl", + "http_server", + "http_server_ssl", + ] + self.excluded = [ + "webrepl", + "_webrepl", + "port_diag", + "example_sub_led.py", + "example_pub_button.py", + ] + # there is no option to discover modules from micropython, list is read from an external file. + self.modules = [] # type: list[str] + + def get_obj_attributes(self, item_instance: object): + "extract information of the objects members and attributes" + # name_, repr_(value), type as text, item_instance + _result = [] + _errors = [] + # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + for name in dir(item_instance): + if name.startswith("_") and not name in self.modules: + continue + # self.log.debug("get attribute {}".format(name)) + try: + val = getattr(item_instance, name) + # name , item_repr(value) , type as text, item_instance, order + try: + type_text = repr(type(val)).split("'")[1] + except IndexError: + type_text = "" + if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: + order = 1 + elif type_text in {"function", "method"}: + order = 2 + elif type_text in ("class"): + order = 3 + else: + order = 4 + _result.append((name, repr(val), repr(type(val)), val, order)) + except AttributeError as e: + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) + except MemoryError as e: + # print("MemoryError: {}".format(e)) + sleep(1) + reset() + + # remove internal __ + # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) + _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) + gc.collect() + return _result, _errors + + def add_modules(self, modules): + "Add additional modules to be exported" + self.modules = sorted(set(self.modules) | set(modules)) + + def create_all_stubs(self): + "Create stubs for all configured modules" + # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + gc.collect() + for module_name in self.modules: + self.create_one_stub(module_name) + # self.log.info("Finally done") + + def create_one_stub(self, module_name: str): + if module_name in self.problematic: + # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + return False + if module_name in self.excluded: + # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + return False + + file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + gc.collect() + result = False + try: + result = self.create_module_stub(module_name, file_name) + except OSError: + return False + gc.collect() + return result + + def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore + """Create a Stub of a single python module + + Args: + - module_name (str): name of the module to document. This module will be imported. + - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + """ + if file_name is None: + fname = module_name.replace(".", "_") + ".py" + file_name = self.path + "/" + fname + else: + fname = file_name.split("/")[-1] + + if "/" in module_name: + # for nested modules + module_name = module_name.replace("/", ".") + + # import the module (as new_module) to examine it + new_module = None + try: + new_module = __import__(module_name, None, None, ("*")) + m1 = gc.mem_free() # type: ignore + # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + + except ImportError: + # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + return False + + # Start a new file + ensure_folder(file_name) + with open(file_name, "w") as fp: + # todo: improve header + info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format( + module_name, self._fwid, info_, __version__ + ) + fp.write(s) + fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + self.write_object_stub(fp, new_module, module_name, "") + + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + + if module_name not in {"os", "sys", "logging", "gc"}: + # try to unload the module unless we use it + try: + del new_module + except (OSError, KeyError): # lgtm [py/unreachable-statement] + pass + try: + del sys.modules[module_name] + except KeyError: + pass + gc.collect() + return True + + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): + "Write a module/object stub to an open file. Can be called recursive." + gc.collect() + if object_expr in self.problematic: + # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + return + + # # self.log.debug("DUMP : {}".format(object_expr)) + items, errors = self.get_obj_attributes(object_expr) + + if errors: + print(errors) + + for item_name, item_repr, item_type_txt, item_instance, _ in items: + # name_, repr_(value), type as text, item_instance, order + if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: + # do not create stubs for these primitives + continue + if item_name[0].isdigit(): + # self.log.warning("NameError: invalid name {}".format(item_name)) + continue + # Class expansion only on first 3 levels (bit of a hack) + if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: + # self.log.debug("{0}class {1}:".format(indent, item_name)) + superclass = "" + is_exception = ( + item_name.endswith("Exception") + or item_name.endswith("Error") + or item_name + in [ + "KeyboardInterrupt", + "StopIteration", + "SystemExit", + ] + ) + if is_exception: + superclass = "Exception" + s = "\n{}class {}({}):\n".format(indent, item_name, superclass) + # s += indent + " ''\n" + if is_exception: + s += indent + " ...\n" + fp.write(s) + return + # write classdef + fp.write(s) + # first write the class literals and methods + # self.log.debug("# recursion over class {0}".format(item_name)) + self.write_object_stub( + fp, + item_instance, + "{0}.{1}".format(obj_name, item_name), + indent + " ", + in_class + 1, + ) + # end with the __init__ method to make sure that the literals are defined + # Add __init__ + s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" + s += indent + " ...\n\n" + fp.write(s) + elif any(word in item_type_txt for word in ["method", "function", "closure"]): + # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # module Function or class method + # will accept any number of params + # return type Any/Incomplete + ret = "Incomplete" + first = "" + # Self parameter only on class methods/functions + if in_class > 0: + first = "self, " + # class method - add function decoration + if "bound_method" in item_type_txt or "bound_method" in item_repr: + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format( + indent, item_name, ret + ) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) + s += indent + " ...\n\n" + fp.write(s) + # self.log.debug("\n" + s) + elif item_type_txt == "": + # Skip imported modules + # fp.write("# import {}\n".format(item_name)) + pass + + elif item_type_txt.startswith(" dict[str, str] + info = OrderedDict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "UNKNOWN", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" + try: + info["version"] = version_str(sys.implementation.version) # type: ignore + except AttributeError: + pass + try: + _machine = ( + sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + ) + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine + info["cpu"] = _machine.split("with")[-1].strip() + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + gc.collect() + read_boardname(info) + gc.collect() + + try: + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): + pass + # avoid build hashes + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() # type: ignore + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + info["version"] + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # versions from 1.10.0 to 1.20.0 do not have a micro .0 + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" + # simple to use version[-build] string + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" + + return info + + +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): + found = True + break + if not found: + # print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + +def find_board(info: dict, descr: str, filename: str, short_descr: str): + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + info["board"] = board_ + return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True + return False + + +def get_root() -> str: # sourcery skip: use-assigned-variable + "Determine the root folder of the device" + try: + c = os.getcwd() + except (OSError, AttributeError): + # unix port + c = "." + r = c + for r in [c, "/sd", "/flash", "/", "."]: + try: + _ = os.stat(r) + break + except OSError: + continue + return r + + +def file_exists(filename: str): + try: + if os.stat(filename)[0] >> 14: + return True + return False + except OSError: + return False + + +def show_help(): + # print("-p, --path path to store the stubs in, defaults to '.'") + sys.exit(1) + + +def read_path() -> str: + "get --path from cmdline. [unix/win]" + path = "" + if len(sys.argv) == 3: + cmd = (sys.argv[1]).lower() + if cmd in ("--path", "-p"): + path = sys.argv[2] + else: + show_help() + elif len(sys.argv) == 2: + show_help() + return path + + +def is_micropython() -> bool: + "runtime test to determine full or micropython" + # pylint: disable=unused-variable,eval-used + try: + # either test should fail on micropython + # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces + # Micropython : SyntaxError + # a = eval("1and 0") # lgtm [py/unused-local-variable] + # Eval blocks some minification aspects + + # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented + # Micropython: NotImplementedError + b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] + + # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute + # Micropython: AttributeError + c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] + return False + except (NotImplementedError, AttributeError): + return True + + +def main(): + stubber = Stubber(path=read_path()) + # stubber = Stubber(path="/sd") + # Option: Specify a firmware name & version + # stubber = Stubber(firmware_id='HoverBot v1.2.1') + stubber.clean() + # there is no option to discover modules from micropython, need to hardcode + # below contains combined modules from Micropython ESP8622, ESP32, Loboris, Pycom and ulab , lvgl + # spell-checker: disable + # modules to stub : 131 + stubber.modules = [ + "WM8960", + "_OTA", + "_asyncio", + "_boot_fat", + "_coap", + "_espnow", + "_flash_control_OTA", + "_main_pybytes", + "_mqtt", + "_mqtt_core", + "_msg_handl", + "_onewire", + "_periodical_pin", + "_pybytes", + "_pybytes_ca", + "_pybytes_config", + "_pybytes_config_reader", + "_pybytes_connection", + "_pybytes_constants", + "_pybytes_debug", + "_pybytes_library", + "_pybytes_machine_learning", + "_pybytes_main", + "_pybytes_protocol", + "_pybytes_pyconfig", + "_pybytes_pymesh_config", + "_rp2", + "_terminal", + "_thread", + "_uasyncio", + "_urequest", + "adcfft", + "aioble/__init__", + "aioble/central", + "aioble/client", + "aioble/core", + "aioble/device", + "aioble/l2cap", + "aioble/peripheral", + "aioble/security", + "aioble/server", + "aioespnow", + "ak8963", + "apa102", + "apa106", + "argparse", + "array", + "asyncio/__init__", + "asyncio/core", + "asyncio/event", + "asyncio/funcs", + "asyncio/lock", + "asyncio/stream", + "binascii", + "bluetooth", + "breakout_as7262", + "breakout_bh1745", + "breakout_bme280", + "breakout_bme68x", + "breakout_bmp280", + "breakout_dotmatrix", + "breakout_encoder", + "breakout_icp10125", + "breakout_ioexpander", + "breakout_ltr559", + "breakout_matrix11x7", + "breakout_mics6814", + "breakout_msa301", + "breakout_paa5100", + "breakout_pmw3901", + "breakout_potentiometer", + "breakout_rgbmatrix5x5", + "breakout_rtc", + "breakout_scd41", + "breakout_sgp30", + "breakout_trackball", + "breakout_vl53l5cx", + "btree", + "cmath", + "collections", + "crypto", + "cryptolib", + "curl", + "deflate", + "dht", + "display", + "display_driver_utils", + "ds18x20", + "encoder", + "errno", + "esp", + "esp32", + "espidf", + "espnow", + "ffi", + "flashbdev", + "framebuf", + "freesans20", + "fs_driver", + "functools", + "galactic", + "gc", + "gfx_pack", + "gsm", + "hashlib", + "heapq", + "hub75", + "ili9341", + "ili9XXX", + "imagetools", + "inisetup", + "interstate75", + "io", + "jpegdec", + "json", + "lcd160cr", + "lodepng", + "logging", + "lsm6dsox", + "lv_colors", + "lv_utils", + "lvgl", + "lwip", + "machine", + "math", + "microWebSocket", + "microWebSrv", + "microWebTemplate", + "micropython", + "mip", + "mip/__init__", + "mip/__main__", + "motor", + "mpu6500", + "mpu9250", + "neopixel", + "network", + "ntptime", + "onewire", + "os", + "pcf85063a", + "picoexplorer", + "picographics", + "picokeypad", + "picoscroll", + "picounicorn", + "picowireless", + "pimoroni", + "pimoroni_bus", + "pimoroni_i2c", + "plasma", + "platform", + "pyb", + "pycom", + "pye", + "qrcode", + "queue", + "random", + "requests", + "requests/__init__", + "rp2", + "rtch", + "samd", + "select", + "servo", + "socket", + "ssd1306", + "ssh", + "ssl", + "stm", + "struct", + "sys", + "termios", + "time", + "tpcalib", + "uarray", + "uasyncio/__init__", + "uasyncio/core", + "uasyncio/event", + "uasyncio/funcs", + "uasyncio/lock", + "uasyncio/stream", + "uasyncio/tasks", + "ubinascii", + "ubluetooth", + "ucollections", + "ucrypto", + "ucryptolib", + "uctypes", + "uerrno", + "uftpd", + "uhashlib", + "uheapq", + "uio", + "ujson", + "ulab", + "ulab/approx", + "ulab/compare", + "ulab/fft", + "ulab/filter", + "ulab/linalg", + "ulab/numerical", + "ulab/poly", + "ulab/user", + "ulab/vector", + "umachine", + "umqtt/__init__", + "umqtt/robust", + "umqtt/simple", + "uos", + "uplatform", + "uqueue", + "urandom", + "ure", + "urequests", + "urllib/urequest", + "uselect", + "usocket", + "ussl", + "ustruct", + "usys", + "utelnetserver", + "utime", + "utimeq", + "uwebsocket", + "uzlib", + "version", + "websocket", + "websocket_helper", + "wipy", + "writer", + "xpt2046", + "ymodem", + "zephyr", + "zlib", + ] # spell-checker: enable + + gc.collect() + + stubber.create_all_stubs() + stubber.report() + + +if __name__ == "__main__" or is_micropython(): + try: + log = logging.getLogger("stubber") + logging.basicConfig(level=logging.INFO) + # logging.basicConfig(level=logging.DEBUG) + except NameError: + pass + if not file_exists("no_auto_stubber.txt"): + try: + gc.threshold(4 * 1024) # type: ignore + gc.enable() + except BaseException: + pass + main() From 20c2f69512860e57255f1ca89ac93eb5a234d34f Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Sun, 21 Jan 2024 22:15:29 +0100 Subject: [PATCH 34/68] settings Signed-off-by: Jos Verlinde --- .vscode/launch.json | 3 ++- .vscode/settings.json | 5 ++++- pyproject.toml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 1a452b4f9..383cbd072 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -44,6 +44,7 @@ "module": "stubber.stubber", "cwd": "${workspaceFolder}", "args": [ + "-v", "-v", "make-variants", // "switch", @@ -98,7 +99,7 @@ "type": "python", "request": "launch", "program": "${file}", - // "cwd": "${fileDirname}", + "cwd": "${workspaceFolder}", "console": "integratedTerminal" }, { diff --git a/.vscode/settings.json b/.vscode/settings.json index 28608a455..4941d8665 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -140,5 +140,8 @@ ], "python.analysis.enablePytestExtra": true, "testExplorer.addToEditorContextMenu": true, - "todo-tree.tree.scanMode": "open files" + "todo-tree.tree.scanMode": "open files", + "python.analysis.typeshedPaths": [ + "typings" + ] } \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index f972d6d24..d7456a82e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -262,7 +262,7 @@ markers = [ [tool.coverage.run] parallel = false branch = true -source = ["board", "src"] +source = ["src"] omit = [ # helper files in board "*/boot.py", From c1e6aa5bd181361ad828105741054e0f3782774e Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Sun, 21 Jan 2024 22:15:42 +0100 Subject: [PATCH 35/68] variants Signed-off-by: Jos Verlinde --- src/stubber/board/createstubs_db_min.py | 1107 ++++++++++++----- src/stubber/board/createstubs_db_mpy.mpy | Bin 8775 -> 8470 bytes src/stubber/board/createstubs_lvgl_min.py | 1017 +++++++++++----- src/stubber/board/createstubs_lvgl_mpy.mpy | Bin 8250 -> 7967 bytes src/stubber/board/createstubs_mem_min.py | 1034 +++++++++++----- src/stubber/board/createstubs_mem_mpy.mpy | Bin 8286 -> 7966 bytes src/stubber/board/createstubs_min.py | 1242 +++++++++++++++----- src/stubber/board/createstubs_mpy.mpy | Bin 11298 -> 11094 bytes 8 files changed, 3196 insertions(+), 1204 deletions(-) diff --git a/src/stubber/board/createstubs_db_min.py b/src/stubber/board/createstubs_db_min.py index adae0e729..50065e687 100644 --- a/src/stubber/board/createstubs_db_min.py +++ b/src/stubber/board/createstubs_db_min.py @@ -1,323 +1,790 @@ -x='with' -w='stubber' -v='{}/{}' -u='method' -t='function' -s='bool' -r='str' -q='float' -p='int' -o=TypeError -n=NameError -m=sorted -l=MemoryError -k=NotImplementedError -d='-' -c=',\n' -b='dict' -a='list' -Z='tuple' -Y='micropython' -X=str -W=repr -U='cpu' -T='_' -S=KeyError -R=IndexError -Q=ImportError -P='family' -O=print -N=len -M=dir -L='.' -K=open -J=True -I=AttributeError -H='board' -G='/' -F=None -E=False -A=OSError -D='version' -C='' -import gc as B,os,sys -try:from ujson import dumps -except:from json import dumps -try:from machine import reset -except Q:pass -try:from collections import OrderedDict as e -except Q:from ucollections import OrderedDict as e -__version__='v1.16.2' -y=2 -z=2 -f=[L,'/lib','/sd/lib','/flash/lib','lib'] +""" +Create stubs for (all) modules on a MicroPython board. + + This variant of the createstubs.py script is optimized for use on very-low-memory devices. + Note: this version has undergone limited testing. + + 1) reads the list of modules from a text file `modulelist.txt` that should be uploaded to the device. + 2) stored the already processed modules in a text file `modulelist.done` + 3) process the modules in the database: + - stub the module + - update the modulelist.done file + - reboots the device if it runs out of memory + 4) creates the modules.json + + If that cannot be found then only a single module (micropython) is stubbed. + In order to run this on low-memory devices two additional steps are recommended: + - minification, using python-minifierto reduce overall size, and remove logging overhead. + - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device + + +This variant was generated from createstubs.py by micropython-stubber v1.16.2 +""" +# Copyright (c) 2019-2023 Jos Verlinde + +import gc +# import logging +import os +import sys + +try: + from ujson import dumps +except: + from json import dumps + +try: + from machine import reset # type: ignore +except ImportError: + pass + +try: + from collections import OrderedDict +except ImportError: + from ucollections import OrderedDict # type: ignore + +__version__ = "v1.16.2" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] from time import sleep + + class Stubber: - def __init__(C,path=F,firmware_id=F): - D=firmware_id - try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') - except I:pass - C._report=[];C.info=_info();B.collect() - if D:C._fwid=D.lower() - elif C.info[P]==Y:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info) - else:C._fwid='{family}-v{version}-{port}'.format(**C.info) - C._start_free=B.mem_free() - if path: - if path.endswith(G):path=path[:-1] - else:path=get_root() - C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) - try:g(path+G) - except A:O('error creating stub folder {}'.format(path)) - C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] - def get_obj_attributes(L,item_instance): - H=item_instance;D=[];J=[] - for A in M(H): - if A.startswith(T)and not A in L.modules:continue - try: - E=getattr(H,A) - try:F=W(type(E)).split("'")[1] - except R:F=C - if F in{p,q,r,s,Z,a,b}:G=1 - elif F in{t,u}:G=2 - elif F in'class':G=3 - else:G=4 - D.append((A,W(E),W(type(E)),E,G)) - except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) - except l as K:sleep(1);reset() - D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) - def create_all_stubs(A): - B.collect() - for C in A.modules:A.create_one_stub(C) - def create_one_stub(C,module_name): - D=module_name - if D in C.problematic:return E - if D in C.excluded:return E - H='{}/{}.py'.format(C.path,D.replace(L,G));B.collect();F=E - try:F=C.create_module_stub(D,H) - except A:return E - B.collect();return F - def create_module_stub(I,module_name,file_name=F): - H=file_name;D=module_name - if H is F:O=D.replace(L,T)+'.py';H=I.path+G+O - else:O=H.split(G)[-1] - if G in D:D=D.replace(G,L) - M=F - try:M=__import__(D,F,F,'*');U=B.mem_free() - except Q:return E - g(H) - with K(H,'w')as N:P=X(I.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,D,C) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: - try:del M - except(A,S):pass - try:del sys.modules[D] - except S:pass - B.collect();return J - def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;M='Exception';H=fp;E=indent;B.collect() - if P in K.problematic:return - R,L=K.get_obj_attributes(P) - if L:O(L) - for(F,J,G,T,f)in R: - if F in['classmethod','staticmethod','BaseException',M]:continue - if F[0].isdigit():continue - if G==""and N(E)<=z*4: - U=C;V=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=M - D='\n{}class {}({}):\n'.format(E,F,U) - if V:D+=E+' ...\n';H.write(D);return - H.write(D);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) - elif any(A in G for A in[u,t,'closure']): - W=Y;X=C - if Q>0:X='self, ' - if c in G or c in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) - else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,X,W) - D+=E+' ...\n\n';H.write(D) - elif G=="":0 - elif G.startswith("='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if J in A and A[J]: - K=int(A[J]);N=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if N:A[T]=N - A[J]='v{}.{}'.format(K&255,K>>8&3) - if A[E]and not A[D].endswith(c):A[D]=A[D]+c - A[O]=f"{A[D]}-{A[E]}"if A[E]else f"{A[D]}";return A -def A0(version): - A=version;B=L.join([X(A)for A in A[:3]]) - if N(A)>3 and A[3]:B+=d+A[3] - return B -def A1(info,desc=C): - L='with ';A=info;F=E - for G in[A+'/board_info.csv'for A in f]: - if h(G): - D=desc or A[H].strip();I=D.rfind(' with') - if I!=-1:K=D[:I].strip() - else:K=C - if A2(A,D,G,K):F=J;break - if not F: - D=desc or A[H].strip() - if L+A[U].upper()in D:D=D.split(L+A[U].upper())[0].strip() - A[H]=D - A[H]=A[H].replace(' ',T);B.collect() -def A2(info,descr,filename,short_descr): - B=short_descr;A=info;D=C - with K(filename,'r')as L: - while 1: - F=L.readline() - if not F:break - I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:A[H]=G;return J - elif B and I==B: - if x in B:A[H]=G;return J - D=G - if D:A[H]=D;return J - return E -def get_root(): - try:B=os.getcwd() - except(A,I):B=L - C=B - for C in[B,'/sd','/flash',G,L]: - try:D=os.stat(C);break - except A:continue - return C -def h(filename): - try: - if os.stat(filename)[0]>>14:return J - return E - except A:return E -def i():sys.exit(1) -def read_path(): - path=C - if N(sys.argv)==3: - A=sys.argv[1].lower() - if A in('--path','-p'):path=sys.argv[2] - else:i() - elif N(sys.argv)==2:i() - return path -def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return E - except(k,I):return J + "Generate stubs for modules in firmware" + + def __init__(self, path: str = None, firmware_id: str = None): # type: ignore + try: + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore + raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") + except AttributeError: + pass + # self.log = logging.getLogger("stubber") + self._report = [] # type: list[str] + self.info = _info() + # self.log.info("Port: {}".format(self.info["port"])) + # self.log.info("Board: {}".format(self.info["board"])) + gc.collect() + if firmware_id: + self._fwid = firmware_id.lower() + else: + if self.info["family"] == "micropython": + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + else: + self._fwid = "{family}-v{version}-{port}".format(**self.info) + self._start_free = gc.mem_free() # type: ignore + + if path: + if path.endswith("/"): + path = path[:-1] + else: + path = get_root() + + self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") + # self.log.debug(self.path) + try: + ensure_folder(path + "/") + except OSError: + print("error creating stub folder {}".format(path)) + self.problematic = [ + "upip", + "upysh", + "webrepl_setup", + "http_client", + "http_client_ssl", + "http_server", + "http_server_ssl", + ] + self.excluded = [ + "webrepl", + "_webrepl", + "port_diag", + "example_sub_led.py", + "example_pub_button.py", + ] + # there is no option to discover modules from micropython, list is read from an external file. + self.modules = [] # type: list[str] + + def get_obj_attributes(self, item_instance: object): + "extract information of the objects members and attributes" + # name_, repr_(value), type as text, item_instance + _result = [] + _errors = [] + # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + for name in dir(item_instance): + if name.startswith("_") and not name in self.modules: + continue + # self.log.debug("get attribute {}".format(name)) + try: + val = getattr(item_instance, name) + # name , item_repr(value) , type as text, item_instance, order + try: + type_text = repr(type(val)).split("'")[1] + except IndexError: + type_text = "" + if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: + order = 1 + elif type_text in {"function", "method"}: + order = 2 + elif type_text in ("class"): + order = 3 + else: + order = 4 + _result.append((name, repr(val), repr(type(val)), val, order)) + except AttributeError as e: + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) + except MemoryError as e: + # print("MemoryError: {}".format(e)) + sleep(1) + reset() + + # remove internal __ + # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) + _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) + gc.collect() + return _result, _errors + + def add_modules(self, modules): + "Add additional modules to be exported" + self.modules = sorted(set(self.modules) | set(modules)) + + def create_all_stubs(self): + "Create stubs for all configured modules" + # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + gc.collect() + for module_name in self.modules: + self.create_one_stub(module_name) + # self.log.info("Finally done") + + def create_one_stub(self, module_name: str): + if module_name in self.problematic: + # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + return False + if module_name in self.excluded: + # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + return False + + file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + gc.collect() + result = False + try: + result = self.create_module_stub(module_name, file_name) + except OSError: + return False + gc.collect() + return result + + def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore + """Create a Stub of a single python module + + Args: + - module_name (str): name of the module to document. This module will be imported. + - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + """ + if file_name is None: + fname = module_name.replace(".", "_") + ".py" + file_name = self.path + "/" + fname + else: + fname = file_name.split("/")[-1] + + if "/" in module_name: + # for nested modules + module_name = module_name.replace("/", ".") + + # import the module (as new_module) to examine it + new_module = None + try: + new_module = __import__(module_name, None, None, ("*")) + m1 = gc.mem_free() # type: ignore + # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + + except ImportError: + # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + return False + + # Start a new file + ensure_folder(file_name) + with open(file_name, "w") as fp: + # todo: improve header + info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) + fp.write(s) + fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + self.write_object_stub(fp, new_module, module_name, "") + + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + + if module_name not in {"os", "sys", "logging", "gc"}: + # try to unload the module unless we use it + try: + del new_module + except (OSError, KeyError): # lgtm [py/unreachable-statement] + pass + try: + del sys.modules[module_name] + except KeyError: + pass + gc.collect() + return True + + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): + "Write a module/object stub to an open file. Can be called recursive." + gc.collect() + if object_expr in self.problematic: + # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + return + + # # self.log.debug("DUMP : {}".format(object_expr)) + items, errors = self.get_obj_attributes(object_expr) + + if errors: + print(errors) + + for item_name, item_repr, item_type_txt, item_instance, _ in items: + # name_, repr_(value), type as text, item_instance, order + if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: + # do not create stubs for these primitives + continue + if item_name[0].isdigit(): + # self.log.warning("NameError: invalid name {}".format(item_name)) + continue + # Class expansion only on first 3 levels (bit of a hack) + if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: + # self.log.debug("{0}class {1}:".format(indent, item_name)) + superclass = "" + is_exception = ( + item_name.endswith("Exception") + or item_name.endswith("Error") + or item_name + in [ + "KeyboardInterrupt", + "StopIteration", + "SystemExit", + ] + ) + if is_exception: + superclass = "Exception" + s = "\n{}class {}({}):\n".format(indent, item_name, superclass) + # s += indent + " ''\n" + if is_exception: + s += indent + " ...\n" + fp.write(s) + return + # write classdef + fp.write(s) + # first write the class literals and methods + # self.log.debug("# recursion over class {0}".format(item_name)) + self.write_object_stub( + fp, + item_instance, + "{0}.{1}".format(obj_name, item_name), + indent + " ", + in_class + 1, + ) + # end with the __init__ method to make sure that the literals are defined + # Add __init__ + s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" + s += indent + " ...\n\n" + fp.write(s) + elif any(word in item_type_txt for word in ["method", "function", "closure"]): + # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # module Function or class method + # will accept any number of params + # return type Any/Incomplete + ret = "Incomplete" + first = "" + # Self parameter only on class methods/functions + if in_class > 0: + first = "self, " + # class method - add function decoration + if "bound_method" in item_type_txt or "bound_method" in item_repr: + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) + s += indent + " ...\n\n" + fp.write(s) + # self.log.debug("\n" + s) + elif item_type_txt == "": + # Skip imported modules + # fp.write("# import {}\n".format(item_name)) + pass + + elif item_type_txt.startswith(" dict[str, str] + info = OrderedDict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "UNKNOWN", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" + try: + info["version"] = version_str(sys.implementation.version) # type: ignore + except AttributeError: + pass + try: + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine + info["cpu"] = _machine.split("with")[-1].strip() + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + gc.collect() + read_boardname(info) + gc.collect() + + try: + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): + pass + # avoid build hashes + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() # type: ignore + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + info["version"] + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # versions from 1.10.0 to 1.20.0 do not have a micro .0 + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" + # simple to use version[-build] string + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" + + return info + + +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): + found = True + break + if not found: + # print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + +def find_board(info: dict, descr: str, filename: str, short_descr: str): + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + info["board"] = board_ + return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True + return False + + +def get_root() -> str: # sourcery skip: use-assigned-variable + "Determine the root folder of the device" + try: + c = os.getcwd() + except (OSError, AttributeError): + # unix port + c = "." + r = c + for r in [c, "/sd", "/flash", "/", "."]: + try: + _ = os.stat(r) + break + except OSError: + continue + return r + + +def file_exists(filename: str): + try: + if os.stat(filename)[0] >> 14: + return True + return False + except OSError: + return False + + +def show_help(): + # print("-p, --path path to store the stubs in, defaults to '.'") + sys.exit(1) + + +def read_path() -> str: + "get --path from cmdline. [unix/win]" + path = "" + if len(sys.argv) == 3: + cmd = (sys.argv[1]).lower() + if cmd in ("--path", "-p"): + path = sys.argv[2] + else: + show_help() + elif len(sys.argv) == 2: + show_help() + return path + + +def is_micropython() -> bool: + "runtime test to determine full or micropython" + # pylint: disable=unused-variable,eval-used + try: + # either test should fail on micropython + # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces + # Micropython : SyntaxError + # a = eval("1and 0") # lgtm [py/unused-local-variable] + # Eval blocks some minification aspects + + # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented + # Micropython: NotImplementedError + b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] + + # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute + # Micropython: AttributeError + c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] + return False + except (NotImplementedError, AttributeError): + return True + + def main(): - L='failed';G='modulelist.done';import machine as O - try:C=K(G,'r+b');M=J - except A:C=K(G,'w+b');M=E - stubber=Stubber(path=read_path()) - if not M:stubber.clean() - A3(stubber);D={} - try: - with K(G)as C: - for F in C.read().split('\n'): - F=F.strip();B.collect() - if N(F)>0:P,Q=F.split('=',1);D[P]=Q - except(A,SyntaxError):pass - B.collect();R=[A for A in stubber.modules if A not in D.keys()];B.collect() - for H in R: - I=E - try:I=stubber.create_one_stub(H) - except l:O.reset() - B.collect();D[H]=X(stubber._report[-1]if I else L) - with K(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if I else L)) - if D:stubber._report=[A for(B,A)in D.items()if A!=L];stubber.report() -def A3(stubber): - E='/modulelist.txt';stubber.modules=[] - for D in f: - try: - with K(D+E)as F: - O('DEBUG: list of modules: '+D+E) - for C in F.read().split('\n'): - C=C.strip() - if N(C)>0 and C[0]!='#':stubber.modules.append(C) - B.collect();break - except A:pass - if not stubber.modules:stubber.modules=[Y];_log.warn('Could not find modulelist.txt, using default modules') - B.collect() -if __name__=='__main__'or j(): - try:A4=logging.getLogger(w);logging.basicConfig(level=logging.INFO) - except n:pass - if not h('no_auto_stubber.txt'): - try:B.threshold(4*1024);B.enable() - except BaseException:pass - main() \ No newline at end of file + import machine # type: ignore + + try: + f = open("modulelist.done", "r+b") + was_running = True + # print("Opened existing db") + except OSError: + f = open("modulelist.done", "w+b") + # print("created new db") + was_running = False + stubber = Stubber(path=read_path()) + + # f_name = "{}/{}".format(stubber.path, "modules.json") + if not was_running: + # Only clean folder if this is a first run + stubber.clean() + # get list of modules to process + get_modulelist(stubber) + # remove the ones that are already done + modules_done = {} # type: dict[str, str] + try: + with open("modulelist.done") as f: + # not optimal , but works on mpremote and esp8266 + for line in f.read().split("\n"): + line = line.strip() + gc.collect() + if len(line) > 0: + key, value = line.split("=", 1) + modules_done[key] = value + except (OSError, SyntaxError): + pass + gc.collect() + # see if we can continue from where we left off + modules = [m for m in stubber.modules if m not in modules_done.keys()] + gc.collect() + for modulename in modules: + # ------------------------------------ + # do epic shit + # but sometimes things fail / run out of memory and reboot + ok = False + try: + ok = stubber.create_one_stub(modulename) + except MemoryError: + # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER + machine.reset() + # ------------------------------------- + gc.collect() + modules_done[modulename] = str(stubber._report[-1] if ok else "failed") + with open("modulelist.done", "a") as f: + f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) + + # Finished processing - load all the results , and remove the failed ones + if modules_done: + # stubber.write_json_end(mod_fp) + stubber._report = [v for _, v in modules_done.items() if v != "failed"] + stubber.report() + + +def get_modulelist(stubber): + stubber.modules = [] # avoid duplicates + for p in LIBS: + try: + with open(p + "/modulelist.txt") as f: + print ("DEBUG: list of modules: " + p + "/modulelist.txt") + for line in f.read().split("\n"): + line = line.strip() + if len(line) > 0 and line[0] != "#": + stubber.modules.append(line) + gc.collect() + break + except OSError: + pass + if not stubber.modules: + stubber.modules = ["micropython"] + _log.warn("Could not find modulelist.txt, using default modules") + gc.collect() + + +if __name__ == "__main__" or is_micropython(): + try: + log = logging.getLogger("stubber") + logging.basicConfig(level=logging.INFO) + # logging.basicConfig(level=logging.DEBUG) + except NameError: + pass + if not file_exists("no_auto_stubber.txt"): + try: + gc.threshold(4 * 1024) # type: ignore + gc.enable() + except BaseException: + pass + main() diff --git a/src/stubber/board/createstubs_db_mpy.mpy b/src/stubber/board/createstubs_db_mpy.mpy index 54bc57f32ee8ba4dc934b45d9128a796293b31f0..197a518cd2030081db916e1046014dd715f6b3f8 100644 GIT binary patch literal 8470 zcmZ`-TU1-wdEOEd76RkVk$lGXFy{CibU}!lkmdUXA00s43<86#u|2XlI)H55MiRGS z7_?)vVSJeQF;n0k)Z}CNcOrZ8~{K*J_-E%uDmohpsdc7ts zHceKrbY0fBFC5LJg5qTz-R1iCyi7FW-D#hd+V&zmkuE@DqDw#!xX7~1L=Q>(D ze61d&Z$+lIcx)2Ywq>Jg!`e0#k7Q@mb|oD#XXA>JMy6aWp`h9^U~W>$po(T@TFDKj zrl+A(OIfB=b~2KU$^KMwDmIPGab-@4BU9gno?*n~W`Nh3R6L4mlw@QwuAn1IGCP}5 z!c#zmwZyUCl+8tQXvv(o8I1vul96XnWqOfnA(!a%AoF}I39njsMN{)&jd(0MyMRoy$=CwI z;axkJXH_;#^Re6vDs-5_bhp~F1yF59i7Sz;g3O-Q_SSYprb&YV-Zfwp+NbYRt*21s z!bu-Id|qUZWD;{eRHMEU+WSNT)zbb6C4rc7Bb$EJjHXe|LJm|ML5%hWo>9%*(sJw4 zGQutCj4~Hf=8<`6xdjLY__1Yeg|j)(ey|?AF&b8NqDoV!GIOdxpoH8ESmJ!4qN>h1 z1**_yAw4Wx(Yp}_*9d1)sT`_-mOKwS1@}TVnrk6;Di&A5%0eug%OVDxVm>^h#KFaY zltYYqY&rs(1N~3WArh{SWy6V>oJpk@b2DJg%E+XQu#%Kh(O7aCw4a+giCTzUnQ5Lx zmGkg0sq4)$=sAhV(mwq;2$EEEHm+pRQ7z2EsiXpu&VuiUGm7d7;5NWn6zLCGl4X)0Xj`mJuQhn4Mo|=zE z5l$$H@Ki>DFokm?nVi;PAl{%!XBgVrK$vta4N;z6%+4S-ok>BcB*3?2a5`lYxQK(F z?Y0=ob~qY~OoKWWWq3XtXS57I9^TMdEQ)VOfNimfOIQz^NO{W131deOA(e zYW+MiEH@$jGUDemv7AC#0yNU5=&z#MIDiK=AE_=h`TNLub9W|_%AoP-o0x;Y*49=t zs$FUaf9+TX2!KBbp?Hd72D0{n@oD7eAlS1?e9FzCLzAglaK*AH%4Mr_#+s9*?FKUIfn07d}C5soFpnitONr;r|?8_uJFwt$S5WGWn)&81Wyf_&4O zTgV|}O*ybz)s$#Fq6IOROO^eW(-I5^rZnq~1{JD}Mh(c#6-Iz}8Gr@7ZWv|Am^lPv zMmm;2uih0s=Py!vjWXBS0%;)=lW%5`asO_!bp}#5GMc(4Iz>7L%>BQaaDHV=i;7J~ zeM=e{54?tw)+hiHP}=s8RQV1`-QsxfX^uJymzv_r;-2P^(d$pm#-m&^mE$N3mxt&? zsv0*pn}q=5qRLccHlEvEh>VRx6ii1{Fy%DV;^at@ZZoNHS~8C!Bfq4j(dCx8rLyxu zuAr_1FEuYLBjb@jJP8@AA%f_3SsF*iw-g%SnpG%YbYzcljQh*57KV771?5!F=W^Wy9GlKIaV>9i7rl{R2zOUFyCX5Cg@&v`qJe zW8`=icA;DR&Sp!?bSvT2#HHmwJnI#lYZ6mg4uhgW$J{xpT2A1ojJtY0QXW&)&Itll zH=XFEN13jg4*bZ{57j-mba*{_TCA9J&4G z?Yi4l(XQLIKs)o1wT*YbFF1KuP{;@0)U$ecRUbcs$Oi;gW>lAFPxOF!0$SaJa5 zB2+Nq2FVB&jp&1#XrwJq8wMv5oizhI}CG_v#cdGDFg3ftykB5UF5Vy!6d5dTS4;WK|kiwPt;kWD(Ov z3t@2kIPQBXjS00@+ZZL}PZYG_pm5-KNU#a9s*4Ynq|uVKA0PASq~20+rBy$^DRwhA zyl7LvR$B=+Vtsn6jG^2-=F=AseGsT-8cO)sj#n4zKLl(hzLZ8n3`q)gFx{u4Wbin0 z2$RDCBUl8ha8O{I_W`3vFnJS`dQ9FD-VhEo8-a9G6;2nFKRvt3^pJ)ED(Le!y99r8 zhbRR2u>DM4gC$W{XMS3(Tuj5(PM_ZSMut@1OKjjvTk)@1(@$&2Ud04eo<@+ z+|e%m2$(ct zV#CCaiKAuTwj`0~A{~aMO)Yxp7oLkl(04)e)^kz3{e0C*_OHV!aKxUo?mu)H!GZg` zG(%o_(O0(y6NST8+j?okR{>+e;0veeTK`d)@!^-!#EZTf#zH`SjEOq9HmJKMe(OV~ zQ0YOdUL7XQ9-X(K+uHSkHJ4u27fgLMl|#&kYTDh;GPVFQvcJd1G|7l3hn0^(o#VAZ+1DH zyX$Pl>g}Dgq`TYaQpIq9pD3^*TM5+f`fX_k!?vFk!kCw+QOvO zYAaekD1krKQg`y{cV!uQ9H@p}+e)iG{bSYr!LR(G5&2sA=r#Epfj_Gog$fl;Dwy)c z>(_0q1N}WWc;21qlI??M+nr6rS4Mc7TcGE!27fMvw1X6%9+UQ+$8a+E?b^u$T~b`DJY-A(>b+sMhxd)=)!x`syp z_7BP+UBjwR*RFr|{GrqfNbwMK_aHoQ%g}Co@wvnDPyf7u$w^F3VR9OiGtCC@74g^x zcriKaL(o2Gvj|6DN}m#j%&k*Dox1(&pGda}W`D2&&_&Mpblq>Lt#i=Y54*jM$yYGx zYOdJ+m+wjv%=m%O0D-shkG_g8zAKG>Zyl5KJHPm%1P1sXXf-JBwx}ga-@!z*+SWFF zdYI?mxleX{#?ZRJ?R@dQb>Y~ab>epmOrf^X!Xb#wCKV*4=8AVI)=2-F$E5p*n6=~k z`5#N&nDp2&CcQSxwjZFs_p@#3qQC=BKAj*?*1qqn*!e;n6dGx#5r5xjfYUGu>^<%a z0-CVBl>FioXwe|=1LXTQv_Jk3fZJY&*)JOFR20+T46qFJGtgYQEe#8Hy7Om^b+EJe z^E{pBP;t%%YLafaEASPdOky$!RCo;m4o=z`ZCNAJSU0XMjnb7DFd4>V1Xlit%GPbK z6C5hzbvDaqKI1FRidU&-1*g?!v-ot>fuXy;u_H9?Ku7$|lC#peFJN|>oK;O0r@7x! zc4da#a8;DOHYn@J^{p;UCP@eBxZ5yR8XFs^+FG@t?dgzs9FVFj1i89^?q1=#8*R^qZomB!6PMV{t7*roJ2HY!dHu4+=IHKgK)8N&puU0K{g% z0x6lN;0A9p3XQGZ0848D7L>2S&fSkO8G`^_^XZ>JyusXyV9QXyi%RgNG#LsoMe8yp z(XnxLjAnHe)*$7;fAO=Gp#1U4I~FG~10FBleZOnaA-bKs)798KuWnDl@-;{XdR{}0 z>oNH1#2V~B`h)^Tc;LWOpj=wJzwWCDjXV+Cpm&*$Ylw2N3}pZPOjGig(tw(^U0T8p z%71)PtS1wI2nX(d&2`$Kd2e#asFxFsrwcoKh6;4rIb)-G*VsmAJb-pp7k97Bop+2 z6Kc)#KnXr`R#K}5gHN4C+9;8oEjZHu+Ycd0a!stAr0#AAg4f&NEc*SJm9e9^Ee#eS z6*-7c4;-B@KEh4Av?ibtl~#mE2USS}bgG*cFyg4%gc&R2K&z#+&62#D{x&Y^TkdZ1 ze3Q*)bHHzgb32>hAAeck!#21d`nVOh;IQ}dgY7+@!Hzb$tCM%Q+WZ{P5ArS>-{|gc z>S?lZc6U=O(b_+sud)f7H)D2JL0)OKwBhzi%u*Ax*h3$klR)?4jcv~d|Rl-*&p-Uxn1u%0}J+A{w65OGs zvfZLM5W`TOyhq2qx^1YODP!lw0GN_i*HxRPB0e!u0_FH=nzu?&?c$RYxcm1Ob&Hqr zso$fX5=G1w@u>+l_|s4=zRIrU1joEvq&0w6jt54tNcX6q%*-(5BLCJn<=is?zj6P_ zF11jmitpeK^<28<0*o3gs-&I?u}h6ndMZP*uYeGgFpk-mQVM2z1q!_i=tvcKYt_=L z>WBg;EP|!4*9iu}C{#8BM6|S5Jbv;tV1)u_Js7<2H9T7@;`Rw=Wfy!&WQe@Ch!E>w zXk6I$QtH8hBJKq#v>V18z8m10mD$GN|)#nzyN@he?UDqv_lV52S@NbP;SBm+Vknfetbpi`@kxl z6Giz}opH525$kkUPx4%P-}pFZ~a)hP`ouR^_8$2-aEg5DASRV z^J>L??~Gb;SHoNZDrYFQJLNw${6^RQE@8<0J&_-9xSh5kzl(43yN6HM+DEoLh#}MT z=F;<+Nv=VeuvF?cfv2ht3U`?>zV6dKy$?V&v>v<Ki}t%Li&rucMFQo(jl)@f*{hsrogb0h7S9hoNE zuCjQ3RXhkK!My{*9hW~|__g8e6bQFK7Rmefu5!Xn&MpY&0B3AHHqj;6c+5UgbJR3c z#bZzJTW5g%2Y$c!H2(mYiS6=G?huuscb>m^Sb8b-f~ikTjLK`$#KX0hQV{#swqFr9 zo`_xIKdeA5TbFuO0Y>E!`J?O6`WyG=Io>sB=i7MafIUzJ0ddoZ9_^MAYSM;#UhN}* zengxoNiF>KdjI0NGgzb=e^|^Ch`(`8bm#i}ya}TloG!9nBI& zD!|u%C5iNOZN7R*3Cat&GIj6kjKP{FYEJsddFar4_rA#qEzR~mM~efqkHDoMax>sn zFQo`=f%tHR2mPA1r9Mh1j6Z_QcM9%*;>B093!oZ})&(x>l-S(8zwIhiB{-YlrlCB5 zXYm}Khl}AOCTCgLR2lmKFhE1BQTbX>{)@9kCb)R-JKel1-fxThdwLuB{x-YA)zab? zdYj<`3eRWy94A^DB2t?fzDrd-3ecrb?F`df4^WqYI9Yqm^Zf~t0lV*3VavY@#NUDPdriH;J}>X}Fg$Sc#mMIYGhDg# z8$R9V{dK@ST(bM%s%4@dlz?vyxFK{ulLD~3Vr3k{j2OH+n|WhG6OtIgi|c`HT8iwm z+BQC;#jZ)62bWj1v=TpEv6-a_4=l5iDj)Ld*5GRm9BhVjf^a=QG>Yl569lX1x z&EDDK7`EG;%`hKs>i{a@fy8FuD)3zr%sZg%p)FdURF`(tZfJF{>K%{QsOsS}${d&p zbbfIyKaNSw&!EHrMZ(>a);i)FWgT^m6+r!ai&yc_SLj6l818FUKNm1$#Y$?08dz3d H6qNrDEV#&? literal 8775 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 diff --git a/src/stubber/board/createstubs_lvgl_min.py b/src/stubber/board/createstubs_lvgl_min.py index 5412c8895..cc2548419 100644 --- a/src/stubber/board/createstubs_lvgl_min.py +++ b/src/stubber/board/createstubs_lvgl_min.py @@ -1,297 +1,726 @@ -v='with' -u='stubber' -t='{}/{}' -s='method' -r='function' -q='bool' -p='str' -o='float' -n='int' -m='micropython' -l=Exception -k=TypeError -j=NameError -i=sorted -h=NotImplementedError -b='-' -a=',\n' -Z='dict' -Y='list' -X='tuple' -W=open -V=repr -T='cpu' -S='_' -R=len -Q=KeyError -P=IndexError -O=print -N=ImportError -M='family' -L=dir -K=True -J='.' -I=AttributeError -H='board' -A=False -G='/' -E=None -F=OSError -C='version' -B='' -import gc as D,os,sys -try:from ujson import dumps -except:from json import dumps -try:from machine import reset -except N:pass -try:from collections import OrderedDict as c -except N:from ucollections import OrderedDict as c -__version__='v1.16.2' -w=2 -x=2 -y=[J,'/lib','/sd/lib','/flash/lib','lib'] +""" +Create stubs for the lvgl modules on a MicroPython board. + +Note that the stubs can be very large, and it may be best to directly store them on an SD card if your device supports this. + +This variant was generated from createstubs.py by micropython-stubber v1.16.2 +""" +# Copyright (c) 2019-2023 Jos Verlinde + +import gc +# import logging +import os +import sys + +try: + from ujson import dumps +except: + from json import dumps + +try: + from machine import reset # type: ignore +except ImportError: + pass + +try: + from collections import OrderedDict +except ImportError: + from ucollections import OrderedDict # type: ignore + +__version__ = "v1.16.2" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] from time import sleep + + class Stubber: - def __init__(A,path=E,firmware_id=E): - B=firmware_id - try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise h('MicroPython 1.13.0 cannot be stubbed') - except I:pass - A._report=[];A.info=_info();D.collect() - if B:A._fwid=B.lower() - elif A.info[M]==m:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-v{version}-{port}'.format(**A.info) - A._start_free=D.mem_free() - if path: - if path.endswith(G):path=path[:-1] - else:path=get_root() - A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:d(path+G) - except F:O('error creating stub folder {}'.format(path)) - A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] - def get_obj_attributes(M,item_instance): - H=item_instance;C=[];J=[] - for A in L(H): - if A.startswith(S)and not A in M.modules:continue - try: - E=getattr(H,A) - try:F=V(type(E)).split("'")[1] - except P:F=B - if F in{n,o,p,q,X,Y,Z}:G=1 - elif F in{r,s}:G=2 - elif F in'class':G=3 - else:G=4 - C.append((A,V(E),V(type(E)),E,G)) - except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) - except MemoryError as K:sleep(1);reset() - C=i([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,J - def add_modules(A,modules):A.modules=i(set(A.modules)|set(modules)) - def create_all_stubs(A): - D.collect() - for B in A.modules:A.create_one_stub(B) - def create_one_stub(B,module_name): - C=module_name - if C in B.problematic:return A - if C in B.excluded:return A - H='{}/{}.py'.format(B.path,C.replace(J,G));D.collect();E=A - try:E=B.create_module_stub(C,H) - except F:return A - D.collect();return E - def create_module_stub(I,module_name,file_name=E): - H=file_name;C=module_name - if H is E:O=C.replace(J,S)+'.py';H=I.path+G+O - else:O=H.split(G)[-1] - if G in C:C=C.replace(G,J) - L=E - try:L=__import__(C,E,E,'*');T=D.mem_free() - except N:return A - d(H) - with W(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,I._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,C,B) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) - if C not in{'os','sys','logging','gc'}: - try:del L - except(F,Q):pass - try:del sys.modules[C] - except Q:pass - D.collect();return K - def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;C=indent;D.collect() - if N in K.problematic:return - S,L=K.get_obj_attributes(N) - if L:O(L) - for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',M]:continue - if E[0].isdigit():continue - if G==""and R(C)<=x*4: - U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=M - A='\n{}class {}({}):\n'.format(C,E,U) - if V:A+=C+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),C+' ',P+1);A=C+' def __init__(self, *argv, **kwargs) -> None:\n';A+=C+' ...\n\n';H.write(A) - elif any(A in G for A in[s,r,'closure']): - W=b;a=B - if P>0:a='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(C)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(C,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(C,E,a,W) - A+=C+' ...\n\n';H.write(A) - elif G=="":0 - elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] - if J in A and A[J]: - K=int(A[J]);R=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if R:A[V]=R - A[J]='v{}.{}'.format(K&255,K>>8&3) - if A[F]and not A[C].endswith(b):A[C]=A[C]+b - A[S]=f"{A[C]}-{A[F]}"if A[F]else f"{A[C]}";return A -def z(version): - A=version;B=J.join([str(A)for A in A[:3]]) - if R(A)>3 and A[3]:B+=b+A[3] - return B -def A0(info,desc=B): - L='with ';C=info;F=A - for G in[A+'/board_info.csv'for A in y]: - if e(G): - E=desc or C[H].strip();I=E.rfind(' with') - if I!=-1:J=E[:I].strip() - else:J=B - if A1(C,E,G,J):F=K;break - if not F: - E=desc or C[H].strip() - if L+C[T].upper()in E:E=E.split(L+C[T].upper())[0].strip() - C[H]=E - C[H]=C[H].replace(' ',S);D.collect() -def A1(info,descr,filename,short_descr): - D=short_descr;C=info;E=B - with W(filename,'r')as J: - while 1: - F=J.readline() - if not F:break - I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:C[H]=G;return K - elif D and I==D: - if v in D:C[H]=G;return K - E=G - if E:C[H]=E;return K - return A -def get_root(): - try:A=os.getcwd() - except(F,I):A=J - B=A - for B in[A,'/sd','/flash',G,J]: - try:C=os.stat(B);break - except F:continue - return B -def e(filename): - try: - if os.stat(filename)[0]>>14:return K - return A - except F:return A -def f():sys.exit(1) -def read_path(): - path=B - if R(sys.argv)==3: - A=sys.argv[1].lower() - if A in('--path','-p'):path=sys.argv[2] - else:f() - elif R(sys.argv)==2:f() - return path -def g(): - try:B=bytes('abc',encoding='utf8');C=g.__module__;return A - except(h,I):return K + "Generate stubs for modules in firmware" + + def __init__(self, path: str = None, firmware_id: str = None): # type: ignore + try: + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore + raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") + except AttributeError: + pass + # self.log = logging.getLogger("stubber") + self._report = [] # type: list[str] + self.info = _info() + # self.log.info("Port: {}".format(self.info["port"])) + # self.log.info("Board: {}".format(self.info["board"])) + gc.collect() + if firmware_id: + self._fwid = firmware_id.lower() + else: + if self.info["family"] == "micropython": + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + else: + self._fwid = "{family}-v{version}-{port}".format(**self.info) + self._start_free = gc.mem_free() # type: ignore + + if path: + if path.endswith("/"): + path = path[:-1] + else: + path = get_root() + + self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") + # self.log.debug(self.path) + try: + ensure_folder(path + "/") + except OSError: + print("error creating stub folder {}".format(path)) + self.problematic = [ + "upip", + "upysh", + "webrepl_setup", + "http_client", + "http_client_ssl", + "http_server", + "http_server_ssl", + ] + self.excluded = [ + "webrepl", + "_webrepl", + "port_diag", + "example_sub_led.py", + "example_pub_button.py", + ] + # there is no option to discover modules from micropython, list is read from an external file. + self.modules = [] # type: list[str] + + def get_obj_attributes(self, item_instance: object): + "extract information of the objects members and attributes" + # name_, repr_(value), type as text, item_instance + _result = [] + _errors = [] + # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + for name in dir(item_instance): + if name.startswith("_") and not name in self.modules: + continue + # self.log.debug("get attribute {}".format(name)) + try: + val = getattr(item_instance, name) + # name , item_repr(value) , type as text, item_instance, order + try: + type_text = repr(type(val)).split("'")[1] + except IndexError: + type_text = "" + if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: + order = 1 + elif type_text in {"function", "method"}: + order = 2 + elif type_text in ("class"): + order = 3 + else: + order = 4 + _result.append((name, repr(val), repr(type(val)), val, order)) + except AttributeError as e: + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) + except MemoryError as e: + # print("MemoryError: {}".format(e)) + sleep(1) + reset() + + # remove internal __ + # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) + _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) + gc.collect() + return _result, _errors + + def add_modules(self, modules): + "Add additional modules to be exported" + self.modules = sorted(set(self.modules) | set(modules)) + + def create_all_stubs(self): + "Create stubs for all configured modules" + # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + gc.collect() + for module_name in self.modules: + self.create_one_stub(module_name) + # self.log.info("Finally done") + + def create_one_stub(self, module_name: str): + if module_name in self.problematic: + # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + return False + if module_name in self.excluded: + # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + return False + + file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + gc.collect() + result = False + try: + result = self.create_module_stub(module_name, file_name) + except OSError: + return False + gc.collect() + return result + + def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore + """Create a Stub of a single python module + + Args: + - module_name (str): name of the module to document. This module will be imported. + - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + """ + if file_name is None: + fname = module_name.replace(".", "_") + ".py" + file_name = self.path + "/" + fname + else: + fname = file_name.split("/")[-1] + + if "/" in module_name: + # for nested modules + module_name = module_name.replace("/", ".") + + # import the module (as new_module) to examine it + new_module = None + try: + new_module = __import__(module_name, None, None, ("*")) + m1 = gc.mem_free() # type: ignore + # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + + except ImportError: + # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + return False + + # Start a new file + ensure_folder(file_name) + with open(file_name, "w") as fp: + # todo: improve header + info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) + fp.write(s) + fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + self.write_object_stub(fp, new_module, module_name, "") + + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + + if module_name not in {"os", "sys", "logging", "gc"}: + # try to unload the module unless we use it + try: + del new_module + except (OSError, KeyError): # lgtm [py/unreachable-statement] + pass + try: + del sys.modules[module_name] + except KeyError: + pass + gc.collect() + return True + + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): + "Write a module/object stub to an open file. Can be called recursive." + gc.collect() + if object_expr in self.problematic: + # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + return + + # # self.log.debug("DUMP : {}".format(object_expr)) + items, errors = self.get_obj_attributes(object_expr) + + if errors: + print(errors) + + for item_name, item_repr, item_type_txt, item_instance, _ in items: + # name_, repr_(value), type as text, item_instance, order + if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: + # do not create stubs for these primitives + continue + if item_name[0].isdigit(): + # self.log.warning("NameError: invalid name {}".format(item_name)) + continue + # Class expansion only on first 3 levels (bit of a hack) + if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: + # self.log.debug("{0}class {1}:".format(indent, item_name)) + superclass = "" + is_exception = ( + item_name.endswith("Exception") + or item_name.endswith("Error") + or item_name + in [ + "KeyboardInterrupt", + "StopIteration", + "SystemExit", + ] + ) + if is_exception: + superclass = "Exception" + s = "\n{}class {}({}):\n".format(indent, item_name, superclass) + # s += indent + " ''\n" + if is_exception: + s += indent + " ...\n" + fp.write(s) + return + # write classdef + fp.write(s) + # first write the class literals and methods + # self.log.debug("# recursion over class {0}".format(item_name)) + self.write_object_stub( + fp, + item_instance, + "{0}.{1}".format(obj_name, item_name), + indent + " ", + in_class + 1, + ) + # end with the __init__ method to make sure that the literals are defined + # Add __init__ + s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" + s += indent + " ...\n\n" + fp.write(s) + elif any(word in item_type_txt for word in ["method", "function", "closure"]): + # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # module Function or class method + # will accept any number of params + # return type Any/Incomplete + ret = "Incomplete" + first = "" + # Self parameter only on class methods/functions + if in_class > 0: + first = "self, " + # class method - add function decoration + if "bound_method" in item_type_txt or "bound_method" in item_repr: + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) + s += indent + " ...\n\n" + fp.write(s) + # self.log.debug("\n" + s) + elif item_type_txt == "": + # Skip imported modules + # fp.write("# import {}\n".format(item_name)) + pass + + elif item_type_txt.startswith(" dict[str, str] + info = OrderedDict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "UNKNOWN", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" + try: + info["version"] = version_str(sys.implementation.version) # type: ignore + except AttributeError: + pass + try: + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine + info["cpu"] = _machine.split("with")[-1].strip() + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + gc.collect() + read_boardname(info) + gc.collect() + + try: + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): + pass + # avoid build hashes + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() # type: ignore + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + info["version"] + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # versions from 1.10.0 to 1.20.0 do not have a micro .0 + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" + # simple to use version[-build] string + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" + + return info + + +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): + found = True + break + if not found: + # print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + +def find_board(info: dict, descr: str, filename: str, short_descr: str): + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + info["board"] = board_ + return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True + return False + + +def get_root() -> str: # sourcery skip: use-assigned-variable + "Determine the root folder of the device" + try: + c = os.getcwd() + except (OSError, AttributeError): + # unix port + c = "." + r = c + for r in [c, "/sd", "/flash", "/", "."]: + try: + _ = os.stat(r) + break + except OSError: + continue + return r + + +def file_exists(filename: str): + try: + if os.stat(filename)[0] >> 14: + return True + return False + except OSError: + return False + + +def show_help(): + # print("-p, --path path to store the stubs in, defaults to '.'") + sys.exit(1) + + +def read_path() -> str: + "get --path from cmdline. [unix/win]" + path = "" + if len(sys.argv) == 3: + cmd = (sys.argv[1]).lower() + if cmd in ("--path", "-p"): + path = sys.argv[2] + else: + show_help() + elif len(sys.argv) == 2: + show_help() + return path + + +def is_micropython() -> bool: + "runtime test to determine full or micropython" + # pylint: disable=unused-variable,eval-used + try: + # either test should fail on micropython + # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces + # Micropython : SyntaxError + # a = eval("1and 0") # lgtm [py/unused-local-variable] + # Eval blocks some minification aspects + + # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented + # Micropython: NotImplementedError + b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] + + # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute + # Micropython: AttributeError + c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] + return False + except (NotImplementedError, AttributeError): + return True + + def main(): - C='lvgl' - try:import lvgl as A - except l:return - B=C - try:B='lvgl-{0}_{1}_{2}-{3}-{4}'.format(A.version_major(),A.version_minor(),A.version_patch(),A.version_info(),sys.platform) - except l:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) - finally:stubber=Stubber(firmware_id=B) - stubber.clean();stubber.modules=['io','lodepng','rtch',C];D.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or g(): - try:A2=logging.getLogger(u);logging.basicConfig(level=logging.INFO) - except j:pass - if not e('no_auto_stubber.txt'): - try:D.threshold(4*1024);D.enable() - except BaseException:pass - main() \ No newline at end of file + try: + import lvgl # type: ignore + except Exception: + # print("\n\nNOTE: The `lvgl` module could not be found on this firmware\n\n") + return + # Specify firmware name & version + fw_id = "lvgl" + try: + fw_id = "lvgl-{0}_{1}_{2}-{3}-{4}".format( + lvgl.version_major(), + lvgl.version_minor(), + lvgl.version_patch(), + lvgl.version_info(), + sys.platform, + ) + except Exception: + fw_id = "lvgl-{0}_{1}_{2}_{3}-{4}".format(8, 1, 0, "dev", sys.platform) + finally: + stubber = Stubber(firmware_id=fw_id) + stubber.clean() + # modules to stub : only lvgl specifics + stubber.modules = ["io", "lodepng", "rtch", "lvgl"] # spell-checker: enable + + gc.collect() + + stubber.create_all_stubs() + stubber.report() + + +if __name__ == "__main__" or is_micropython(): + try: + log = logging.getLogger("stubber") + logging.basicConfig(level=logging.INFO) + # logging.basicConfig(level=logging.DEBUG) + except NameError: + pass + if not file_exists("no_auto_stubber.txt"): + try: + gc.threshold(4 * 1024) # type: ignore + gc.enable() + except BaseException: + pass + main() diff --git a/src/stubber/board/createstubs_lvgl_mpy.mpy b/src/stubber/board/createstubs_lvgl_mpy.mpy index 9609c5be1cde717c99e531562a782df183520436..6209ee7c37f829980409815c77dfdb8fa9c0a394 100644 GIT binary patch literal 7967 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 literal 8250 zcmZ`-Yit|Yb-o;tvP4Vt<%k|VZPFZ)qDVa{YAnAcineLVFRn~^Xa2 zDzbRT-geh10t0;l{m}wNTC`|UQIciZ+Ra+>d-M7cpo!DCTObIU{wRXD`5U0;&XBH? zAcQ@0?>YD0^ZxD`ovTDCMD+M=@eR$yY!QZbTp61F*3z;AZ@!Ik$MuAk5r188Dy-Pj3(oW1;lhB z{X{yNjiFk@tdz~s%@x`y5oyyoRGC}IA$@EnnSs~L^&If3l&3x`<)l0^B%|VVJS8FS zLN+F4rI2xB7YNS+jA|W9rhDd8wE)V`#)F*Gm;#ox6m=LP6q*E3o^V%cuY-MJVJ`zt&rV;MQ zWTn}-G>7z=1u>mOHS`4msG3Q|=aGIcp6Uf7qFHeoRf5}4Ws)*8>1-a{ITHubE%9U~ zAtj|02&GP~N=3mGoJmCUlj&>{8A9hr&R@8E9#v)*sJ;0loM?c9W9d2Yb|RjdnMXKM z_OO0N*)R80MW`r4$*ahal@d}kCm~|2JT-U;;ge&%zHD5)f%Klv?#^yR%vyNXfZyqi zz7KUCLY4FV0z3pS(nqt&Spn53FEEt84}yBiTS_9fG{|M%4r3WqGoP1IxhP`QH>izj zW*3(_AsHbjJK&{-|I9~-1hs?R)M5E)aB;QXq9m|9C|6W#2YV0$fmmkR5r)7wTBFq%3j82FMODQoOi>Ia_ zPWj1x)Ir3m#Ozc8HI-5u+<85neP7PW38(L^Gm6fdgDN=kO{Gy=U436_>ZZ%0pe zFET_*%qm5qJ~BB6VsKJQMkccoR2Q5P&F0k!3zY&xx(vDBq1w~{h;GjmA0)P|TPB%iU)W#f5? z3Iw1~7ctkUJEx{-_!=hCGbs?K!kXy}gq2oPUP5QcZnwXUgQ@t5~|dXFCo)WDuSAM9BCsFP%sfqPQ;?e5qoq>N=fsX>~X}*ASRC( zh|JdzlR-=xF)73(5tBek<_5aTTu1T&CXOP^G-4(Y6GhAw#Do#^J|aoxGLm)77-B9V zW)zXj%zJ2*38El#5s^9O0y@W>N6a}y8kw_*89~f28f4BOCV-eh#GFRVNfc#HA!Z0M zKE(JDBSKzA%B2!P%sgTiP?vVlgZeOJU`ER37mz6u0UV_H7C}`pDJQ~p0?#bK}w@{wk~*fKfnR zgyX4*n!$5&ogUnu%OhP~DjkW=U7 zC{oq}u%@e#W_vpTwkgi$kgm2o?3{*s8tEBbWk-inmpY~+gLDlPgE}BNBaobtMGxR( zFZ}nyNx#R6yk*(W#l>v;;sV_4DT@jk7BQMirSp~v$)a`uF{HCDsyF#k$LwM$8gMps zIlPpc9mF*K;YCQd8){bpDcVZt_DQs`RHLC36+!RXUR#2Z2vo=n7`J;mpU;4km&q-NOuFO|wDxa0+qqMdoxtWOwc$`9oZf}{G0V04=KAlqNeM9M)L@d>s zw*XvO-a?h7b#bZH0)?BjsQI7}+AV+)ht+_+)1Nqz?x59b)t^(a`YKZk(ErY2Ay+V%Aa?VXd)|5E^k6U`!Ygt^h zs!3)&Y_TpbS=%jEn$4xz5;(sRbOALi$Eb7*Z=na4MH|YHMTxD)kw_A9gx|@2z zOP$`tTi_zKr1R5Kwq5ZFu#~U?)AZI&?|2*OT2B3L{ladGde3%(&80}>td_%9;gmgH zN~tK_U#FOxMgQ>i_J3kDHoM(U|J&^j`YVmfGl$LY0JaV2y**w1{Go2U&DP!i>C)|* znB}%5X1P;)yY_ZfY{2$$mGp6Sx7o!zPw<%Gj^hfB#ITkl64r5K5?69_co#>ea1}?U zaWzNcSkIB`csECG7|C&tB#b1v4JCVcn?SB zG3LmEk$l9FMI-q-N0zXWBR4V2k!7QdI9X$q8BVS+%34m=8Rbe&-er`lIJp|vakAbh z@8;y1_c*y0n>g8El=pBl#(O#0c#)G?%yDvEkdsYD8Au$i=j3|az{w4TU~?lUH^Qrl zYl3Gp*BmeuaEnXRysxE&YY7kIusYqZPBr6{Zw9`l#mt$*!@DmV&Qso+j{v|Q3CH@GyTy*e)KspMuoySR@$RoqQaHMi`67-&2Y z1FZ+VTy2#1_Mr zhNc61jdG)@$NINO(1hvGBa~JSmRFK$FA4|6+D|T3b-KSHeADd$_G5V zys((=r$op*Bd?(&NWOY%c$gY~g&KYpl=(CKqk={t4Khot1Q!56&0W0EWw!RT^S$;% zLig(9fP-x^jS8slGA50${9~nAJtj>*@&{Ow=c~LL38Ku(xMZsvtu&Bk_Jo(dTUc<% z7`S82e|F78Dg;X0=gY3tQIC}(;BE@dy6o8*dx$!0Gn#PP4W3M3>uYcA5Eu#T_?#>_$&mxn|X?iH!VQ^YotS7)zEx@!@-* z=HAysKA$siN5jg_)q7s%S)iUJORU_s;RTIMM=)^<8WMUwyazPaedRw58aF%#MenoZ zI!od#nP$lpOBPr%&yu;0U9bIq^1^rRK0C*f$qojl@(bU&`-NlHETy>^~d`P^7G4Nt!gxxL{LZ)Mw zL){qIgr7*T~J0!|Z7lx*hC3_2(;b@l7T-i&tA1!({|Krs_Kp+&d zbI?El%?e>>Ssq;%8QHzPVj|rT*Y z8{=W(k+JNS+Y2$9+3xPOnH_eA*?i<^cWYN4zxufNWQ~tZZF}5&Xl%>(xG^deG8&uILA7 zT-L7_Viab{;uUgq@K7i<*>Yk|be^LruD1f_-qOb!anOP(|JuLFDE16FPpv|nzT zNdH6dDSh+xFaS3k+S~xi4T3ftyfzMNn`s6$z`iwFjE76^gSG3p2{&VM1UGhQU;ogb z3TT~`!wctUzMZ0izS?VV<~`I@)KZ9ZV@XyzNAVRH02CdXdfd%5~0 zCda>1{OU@<7#iq#eoRhca>`xt+OgNR*FUu7F!9Z%{?BdLW)dnK9MD2G?sH5|zxla? z`wT*1|ib(#S6gD08RON;Tg&+Gtw-HCfeS7okp;Py5#@GJK{C?0*(C}te z$$FszB=|1y7IofWs~5D2NKDTDw#7{Z&3!C4(i@)-Zz`|X;UA@~W^bZ^0ujLKPg@3{1+D;MTgvmG@Ku2s#y9NZctWJ0} zgtioAI+-nxTH2X*C|m&8`U#fACP3K_{@`lfK{bQ8t!Nv_6`5To*JW?vUpv-@h81yd zk6l&P5vSEauEMfHQPnG=kUyO#cbWaY5X?0j?{f59b_?bMh0EJJzTXs9OkP0LRS0}> z`KSK>E))x|AjpM~@6<}L2nIY3=xMCMLr;d!s*!nIczWj0y*i-~VoBdCe^Oa-kos`= zfVv|5?93kOGzQ>8>54X_;4^3CID|78eCpKEL6N-K0g*$$xfvAy$k}5!L?#Pg@U8gp z_R0`kp$%ej<+Xog#dM@d1P1gOTzQ0#0_iM}@KK-qx+RzEmS&6CK@Q{x0 zPXO!eg9&_&m5mCM+@!Bf`q+Soe`o6f?O4v!{u5u=dNAg@29$fRV0Mwt&ch4`U-?h1 z)7e14$R-tG^u2vTpea>E?Bj^Bd@kuLCRUPD(+)q2ktfY{N_+w$GdV2^R^GjIoZ z3*2%^KwB)iIfg^Ow=Lv*fAjZO&BT8Hu5aFl+`X&e|Oa9Z`d9fq%(@|Z?DF| z(vIvy9K{n@#4#-4Nj!z8aooMz#@_i=2s(&5|4Ccj*2WmVZtAzOR;Bl5ccoj+#25){2)u$nWLA7Q7nbNZBx7jLK z3$40W{FB5Tqa#gPWWMlUZEk0u$99nKFt<8zW@iN&W%h{&vGP9p^)vF6y?GCMh%XAo zlhtdG(@H8o+c13%X9dmk`v79+HiGv-ADZGXd=yGvu(N9$_cpy+|1iA?!tnDA`PP=# zhZcV8kX5(>Z-z`c0lnFPHe|zezV!`Q+9!V6f7{eP3zphsyX+|Z+Ud499LGHNZdb?JlNIR48=fgQ*c|lI;pg{F z^I*j0(2(ytg-yV{g|Zf<2~kwK^76|EkbT1s?@`TYL%Z$|KUja|zr-Gg?*1M6!)Lw$ z-#;$HUAN&M-gvv5erbGsF~)v$SJU2W?dfv_s-cD!1@vgxL=hcohgLiNa5Ovu>|WVk z!C%MliCG5(w=Oc$vaMY2v?bUXxIileZg78izybHSwJ6?#zx>~n?RTr;uL6O+aC9H! zULo|&U(t`HT9JxZx0F6Af+9h-vY&i{q%>f%;_3#Rc{|BFaeLVmG diff --git a/src/stubber/board/createstubs_mem_min.py b/src/stubber/board/createstubs_mem_min.py index ef72491b9..1f76a726c 100644 --- a/src/stubber/board/createstubs_mem_min.py +++ b/src/stubber/board/createstubs_mem_min.py @@ -1,303 +1,737 @@ -w='with' -v='stubber' -u='{}/{}' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n=TypeError -m=NameError -l=sorted -k=NotImplementedError -d='-' -c=',\n' -b='dict' -a='list' -Z='tuple' -Y='micropython' -X=str -W=repr -U='cpu' -T='_' -S=KeyError -R=open -Q=IndexError -P=ImportError -O='family' -N=len -M=dir -L=print -K=True -J='.' -I=AttributeError -H='board' -A=False -G='/' -E=None -F=OSError -D='version' -C='' -import gc as B,os,sys -try:from ujson import dumps -except:from json import dumps -try:from machine import reset -except P:pass -try:from collections import OrderedDict as e -except P:from ucollections import OrderedDict as e -__version__='v1.16.2' -x=2 -y=2 -f=[J,'/lib','/sd/lib','/flash/lib','lib'] +"""Create stubs for (all) modules on a MicroPython board. + + This variant of the createstubs.py script is optimised for use on low-memory devices, and reads the list of modules from a text file + `modulelist.txt` in the root or `libs` folder that should be uploaded to the device. + If that cannot be found then only a single module (micropython) is stubbed. + In order to run this on low-memory devices two additional steps are recommended: + - minifification, using python-minifier + to reduce overall size, and remove logging overhead. + - cross compilation, using mpy-cross, + to avoid the compilation step on the micropython device + +This variant was generated from createstubs.py by micropython-stubber v1.16.2 +""" +# Copyright (c) 2019-2023 Jos Verlinde + +import gc +# import logging +import os +import sys + +try: + from ujson import dumps +except: + from json import dumps + +try: + from machine import reset # type: ignore +except ImportError: + pass + +try: + from collections import OrderedDict +except ImportError: + from ucollections import OrderedDict # type: ignore + +__version__ = "v1.16.2" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] from time import sleep + + class Stubber: - def __init__(A,path=E,firmware_id=E): - C=firmware_id - try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') - except I:pass - A._report=[];A.info=_info();B.collect() - if C:A._fwid=C.lower() - elif A.info[O]==Y:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-v{version}-{port}'.format(**A.info) - A._start_free=B.mem_free() - if path: - if path.endswith(G):path=path[:-1] - else:path=get_root() - A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:g(path+G) - except F:L('error creating stub folder {}'.format(path)) - A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] - def get_obj_attributes(L,item_instance): - H=item_instance;D=[];J=[] - for A in M(H): - if A.startswith(T)and not A in L.modules:continue - try: - E=getattr(H,A) - try:F=W(type(E)).split("'")[1] - except Q:F=C - if F in{o,p,q,r,Z,a,b}:G=1 - elif F in{s,t}:G=2 - elif F in'class':G=3 - else:G=4 - D.append((A,W(E),W(type(E)),E,G)) - except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) - except MemoryError as K:sleep(1);reset() - D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) - def create_all_stubs(A): - B.collect() - for C in A.modules:A.create_one_stub(C) - def create_one_stub(C,module_name): - D=module_name - if D in C.problematic:return A - if D in C.excluded:return A - H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=A - try:E=C.create_module_stub(D,H) - except F:return A - B.collect();return E - def create_module_stub(I,module_name,file_name=E): - H=file_name;D=module_name - if H is E:N=D.replace(J,T)+'.py';H=I.path+G+N - else:N=H.split(G)[-1] - if G in D:D=D.replace(G,J) - L=E - try:L=__import__(D,E,E,'*');U=B.mem_free() - except P:return A - g(H) - with R(H,'w')as M:O=X(I.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,O,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,C) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: - try:del L - except(F,S):pass - try:del sys.modules[D] - except S:pass - B.collect();return K - def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() - if P in K.problematic:return - R,M=K.get_obj_attributes(P) - if M:L(M) - for(E,J,G,T,f)in R: - if E in['classmethod','staticmethod','BaseException',O]:continue - if E[0].isdigit():continue - if G==""and N(D)<=y*4: - U=C;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=O - A='\n{}class {}({}):\n'.format(D,E,U) - if V:A+=D+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[t,s,'closure']): - W=Y;X=C - if Q>0:X='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) - A+=D+' ...\n\n';H.write(A) - elif G=="":0 - elif G.startswith("='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if J in A and A[J]: - K=int(A[J]);N=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if N:A[T]=N - A[J]='v{}.{}'.format(K&255,K>>8&3) - if A[F]and not A[D].endswith(c):A[D]=A[D]+c - A[R]=f"{A[D]}-{A[F]}"if A[F]else f"{A[D]}";return A -def z(version): - A=version;B=J.join([X(A)for A in A[:3]]) - if N(A)>3 and A[3]:B+=d+A[3] - return B -def A0(info,desc=C): - L='with ';D=info;F=A - for G in[A+'/board_info.csv'for A in f]: - if h(G): - E=desc or D[H].strip();I=E.rfind(' with') - if I!=-1:J=E[:I].strip() - else:J=C - if A1(D,E,G,J):F=K;break - if not F: - E=desc or D[H].strip() - if L+D[U].upper()in E:E=E.split(L+D[U].upper())[0].strip() - D[H]=E - D[H]=D[H].replace(' ',T);B.collect() -def A1(info,descr,filename,short_descr): - D=short_descr;B=info;E=C - with R(filename,'r')as J: - while 1: - F=J.readline() - if not F:break - I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:B[H]=G;return K - elif D and I==D: - if w in D:B[H]=G;return K - E=G - if E:B[H]=E;return K - return A -def get_root(): - try:A=os.getcwd() - except(F,I):A=J - B=A - for B in[A,'/sd','/flash',G,J]: - try:C=os.stat(B);break - except F:continue - return B -def h(filename): - try: - if os.stat(filename)[0]>>14:return K - return A - except F:return A -def i():sys.exit(1) -def read_path(): - path=C - if N(sys.argv)==3: - A=sys.argv[1].lower() - if A in('--path','-p'):path=sys.argv[2] - else:i() - elif N(sys.argv)==2:i() - return path -def j(): - try:B=bytes('abc',encoding='utf8');C=j.__module__;return A - except(k,I):return K + "Generate stubs for modules in firmware" + + def __init__(self, path: str = None, firmware_id: str = None): # type: ignore + try: + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore + raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") + except AttributeError: + pass + # self.log = logging.getLogger("stubber") + self._report = [] # type: list[str] + self.info = _info() + # self.log.info("Port: {}".format(self.info["port"])) + # self.log.info("Board: {}".format(self.info["board"])) + gc.collect() + if firmware_id: + self._fwid = firmware_id.lower() + else: + if self.info["family"] == "micropython": + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + else: + self._fwid = "{family}-v{version}-{port}".format(**self.info) + self._start_free = gc.mem_free() # type: ignore + + if path: + if path.endswith("/"): + path = path[:-1] + else: + path = get_root() + + self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") + # self.log.debug(self.path) + try: + ensure_folder(path + "/") + except OSError: + print("error creating stub folder {}".format(path)) + self.problematic = [ + "upip", + "upysh", + "webrepl_setup", + "http_client", + "http_client_ssl", + "http_server", + "http_server_ssl", + ] + self.excluded = [ + "webrepl", + "_webrepl", + "port_diag", + "example_sub_led.py", + "example_pub_button.py", + ] + # there is no option to discover modules from micropython, list is read from an external file. + self.modules = [] # type: list[str] + + def get_obj_attributes(self, item_instance: object): + "extract information of the objects members and attributes" + # name_, repr_(value), type as text, item_instance + _result = [] + _errors = [] + # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + for name in dir(item_instance): + if name.startswith("_") and not name in self.modules: + continue + # self.log.debug("get attribute {}".format(name)) + try: + val = getattr(item_instance, name) + # name , item_repr(value) , type as text, item_instance, order + try: + type_text = repr(type(val)).split("'")[1] + except IndexError: + type_text = "" + if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: + order = 1 + elif type_text in {"function", "method"}: + order = 2 + elif type_text in ("class"): + order = 3 + else: + order = 4 + _result.append((name, repr(val), repr(type(val)), val, order)) + except AttributeError as e: + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) + except MemoryError as e: + # print("MemoryError: {}".format(e)) + sleep(1) + reset() + + # remove internal __ + # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) + _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) + gc.collect() + return _result, _errors + + def add_modules(self, modules): + "Add additional modules to be exported" + self.modules = sorted(set(self.modules) | set(modules)) + + def create_all_stubs(self): + "Create stubs for all configured modules" + # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + gc.collect() + for module_name in self.modules: + self.create_one_stub(module_name) + # self.log.info("Finally done") + + def create_one_stub(self, module_name: str): + if module_name in self.problematic: + # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + return False + if module_name in self.excluded: + # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + return False + + file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + gc.collect() + result = False + try: + result = self.create_module_stub(module_name, file_name) + except OSError: + return False + gc.collect() + return result + + def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore + """Create a Stub of a single python module + + Args: + - module_name (str): name of the module to document. This module will be imported. + - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + """ + if file_name is None: + fname = module_name.replace(".", "_") + ".py" + file_name = self.path + "/" + fname + else: + fname = file_name.split("/")[-1] + + if "/" in module_name: + # for nested modules + module_name = module_name.replace("/", ".") + + # import the module (as new_module) to examine it + new_module = None + try: + new_module = __import__(module_name, None, None, ("*")) + m1 = gc.mem_free() # type: ignore + # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + + except ImportError: + # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + return False + + # Start a new file + ensure_folder(file_name) + with open(file_name, "w") as fp: + # todo: improve header + info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) + fp.write(s) + fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + self.write_object_stub(fp, new_module, module_name, "") + + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + + if module_name not in {"os", "sys", "logging", "gc"}: + # try to unload the module unless we use it + try: + del new_module + except (OSError, KeyError): # lgtm [py/unreachable-statement] + pass + try: + del sys.modules[module_name] + except KeyError: + pass + gc.collect() + return True + + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): + "Write a module/object stub to an open file. Can be called recursive." + gc.collect() + if object_expr in self.problematic: + # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + return + + # # self.log.debug("DUMP : {}".format(object_expr)) + items, errors = self.get_obj_attributes(object_expr) + + if errors: + print(errors) + + for item_name, item_repr, item_type_txt, item_instance, _ in items: + # name_, repr_(value), type as text, item_instance, order + if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: + # do not create stubs for these primitives + continue + if item_name[0].isdigit(): + # self.log.warning("NameError: invalid name {}".format(item_name)) + continue + # Class expansion only on first 3 levels (bit of a hack) + if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: + # self.log.debug("{0}class {1}:".format(indent, item_name)) + superclass = "" + is_exception = ( + item_name.endswith("Exception") + or item_name.endswith("Error") + or item_name + in [ + "KeyboardInterrupt", + "StopIteration", + "SystemExit", + ] + ) + if is_exception: + superclass = "Exception" + s = "\n{}class {}({}):\n".format(indent, item_name, superclass) + # s += indent + " ''\n" + if is_exception: + s += indent + " ...\n" + fp.write(s) + return + # write classdef + fp.write(s) + # first write the class literals and methods + # self.log.debug("# recursion over class {0}".format(item_name)) + self.write_object_stub( + fp, + item_instance, + "{0}.{1}".format(obj_name, item_name), + indent + " ", + in_class + 1, + ) + # end with the __init__ method to make sure that the literals are defined + # Add __init__ + s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" + s += indent + " ...\n\n" + fp.write(s) + elif any(word in item_type_txt for word in ["method", "function", "closure"]): + # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # module Function or class method + # will accept any number of params + # return type Any/Incomplete + ret = "Incomplete" + first = "" + # Self parameter only on class methods/functions + if in_class > 0: + first = "self, " + # class method - add function decoration + if "bound_method" in item_type_txt or "bound_method" in item_repr: + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) + s += indent + " ...\n\n" + fp.write(s) + # self.log.debug("\n" + s) + elif item_type_txt == "": + # Skip imported modules + # fp.write("# import {}\n".format(item_name)) + pass + + elif item_type_txt.startswith(" dict[str, str] + info = OrderedDict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "UNKNOWN", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" + try: + info["version"] = version_str(sys.implementation.version) # type: ignore + except AttributeError: + pass + try: + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine + info["cpu"] = _machine.split("with")[-1].strip() + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + gc.collect() + read_boardname(info) + gc.collect() + + try: + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): + pass + # avoid build hashes + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() # type: ignore + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + info["version"] + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # versions from 1.10.0 to 1.20.0 do not have a micro .0 + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" + # simple to use version[-build] string + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" + + return info + + +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): + found = True + break + if not found: + # print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + +def find_board(info: dict, descr: str, filename: str, short_descr: str): + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + info["board"] = board_ + return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True + return False + + +def get_root() -> str: # sourcery skip: use-assigned-variable + "Determine the root folder of the device" + try: + c = os.getcwd() + except (OSError, AttributeError): + # unix port + c = "." + r = c + for r in [c, "/sd", "/flash", "/", "."]: + try: + _ = os.stat(r) + break + except OSError: + continue + return r + + +def file_exists(filename: str): + try: + if os.stat(filename)[0] >> 14: + return True + return False + except OSError: + return False + + +def show_help(): + # print("-p, --path path to store the stubs in, defaults to '.'") + sys.exit(1) + + +def read_path() -> str: + "get --path from cmdline. [unix/win]" + path = "" + if len(sys.argv) == 3: + cmd = (sys.argv[1]).lower() + if cmd in ("--path", "-p"): + path = sys.argv[2] + else: + show_help() + elif len(sys.argv) == 2: + show_help() + return path + + +def is_micropython() -> bool: + "runtime test to determine full or micropython" + # pylint: disable=unused-variable,eval-used + try: + # either test should fail on micropython + # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces + # Micropython : SyntaxError + # a = eval("1and 0") # lgtm [py/unused-local-variable] + # Eval blocks some minification aspects + + # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented + # Micropython: NotImplementedError + b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] + + # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute + # Micropython: AttributeError + c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] + return False + except (NotImplementedError, AttributeError): + return True + + def main(): - E='/modulelist.txt';stubber=Stubber(path=read_path());stubber.clean();stubber.modules=[] - for C in f: - try: - F=B.mem_free() - with R(C+E)as D: - L('Debug: List of modules: '+C+E);A=D.readline() - while A: - A=A.strip() - if N(A)>0 and A[0]!='#':stubber.modules.append(A) - A=D.readline() - B.collect();L('Debug: Used memory to load modulelist.txt: '+X(F-B.mem_free())+' bytes');break - except Exception:pass - if not stubber.modules:stubber.modules=[Y] - B.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or j(): - try:A2=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except m:pass - if not h('no_auto_stubber.txt'): - try:B.threshold(4*1024);B.enable() - except BaseException:pass - main() \ No newline at end of file + stubber = Stubber(path=read_path()) + # stubber = Stubber(path="/sd") + # Option: Specify a firmware name & version + # stubber = Stubber(firmware_id='HoverBot v1.2.1') + stubber.clean() + # Read stubs from modulelist in the current folder or in /libs + # fall back to default modules + stubber.modules = [] # avoid duplicates + for p in LIBS: + try: + _1 = gc.mem_free() # type: ignore + with open(p + "/modulelist.txt") as f: + print ("Debug: List of modules: " + p + "/modulelist.txt") + line = f.readline() + while line: + line = line.strip() + if len(line) > 0 and line[0] != "#": + stubber.modules.append(line) + line = f.readline() + gc.collect() # type: ignore + print ("Debug: Used memory to load modulelist.txt: " + str(_1 - gc.mem_free()) + " bytes") # type: ignore + break + except Exception: + pass + if not stubber.modules: + stubber.modules = ["micropython"] + # print("Could not find modulelist.txt, using default modules") + + gc.collect() + + stubber.create_all_stubs() + stubber.report() + + +if __name__ == "__main__" or is_micropython(): + try: + log = logging.getLogger("stubber") + logging.basicConfig(level=logging.INFO) + # logging.basicConfig(level=logging.DEBUG) + except NameError: + pass + if not file_exists("no_auto_stubber.txt"): + try: + gc.threshold(4 * 1024) # type: ignore + gc.enable() + except BaseException: + pass + main() diff --git a/src/stubber/board/createstubs_mem_mpy.mpy b/src/stubber/board/createstubs_mem_mpy.mpy index 32f83286302c5ecc5eddc2fcab92e4a0b1373e35..66f04ca0cb160398f948ed9e2cd0b5be2c0edaa6 100644 GIT binary patch literal 7966 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 ZInX^1w9v29$_dcr=s;k2>ERWS{}%(GKJ5Si literal 8286 zcmZ`;d2Acmd4C*{GDT6+ zWknX>*xT-Iiqz;0^p6$=(iTOFin=UYyID)VH`gCQkvNIF1%jY0iXw=be*^S;GnDIW z5qiaW?|a90|Gsay=gN^uYHw{4vSKtZ=JM0yx%SLFs?pBI^HZpr62`?W(k(1@EG!~@ zQp``KV+c=7r-XbwokELJhi)Q~j^+_L!L%W@ONYn-5|)mU$#NkxjSTvUXfmFdM@&1? zji;m87^D`_Gw_(ck%Kj@{H@E1IWdo_lTl$Ro)Qsv zAsZ93V$2^G@`w}CiG(Q2kwbOUZ_lb{y4t(E?QW#)NW{lcbw@5H4~!iXiD+(09+%S< zT`nPt8Klj}lOn1fDXHsZC&m2P^yDO{&W%TNabYl>nut##T|%4@6G(gJ{HY6w%};@N zQ|Uwu>BUrZJRu@x5|I{dE)Vut&?Rri;#ovmnNg%Qr&DGm@#^aTe(^^Flg_^z;D^&`zh~b4WKEPj!P5(X23q%E4@?JV_Tb>1-a%IUNVqP4Q$V zAtuEXFr`M-rlOz<&LpDwiF7uJszc|8&tJH59+hY2slNFn+*l14$I`Q4?L<5^J%?~) z&%(NC`MlJnjZjwAC99(9te6m^IS~;<`Kf`+2%jA7_GRP3O{8k4F@&gp5&%+>|{1lUjEe&#+H^W#4>F4rdDi=kp@&vJw zer92@9fA>JvJD<;_+xG%5>yX#QiJ8Ez{C|gvmC(EfK*nY9_T_0IAV!$AqJUT8QET)8XES{PK zKjkNSQ5zAo@#1n|2!4!0%1;d>*NGLFRJ(MeEiPDo70#2B(tGo{CGM56h8Ha=S6geR7$ObWI%T^n@wj?X!0gD z!>7HyU5Ba{Iw4HD79scG1A&}K=ccnF(&xm)gv*TBy`4IQkIQr!1(NeMlXNfPjf;ay%C8L+tTMF(uAr zvVDk|MobyRVXh!1 zgqX`{gc(63$y`D~CWy{47ZGy-kt@u3MCzGyh|Dr)5i^XKAvD08K}-NK1Bf||n3E{V zoI;ErF@uQlAqH?c5-EW?NXyJ21^|Bob*Km2s0Tv;X2fiM9vLGM04o}95u}ZYIRP*q zzO&R82|!T5Ee`OMhNDd8_DmFkz;1vLNdjs@*rx=5p$_Rpm@CDVe3Ye^MC74*B7?Y6 zI8kFEOk-JI(gW}TRw5ivMU-fsm1=dsD3?c?+Eh9cozAD_7=*glo}UA%z7*)~a!JxO zOhkcE%$!e`^4L59B|yxY0f;nuai+TsfR-X-4r!|PhV4^OS&@#>l()6XNTFfcGDuU? zq1;W~tuU+ei{sOiN6lw}Vopz(OT3Sok;YkC3gv)1082VMPlbT$3sV_z_O7A3t>@xG zHhpm(3U4kf&tM@>T5?lI^#sCFW!M%k=`@&-DQQ*-<0c^1WUkfR)@MEscu&t%(KGZzVHf5#3yb~oy$WCh#kR0W?*ukN zA_uq7E535s!Xmwjf3tC6@ptcf1J{Z*s4fj9#bvXbd7he^TERn&-oTro(wfuxDKYDk zZ30WO+hEc7#!PQn8)=$OeKpD9v{@;{?VxkX6FH0d=ry>drbA8@xv6Uxax>`f60Uz> zRL$1rX8F$s9~jaPJmndDSz%&rwgRQQtD~1c(%EdacDg=ZysM9y@0w%gPpa-#-POkW ztsiQ|4{JJ2t-SqR9y1(i!)06_R&(S!)^KDDmviKOypNm3T8>0;1xG%>I*vpQWSk>{ zfy6i>8ps4kCJkhYBXL~GksDagk(;=RBMDs1ktD9+ND5<)qz!OM#z4Ntkt{ZFB!^j! zQ@BvP$#&w)jQwTQJa}tI}1J?lGja*}(x`3M;s>XMk znz*L$5DqKTgUVDjM%PWSZf-JhrtnbZ6$APDm;S-<5G>Uc@F7^TG#%n3LwKl8S-S{V zP%>X4tH!XElURw9YT?glkTkd%+i(lEJ2jlNzkpj|v!kh%YYks^Bkc4roYSr1y4?(S z#9hX{>sE6~gH+>CjdW|cw7Z;}aqr`9xwYJFcLlfP1{bK@U~07+OkH7+IP7{g7%&jE z2l;6MV8j#yI1aGOUS)!aezN3__uG^@yWD2M}pp2C3e?&jXtqN~;hsmAr~BL+G(o z?;zFt64iSIg!vQvqk_syYNZOIlS~DGPg4i)?J!xoTzq%)5pU*#S)U|HvO;Nu00ns6=owEA1=k>O{+Rgk#_J(B}ab%rOe)SoNP>HIgzfCD!?} z%eAmX7DFsazw(dpI%Dq$B^3@!%7!3c`4tkqh*Zhv>x=%8qVYN_>AWic>0)rHoe6FG zPO`T=Xq(p?dy8;YgO@SpF=?cm7~rW3=-KWf%yvC08hET!^`-w}n3c--DmdX)Q8EM` zX~N_kzM8M$F>l~m=RP=l5EBz7W=sz8wY<@(0g^@5QXdrlSpSf96J9El%!Pp6>EZ1r zOG{s;(_(U%_`}5=CwlBePgqH{;!#D0f1!H1Zal$~JP1Ct4r1zG5Bhxez$YqJI<&Ix zVV(uRELm2vY+l3QQ;PlLoY&q2`pEQzw@1C~VCS(c<&l4MDu zZQpCZpSv3; z&luKVBfsC+yT0v;7fbO*w8`P!GGx=eR)RDwi2)#YofueEULzQe{q{7lWw%? zQDI_pt2~nG@tY`Eb1(uUY0v1%d&E^31uI5|+3jK>WITaM*sB`sDs~usF5v@%o?Mk` z3!}?-LxN;?VA29nsxN>QCRs8}Ek~svE_zh|?NNb4z!j2xpqdz@ibB}F$B*ud3|DS1 z8;Ko!9QJhwh2O{TA0&3EMzR*JTU;)awWqnbvjRI0f`wSALZD+yX^cs$u@~mL6=R;2 zG;%a~nK$~t_9uZ#xZSa`>Sdk`RVi_G61-F)jO|IWCj9BezcL&p4r!lcm6{7NtEt)9 zZ8h1NZ6?$4F@9Bq4j+V9~ zCX?lu-C?qJcpa{G$jj@VE~n{`wXKnFc!r7RIVL?X)?coCfr=sRe| z5ZdIZ7s15P+{ib+@_&o4Wa%@AUded(*FW+983B9Qj8<&CzU5V&tfvD^j=`{+-gg`m z$c#Q`*=yT=>wf>>md(gF8GApoVyn?xX5)YsvT~nc^6u_0Y}}{d3M&WZ4GM3D)GMD_ zSxowky{lI2WnlBb?gO&x)r3Fe-`RybxX<{5zjfUA1(aW>wb6_q$;JRoF!4Fd-lv%4 z|4Cufc7V!U_n`1&|4B>+ZFTpX8($Bex^FeS_Fv&mAf8vnn-wV!c*}r=?*e~Fnb%nl zc-1mbO#Hvi^j`>A$nwfR==%rl-d0b!a@KkZdJ6i@VsZ+T)6VkO z{@{jkzrk8h@Av&%fo@F5z?cH_`ER<)FiaEUm_Xr5!s848=eVt*bg;o%A1a*{t@W4; zVKR)#SvdMb|KO&rp63+?_05e|gIDvGv3+CI*u2%)+uZ0?f%WMWJhaO<@50RYqXm1l zy(XZuW4ocX(asLlmg1ZxqNA)7(m_E*KG^BURSxMPq)I))Z#j*Hsign){^oAp8J>iLUUME^kM(BXj}^ zA0W#~IHubU)It&Op=bzCavladrNoo=DTx;p#^Bylk6CgZN+SifKqcLKVGRxqITef( z!hu={tx8Ixix=fZ+6X{lmAgHtQohZlpzu+E3Ix8B-YI;m2OziC*(+a7#VLB3oxOYu z38e&09tR_KB|z<|A~E0yYpISO&WPd8U~7 zOaCxzEaPpEtso7>e(-8g!q7zi6DF5;ir^?rLU02eu}v-&a5}Iu?okoiRP52o&Am~R zi*Z5bvaD1+&i0Liu%o|oGv7ib6Qtf{bpyF1RY?1ZAhi|#xovfDNM`ru+7)>t>9k-n zLiZJlieOh{`p0wR9&@l8+_`Gy9k#A3POs@u;mY=o?>B{IqX#f`1zcZT`kDVf3&p}K zaC0H#JGC4vf(DNRI_hn((UYOGif0;|_{?5DMok!eYS+*~k?igO%fa8=4hp|#@2WmR-Y4}08weO(<+o2l1ja=wsCX4$Dy%|klAKMqT0AB^L3 ztfZ9}Nsc}?>DLDM{5x9@Xw!0@wxIaJ)`L;sb)c-jg4snnI}bA)eC0p2MrZv21DlkY zL2=yzMshuS(=!Kd;!DsY(hVNfYiO*gSeJYO@EvWw&ENeL&S*zJrG{yv#ou_@i?&#j z8^z$oubd0{-rM|t#M8b(5PWNMRL=E%&`iE5vU};rrnhK2P-@r%=kN%St7haJZc7zzUGxb3tP{w ztveWi+6l0fto8RktG%LF3g8k>N^t)F4zI4__Z(#_D>&>ZEAnc5)ludwiwyU4mVN&R zHZ1o*pDR6(6?@b+!?(d&i=%c!{|KQy(A!OhuY#_Hir_1JZ3|x+m8UFyGg*{n49nmC zjQoJ=JO(}&M}FeJAk%`hR?*Su=GJTf_X=B^A^-CNtAnRUWdr1>#2?@& z9>)TXVG&Q@Nj!z)&Ppr$$*)4tMAZ6ET5Gp9M)3_}ua&isrC(avkA8LMmtF?E2Zr~* zSCV5H+U2wIczIXmM;9;Ro5o(52s1C^8^(#!+^gEUKe{E{IX<9I9w_|Wb7XlNa?6-< zqhjz5i0pyNwF9jQwA6Qg?7vXF6Y>wOKpw(i_ZN_UDspi^Y1@A;x9yeNEXlxT=-0c2 zKS+FHu%*cXsj=|ytxkK7+j^L9Gqu=oW@j0?<%%b6#7g_=E70&$_Vzlo5uX=|Co7=i z)ylE_Y{U39ob{@n-v<~ww-LM#0?`#K`RDVKHH#NM-|q2JS|sFnY0)Bv=sN3bo~!m*NW{T zZ{Gz?dxVes?;2e*plOrzj&!i_YrE5Ivz>4^cRAWtpDaUDUh_<@VzbatUwwYxI0s5> z4i5UhTi68To8Ob7G$FD`S6_bd0K#wR;X0L!HnnU1s}I&*`9qNI(Br?g@bHZ-XLkDGGPs{}{Aw$Vrsk?YupfjT2m-K(*-w{^DkfT12iv_a+*1|sg2 zKPC^sAoN!Pu(t;EmPu0R5xm?l!8@i8?6G%30;E-l{ma6ge!q^W?;Yra#3!dQ(O^=J z$v$}X1Rm;IqJ>bW5|Vhy5L8UH03E>})_ufUNyWW}K0Dv)bX#nFttOAHgD-!?I-!GN ziOPdK637Fs4*ZPaL`8VlgiwwQ|B-4ZP=H=QX*r--np;_h9~Vx?;VrC;-?y?$XW=y( z08f24)@kTH1@R&Fp>4jrUI<}Q{WJe?5#Dd;3ptob*}FbiyBCP`A}wSYL}#h7@u+q& t!Sv$(5$XDv{8HpC^;^FGx=k+|gtj*AR4H;QKfZwQ1`r+|EIfk3{{r-8hOGbq diff --git a/src/stubber/board/createstubs_min.py b/src/stubber/board/createstubs_min.py index e01b97706..ad7e11574 100644 --- a/src/stubber/board/createstubs_min.py +++ b/src/stubber/board/createstubs_min.py @@ -1,292 +1,954 @@ -y='with' -x='pyb' -w='stubber' -v='{}/{}' -u='logging' -t='sys' -s='method' -r='function' -q='bool' -p='str' -o='float' -n='int' -m=TypeError -l=NameError -k=sorted -j=NotImplementedError -d='pycom' -c='-' -b=',\n' -a='dict' -Z='list' -Y='tuple' -X='micropython' -W=open -V=repr -T='cpu' -S='_' -R=len -Q=KeyError -P=IndexError -O=print -N=ImportError -M='family' -L=dir -K=True -J='.' -I=AttributeError -H='board' -A=False -G='/' -E=None -F=OSError -C='version' -B='' -import gc as D,os,sys -try:from ujson import dumps -except:from json import dumps -try:from machine import reset -except N:pass -try:from collections import OrderedDict as e -except N:from ucollections import OrderedDict as e -__version__='v1.16.2' -z=2 -A0=2 -A1=[J,'/lib','/sd/lib','/flash/lib','lib'] +""" +Create stubs for (all) modules on a MicroPython board +""" +# Copyright (c) 2019-2023 Jos Verlinde + +import gc +# import logging +import os +import sys + +try: + from ujson import dumps +except: + from json import dumps + +try: + from machine import reset # type: ignore +except ImportError: + pass + +try: + from collections import OrderedDict +except ImportError: + from ucollections import OrderedDict # type: ignore + +__version__ = "v1.16.2" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] from time import sleep + + class Stubber: - def __init__(A,path=E,firmware_id=E): - B=firmware_id - try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') - except I:pass - A._report=[];A.info=_info();D.collect() - if B:A._fwid=B.lower() - elif A.info[M]==X:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-v{version}-{port}'.format(**A.info) - A._start_free=D.mem_free() - if path: - if path.endswith(G):path=path[:-1] - else:path=get_root() - A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:f(path+G) - except F:O('error creating stub folder {}'.format(path)) - A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] - def get_obj_attributes(M,item_instance): - H=item_instance;C=[];J=[] - for A in L(H): - if A.startswith(S)and not A in M.modules:continue - try: - E=getattr(H,A) - try:F=V(type(E)).split("'")[1] - except P:F=B - if F in{n,o,p,q,Y,Z,a}:G=1 - elif F in{r,s}:G=2 - elif F in'class':G=3 - else:G=4 - C.append((A,V(E),V(type(E)),E,G)) - except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) - except MemoryError as K:sleep(1);reset() - C=k([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,J - def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) - def create_all_stubs(A): - D.collect() - for B in A.modules:A.create_one_stub(B) - def create_one_stub(B,module_name): - C=module_name - if C in B.problematic:return A - if C in B.excluded:return A - H='{}/{}.py'.format(B.path,C.replace(J,G));D.collect();E=A - try:E=B.create_module_stub(C,H) - except F:return A - D.collect();return E - def create_module_stub(I,module_name,file_name=E): - H=file_name;C=module_name - if H is E:O=C.replace(J,S)+'.py';H=I.path+G+O - else:O=H.split(G)[-1] - if G in C:C=C.replace(G,J) - L=E - try:L=__import__(C,E,E,'*');T=D.mem_free() - except N:return A - f(H) - with W(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,I._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,C,B) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) - if C not in{'os',t,u,'gc'}: - try:del L - except(F,Q):pass - try:del sys.modules[C] - except Q:pass - D.collect();return K - def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;C=indent;D.collect() - if N in K.problematic:return - S,L=K.get_obj_attributes(N) - if L:O(L) - for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',M]:continue - if E[0].isdigit():continue - if G==""and R(C)<=A0*4: - U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=M - A='\n{}class {}({}):\n'.format(C,E,U) - if V:A+=C+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),C+' ',P+1);A=C+' def __init__(self, *argv, **kwargs) -> None:\n';A+=C+' ...\n\n';H.write(A) - elif any(A in G for A in[s,r,'closure']): - W=b;X=B - if P>0:X='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(C)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(C,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(C,E,X,W) - A+=C+' ...\n\n';H.write(A) - elif G=="":0 - elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] - if J in A and A[J]: - K=int(A[J]);R=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if R:A[V]=R - A[J]='v{}.{}'.format(K&255,K>>8&3) - if A[F]and not A[C].endswith(b):A[C]=A[C]+b - A[S]=f"{A[C]}-{A[F]}"if A[F]else f"{A[C]}";return A -def A2(version): - A=version;B=J.join([str(A)for A in A[:3]]) - if R(A)>3 and A[3]:B+=c+A[3] - return B -def A3(info,desc=B): - L='with ';C=info;F=A - for G in[A+'/board_info.csv'for A in A1]: - if g(G): - E=desc or C[H].strip();I=E.rfind(' with') - if I!=-1:J=E[:I].strip() - else:J=B - if A4(C,E,G,J):F=K;break - if not F: - E=desc or C[H].strip() - if L+C[T].upper()in E:E=E.split(L+C[T].upper())[0].strip() - C[H]=E - C[H]=C[H].replace(' ',S);D.collect() -def A4(info,descr,filename,short_descr): - D=short_descr;C=info;E=B - with W(filename,'r')as J: - while 1: - F=J.readline() - if not F:break - I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:C[H]=G;return K - elif D and I==D: - if y in D:C[H]=G;return K - E=G - if E:C[H]=E;return K - return A -def get_root(): - try:A=os.getcwd() - except(F,I):A=J - B=A - for B in[A,'/sd','/flash',G,J]: - try:C=os.stat(B);break - except F:continue - return B -def g(filename): - try: - if os.stat(filename)[0]>>14:return K - return A - except F:return A -def h():sys.exit(1) -def read_path(): - path=B - if R(sys.argv)==3: - A=sys.argv[1].lower() - if A in('--path','-p'):path=sys.argv[2] - else:h() - elif R(sys.argv)==2:h() - return path -def i(): - try:B=bytes('abc',encoding='utf8');C=i.__module__;return A - except(j,I):return K -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',u,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',X,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',x,d,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',t,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];D.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or i(): - try:A5=logging.getLogger(w);logging.basicConfig(level=logging.INFO) - except l:pass - if not g('no_auto_stubber.txt'): - try:D.threshold(4*1024);D.enable() - except BaseException:pass - main() \ No newline at end of file + "Generate stubs for modules in firmware" + + def __init__(self, path: str = None, firmware_id: str = None): # type: ignore + try: + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore + raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") + except AttributeError: + pass + # self.log = logging.getLogger("stubber") + self._report = [] # type: list[str] + self.info = _info() + # self.log.info("Port: {}".format(self.info["port"])) + # self.log.info("Board: {}".format(self.info["board"])) + gc.collect() + if firmware_id: + self._fwid = firmware_id.lower() + else: + if self.info["family"] == "micropython": + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + else: + self._fwid = "{family}-v{version}-{port}".format(**self.info) + self._start_free = gc.mem_free() # type: ignore + + if path: + if path.endswith("/"): + path = path[:-1] + else: + path = get_root() + + self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") + # self.log.debug(self.path) + try: + ensure_folder(path + "/") + except OSError: + print("error creating stub folder {}".format(path)) + self.problematic = [ + "upip", + "upysh", + "webrepl_setup", + "http_client", + "http_client_ssl", + "http_server", + "http_server_ssl", + ] + self.excluded = [ + "webrepl", + "_webrepl", + "port_diag", + "example_sub_led.py", + "example_pub_button.py", + ] + # there is no option to discover modules from micropython, list is read from an external file. + self.modules = [] # type: list[str] + + def get_obj_attributes(self, item_instance: object): + "extract information of the objects members and attributes" + # name_, repr_(value), type as text, item_instance + _result = [] + _errors = [] + # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + for name in dir(item_instance): + if name.startswith("_") and not name in self.modules: + continue + # self.log.debug("get attribute {}".format(name)) + try: + val = getattr(item_instance, name) + # name , item_repr(value) , type as text, item_instance, order + try: + type_text = repr(type(val)).split("'")[1] + except IndexError: + type_text = "" + if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: + order = 1 + elif type_text in {"function", "method"}: + order = 2 + elif type_text in ("class"): + order = 3 + else: + order = 4 + _result.append((name, repr(val), repr(type(val)), val, order)) + except AttributeError as e: + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) + except MemoryError as e: + # print("MemoryError: {}".format(e)) + sleep(1) + reset() + + # remove internal __ + # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) + _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) + gc.collect() + return _result, _errors + + def add_modules(self, modules): + "Add additional modules to be exported" + self.modules = sorted(set(self.modules) | set(modules)) + + def create_all_stubs(self): + "Create stubs for all configured modules" + # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + gc.collect() + for module_name in self.modules: + self.create_one_stub(module_name) + # self.log.info("Finally done") + + def create_one_stub(self, module_name: str): + if module_name in self.problematic: + # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + return False + if module_name in self.excluded: + # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + return False + + file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + gc.collect() + result = False + try: + result = self.create_module_stub(module_name, file_name) + except OSError: + return False + gc.collect() + return result + + def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore + """Create a Stub of a single python module + + Args: + - module_name (str): name of the module to document. This module will be imported. + - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + """ + if file_name is None: + fname = module_name.replace(".", "_") + ".py" + file_name = self.path + "/" + fname + else: + fname = file_name.split("/")[-1] + + if "/" in module_name: + # for nested modules + module_name = module_name.replace("/", ".") + + # import the module (as new_module) to examine it + new_module = None + try: + new_module = __import__(module_name, None, None, ("*")) + m1 = gc.mem_free() # type: ignore + # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + + except ImportError: + # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + return False + + # Start a new file + ensure_folder(file_name) + with open(file_name, "w") as fp: + # todo: improve header + info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format( + module_name, self._fwid, info_, __version__ + ) + fp.write(s) + fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + self.write_object_stub(fp, new_module, module_name, "") + + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + + if module_name not in {"os", "sys", "logging", "gc"}: + # try to unload the module unless we use it + try: + del new_module + except (OSError, KeyError): # lgtm [py/unreachable-statement] + pass + try: + del sys.modules[module_name] + except KeyError: + pass + gc.collect() + return True + + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): + "Write a module/object stub to an open file. Can be called recursive." + gc.collect() + if object_expr in self.problematic: + # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + return + + # # self.log.debug("DUMP : {}".format(object_expr)) + items, errors = self.get_obj_attributes(object_expr) + + if errors: + print(errors) + + for item_name, item_repr, item_type_txt, item_instance, _ in items: + # name_, repr_(value), type as text, item_instance, order + if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: + # do not create stubs for these primitives + continue + if item_name[0].isdigit(): + # self.log.warning("NameError: invalid name {}".format(item_name)) + continue + # Class expansion only on first 3 levels (bit of a hack) + if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: + # self.log.debug("{0}class {1}:".format(indent, item_name)) + superclass = "" + is_exception = ( + item_name.endswith("Exception") + or item_name.endswith("Error") + or item_name + in [ + "KeyboardInterrupt", + "StopIteration", + "SystemExit", + ] + ) + if is_exception: + superclass = "Exception" + s = "\n{}class {}({}):\n".format(indent, item_name, superclass) + # s += indent + " ''\n" + if is_exception: + s += indent + " ...\n" + fp.write(s) + return + # write classdef + fp.write(s) + # first write the class literals and methods + # self.log.debug("# recursion over class {0}".format(item_name)) + self.write_object_stub( + fp, + item_instance, + "{0}.{1}".format(obj_name, item_name), + indent + " ", + in_class + 1, + ) + # end with the __init__ method to make sure that the literals are defined + # Add __init__ + s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" + s += indent + " ...\n\n" + fp.write(s) + elif any(word in item_type_txt for word in ["method", "function", "closure"]): + # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # module Function or class method + # will accept any number of params + # return type Any/Incomplete + ret = "Incomplete" + first = "" + # Self parameter only on class methods/functions + if in_class > 0: + first = "self, " + # class method - add function decoration + if "bound_method" in item_type_txt or "bound_method" in item_repr: + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format( + indent, item_name, ret + ) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) + s += indent + " ...\n\n" + fp.write(s) + # self.log.debug("\n" + s) + elif item_type_txt == "": + # Skip imported modules + # fp.write("# import {}\n".format(item_name)) + pass + + elif item_type_txt.startswith(" dict[str, str] + info = OrderedDict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "UNKNOWN", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" + try: + info["version"] = version_str(sys.implementation.version) # type: ignore + except AttributeError: + pass + try: + _machine = ( + sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + ) + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine + info["cpu"] = _machine.split("with")[-1].strip() + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + gc.collect() + read_boardname(info) + gc.collect() + + try: + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): + pass + # avoid build hashes + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() # type: ignore + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + info["version"] + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # versions from 1.10.0 to 1.20.0 do not have a micro .0 + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" + # simple to use version[-build] string + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" + + return info + + +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): + found = True + break + if not found: + # print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + +def find_board(info: dict, descr: str, filename: str, short_descr: str): + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + info["board"] = board_ + return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True + return False + + +def get_root() -> str: # sourcery skip: use-assigned-variable + "Determine the root folder of the device" + try: + c = os.getcwd() + except (OSError, AttributeError): + # unix port + c = "." + r = c + for r in [c, "/sd", "/flash", "/", "."]: + try: + _ = os.stat(r) + break + except OSError: + continue + return r + + +def file_exists(filename: str): + try: + if os.stat(filename)[0] >> 14: + return True + return False + except OSError: + return False + + +def show_help(): + # print("-p, --path path to store the stubs in, defaults to '.'") + sys.exit(1) + + +def read_path() -> str: + "get --path from cmdline. [unix/win]" + path = "" + if len(sys.argv) == 3: + cmd = (sys.argv[1]).lower() + if cmd in ("--path", "-p"): + path = sys.argv[2] + else: + show_help() + elif len(sys.argv) == 2: + show_help() + return path + + +def is_micropython() -> bool: + "runtime test to determine full or micropython" + # pylint: disable=unused-variable,eval-used + try: + # either test should fail on micropython + # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces + # Micropython : SyntaxError + # a = eval("1and 0") # lgtm [py/unused-local-variable] + # Eval blocks some minification aspects + + # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented + # Micropython: NotImplementedError + b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] + + # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute + # Micropython: AttributeError + c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] + return False + except (NotImplementedError, AttributeError): + return True + + +def main(): + stubber = Stubber(path=read_path()) + # stubber = Stubber(path="/sd") + # Option: Specify a firmware name & version + # stubber = Stubber(firmware_id='HoverBot v1.2.1') + stubber.clean() + # there is no option to discover modules from micropython, need to hardcode + # below contains combined modules from Micropython ESP8622, ESP32, Loboris, Pycom and ulab , lvgl + # spell-checker: disable + # modules to stub : 131 + stubber.modules = [ + "WM8960", + "_OTA", + "_asyncio", + "_boot_fat", + "_coap", + "_espnow", + "_flash_control_OTA", + "_main_pybytes", + "_mqtt", + "_mqtt_core", + "_msg_handl", + "_onewire", + "_periodical_pin", + "_pybytes", + "_pybytes_ca", + "_pybytes_config", + "_pybytes_config_reader", + "_pybytes_connection", + "_pybytes_constants", + "_pybytes_debug", + "_pybytes_library", + "_pybytes_machine_learning", + "_pybytes_main", + "_pybytes_protocol", + "_pybytes_pyconfig", + "_pybytes_pymesh_config", + "_rp2", + "_terminal", + "_thread", + "_uasyncio", + "_urequest", + "adcfft", + "aioble/__init__", + "aioble/central", + "aioble/client", + "aioble/core", + "aioble/device", + "aioble/l2cap", + "aioble/peripheral", + "aioble/security", + "aioble/server", + "aioespnow", + "ak8963", + "apa102", + "apa106", + "argparse", + "array", + "asyncio/__init__", + "asyncio/core", + "asyncio/event", + "asyncio/funcs", + "asyncio/lock", + "asyncio/stream", + "binascii", + "bluetooth", + "breakout_as7262", + "breakout_bh1745", + "breakout_bme280", + "breakout_bme68x", + "breakout_bmp280", + "breakout_dotmatrix", + "breakout_encoder", + "breakout_icp10125", + "breakout_ioexpander", + "breakout_ltr559", + "breakout_matrix11x7", + "breakout_mics6814", + "breakout_msa301", + "breakout_paa5100", + "breakout_pmw3901", + "breakout_potentiometer", + "breakout_rgbmatrix5x5", + "breakout_rtc", + "breakout_scd41", + "breakout_sgp30", + "breakout_trackball", + "breakout_vl53l5cx", + "btree", + "cmath", + "collections", + "crypto", + "cryptolib", + "curl", + "deflate", + "dht", + "display", + "display_driver_utils", + "ds18x20", + "encoder", + "errno", + "esp", + "esp32", + "espidf", + "espnow", + "ffi", + "flashbdev", + "framebuf", + "freesans20", + "fs_driver", + "functools", + "galactic", + "gc", + "gfx_pack", + "gsm", + "hashlib", + "heapq", + "hub75", + "ili9341", + "ili9XXX", + "imagetools", + "inisetup", + "interstate75", + "io", + "jpegdec", + "json", + "lcd160cr", + "lodepng", + "logging", + "lsm6dsox", + "lv_colors", + "lv_utils", + "lvgl", + "lwip", + "machine", + "math", + "microWebSocket", + "microWebSrv", + "microWebTemplate", + "micropython", + "mip", + "mip/__init__", + "mip/__main__", + "motor", + "mpu6500", + "mpu9250", + "neopixel", + "network", + "ntptime", + "onewire", + "os", + "pcf85063a", + "picoexplorer", + "picographics", + "picokeypad", + "picoscroll", + "picounicorn", + "picowireless", + "pimoroni", + "pimoroni_bus", + "pimoroni_i2c", + "plasma", + "platform", + "pyb", + "pycom", + "pye", + "qrcode", + "queue", + "random", + "requests", + "requests/__init__", + "rp2", + "rtch", + "samd", + "select", + "servo", + "socket", + "ssd1306", + "ssh", + "ssl", + "stm", + "struct", + "sys", + "termios", + "time", + "tpcalib", + "uarray", + "uasyncio/__init__", + "uasyncio/core", + "uasyncio/event", + "uasyncio/funcs", + "uasyncio/lock", + "uasyncio/stream", + "uasyncio/tasks", + "ubinascii", + "ubluetooth", + "ucollections", + "ucrypto", + "ucryptolib", + "uctypes", + "uerrno", + "uftpd", + "uhashlib", + "uheapq", + "uio", + "ujson", + "ulab", + "ulab/approx", + "ulab/compare", + "ulab/fft", + "ulab/filter", + "ulab/linalg", + "ulab/numerical", + "ulab/poly", + "ulab/user", + "ulab/vector", + "umachine", + "umqtt/__init__", + "umqtt/robust", + "umqtt/simple", + "uos", + "uplatform", + "uqueue", + "urandom", + "ure", + "urequests", + "urllib/urequest", + "uselect", + "usocket", + "ussl", + "ustruct", + "usys", + "utelnetserver", + "utime", + "utimeq", + "uwebsocket", + "uzlib", + "version", + "websocket", + "websocket_helper", + "wipy", + "writer", + "xpt2046", + "ymodem", + "zephyr", + "zlib", + ] # spell-checker: enable + + gc.collect() + + stubber.create_all_stubs() + stubber.report() + + +if __name__ == "__main__" or is_micropython(): + try: + log = logging.getLogger("stubber") + logging.basicConfig(level=logging.INFO) + # logging.basicConfig(level=logging.DEBUG) + except NameError: + pass + if not file_exists("no_auto_stubber.txt"): + try: + gc.threshold(4 * 1024) # type: ignore + gc.enable() + except BaseException: + pass + main() diff --git a/src/stubber/board/createstubs_mpy.mpy b/src/stubber/board/createstubs_mpy.mpy index 00887e7b699f7a540f8a6dd0c27e1948e80b733a..f70b1bb14b9983575ecda7ac0ba57e9fd5f362c9 100644 GIT binary patch delta 6395 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 delta 6654 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 Y=VsT%Yl+=7gWYOA#uh$Qe1szZ1w;*Vw*UYD From 81e49256b311f11db185a5e987f960600620a127 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Sun, 21 Jan 2024 22:16:00 +0100 Subject: [PATCH 36/68] Refactor code to improve performance and readability Signed-off-by: Jos Verlinde --- scripts/flash.ipynb | 266 +++++++++++++++++++------------------------- 1 file changed, 116 insertions(+), 150 deletions(-) diff --git a/scripts/flash.ipynb b/scripts/flash.ipynb index 8ee85996c..619e88720 100644 --- a/scripts/flash.ipynb +++ b/scripts/flash.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -20,8 +20,6 @@ "# firmwares downloaded via get_firmware.ipynb are stored in firmware//-v[-preview.].\n", "# NOTE: The build dates have been removed from the filenames as they mostly get in the way\n", "\n", - "\n", - "\n", "PORT_FWTYPES = {\n", " \"stm32\": \".hex\",\n", " \"esp32\": \".bin\",\n", @@ -30,7 +28,6 @@ "}\n", "\n", "\n", - "\n", "def find_firmware(version: str, *, board: str = \"*\", port: str):\n", " fw_folder = Path.cwd() / \"firmware\" / port\n", " if not fw_folder.exists():\n", @@ -42,19 +39,27 @@ " # PICO boards were renamed to RPI_PICO starting @v1.22.0 for all versions on the download page\n", " if board.startswith(\"PICO\"):\n", " board = f\"RPI_{board}\"\n", + " search = f\"{board}-{v_str}{ext}\"\n", + " elif port == \"esp32\":\n", + " board = board.replace(\"_OTA\", \"-OTA\")\n", + " search = f\"ESP32_{board}-{v_str}{ext}\"\n", + " else:\n", + " search = f\"{board}-{v_str}{ext}\"\n", "\n", - " fw_files = list(fw_folder.glob(f\"{board}-{v_str}{ext}\"))\n", + " print(f\"Searching for {search} in {fw_folder}\")\n", + "\n", + " fw_files = list(fw_folder.glob(search))\n", "\n", " if not fw_files:\n", " print(f\"No firmware files found for {v_str}\")\n", " return None\n", " fw_files.sort()\n", - " yield from fw_files" + " return fw_files" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -65,152 +70,112 @@ "import os\n", "\n", "\n", - "\n", "LIBS = [\"../src/stubber/data\"]\n", "\n", "\n", - "\n", "def file_exists(filename: str):\n", " try:\n", " if os.stat(filename)[0] >> 14:\n", " return True\n", "\n", - "\n", " return False\n", "\n", - "\n", " except OSError:\n", " return False\n", "\n", "\n", - "\n", "def read_boardname(info, desc: str = \"\"):\n", " found = False\n", "\n", - "\n", " for filename in [d + \"/board_info.csv\" for d in LIBS]:\n", " # print(\"look up the board name in the file\", filename)\n", "\n", - "\n", " if file_exists(filename):\n", " descr = desc or info[\"board\"].strip()\n", "\n", - "\n", " print(\"searching info file: {} for: '{}' \".format(filename, descr))\n", "\n", - "\n", " if find_board(info, descr, filename):\n", " found = True\n", "\n", - "\n", " break\n", " if not found:\n", - "\n", " print(\"Board not found, guessing board name\")\n", "\n", - "\n", " descr = desc or info[\"board\"].strip()\n", "\n", - "\n", " if \"with \" + info[\"cpu\"].upper() in descr:\n", " # remove the with cpu part\n", "\n", - "\n", " descr = descr.split(\"with \" + info[\"cpu\"].upper())[0].strip()\n", "\n", - "\n", " info[\"board\"] = descr\n", "\n", - "\n", " info[\"board\"] = info[\"board\"].replace(\" \", \"_\")\n", "\n", - "\n", " gc.collect()\n", "\n", "\n", - "\n", "def find_board(info: dict, descr: str, filename: str):\n", " # find a board based on its description\n", "\n", - "\n", " short_hit = \"\"\n", "\n", - "\n", " lines = []\n", "\n", - "\n", " pos = descr.rfind(\" with\")\n", "\n", - "\n", " if pos != -1:\n", " short_descr = descr[:pos].strip()\n", " else:\n", - "\n", " short_descr = \"\"\n", "\n", - "\n", " try:\n", " with open(filename, \"r\") as file:\n", " lines = file.readlines()\n", " for line in lines:\n", - "\n", " line = line.strip()\n", "\n", - "\n", " if line.startswith(\"#\"):\n", " continue\n", "\n", - "\n", " _descr = line.split(\",\")[0].strip()\n", "\n", - "\n", " _board = line.split(\",\")[1].strip()\n", "\n", - "\n", " if _descr == descr:\n", " info[\"board\"] = _board\n", "\n", - "\n", " return True\n", "\n", - "\n", " elif short_descr and _descr == short_descr:\n", " if \"with\" in short_descr:\n", " # Good enough - no need to trawl the entire file\n", "\n", - "\n", " info[\"board\"] = _board\n", "\n", - "\n", " return True\n", "\n", - "\n", " # good enough if not found in the rest of the file (but slow)\n", "\n", - "\n", " short_hit = _board\n", "\n", - "\n", " if short_hit:\n", " info[\"board\"] = short_hit\n", "\n", - "\n", " return True\n", "\n", - "\n", " return False\n", "\n", - "\n", " finally:\n", " del lines\n", "\n", - "\n", " gc.collect()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -254,7 +219,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -266,7 +231,8 @@ "\n", " fw_file = fw_file or find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"]).__next__()\n", " print(f\"Flashing {fw_file} on {mcu['board']} on {mcu['serial_port']}\")\n", - " baud_rate = str(2000000)\n", + " baud_rate = str(2_000_000)\n", + " baud_rate = str(512_000)\n", " if mcu[\"cpu\"].upper()== \"ESP32\":\n", " if erase_flash:\n", " !esptool --chip esp32 --port {mcu[\"serial_port\"]} erase_flash\n", @@ -284,7 +250,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -337,9 +303,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "searching info file: ../src/stubber/data/board_info.csv for: 'Wio Terminal D51R with SAMD51P19A' \n", + "| ver | version | port | mpy | build | cpu | family | board | arch | serial_port |\n", + "|-----------------|-----------|--------|-------|---------|------------|-------------|--------------------|-----------|---------------|\n", + "| v1.23.0.preview | 1...2-3 | samd | v6.2 | | SAMD51P19A | micropython | SEEED_WIO_TERMINAL | armv7emsp | COM10 |\n" + ] + } + ], "source": [ "def get_dev_info():\n", " devs = %mpy --list\n", @@ -356,6 +333,13 @@ " dev_info.append(info)\n", " return dev_info\n", "\n", + "def version_str(version: tuple): # -> str:\n", + " \"\"\"Convert a micropython version tuple to a string\"\"\"\n", + " v_str = \".\".join([str(n) for n in version[:3]])\n", + " if len(version) > 3 and version[3]:\n", + " v_str += \"-\" + version[3]\n", + " return v_str\n", + "\n", "dev_info = get_dev_info()\n", "from tabulate import tabulate\n", "print(tabulate(dev_info, headers=\"keys\", tablefmt=\"github\"))\n" @@ -363,24 +347,50 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Searching for SEEED_WIO_TERMINAL-v1.23.0-preview.*.uf2 in c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\samd\n", + "c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\samd\\SEEED_WIO_TERMINAL-v1.23.0-preview.6.uf2 {'ver': 'v1.22.0', 'version': '1.22.0', 'port': 'samd', 'mpy': 'v6.2', 'build': '', 'cpu': 'SAMD51P19A', 'family': 'micropython', 'board': 'SEEED_WIO_TERMINAL', 'arch': 'armv7emsp', 'serial_port': 'COM10'}\n", + "Entering bootloader on SEEED_WIO_TERMINAL on COM10\n", + "Waiting for mcu to mount as a drive : 5 seconds left\n", + "Waiting for mcu to mount as a drive : 4 seconds left\n", + "Board is in bootloader mode\n", + "Copying c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\samd\\SEEED_WIO_TERMINAL-v1.23.0-preview.6.uf2 to E:\\\n", + "Done copying, resetting the board and wait for it to restart\n", + "searching info file: ../src/stubber/data/board_info.csv for: 'Wio Terminal D51R with SAMD51P19A' \n", + "| ver | version | port | mpy | build | cpu | family | board | arch | serial_port |\n", + "|-----------------|----------------|--------|-------|---------|------------|-------------|--------------------|-----------|---------------|\n", + "| v1.23.0.preview | 1.23.0.preview | samd | v6.2 | | SAMD51P19A | micropython | SEEED_WIO_TERMINAL | armv7emsp | COM10 |\n" + ] + } + ], "source": [ - "target_version = \"1.22.0\"\n", + "target_version = \"1.23.0-preview.*\"\n", "updated = []\n", "for mcu in dev_info:\n", - " fw_file = find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"]).__next__()\n", + " firmwares = find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"])\n", + " if not firmwares:\n", + " firmwares = find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"].split(\"_\")[0])\n", + " if not firmwares:\n", + " print(f\"No firmware found for {mcu['board']} on {mcu['serial_port']}\")\n", + " continue\n", + "\n", + " fw_file = firmwares[0]\n", " print(fw_file, mcu)\n", "\n", " new = None\n", "\n", " if mcu[\"port\"] in [\"samd\", \"rp2\"]:\n", - " new = flash_uf2(mcu)\n", + " new = flash_uf2(mcu, fw_file=fw_file)\n", " elif mcu[\"port\"] in [\"esp32\"]:\n", - " new = flash_esp32(mcu, erase_flash=False)\n", + " new = flash_esp32(mcu, erase_flash=False, fw_file=fw_file)\n", " elif mcu[\"port\"] in [\"stm32\"]:\n", - " new = flash_stm32(mcu, erase_flash=False)\n", + " new = flash_stm32(mcu, erase_flash=False, fw_file=fw_file)\n", "\n", " if new:\n", " read_boardname(new)\n", @@ -393,117 +403,73 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 9, "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Entering bootloader on PYBV11 on COM17\n", - "===== DFU Interface =====\n", - "\n", - "Total number of available STM32 device in DFU mode: 1\n", - "\n", - " Device Index : USB1\n", - " USB Bus Number : 001\n", - " USB Address Number : 002\n", - " Product ID : STM32 BOOTLOADER\n", - " Serial number : 206437A1304E\n", - " Firmware version : 0x011a\n", - " Device ID : 0x0413\n", - "\n", - "Flashing\n", - "STM32_Programmer_CLI.exe --connect port=USB1 --write c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\stm32\\PYBV11-v1.22.0.hex --go 0x08020161\n", - " -------------------------------------------------------------------\n", - " STM32CubeProgrammer v2.13.0 \n", - " -------------------------------------------------------------------\n", - "\n", - "\n", - "\n", - "USB speed : Full Speed (12MBit/s)\n", - "Manuf. ID : STMicroelectronics\n", - "Product ID : STM32 BOOTLOADER\n", - "SN : 206437A1304E\n", - "DFU protocol: 1.1\n", - "Board : --\n", - "Device ID : 0x0413\n", - "Device name : STM32F405xx/F407xx/F415xx/F417xx\n", - "Flash size : 1 MBytes (default)\n", - "Device type : MCU\n", - "Revision ID : -- \n", - "Device CPU : Cortex-M4\n", - "\n", - "\n", - "Memory Programming ...\n", - "Opening and parsing file: PYBV11-v1.22.0.hex\n", - " File : PYBV11-v1.22.0.hex\n", - " Size : 355.81 KB \n", - " Address : 0x08000000 \n", - "\n", - "\n", - "Erasing memory corresponding to segment 0:\n", - "Erasing internal memory sector 0\n", - "erasing sector 0000 @: 0x08000000 done\n", - "Erasing memory corresponding to segment 1:\n", - "Erasing internal memory sectors [5 7]\n", - "erasing sector 0005 @: 0x08020000 done\n", - "erasing sector 0006 @: 0x08040000 done\n", - "erasing sector 0007 @: 0x08060000 done\n", - "Download in Progress:\n", - "�������������������������������������������������� 0%\n", - "� 2%� 4%� 2%� 4%� 6%� 8%� 10%� 12%� 14%� 16%� 18%� 20%� 22%� 24%� 26%� 28%� 30%� 32%� 34%� 36%� 38%� 40%� 42%� 44%� 46%� 48%� 50%� 52%� 54%� 56%� 58%� 60%� 62%� 64%� 66%� 68%� 70%� 72%� 74%� 76%� 78%� 80%� 82%� 84%� 86%� 88%� 90%� 92%� 94%� 96%� 98%� 100%\n", - "\n", - "File download complete\n", - "Time elapsed during download operation: 00:00:13.463\n", - "\n", - "RUNNING Program ... \n", - " Address: : 0x8020161\n", - "Start operation achieved successfully\n" - ] + "data": { + "text/plain": [ + "{'ver': 'v1.22.0',\n", + " 'version': '1.22.0',\n", + " 'port': 'samd',\n", + " 'mpy': 'v6.2',\n", + " 'build': '',\n", + " 'cpu': 'SAMD51P19A',\n", + " 'family': 'micropython',\n", + " 'board': 'Wio Terminal D51R with SAMD51P19A',\n", + " 'arch': 'armv7emsp',\n", + " 'serial_port': 'COM10'}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "# mcu = dev_info[0]\n", - "# flash_stm32(mcu, erase_flash=False)" + "\n", + "%mpy --info" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 10, "metadata": {}, "outputs": [ { - "data": { - "text/plain": [ - "{'port': 'stm32',\n", - " 'build': '',\n", - " 'arch': 'armv7emsp',\n", - " 'family': 'micropython',\n", - " 'board': 'PYBv1.1 with STM32F405RG',\n", - " 'cpu': 'STM32F405RG',\n", - " 'version': '1.22.0.',\n", - " 'mpy': 'v6.2',\n", - " 'ver': 'v1.22.0.',\n", - " 'serial_port': 'COM17'}" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "(name='micropython', version=(1, 22, 0, ''), _machine='Wio Terminal D51R with SAMD51P19A', _mpy=7686)\n" + ] } ], "source": [ + "# %%micropython\n", "\n", - "%mpy --info" + "import sys\n", + "\n", + "print(sys.implementation)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "namespace(name='cpython', cache_tag='cpython-311', version=sys.version_info(major=3, minor=11, micro=7, releaselevel='final', serial=0), hexversion=51054576)\n" + ] + } + ], + "source": [ + "import sys\n", + "\n", + "print(sys.implementation)" + ] } ], "metadata": { From bf6f5749891fdde7aa89f246ab18b4efeb268bf4 Mon Sep 17 00:00:00 2001 From: Josverl Date: Sun, 21 Jan 2024 21:17:10 +0000 Subject: [PATCH 37/68] Update mip packages --- mip/v5/createstubs_db_min.py | 1107 +++++++++++++++++++-------- mip/v5/createstubs_db_mpy.mpy | Bin 8997 -> 9168 bytes mip/v5/createstubs_lvgl_min.py | 1017 +++++++++++++++++-------- mip/v5/createstubs_lvgl_mpy.mpy | Bin 8447 -> 8527 bytes mip/v5/createstubs_mem_min.py | 1034 +++++++++++++++++-------- mip/v5/createstubs_mem_mpy.mpy | Bin 8486 -> 8585 bytes mip/v5/createstubs_min.py | 1242 +++++++++++++++++++++++-------- mip/v5/createstubs_mpy.mpy | Bin 11057 -> 11249 bytes mip/v6/createstubs_db_min.py | 1107 +++++++++++++++++++-------- mip/v6/createstubs_db_mpy.mpy | Bin 8799 -> 8492 bytes mip/v6/createstubs_lvgl_min.py | 1017 +++++++++++++++++-------- mip/v6/createstubs_lvgl_mpy.mpy | Bin 8275 -> 7990 bytes mip/v6/createstubs_mem_min.py | 1034 +++++++++++++++++-------- mip/v6/createstubs_mem_mpy.mpy | Bin 8310 -> 7988 bytes mip/v6/createstubs_min.py | 1242 +++++++++++++++++++++++-------- mip/v6/createstubs_mpy.mpy | Bin 11320 -> 11115 bytes 16 files changed, 6392 insertions(+), 2408 deletions(-) diff --git a/mip/v5/createstubs_db_min.py b/mip/v5/createstubs_db_min.py index adae0e729..50065e687 100644 --- a/mip/v5/createstubs_db_min.py +++ b/mip/v5/createstubs_db_min.py @@ -1,323 +1,790 @@ -x='with' -w='stubber' -v='{}/{}' -u='method' -t='function' -s='bool' -r='str' -q='float' -p='int' -o=TypeError -n=NameError -m=sorted -l=MemoryError -k=NotImplementedError -d='-' -c=',\n' -b='dict' -a='list' -Z='tuple' -Y='micropython' -X=str -W=repr -U='cpu' -T='_' -S=KeyError -R=IndexError -Q=ImportError -P='family' -O=print -N=len -M=dir -L='.' -K=open -J=True -I=AttributeError -H='board' -G='/' -F=None -E=False -A=OSError -D='version' -C='' -import gc as B,os,sys -try:from ujson import dumps -except:from json import dumps -try:from machine import reset -except Q:pass -try:from collections import OrderedDict as e -except Q:from ucollections import OrderedDict as e -__version__='v1.16.2' -y=2 -z=2 -f=[L,'/lib','/sd/lib','/flash/lib','lib'] +""" +Create stubs for (all) modules on a MicroPython board. + + This variant of the createstubs.py script is optimized for use on very-low-memory devices. + Note: this version has undergone limited testing. + + 1) reads the list of modules from a text file `modulelist.txt` that should be uploaded to the device. + 2) stored the already processed modules in a text file `modulelist.done` + 3) process the modules in the database: + - stub the module + - update the modulelist.done file + - reboots the device if it runs out of memory + 4) creates the modules.json + + If that cannot be found then only a single module (micropython) is stubbed. + In order to run this on low-memory devices two additional steps are recommended: + - minification, using python-minifierto reduce overall size, and remove logging overhead. + - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device + + +This variant was generated from createstubs.py by micropython-stubber v1.16.2 +""" +# Copyright (c) 2019-2023 Jos Verlinde + +import gc +# import logging +import os +import sys + +try: + from ujson import dumps +except: + from json import dumps + +try: + from machine import reset # type: ignore +except ImportError: + pass + +try: + from collections import OrderedDict +except ImportError: + from ucollections import OrderedDict # type: ignore + +__version__ = "v1.16.2" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] from time import sleep + + class Stubber: - def __init__(C,path=F,firmware_id=F): - D=firmware_id - try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') - except I:pass - C._report=[];C.info=_info();B.collect() - if D:C._fwid=D.lower() - elif C.info[P]==Y:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info) - else:C._fwid='{family}-v{version}-{port}'.format(**C.info) - C._start_free=B.mem_free() - if path: - if path.endswith(G):path=path[:-1] - else:path=get_root() - C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) - try:g(path+G) - except A:O('error creating stub folder {}'.format(path)) - C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] - def get_obj_attributes(L,item_instance): - H=item_instance;D=[];J=[] - for A in M(H): - if A.startswith(T)and not A in L.modules:continue - try: - E=getattr(H,A) - try:F=W(type(E)).split("'")[1] - except R:F=C - if F in{p,q,r,s,Z,a,b}:G=1 - elif F in{t,u}:G=2 - elif F in'class':G=3 - else:G=4 - D.append((A,W(E),W(type(E)),E,G)) - except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) - except l as K:sleep(1);reset() - D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) - def create_all_stubs(A): - B.collect() - for C in A.modules:A.create_one_stub(C) - def create_one_stub(C,module_name): - D=module_name - if D in C.problematic:return E - if D in C.excluded:return E - H='{}/{}.py'.format(C.path,D.replace(L,G));B.collect();F=E - try:F=C.create_module_stub(D,H) - except A:return E - B.collect();return F - def create_module_stub(I,module_name,file_name=F): - H=file_name;D=module_name - if H is F:O=D.replace(L,T)+'.py';H=I.path+G+O - else:O=H.split(G)[-1] - if G in D:D=D.replace(G,L) - M=F - try:M=__import__(D,F,F,'*');U=B.mem_free() - except Q:return E - g(H) - with K(H,'w')as N:P=X(I.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,D,C) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: - try:del M - except(A,S):pass - try:del sys.modules[D] - except S:pass - B.collect();return J - def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;M='Exception';H=fp;E=indent;B.collect() - if P in K.problematic:return - R,L=K.get_obj_attributes(P) - if L:O(L) - for(F,J,G,T,f)in R: - if F in['classmethod','staticmethod','BaseException',M]:continue - if F[0].isdigit():continue - if G==""and N(E)<=z*4: - U=C;V=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=M - D='\n{}class {}({}):\n'.format(E,F,U) - if V:D+=E+' ...\n';H.write(D);return - H.write(D);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) - elif any(A in G for A in[u,t,'closure']): - W=Y;X=C - if Q>0:X='self, ' - if c in G or c in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) - else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,X,W) - D+=E+' ...\n\n';H.write(D) - elif G=="":0 - elif G.startswith("='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if J in A and A[J]: - K=int(A[J]);N=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if N:A[T]=N - A[J]='v{}.{}'.format(K&255,K>>8&3) - if A[E]and not A[D].endswith(c):A[D]=A[D]+c - A[O]=f"{A[D]}-{A[E]}"if A[E]else f"{A[D]}";return A -def A0(version): - A=version;B=L.join([X(A)for A in A[:3]]) - if N(A)>3 and A[3]:B+=d+A[3] - return B -def A1(info,desc=C): - L='with ';A=info;F=E - for G in[A+'/board_info.csv'for A in f]: - if h(G): - D=desc or A[H].strip();I=D.rfind(' with') - if I!=-1:K=D[:I].strip() - else:K=C - if A2(A,D,G,K):F=J;break - if not F: - D=desc or A[H].strip() - if L+A[U].upper()in D:D=D.split(L+A[U].upper())[0].strip() - A[H]=D - A[H]=A[H].replace(' ',T);B.collect() -def A2(info,descr,filename,short_descr): - B=short_descr;A=info;D=C - with K(filename,'r')as L: - while 1: - F=L.readline() - if not F:break - I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:A[H]=G;return J - elif B and I==B: - if x in B:A[H]=G;return J - D=G - if D:A[H]=D;return J - return E -def get_root(): - try:B=os.getcwd() - except(A,I):B=L - C=B - for C in[B,'/sd','/flash',G,L]: - try:D=os.stat(C);break - except A:continue - return C -def h(filename): - try: - if os.stat(filename)[0]>>14:return J - return E - except A:return E -def i():sys.exit(1) -def read_path(): - path=C - if N(sys.argv)==3: - A=sys.argv[1].lower() - if A in('--path','-p'):path=sys.argv[2] - else:i() - elif N(sys.argv)==2:i() - return path -def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return E - except(k,I):return J + "Generate stubs for modules in firmware" + + def __init__(self, path: str = None, firmware_id: str = None): # type: ignore + try: + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore + raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") + except AttributeError: + pass + # self.log = logging.getLogger("stubber") + self._report = [] # type: list[str] + self.info = _info() + # self.log.info("Port: {}".format(self.info["port"])) + # self.log.info("Board: {}".format(self.info["board"])) + gc.collect() + if firmware_id: + self._fwid = firmware_id.lower() + else: + if self.info["family"] == "micropython": + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + else: + self._fwid = "{family}-v{version}-{port}".format(**self.info) + self._start_free = gc.mem_free() # type: ignore + + if path: + if path.endswith("/"): + path = path[:-1] + else: + path = get_root() + + self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") + # self.log.debug(self.path) + try: + ensure_folder(path + "/") + except OSError: + print("error creating stub folder {}".format(path)) + self.problematic = [ + "upip", + "upysh", + "webrepl_setup", + "http_client", + "http_client_ssl", + "http_server", + "http_server_ssl", + ] + self.excluded = [ + "webrepl", + "_webrepl", + "port_diag", + "example_sub_led.py", + "example_pub_button.py", + ] + # there is no option to discover modules from micropython, list is read from an external file. + self.modules = [] # type: list[str] + + def get_obj_attributes(self, item_instance: object): + "extract information of the objects members and attributes" + # name_, repr_(value), type as text, item_instance + _result = [] + _errors = [] + # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + for name in dir(item_instance): + if name.startswith("_") and not name in self.modules: + continue + # self.log.debug("get attribute {}".format(name)) + try: + val = getattr(item_instance, name) + # name , item_repr(value) , type as text, item_instance, order + try: + type_text = repr(type(val)).split("'")[1] + except IndexError: + type_text = "" + if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: + order = 1 + elif type_text in {"function", "method"}: + order = 2 + elif type_text in ("class"): + order = 3 + else: + order = 4 + _result.append((name, repr(val), repr(type(val)), val, order)) + except AttributeError as e: + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) + except MemoryError as e: + # print("MemoryError: {}".format(e)) + sleep(1) + reset() + + # remove internal __ + # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) + _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) + gc.collect() + return _result, _errors + + def add_modules(self, modules): + "Add additional modules to be exported" + self.modules = sorted(set(self.modules) | set(modules)) + + def create_all_stubs(self): + "Create stubs for all configured modules" + # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + gc.collect() + for module_name in self.modules: + self.create_one_stub(module_name) + # self.log.info("Finally done") + + def create_one_stub(self, module_name: str): + if module_name in self.problematic: + # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + return False + if module_name in self.excluded: + # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + return False + + file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + gc.collect() + result = False + try: + result = self.create_module_stub(module_name, file_name) + except OSError: + return False + gc.collect() + return result + + def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore + """Create a Stub of a single python module + + Args: + - module_name (str): name of the module to document. This module will be imported. + - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + """ + if file_name is None: + fname = module_name.replace(".", "_") + ".py" + file_name = self.path + "/" + fname + else: + fname = file_name.split("/")[-1] + + if "/" in module_name: + # for nested modules + module_name = module_name.replace("/", ".") + + # import the module (as new_module) to examine it + new_module = None + try: + new_module = __import__(module_name, None, None, ("*")) + m1 = gc.mem_free() # type: ignore + # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + + except ImportError: + # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + return False + + # Start a new file + ensure_folder(file_name) + with open(file_name, "w") as fp: + # todo: improve header + info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) + fp.write(s) + fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + self.write_object_stub(fp, new_module, module_name, "") + + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + + if module_name not in {"os", "sys", "logging", "gc"}: + # try to unload the module unless we use it + try: + del new_module + except (OSError, KeyError): # lgtm [py/unreachable-statement] + pass + try: + del sys.modules[module_name] + except KeyError: + pass + gc.collect() + return True + + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): + "Write a module/object stub to an open file. Can be called recursive." + gc.collect() + if object_expr in self.problematic: + # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + return + + # # self.log.debug("DUMP : {}".format(object_expr)) + items, errors = self.get_obj_attributes(object_expr) + + if errors: + print(errors) + + for item_name, item_repr, item_type_txt, item_instance, _ in items: + # name_, repr_(value), type as text, item_instance, order + if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: + # do not create stubs for these primitives + continue + if item_name[0].isdigit(): + # self.log.warning("NameError: invalid name {}".format(item_name)) + continue + # Class expansion only on first 3 levels (bit of a hack) + if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: + # self.log.debug("{0}class {1}:".format(indent, item_name)) + superclass = "" + is_exception = ( + item_name.endswith("Exception") + or item_name.endswith("Error") + or item_name + in [ + "KeyboardInterrupt", + "StopIteration", + "SystemExit", + ] + ) + if is_exception: + superclass = "Exception" + s = "\n{}class {}({}):\n".format(indent, item_name, superclass) + # s += indent + " ''\n" + if is_exception: + s += indent + " ...\n" + fp.write(s) + return + # write classdef + fp.write(s) + # first write the class literals and methods + # self.log.debug("# recursion over class {0}".format(item_name)) + self.write_object_stub( + fp, + item_instance, + "{0}.{1}".format(obj_name, item_name), + indent + " ", + in_class + 1, + ) + # end with the __init__ method to make sure that the literals are defined + # Add __init__ + s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" + s += indent + " ...\n\n" + fp.write(s) + elif any(word in item_type_txt for word in ["method", "function", "closure"]): + # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # module Function or class method + # will accept any number of params + # return type Any/Incomplete + ret = "Incomplete" + first = "" + # Self parameter only on class methods/functions + if in_class > 0: + first = "self, " + # class method - add function decoration + if "bound_method" in item_type_txt or "bound_method" in item_repr: + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) + s += indent + " ...\n\n" + fp.write(s) + # self.log.debug("\n" + s) + elif item_type_txt == "": + # Skip imported modules + # fp.write("# import {}\n".format(item_name)) + pass + + elif item_type_txt.startswith(" dict[str, str] + info = OrderedDict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "UNKNOWN", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" + try: + info["version"] = version_str(sys.implementation.version) # type: ignore + except AttributeError: + pass + try: + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine + info["cpu"] = _machine.split("with")[-1].strip() + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + gc.collect() + read_boardname(info) + gc.collect() + + try: + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): + pass + # avoid build hashes + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() # type: ignore + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + info["version"] + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # versions from 1.10.0 to 1.20.0 do not have a micro .0 + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" + # simple to use version[-build] string + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" + + return info + + +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): + found = True + break + if not found: + # print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + +def find_board(info: dict, descr: str, filename: str, short_descr: str): + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + info["board"] = board_ + return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True + return False + + +def get_root() -> str: # sourcery skip: use-assigned-variable + "Determine the root folder of the device" + try: + c = os.getcwd() + except (OSError, AttributeError): + # unix port + c = "." + r = c + for r in [c, "/sd", "/flash", "/", "."]: + try: + _ = os.stat(r) + break + except OSError: + continue + return r + + +def file_exists(filename: str): + try: + if os.stat(filename)[0] >> 14: + return True + return False + except OSError: + return False + + +def show_help(): + # print("-p, --path path to store the stubs in, defaults to '.'") + sys.exit(1) + + +def read_path() -> str: + "get --path from cmdline. [unix/win]" + path = "" + if len(sys.argv) == 3: + cmd = (sys.argv[1]).lower() + if cmd in ("--path", "-p"): + path = sys.argv[2] + else: + show_help() + elif len(sys.argv) == 2: + show_help() + return path + + +def is_micropython() -> bool: + "runtime test to determine full or micropython" + # pylint: disable=unused-variable,eval-used + try: + # either test should fail on micropython + # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces + # Micropython : SyntaxError + # a = eval("1and 0") # lgtm [py/unused-local-variable] + # Eval blocks some minification aspects + + # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented + # Micropython: NotImplementedError + b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] + + # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute + # Micropython: AttributeError + c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] + return False + except (NotImplementedError, AttributeError): + return True + + def main(): - L='failed';G='modulelist.done';import machine as O - try:C=K(G,'r+b');M=J - except A:C=K(G,'w+b');M=E - stubber=Stubber(path=read_path()) - if not M:stubber.clean() - A3(stubber);D={} - try: - with K(G)as C: - for F in C.read().split('\n'): - F=F.strip();B.collect() - if N(F)>0:P,Q=F.split('=',1);D[P]=Q - except(A,SyntaxError):pass - B.collect();R=[A for A in stubber.modules if A not in D.keys()];B.collect() - for H in R: - I=E - try:I=stubber.create_one_stub(H) - except l:O.reset() - B.collect();D[H]=X(stubber._report[-1]if I else L) - with K(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if I else L)) - if D:stubber._report=[A for(B,A)in D.items()if A!=L];stubber.report() -def A3(stubber): - E='/modulelist.txt';stubber.modules=[] - for D in f: - try: - with K(D+E)as F: - O('DEBUG: list of modules: '+D+E) - for C in F.read().split('\n'): - C=C.strip() - if N(C)>0 and C[0]!='#':stubber.modules.append(C) - B.collect();break - except A:pass - if not stubber.modules:stubber.modules=[Y];_log.warn('Could not find modulelist.txt, using default modules') - B.collect() -if __name__=='__main__'or j(): - try:A4=logging.getLogger(w);logging.basicConfig(level=logging.INFO) - except n:pass - if not h('no_auto_stubber.txt'): - try:B.threshold(4*1024);B.enable() - except BaseException:pass - main() \ No newline at end of file + import machine # type: ignore + + try: + f = open("modulelist.done", "r+b") + was_running = True + # print("Opened existing db") + except OSError: + f = open("modulelist.done", "w+b") + # print("created new db") + was_running = False + stubber = Stubber(path=read_path()) + + # f_name = "{}/{}".format(stubber.path, "modules.json") + if not was_running: + # Only clean folder if this is a first run + stubber.clean() + # get list of modules to process + get_modulelist(stubber) + # remove the ones that are already done + modules_done = {} # type: dict[str, str] + try: + with open("modulelist.done") as f: + # not optimal , but works on mpremote and esp8266 + for line in f.read().split("\n"): + line = line.strip() + gc.collect() + if len(line) > 0: + key, value = line.split("=", 1) + modules_done[key] = value + except (OSError, SyntaxError): + pass + gc.collect() + # see if we can continue from where we left off + modules = [m for m in stubber.modules if m not in modules_done.keys()] + gc.collect() + for modulename in modules: + # ------------------------------------ + # do epic shit + # but sometimes things fail / run out of memory and reboot + ok = False + try: + ok = stubber.create_one_stub(modulename) + except MemoryError: + # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER + machine.reset() + # ------------------------------------- + gc.collect() + modules_done[modulename] = str(stubber._report[-1] if ok else "failed") + with open("modulelist.done", "a") as f: + f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) + + # Finished processing - load all the results , and remove the failed ones + if modules_done: + # stubber.write_json_end(mod_fp) + stubber._report = [v for _, v in modules_done.items() if v != "failed"] + stubber.report() + + +def get_modulelist(stubber): + stubber.modules = [] # avoid duplicates + for p in LIBS: + try: + with open(p + "/modulelist.txt") as f: + print ("DEBUG: list of modules: " + p + "/modulelist.txt") + for line in f.read().split("\n"): + line = line.strip() + if len(line) > 0 and line[0] != "#": + stubber.modules.append(line) + gc.collect() + break + except OSError: + pass + if not stubber.modules: + stubber.modules = ["micropython"] + _log.warn("Could not find modulelist.txt, using default modules") + gc.collect() + + +if __name__ == "__main__" or is_micropython(): + try: + log = logging.getLogger("stubber") + logging.basicConfig(level=logging.INFO) + # logging.basicConfig(level=logging.DEBUG) + except NameError: + pass + if not file_exists("no_auto_stubber.txt"): + try: + gc.threshold(4 * 1024) # type: ignore + gc.enable() + except BaseException: + pass + main() diff --git a/mip/v5/createstubs_db_mpy.mpy b/mip/v5/createstubs_db_mpy.mpy index b991b8b5bb6732e7baf8233f758b544ca921a6d6..4d892daed7e6d4c237264a607ded044a9d38f9fe 100644 GIT binary patch literal 9168 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 literal 8997 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 diff --git a/mip/v5/createstubs_lvgl_min.py b/mip/v5/createstubs_lvgl_min.py index 5412c8895..cc2548419 100644 --- a/mip/v5/createstubs_lvgl_min.py +++ b/mip/v5/createstubs_lvgl_min.py @@ -1,297 +1,726 @@ -v='with' -u='stubber' -t='{}/{}' -s='method' -r='function' -q='bool' -p='str' -o='float' -n='int' -m='micropython' -l=Exception -k=TypeError -j=NameError -i=sorted -h=NotImplementedError -b='-' -a=',\n' -Z='dict' -Y='list' -X='tuple' -W=open -V=repr -T='cpu' -S='_' -R=len -Q=KeyError -P=IndexError -O=print -N=ImportError -M='family' -L=dir -K=True -J='.' -I=AttributeError -H='board' -A=False -G='/' -E=None -F=OSError -C='version' -B='' -import gc as D,os,sys -try:from ujson import dumps -except:from json import dumps -try:from machine import reset -except N:pass -try:from collections import OrderedDict as c -except N:from ucollections import OrderedDict as c -__version__='v1.16.2' -w=2 -x=2 -y=[J,'/lib','/sd/lib','/flash/lib','lib'] +""" +Create stubs for the lvgl modules on a MicroPython board. + +Note that the stubs can be very large, and it may be best to directly store them on an SD card if your device supports this. + +This variant was generated from createstubs.py by micropython-stubber v1.16.2 +""" +# Copyright (c) 2019-2023 Jos Verlinde + +import gc +# import logging +import os +import sys + +try: + from ujson import dumps +except: + from json import dumps + +try: + from machine import reset # type: ignore +except ImportError: + pass + +try: + from collections import OrderedDict +except ImportError: + from ucollections import OrderedDict # type: ignore + +__version__ = "v1.16.2" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] from time import sleep + + class Stubber: - def __init__(A,path=E,firmware_id=E): - B=firmware_id - try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise h('MicroPython 1.13.0 cannot be stubbed') - except I:pass - A._report=[];A.info=_info();D.collect() - if B:A._fwid=B.lower() - elif A.info[M]==m:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-v{version}-{port}'.format(**A.info) - A._start_free=D.mem_free() - if path: - if path.endswith(G):path=path[:-1] - else:path=get_root() - A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:d(path+G) - except F:O('error creating stub folder {}'.format(path)) - A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] - def get_obj_attributes(M,item_instance): - H=item_instance;C=[];J=[] - for A in L(H): - if A.startswith(S)and not A in M.modules:continue - try: - E=getattr(H,A) - try:F=V(type(E)).split("'")[1] - except P:F=B - if F in{n,o,p,q,X,Y,Z}:G=1 - elif F in{r,s}:G=2 - elif F in'class':G=3 - else:G=4 - C.append((A,V(E),V(type(E)),E,G)) - except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) - except MemoryError as K:sleep(1);reset() - C=i([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,J - def add_modules(A,modules):A.modules=i(set(A.modules)|set(modules)) - def create_all_stubs(A): - D.collect() - for B in A.modules:A.create_one_stub(B) - def create_one_stub(B,module_name): - C=module_name - if C in B.problematic:return A - if C in B.excluded:return A - H='{}/{}.py'.format(B.path,C.replace(J,G));D.collect();E=A - try:E=B.create_module_stub(C,H) - except F:return A - D.collect();return E - def create_module_stub(I,module_name,file_name=E): - H=file_name;C=module_name - if H is E:O=C.replace(J,S)+'.py';H=I.path+G+O - else:O=H.split(G)[-1] - if G in C:C=C.replace(G,J) - L=E - try:L=__import__(C,E,E,'*');T=D.mem_free() - except N:return A - d(H) - with W(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,I._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,C,B) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) - if C not in{'os','sys','logging','gc'}: - try:del L - except(F,Q):pass - try:del sys.modules[C] - except Q:pass - D.collect();return K - def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;C=indent;D.collect() - if N in K.problematic:return - S,L=K.get_obj_attributes(N) - if L:O(L) - for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',M]:continue - if E[0].isdigit():continue - if G==""and R(C)<=x*4: - U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=M - A='\n{}class {}({}):\n'.format(C,E,U) - if V:A+=C+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),C+' ',P+1);A=C+' def __init__(self, *argv, **kwargs) -> None:\n';A+=C+' ...\n\n';H.write(A) - elif any(A in G for A in[s,r,'closure']): - W=b;a=B - if P>0:a='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(C)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(C,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(C,E,a,W) - A+=C+' ...\n\n';H.write(A) - elif G=="":0 - elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] - if J in A and A[J]: - K=int(A[J]);R=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if R:A[V]=R - A[J]='v{}.{}'.format(K&255,K>>8&3) - if A[F]and not A[C].endswith(b):A[C]=A[C]+b - A[S]=f"{A[C]}-{A[F]}"if A[F]else f"{A[C]}";return A -def z(version): - A=version;B=J.join([str(A)for A in A[:3]]) - if R(A)>3 and A[3]:B+=b+A[3] - return B -def A0(info,desc=B): - L='with ';C=info;F=A - for G in[A+'/board_info.csv'for A in y]: - if e(G): - E=desc or C[H].strip();I=E.rfind(' with') - if I!=-1:J=E[:I].strip() - else:J=B - if A1(C,E,G,J):F=K;break - if not F: - E=desc or C[H].strip() - if L+C[T].upper()in E:E=E.split(L+C[T].upper())[0].strip() - C[H]=E - C[H]=C[H].replace(' ',S);D.collect() -def A1(info,descr,filename,short_descr): - D=short_descr;C=info;E=B - with W(filename,'r')as J: - while 1: - F=J.readline() - if not F:break - I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:C[H]=G;return K - elif D and I==D: - if v in D:C[H]=G;return K - E=G - if E:C[H]=E;return K - return A -def get_root(): - try:A=os.getcwd() - except(F,I):A=J - B=A - for B in[A,'/sd','/flash',G,J]: - try:C=os.stat(B);break - except F:continue - return B -def e(filename): - try: - if os.stat(filename)[0]>>14:return K - return A - except F:return A -def f():sys.exit(1) -def read_path(): - path=B - if R(sys.argv)==3: - A=sys.argv[1].lower() - if A in('--path','-p'):path=sys.argv[2] - else:f() - elif R(sys.argv)==2:f() - return path -def g(): - try:B=bytes('abc',encoding='utf8');C=g.__module__;return A - except(h,I):return K + "Generate stubs for modules in firmware" + + def __init__(self, path: str = None, firmware_id: str = None): # type: ignore + try: + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore + raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") + except AttributeError: + pass + # self.log = logging.getLogger("stubber") + self._report = [] # type: list[str] + self.info = _info() + # self.log.info("Port: {}".format(self.info["port"])) + # self.log.info("Board: {}".format(self.info["board"])) + gc.collect() + if firmware_id: + self._fwid = firmware_id.lower() + else: + if self.info["family"] == "micropython": + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + else: + self._fwid = "{family}-v{version}-{port}".format(**self.info) + self._start_free = gc.mem_free() # type: ignore + + if path: + if path.endswith("/"): + path = path[:-1] + else: + path = get_root() + + self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") + # self.log.debug(self.path) + try: + ensure_folder(path + "/") + except OSError: + print("error creating stub folder {}".format(path)) + self.problematic = [ + "upip", + "upysh", + "webrepl_setup", + "http_client", + "http_client_ssl", + "http_server", + "http_server_ssl", + ] + self.excluded = [ + "webrepl", + "_webrepl", + "port_diag", + "example_sub_led.py", + "example_pub_button.py", + ] + # there is no option to discover modules from micropython, list is read from an external file. + self.modules = [] # type: list[str] + + def get_obj_attributes(self, item_instance: object): + "extract information of the objects members and attributes" + # name_, repr_(value), type as text, item_instance + _result = [] + _errors = [] + # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + for name in dir(item_instance): + if name.startswith("_") and not name in self.modules: + continue + # self.log.debug("get attribute {}".format(name)) + try: + val = getattr(item_instance, name) + # name , item_repr(value) , type as text, item_instance, order + try: + type_text = repr(type(val)).split("'")[1] + except IndexError: + type_text = "" + if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: + order = 1 + elif type_text in {"function", "method"}: + order = 2 + elif type_text in ("class"): + order = 3 + else: + order = 4 + _result.append((name, repr(val), repr(type(val)), val, order)) + except AttributeError as e: + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) + except MemoryError as e: + # print("MemoryError: {}".format(e)) + sleep(1) + reset() + + # remove internal __ + # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) + _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) + gc.collect() + return _result, _errors + + def add_modules(self, modules): + "Add additional modules to be exported" + self.modules = sorted(set(self.modules) | set(modules)) + + def create_all_stubs(self): + "Create stubs for all configured modules" + # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + gc.collect() + for module_name in self.modules: + self.create_one_stub(module_name) + # self.log.info("Finally done") + + def create_one_stub(self, module_name: str): + if module_name in self.problematic: + # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + return False + if module_name in self.excluded: + # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + return False + + file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + gc.collect() + result = False + try: + result = self.create_module_stub(module_name, file_name) + except OSError: + return False + gc.collect() + return result + + def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore + """Create a Stub of a single python module + + Args: + - module_name (str): name of the module to document. This module will be imported. + - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + """ + if file_name is None: + fname = module_name.replace(".", "_") + ".py" + file_name = self.path + "/" + fname + else: + fname = file_name.split("/")[-1] + + if "/" in module_name: + # for nested modules + module_name = module_name.replace("/", ".") + + # import the module (as new_module) to examine it + new_module = None + try: + new_module = __import__(module_name, None, None, ("*")) + m1 = gc.mem_free() # type: ignore + # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + + except ImportError: + # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + return False + + # Start a new file + ensure_folder(file_name) + with open(file_name, "w") as fp: + # todo: improve header + info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) + fp.write(s) + fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + self.write_object_stub(fp, new_module, module_name, "") + + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + + if module_name not in {"os", "sys", "logging", "gc"}: + # try to unload the module unless we use it + try: + del new_module + except (OSError, KeyError): # lgtm [py/unreachable-statement] + pass + try: + del sys.modules[module_name] + except KeyError: + pass + gc.collect() + return True + + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): + "Write a module/object stub to an open file. Can be called recursive." + gc.collect() + if object_expr in self.problematic: + # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + return + + # # self.log.debug("DUMP : {}".format(object_expr)) + items, errors = self.get_obj_attributes(object_expr) + + if errors: + print(errors) + + for item_name, item_repr, item_type_txt, item_instance, _ in items: + # name_, repr_(value), type as text, item_instance, order + if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: + # do not create stubs for these primitives + continue + if item_name[0].isdigit(): + # self.log.warning("NameError: invalid name {}".format(item_name)) + continue + # Class expansion only on first 3 levels (bit of a hack) + if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: + # self.log.debug("{0}class {1}:".format(indent, item_name)) + superclass = "" + is_exception = ( + item_name.endswith("Exception") + or item_name.endswith("Error") + or item_name + in [ + "KeyboardInterrupt", + "StopIteration", + "SystemExit", + ] + ) + if is_exception: + superclass = "Exception" + s = "\n{}class {}({}):\n".format(indent, item_name, superclass) + # s += indent + " ''\n" + if is_exception: + s += indent + " ...\n" + fp.write(s) + return + # write classdef + fp.write(s) + # first write the class literals and methods + # self.log.debug("# recursion over class {0}".format(item_name)) + self.write_object_stub( + fp, + item_instance, + "{0}.{1}".format(obj_name, item_name), + indent + " ", + in_class + 1, + ) + # end with the __init__ method to make sure that the literals are defined + # Add __init__ + s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" + s += indent + " ...\n\n" + fp.write(s) + elif any(word in item_type_txt for word in ["method", "function", "closure"]): + # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # module Function or class method + # will accept any number of params + # return type Any/Incomplete + ret = "Incomplete" + first = "" + # Self parameter only on class methods/functions + if in_class > 0: + first = "self, " + # class method - add function decoration + if "bound_method" in item_type_txt or "bound_method" in item_repr: + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) + s += indent + " ...\n\n" + fp.write(s) + # self.log.debug("\n" + s) + elif item_type_txt == "": + # Skip imported modules + # fp.write("# import {}\n".format(item_name)) + pass + + elif item_type_txt.startswith(" dict[str, str] + info = OrderedDict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "UNKNOWN", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" + try: + info["version"] = version_str(sys.implementation.version) # type: ignore + except AttributeError: + pass + try: + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine + info["cpu"] = _machine.split("with")[-1].strip() + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + gc.collect() + read_boardname(info) + gc.collect() + + try: + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): + pass + # avoid build hashes + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() # type: ignore + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + info["version"] + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # versions from 1.10.0 to 1.20.0 do not have a micro .0 + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" + # simple to use version[-build] string + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" + + return info + + +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): + found = True + break + if not found: + # print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + +def find_board(info: dict, descr: str, filename: str, short_descr: str): + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + info["board"] = board_ + return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True + return False + + +def get_root() -> str: # sourcery skip: use-assigned-variable + "Determine the root folder of the device" + try: + c = os.getcwd() + except (OSError, AttributeError): + # unix port + c = "." + r = c + for r in [c, "/sd", "/flash", "/", "."]: + try: + _ = os.stat(r) + break + except OSError: + continue + return r + + +def file_exists(filename: str): + try: + if os.stat(filename)[0] >> 14: + return True + return False + except OSError: + return False + + +def show_help(): + # print("-p, --path path to store the stubs in, defaults to '.'") + sys.exit(1) + + +def read_path() -> str: + "get --path from cmdline. [unix/win]" + path = "" + if len(sys.argv) == 3: + cmd = (sys.argv[1]).lower() + if cmd in ("--path", "-p"): + path = sys.argv[2] + else: + show_help() + elif len(sys.argv) == 2: + show_help() + return path + + +def is_micropython() -> bool: + "runtime test to determine full or micropython" + # pylint: disable=unused-variable,eval-used + try: + # either test should fail on micropython + # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces + # Micropython : SyntaxError + # a = eval("1and 0") # lgtm [py/unused-local-variable] + # Eval blocks some minification aspects + + # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented + # Micropython: NotImplementedError + b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] + + # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute + # Micropython: AttributeError + c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] + return False + except (NotImplementedError, AttributeError): + return True + + def main(): - C='lvgl' - try:import lvgl as A - except l:return - B=C - try:B='lvgl-{0}_{1}_{2}-{3}-{4}'.format(A.version_major(),A.version_minor(),A.version_patch(),A.version_info(),sys.platform) - except l:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) - finally:stubber=Stubber(firmware_id=B) - stubber.clean();stubber.modules=['io','lodepng','rtch',C];D.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or g(): - try:A2=logging.getLogger(u);logging.basicConfig(level=logging.INFO) - except j:pass - if not e('no_auto_stubber.txt'): - try:D.threshold(4*1024);D.enable() - except BaseException:pass - main() \ No newline at end of file + try: + import lvgl # type: ignore + except Exception: + # print("\n\nNOTE: The `lvgl` module could not be found on this firmware\n\n") + return + # Specify firmware name & version + fw_id = "lvgl" + try: + fw_id = "lvgl-{0}_{1}_{2}-{3}-{4}".format( + lvgl.version_major(), + lvgl.version_minor(), + lvgl.version_patch(), + lvgl.version_info(), + sys.platform, + ) + except Exception: + fw_id = "lvgl-{0}_{1}_{2}_{3}-{4}".format(8, 1, 0, "dev", sys.platform) + finally: + stubber = Stubber(firmware_id=fw_id) + stubber.clean() + # modules to stub : only lvgl specifics + stubber.modules = ["io", "lodepng", "rtch", "lvgl"] # spell-checker: enable + + gc.collect() + + stubber.create_all_stubs() + stubber.report() + + +if __name__ == "__main__" or is_micropython(): + try: + log = logging.getLogger("stubber") + logging.basicConfig(level=logging.INFO) + # logging.basicConfig(level=logging.DEBUG) + except NameError: + pass + if not file_exists("no_auto_stubber.txt"): + try: + gc.threshold(4 * 1024) # type: ignore + gc.enable() + except BaseException: + pass + main() diff --git a/mip/v5/createstubs_lvgl_mpy.mpy b/mip/v5/createstubs_lvgl_mpy.mpy index b637b49e423ade08089956031558af36e715c191..6d349d2f9f00a1e9b02d7918b1620743d349f119 100644 GIT binary patch literal 8527 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 literal 8447 zcmaJ`S#Vp|c|P}m-~y81!2x(hin0L_Ah<6AA;^?uTLK{mB5g^uL@M-#fWRdQ8w6ln zkdneOywuV<(x{$knrUV_ZN^NV+kWR> zkfQ0Nu*G}sfA)X<{{OyYrcT#~j*ewY%67%FN;Idax#=;rD|62K|NlJb_TWFS_nCeE z=RME+y&jLh=e@a0Rf_A9OL4tdeX06VxpJrpe=b${oO?WN&L$6G+bSjohq*F4@GV+{E-)7`PnP!+}JeiK>WSVB= z4Vk7GQDr)1BOaM1Z6qMmw``yq+6zwjDj-8N;)hujWRMQ(^nWt%5;>G zznAHkZDdBKr)}iCOh;I0EHf?BQ;d|$^rVfvCDWH}q*bOvHqs)~6E-p{)8jVcmFY27 zH6EQxB+tq8B^!BBrZ2uM(?LeNWIA9YE}0%>ma%j+i|d3>$n-EHr851}kW7!*NRLck zVAdHWtLiuGXGD@|P#bC}nTW|WBpPW|mhdc9&!G{v6OCEo(^DC>O=_@Azp18EyG*h) zI#5eSH70>r{)8rx*Nq8TMOAX>vra{0lZljKOsOWPZM~m{O0>~|jgj*4Y+T7I@lYZr z#>=sEGO6h7S22giMhBk4q_Rh`FxF{Ez#^JB{N#c-!RU3&suK3R@Lir0%oz}PeR zch=U&%Da<^F=p*n<9frq1hXWS86{~m+slt0d*OKCJQ*Dj?51yS^4qqDBs!f- zM~arzl{=fec(6Rsz0H!}4}8ORi8U#g%HOknefOJ(-m|=0(WDUER3hkoQD<7X0aW3dX^ z5=$!4l$(eJEOJ#=$)vM6h_kqqu!6`WB&%d0)~Aj2bz&+VS0LnFTS!VOuJf|0c&{!o z@ZHQWHK~W#oZ7xdx3kal%pRw^r^6HQ9@y_Ai+94^gu^%;mg!V<3No@=vkFe6Dy#~s z-`mymD6~`KWsWk@RWt#{g<14=?&<0MWvE=^bkc3|ONvkpPLFO%x1HqctP$fz+|X%1 zNaaGgd7r~tv^eO+Qm9&6a*%WY-4>laL7$elmvQ>iFsDUk*<%cf79L%>P7 z49U4-(Nrp(bB!r3!>HnF{XSlIF-?B zyy(4LIUAkIBw>crW09m1M?_a^H)t8qVAZ*F3gmZtZgAh9vG{FXL<_gHKjUt3dRv^0 zzRpHxr?YuKDco)+ciPEaPG4N~OOe6U ziz|M5KU@#R7~$mGSNu=_2l;@}=76*?{4s(il;p&xFc2t7@MEDGS2;~_n&vda>D!!s znNxJV(pmO6WY!iQ1b1r~kmXeEq=It(L9j-<%HScQswxN<9t5d&@c}I5;0kZRhFsd% z_{z05GraA<(V_`Htvx)-$udT|q0OgO7Ow|P=pPz-*i!NOfE%Mo$EUFDhex5&JA%KTj}b!5ew&pYOh%{1;?d{Kn32CY3_3l# zz}l=^eZ5&bO?WLQ@8|7(U?6$F;Ftc(FXii`Au;~2X~A=teIXiDXrrx!H#i#Ltn&7X z$Y2#&%R9CQ2>5`};AitI?J#X#M(ah+s} zF{UF(Xfq_2x9k3A5iW_-0pY@EfZpLd96N9nUVS%QMe>e66Ok5|0`#t-gK$(r2hA~| zg1o{}ftkzVvO&2R!i4L8Fa8}{pt?bedz>vDdp*w9mS(5Zx%)YP>z+Oj0!88O5~oN0 zHRRNwRSRGt%!0B~oO1nM-rm3))>qc=1gnG}|A0#YX@2+~mzE#Hv+Ls}UV#Jg%KPD6 zggYXU#FXyqBFo℘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 diff --git a/mip/v5/createstubs_mem_min.py b/mip/v5/createstubs_mem_min.py index ef72491b9..1f76a726c 100644 --- a/mip/v5/createstubs_mem_min.py +++ b/mip/v5/createstubs_mem_min.py @@ -1,303 +1,737 @@ -w='with' -v='stubber' -u='{}/{}' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n=TypeError -m=NameError -l=sorted -k=NotImplementedError -d='-' -c=',\n' -b='dict' -a='list' -Z='tuple' -Y='micropython' -X=str -W=repr -U='cpu' -T='_' -S=KeyError -R=open -Q=IndexError -P=ImportError -O='family' -N=len -M=dir -L=print -K=True -J='.' -I=AttributeError -H='board' -A=False -G='/' -E=None -F=OSError -D='version' -C='' -import gc as B,os,sys -try:from ujson import dumps -except:from json import dumps -try:from machine import reset -except P:pass -try:from collections import OrderedDict as e -except P:from ucollections import OrderedDict as e -__version__='v1.16.2' -x=2 -y=2 -f=[J,'/lib','/sd/lib','/flash/lib','lib'] +"""Create stubs for (all) modules on a MicroPython board. + + This variant of the createstubs.py script is optimised for use on low-memory devices, and reads the list of modules from a text file + `modulelist.txt` in the root or `libs` folder that should be uploaded to the device. + If that cannot be found then only a single module (micropython) is stubbed. + In order to run this on low-memory devices two additional steps are recommended: + - minifification, using python-minifier + to reduce overall size, and remove logging overhead. + - cross compilation, using mpy-cross, + to avoid the compilation step on the micropython device + +This variant was generated from createstubs.py by micropython-stubber v1.16.2 +""" +# Copyright (c) 2019-2023 Jos Verlinde + +import gc +# import logging +import os +import sys + +try: + from ujson import dumps +except: + from json import dumps + +try: + from machine import reset # type: ignore +except ImportError: + pass + +try: + from collections import OrderedDict +except ImportError: + from ucollections import OrderedDict # type: ignore + +__version__ = "v1.16.2" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] from time import sleep + + class Stubber: - def __init__(A,path=E,firmware_id=E): - C=firmware_id - try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') - except I:pass - A._report=[];A.info=_info();B.collect() - if C:A._fwid=C.lower() - elif A.info[O]==Y:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-v{version}-{port}'.format(**A.info) - A._start_free=B.mem_free() - if path: - if path.endswith(G):path=path[:-1] - else:path=get_root() - A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:g(path+G) - except F:L('error creating stub folder {}'.format(path)) - A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] - def get_obj_attributes(L,item_instance): - H=item_instance;D=[];J=[] - for A in M(H): - if A.startswith(T)and not A in L.modules:continue - try: - E=getattr(H,A) - try:F=W(type(E)).split("'")[1] - except Q:F=C - if F in{o,p,q,r,Z,a,b}:G=1 - elif F in{s,t}:G=2 - elif F in'class':G=3 - else:G=4 - D.append((A,W(E),W(type(E)),E,G)) - except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) - except MemoryError as K:sleep(1);reset() - D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) - def create_all_stubs(A): - B.collect() - for C in A.modules:A.create_one_stub(C) - def create_one_stub(C,module_name): - D=module_name - if D in C.problematic:return A - if D in C.excluded:return A - H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=A - try:E=C.create_module_stub(D,H) - except F:return A - B.collect();return E - def create_module_stub(I,module_name,file_name=E): - H=file_name;D=module_name - if H is E:N=D.replace(J,T)+'.py';H=I.path+G+N - else:N=H.split(G)[-1] - if G in D:D=D.replace(G,J) - L=E - try:L=__import__(D,E,E,'*');U=B.mem_free() - except P:return A - g(H) - with R(H,'w')as M:O=X(I.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,O,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,C) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: - try:del L - except(F,S):pass - try:del sys.modules[D] - except S:pass - B.collect();return K - def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() - if P in K.problematic:return - R,M=K.get_obj_attributes(P) - if M:L(M) - for(E,J,G,T,f)in R: - if E in['classmethod','staticmethod','BaseException',O]:continue - if E[0].isdigit():continue - if G==""and N(D)<=y*4: - U=C;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=O - A='\n{}class {}({}):\n'.format(D,E,U) - if V:A+=D+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[t,s,'closure']): - W=Y;X=C - if Q>0:X='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) - A+=D+' ...\n\n';H.write(A) - elif G=="":0 - elif G.startswith("='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if J in A and A[J]: - K=int(A[J]);N=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if N:A[T]=N - A[J]='v{}.{}'.format(K&255,K>>8&3) - if A[F]and not A[D].endswith(c):A[D]=A[D]+c - A[R]=f"{A[D]}-{A[F]}"if A[F]else f"{A[D]}";return A -def z(version): - A=version;B=J.join([X(A)for A in A[:3]]) - if N(A)>3 and A[3]:B+=d+A[3] - return B -def A0(info,desc=C): - L='with ';D=info;F=A - for G in[A+'/board_info.csv'for A in f]: - if h(G): - E=desc or D[H].strip();I=E.rfind(' with') - if I!=-1:J=E[:I].strip() - else:J=C - if A1(D,E,G,J):F=K;break - if not F: - E=desc or D[H].strip() - if L+D[U].upper()in E:E=E.split(L+D[U].upper())[0].strip() - D[H]=E - D[H]=D[H].replace(' ',T);B.collect() -def A1(info,descr,filename,short_descr): - D=short_descr;B=info;E=C - with R(filename,'r')as J: - while 1: - F=J.readline() - if not F:break - I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:B[H]=G;return K - elif D and I==D: - if w in D:B[H]=G;return K - E=G - if E:B[H]=E;return K - return A -def get_root(): - try:A=os.getcwd() - except(F,I):A=J - B=A - for B in[A,'/sd','/flash',G,J]: - try:C=os.stat(B);break - except F:continue - return B -def h(filename): - try: - if os.stat(filename)[0]>>14:return K - return A - except F:return A -def i():sys.exit(1) -def read_path(): - path=C - if N(sys.argv)==3: - A=sys.argv[1].lower() - if A in('--path','-p'):path=sys.argv[2] - else:i() - elif N(sys.argv)==2:i() - return path -def j(): - try:B=bytes('abc',encoding='utf8');C=j.__module__;return A - except(k,I):return K + "Generate stubs for modules in firmware" + + def __init__(self, path: str = None, firmware_id: str = None): # type: ignore + try: + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore + raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") + except AttributeError: + pass + # self.log = logging.getLogger("stubber") + self._report = [] # type: list[str] + self.info = _info() + # self.log.info("Port: {}".format(self.info["port"])) + # self.log.info("Board: {}".format(self.info["board"])) + gc.collect() + if firmware_id: + self._fwid = firmware_id.lower() + else: + if self.info["family"] == "micropython": + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + else: + self._fwid = "{family}-v{version}-{port}".format(**self.info) + self._start_free = gc.mem_free() # type: ignore + + if path: + if path.endswith("/"): + path = path[:-1] + else: + path = get_root() + + self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") + # self.log.debug(self.path) + try: + ensure_folder(path + "/") + except OSError: + print("error creating stub folder {}".format(path)) + self.problematic = [ + "upip", + "upysh", + "webrepl_setup", + "http_client", + "http_client_ssl", + "http_server", + "http_server_ssl", + ] + self.excluded = [ + "webrepl", + "_webrepl", + "port_diag", + "example_sub_led.py", + "example_pub_button.py", + ] + # there is no option to discover modules from micropython, list is read from an external file. + self.modules = [] # type: list[str] + + def get_obj_attributes(self, item_instance: object): + "extract information of the objects members and attributes" + # name_, repr_(value), type as text, item_instance + _result = [] + _errors = [] + # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + for name in dir(item_instance): + if name.startswith("_") and not name in self.modules: + continue + # self.log.debug("get attribute {}".format(name)) + try: + val = getattr(item_instance, name) + # name , item_repr(value) , type as text, item_instance, order + try: + type_text = repr(type(val)).split("'")[1] + except IndexError: + type_text = "" + if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: + order = 1 + elif type_text in {"function", "method"}: + order = 2 + elif type_text in ("class"): + order = 3 + else: + order = 4 + _result.append((name, repr(val), repr(type(val)), val, order)) + except AttributeError as e: + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) + except MemoryError as e: + # print("MemoryError: {}".format(e)) + sleep(1) + reset() + + # remove internal __ + # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) + _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) + gc.collect() + return _result, _errors + + def add_modules(self, modules): + "Add additional modules to be exported" + self.modules = sorted(set(self.modules) | set(modules)) + + def create_all_stubs(self): + "Create stubs for all configured modules" + # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + gc.collect() + for module_name in self.modules: + self.create_one_stub(module_name) + # self.log.info("Finally done") + + def create_one_stub(self, module_name: str): + if module_name in self.problematic: + # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + return False + if module_name in self.excluded: + # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + return False + + file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + gc.collect() + result = False + try: + result = self.create_module_stub(module_name, file_name) + except OSError: + return False + gc.collect() + return result + + def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore + """Create a Stub of a single python module + + Args: + - module_name (str): name of the module to document. This module will be imported. + - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + """ + if file_name is None: + fname = module_name.replace(".", "_") + ".py" + file_name = self.path + "/" + fname + else: + fname = file_name.split("/")[-1] + + if "/" in module_name: + # for nested modules + module_name = module_name.replace("/", ".") + + # import the module (as new_module) to examine it + new_module = None + try: + new_module = __import__(module_name, None, None, ("*")) + m1 = gc.mem_free() # type: ignore + # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + + except ImportError: + # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + return False + + # Start a new file + ensure_folder(file_name) + with open(file_name, "w") as fp: + # todo: improve header + info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) + fp.write(s) + fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + self.write_object_stub(fp, new_module, module_name, "") + + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + + if module_name not in {"os", "sys", "logging", "gc"}: + # try to unload the module unless we use it + try: + del new_module + except (OSError, KeyError): # lgtm [py/unreachable-statement] + pass + try: + del sys.modules[module_name] + except KeyError: + pass + gc.collect() + return True + + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): + "Write a module/object stub to an open file. Can be called recursive." + gc.collect() + if object_expr in self.problematic: + # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + return + + # # self.log.debug("DUMP : {}".format(object_expr)) + items, errors = self.get_obj_attributes(object_expr) + + if errors: + print(errors) + + for item_name, item_repr, item_type_txt, item_instance, _ in items: + # name_, repr_(value), type as text, item_instance, order + if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: + # do not create stubs for these primitives + continue + if item_name[0].isdigit(): + # self.log.warning("NameError: invalid name {}".format(item_name)) + continue + # Class expansion only on first 3 levels (bit of a hack) + if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: + # self.log.debug("{0}class {1}:".format(indent, item_name)) + superclass = "" + is_exception = ( + item_name.endswith("Exception") + or item_name.endswith("Error") + or item_name + in [ + "KeyboardInterrupt", + "StopIteration", + "SystemExit", + ] + ) + if is_exception: + superclass = "Exception" + s = "\n{}class {}({}):\n".format(indent, item_name, superclass) + # s += indent + " ''\n" + if is_exception: + s += indent + " ...\n" + fp.write(s) + return + # write classdef + fp.write(s) + # first write the class literals and methods + # self.log.debug("# recursion over class {0}".format(item_name)) + self.write_object_stub( + fp, + item_instance, + "{0}.{1}".format(obj_name, item_name), + indent + " ", + in_class + 1, + ) + # end with the __init__ method to make sure that the literals are defined + # Add __init__ + s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" + s += indent + " ...\n\n" + fp.write(s) + elif any(word in item_type_txt for word in ["method", "function", "closure"]): + # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # module Function or class method + # will accept any number of params + # return type Any/Incomplete + ret = "Incomplete" + first = "" + # Self parameter only on class methods/functions + if in_class > 0: + first = "self, " + # class method - add function decoration + if "bound_method" in item_type_txt or "bound_method" in item_repr: + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) + s += indent + " ...\n\n" + fp.write(s) + # self.log.debug("\n" + s) + elif item_type_txt == "": + # Skip imported modules + # fp.write("# import {}\n".format(item_name)) + pass + + elif item_type_txt.startswith(" dict[str, str] + info = OrderedDict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "UNKNOWN", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" + try: + info["version"] = version_str(sys.implementation.version) # type: ignore + except AttributeError: + pass + try: + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine + info["cpu"] = _machine.split("with")[-1].strip() + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + gc.collect() + read_boardname(info) + gc.collect() + + try: + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): + pass + # avoid build hashes + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() # type: ignore + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + info["version"] + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # versions from 1.10.0 to 1.20.0 do not have a micro .0 + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" + # simple to use version[-build] string + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" + + return info + + +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): + found = True + break + if not found: + # print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + +def find_board(info: dict, descr: str, filename: str, short_descr: str): + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + info["board"] = board_ + return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True + return False + + +def get_root() -> str: # sourcery skip: use-assigned-variable + "Determine the root folder of the device" + try: + c = os.getcwd() + except (OSError, AttributeError): + # unix port + c = "." + r = c + for r in [c, "/sd", "/flash", "/", "."]: + try: + _ = os.stat(r) + break + except OSError: + continue + return r + + +def file_exists(filename: str): + try: + if os.stat(filename)[0] >> 14: + return True + return False + except OSError: + return False + + +def show_help(): + # print("-p, --path path to store the stubs in, defaults to '.'") + sys.exit(1) + + +def read_path() -> str: + "get --path from cmdline. [unix/win]" + path = "" + if len(sys.argv) == 3: + cmd = (sys.argv[1]).lower() + if cmd in ("--path", "-p"): + path = sys.argv[2] + else: + show_help() + elif len(sys.argv) == 2: + show_help() + return path + + +def is_micropython() -> bool: + "runtime test to determine full or micropython" + # pylint: disable=unused-variable,eval-used + try: + # either test should fail on micropython + # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces + # Micropython : SyntaxError + # a = eval("1and 0") # lgtm [py/unused-local-variable] + # Eval blocks some minification aspects + + # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented + # Micropython: NotImplementedError + b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] + + # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute + # Micropython: AttributeError + c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] + return False + except (NotImplementedError, AttributeError): + return True + + def main(): - E='/modulelist.txt';stubber=Stubber(path=read_path());stubber.clean();stubber.modules=[] - for C in f: - try: - F=B.mem_free() - with R(C+E)as D: - L('Debug: List of modules: '+C+E);A=D.readline() - while A: - A=A.strip() - if N(A)>0 and A[0]!='#':stubber.modules.append(A) - A=D.readline() - B.collect();L('Debug: Used memory to load modulelist.txt: '+X(F-B.mem_free())+' bytes');break - except Exception:pass - if not stubber.modules:stubber.modules=[Y] - B.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or j(): - try:A2=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except m:pass - if not h('no_auto_stubber.txt'): - try:B.threshold(4*1024);B.enable() - except BaseException:pass - main() \ No newline at end of file + stubber = Stubber(path=read_path()) + # stubber = Stubber(path="/sd") + # Option: Specify a firmware name & version + # stubber = Stubber(firmware_id='HoverBot v1.2.1') + stubber.clean() + # Read stubs from modulelist in the current folder or in /libs + # fall back to default modules + stubber.modules = [] # avoid duplicates + for p in LIBS: + try: + _1 = gc.mem_free() # type: ignore + with open(p + "/modulelist.txt") as f: + print ("Debug: List of modules: " + p + "/modulelist.txt") + line = f.readline() + while line: + line = line.strip() + if len(line) > 0 and line[0] != "#": + stubber.modules.append(line) + line = f.readline() + gc.collect() # type: ignore + print ("Debug: Used memory to load modulelist.txt: " + str(_1 - gc.mem_free()) + " bytes") # type: ignore + break + except Exception: + pass + if not stubber.modules: + stubber.modules = ["micropython"] + # print("Could not find modulelist.txt, using default modules") + + gc.collect() + + stubber.create_all_stubs() + stubber.report() + + +if __name__ == "__main__" or is_micropython(): + try: + log = logging.getLogger("stubber") + logging.basicConfig(level=logging.INFO) + # logging.basicConfig(level=logging.DEBUG) + except NameError: + pass + if not file_exists("no_auto_stubber.txt"): + try: + gc.threshold(4 * 1024) # type: ignore + gc.enable() + except BaseException: + pass + main() diff --git a/mip/v5/createstubs_mem_mpy.mpy b/mip/v5/createstubs_mem_mpy.mpy index 42b519779063d8c0909a812755acd995118cf9b9..08653556ced1e52895b80d28ad396af8af3cc02b 100644 GIT binary patch literal 8585 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 literal 8486 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"and R(C)<=A0*4: - U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=M - A='\n{}class {}({}):\n'.format(C,E,U) - if V:A+=C+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),C+' ',P+1);A=C+' def __init__(self, *argv, **kwargs) -> None:\n';A+=C+' ...\n\n';H.write(A) - elif any(A in G for A in[s,r,'closure']): - W=b;X=B - if P>0:X='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(C)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(C,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(C,E,X,W) - A+=C+' ...\n\n';H.write(A) - elif G=="":0 - elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] - if J in A and A[J]: - K=int(A[J]);R=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if R:A[V]=R - A[J]='v{}.{}'.format(K&255,K>>8&3) - if A[F]and not A[C].endswith(b):A[C]=A[C]+b - A[S]=f"{A[C]}-{A[F]}"if A[F]else f"{A[C]}";return A -def A2(version): - A=version;B=J.join([str(A)for A in A[:3]]) - if R(A)>3 and A[3]:B+=c+A[3] - return B -def A3(info,desc=B): - L='with ';C=info;F=A - for G in[A+'/board_info.csv'for A in A1]: - if g(G): - E=desc or C[H].strip();I=E.rfind(' with') - if I!=-1:J=E[:I].strip() - else:J=B - if A4(C,E,G,J):F=K;break - if not F: - E=desc or C[H].strip() - if L+C[T].upper()in E:E=E.split(L+C[T].upper())[0].strip() - C[H]=E - C[H]=C[H].replace(' ',S);D.collect() -def A4(info,descr,filename,short_descr): - D=short_descr;C=info;E=B - with W(filename,'r')as J: - while 1: - F=J.readline() - if not F:break - I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:C[H]=G;return K - elif D and I==D: - if y in D:C[H]=G;return K - E=G - if E:C[H]=E;return K - return A -def get_root(): - try:A=os.getcwd() - except(F,I):A=J - B=A - for B in[A,'/sd','/flash',G,J]: - try:C=os.stat(B);break - except F:continue - return B -def g(filename): - try: - if os.stat(filename)[0]>>14:return K - return A - except F:return A -def h():sys.exit(1) -def read_path(): - path=B - if R(sys.argv)==3: - A=sys.argv[1].lower() - if A in('--path','-p'):path=sys.argv[2] - else:h() - elif R(sys.argv)==2:h() - return path -def i(): - try:B=bytes('abc',encoding='utf8');C=i.__module__;return A - except(j,I):return K -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',u,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',X,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',x,d,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',t,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];D.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or i(): - try:A5=logging.getLogger(w);logging.basicConfig(level=logging.INFO) - except l:pass - if not g('no_auto_stubber.txt'): - try:D.threshold(4*1024);D.enable() - except BaseException:pass - main() \ No newline at end of file + "Generate stubs for modules in firmware" + + def __init__(self, path: str = None, firmware_id: str = None): # type: ignore + try: + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore + raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") + except AttributeError: + pass + # self.log = logging.getLogger("stubber") + self._report = [] # type: list[str] + self.info = _info() + # self.log.info("Port: {}".format(self.info["port"])) + # self.log.info("Board: {}".format(self.info["board"])) + gc.collect() + if firmware_id: + self._fwid = firmware_id.lower() + else: + if self.info["family"] == "micropython": + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + else: + self._fwid = "{family}-v{version}-{port}".format(**self.info) + self._start_free = gc.mem_free() # type: ignore + + if path: + if path.endswith("/"): + path = path[:-1] + else: + path = get_root() + + self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") + # self.log.debug(self.path) + try: + ensure_folder(path + "/") + except OSError: + print("error creating stub folder {}".format(path)) + self.problematic = [ + "upip", + "upysh", + "webrepl_setup", + "http_client", + "http_client_ssl", + "http_server", + "http_server_ssl", + ] + self.excluded = [ + "webrepl", + "_webrepl", + "port_diag", + "example_sub_led.py", + "example_pub_button.py", + ] + # there is no option to discover modules from micropython, list is read from an external file. + self.modules = [] # type: list[str] + + def get_obj_attributes(self, item_instance: object): + "extract information of the objects members and attributes" + # name_, repr_(value), type as text, item_instance + _result = [] + _errors = [] + # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + for name in dir(item_instance): + if name.startswith("_") and not name in self.modules: + continue + # self.log.debug("get attribute {}".format(name)) + try: + val = getattr(item_instance, name) + # name , item_repr(value) , type as text, item_instance, order + try: + type_text = repr(type(val)).split("'")[1] + except IndexError: + type_text = "" + if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: + order = 1 + elif type_text in {"function", "method"}: + order = 2 + elif type_text in ("class"): + order = 3 + else: + order = 4 + _result.append((name, repr(val), repr(type(val)), val, order)) + except AttributeError as e: + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) + except MemoryError as e: + # print("MemoryError: {}".format(e)) + sleep(1) + reset() + + # remove internal __ + # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) + _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) + gc.collect() + return _result, _errors + + def add_modules(self, modules): + "Add additional modules to be exported" + self.modules = sorted(set(self.modules) | set(modules)) + + def create_all_stubs(self): + "Create stubs for all configured modules" + # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + gc.collect() + for module_name in self.modules: + self.create_one_stub(module_name) + # self.log.info("Finally done") + + def create_one_stub(self, module_name: str): + if module_name in self.problematic: + # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + return False + if module_name in self.excluded: + # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + return False + + file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + gc.collect() + result = False + try: + result = self.create_module_stub(module_name, file_name) + except OSError: + return False + gc.collect() + return result + + def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore + """Create a Stub of a single python module + + Args: + - module_name (str): name of the module to document. This module will be imported. + - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + """ + if file_name is None: + fname = module_name.replace(".", "_") + ".py" + file_name = self.path + "/" + fname + else: + fname = file_name.split("/")[-1] + + if "/" in module_name: + # for nested modules + module_name = module_name.replace("/", ".") + + # import the module (as new_module) to examine it + new_module = None + try: + new_module = __import__(module_name, None, None, ("*")) + m1 = gc.mem_free() # type: ignore + # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + + except ImportError: + # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + return False + + # Start a new file + ensure_folder(file_name) + with open(file_name, "w") as fp: + # todo: improve header + info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format( + module_name, self._fwid, info_, __version__ + ) + fp.write(s) + fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + self.write_object_stub(fp, new_module, module_name, "") + + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + + if module_name not in {"os", "sys", "logging", "gc"}: + # try to unload the module unless we use it + try: + del new_module + except (OSError, KeyError): # lgtm [py/unreachable-statement] + pass + try: + del sys.modules[module_name] + except KeyError: + pass + gc.collect() + return True + + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): + "Write a module/object stub to an open file. Can be called recursive." + gc.collect() + if object_expr in self.problematic: + # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + return + + # # self.log.debug("DUMP : {}".format(object_expr)) + items, errors = self.get_obj_attributes(object_expr) + + if errors: + print(errors) + + for item_name, item_repr, item_type_txt, item_instance, _ in items: + # name_, repr_(value), type as text, item_instance, order + if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: + # do not create stubs for these primitives + continue + if item_name[0].isdigit(): + # self.log.warning("NameError: invalid name {}".format(item_name)) + continue + # Class expansion only on first 3 levels (bit of a hack) + if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: + # self.log.debug("{0}class {1}:".format(indent, item_name)) + superclass = "" + is_exception = ( + item_name.endswith("Exception") + or item_name.endswith("Error") + or item_name + in [ + "KeyboardInterrupt", + "StopIteration", + "SystemExit", + ] + ) + if is_exception: + superclass = "Exception" + s = "\n{}class {}({}):\n".format(indent, item_name, superclass) + # s += indent + " ''\n" + if is_exception: + s += indent + " ...\n" + fp.write(s) + return + # write classdef + fp.write(s) + # first write the class literals and methods + # self.log.debug("# recursion over class {0}".format(item_name)) + self.write_object_stub( + fp, + item_instance, + "{0}.{1}".format(obj_name, item_name), + indent + " ", + in_class + 1, + ) + # end with the __init__ method to make sure that the literals are defined + # Add __init__ + s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" + s += indent + " ...\n\n" + fp.write(s) + elif any(word in item_type_txt for word in ["method", "function", "closure"]): + # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # module Function or class method + # will accept any number of params + # return type Any/Incomplete + ret = "Incomplete" + first = "" + # Self parameter only on class methods/functions + if in_class > 0: + first = "self, " + # class method - add function decoration + if "bound_method" in item_type_txt or "bound_method" in item_repr: + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format( + indent, item_name, ret + ) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) + s += indent + " ...\n\n" + fp.write(s) + # self.log.debug("\n" + s) + elif item_type_txt == "": + # Skip imported modules + # fp.write("# import {}\n".format(item_name)) + pass + + elif item_type_txt.startswith(" dict[str, str] + info = OrderedDict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "UNKNOWN", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" + try: + info["version"] = version_str(sys.implementation.version) # type: ignore + except AttributeError: + pass + try: + _machine = ( + sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + ) + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine + info["cpu"] = _machine.split("with")[-1].strip() + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + gc.collect() + read_boardname(info) + gc.collect() + + try: + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): + pass + # avoid build hashes + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() # type: ignore + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + info["version"] + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # versions from 1.10.0 to 1.20.0 do not have a micro .0 + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" + # simple to use version[-build] string + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" + + return info + + +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): + found = True + break + if not found: + # print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + +def find_board(info: dict, descr: str, filename: str, short_descr: str): + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + info["board"] = board_ + return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True + return False + + +def get_root() -> str: # sourcery skip: use-assigned-variable + "Determine the root folder of the device" + try: + c = os.getcwd() + except (OSError, AttributeError): + # unix port + c = "." + r = c + for r in [c, "/sd", "/flash", "/", "."]: + try: + _ = os.stat(r) + break + except OSError: + continue + return r + + +def file_exists(filename: str): + try: + if os.stat(filename)[0] >> 14: + return True + return False + except OSError: + return False + + +def show_help(): + # print("-p, --path path to store the stubs in, defaults to '.'") + sys.exit(1) + + +def read_path() -> str: + "get --path from cmdline. [unix/win]" + path = "" + if len(sys.argv) == 3: + cmd = (sys.argv[1]).lower() + if cmd in ("--path", "-p"): + path = sys.argv[2] + else: + show_help() + elif len(sys.argv) == 2: + show_help() + return path + + +def is_micropython() -> bool: + "runtime test to determine full or micropython" + # pylint: disable=unused-variable,eval-used + try: + # either test should fail on micropython + # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces + # Micropython : SyntaxError + # a = eval("1and 0") # lgtm [py/unused-local-variable] + # Eval blocks some minification aspects + + # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented + # Micropython: NotImplementedError + b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] + + # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute + # Micropython: AttributeError + c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] + return False + except (NotImplementedError, AttributeError): + return True + + +def main(): + stubber = Stubber(path=read_path()) + # stubber = Stubber(path="/sd") + # Option: Specify a firmware name & version + # stubber = Stubber(firmware_id='HoverBot v1.2.1') + stubber.clean() + # there is no option to discover modules from micropython, need to hardcode + # below contains combined modules from Micropython ESP8622, ESP32, Loboris, Pycom and ulab , lvgl + # spell-checker: disable + # modules to stub : 131 + stubber.modules = [ + "WM8960", + "_OTA", + "_asyncio", + "_boot_fat", + "_coap", + "_espnow", + "_flash_control_OTA", + "_main_pybytes", + "_mqtt", + "_mqtt_core", + "_msg_handl", + "_onewire", + "_periodical_pin", + "_pybytes", + "_pybytes_ca", + "_pybytes_config", + "_pybytes_config_reader", + "_pybytes_connection", + "_pybytes_constants", + "_pybytes_debug", + "_pybytes_library", + "_pybytes_machine_learning", + "_pybytes_main", + "_pybytes_protocol", + "_pybytes_pyconfig", + "_pybytes_pymesh_config", + "_rp2", + "_terminal", + "_thread", + "_uasyncio", + "_urequest", + "adcfft", + "aioble/__init__", + "aioble/central", + "aioble/client", + "aioble/core", + "aioble/device", + "aioble/l2cap", + "aioble/peripheral", + "aioble/security", + "aioble/server", + "aioespnow", + "ak8963", + "apa102", + "apa106", + "argparse", + "array", + "asyncio/__init__", + "asyncio/core", + "asyncio/event", + "asyncio/funcs", + "asyncio/lock", + "asyncio/stream", + "binascii", + "bluetooth", + "breakout_as7262", + "breakout_bh1745", + "breakout_bme280", + "breakout_bme68x", + "breakout_bmp280", + "breakout_dotmatrix", + "breakout_encoder", + "breakout_icp10125", + "breakout_ioexpander", + "breakout_ltr559", + "breakout_matrix11x7", + "breakout_mics6814", + "breakout_msa301", + "breakout_paa5100", + "breakout_pmw3901", + "breakout_potentiometer", + "breakout_rgbmatrix5x5", + "breakout_rtc", + "breakout_scd41", + "breakout_sgp30", + "breakout_trackball", + "breakout_vl53l5cx", + "btree", + "cmath", + "collections", + "crypto", + "cryptolib", + "curl", + "deflate", + "dht", + "display", + "display_driver_utils", + "ds18x20", + "encoder", + "errno", + "esp", + "esp32", + "espidf", + "espnow", + "ffi", + "flashbdev", + "framebuf", + "freesans20", + "fs_driver", + "functools", + "galactic", + "gc", + "gfx_pack", + "gsm", + "hashlib", + "heapq", + "hub75", + "ili9341", + "ili9XXX", + "imagetools", + "inisetup", + "interstate75", + "io", + "jpegdec", + "json", + "lcd160cr", + "lodepng", + "logging", + "lsm6dsox", + "lv_colors", + "lv_utils", + "lvgl", + "lwip", + "machine", + "math", + "microWebSocket", + "microWebSrv", + "microWebTemplate", + "micropython", + "mip", + "mip/__init__", + "mip/__main__", + "motor", + "mpu6500", + "mpu9250", + "neopixel", + "network", + "ntptime", + "onewire", + "os", + "pcf85063a", + "picoexplorer", + "picographics", + "picokeypad", + "picoscroll", + "picounicorn", + "picowireless", + "pimoroni", + "pimoroni_bus", + "pimoroni_i2c", + "plasma", + "platform", + "pyb", + "pycom", + "pye", + "qrcode", + "queue", + "random", + "requests", + "requests/__init__", + "rp2", + "rtch", + "samd", + "select", + "servo", + "socket", + "ssd1306", + "ssh", + "ssl", + "stm", + "struct", + "sys", + "termios", + "time", + "tpcalib", + "uarray", + "uasyncio/__init__", + "uasyncio/core", + "uasyncio/event", + "uasyncio/funcs", + "uasyncio/lock", + "uasyncio/stream", + "uasyncio/tasks", + "ubinascii", + "ubluetooth", + "ucollections", + "ucrypto", + "ucryptolib", + "uctypes", + "uerrno", + "uftpd", + "uhashlib", + "uheapq", + "uio", + "ujson", + "ulab", + "ulab/approx", + "ulab/compare", + "ulab/fft", + "ulab/filter", + "ulab/linalg", + "ulab/numerical", + "ulab/poly", + "ulab/user", + "ulab/vector", + "umachine", + "umqtt/__init__", + "umqtt/robust", + "umqtt/simple", + "uos", + "uplatform", + "uqueue", + "urandom", + "ure", + "urequests", + "urllib/urequest", + "uselect", + "usocket", + "ussl", + "ustruct", + "usys", + "utelnetserver", + "utime", + "utimeq", + "uwebsocket", + "uzlib", + "version", + "websocket", + "websocket_helper", + "wipy", + "writer", + "xpt2046", + "ymodem", + "zephyr", + "zlib", + ] # spell-checker: enable + + gc.collect() + + stubber.create_all_stubs() + stubber.report() + + +if __name__ == "__main__" or is_micropython(): + try: + log = logging.getLogger("stubber") + logging.basicConfig(level=logging.INFO) + # logging.basicConfig(level=logging.DEBUG) + except NameError: + pass + if not file_exists("no_auto_stubber.txt"): + try: + gc.threshold(4 * 1024) # type: ignore + gc.enable() + except BaseException: + pass + main() diff --git a/mip/v5/createstubs_mpy.mpy b/mip/v5/createstubs_mpy.mpy index 8884012220b45698d21b07bdb7dc3ef4edd60f1b..caa5d220dc6788f801dd5acdd623a5d2157d72d7 100644 GIT binary patch delta 5980 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 VqhLlc+ADlrNCSj@C0Vzw`(J1ojcxz{ delta 5678 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 KOO4JA{r>^?q5T^G diff --git a/mip/v6/createstubs_db_min.py b/mip/v6/createstubs_db_min.py index adae0e729..50065e687 100644 --- a/mip/v6/createstubs_db_min.py +++ b/mip/v6/createstubs_db_min.py @@ -1,323 +1,790 @@ -x='with' -w='stubber' -v='{}/{}' -u='method' -t='function' -s='bool' -r='str' -q='float' -p='int' -o=TypeError -n=NameError -m=sorted -l=MemoryError -k=NotImplementedError -d='-' -c=',\n' -b='dict' -a='list' -Z='tuple' -Y='micropython' -X=str -W=repr -U='cpu' -T='_' -S=KeyError -R=IndexError -Q=ImportError -P='family' -O=print -N=len -M=dir -L='.' -K=open -J=True -I=AttributeError -H='board' -G='/' -F=None -E=False -A=OSError -D='version' -C='' -import gc as B,os,sys -try:from ujson import dumps -except:from json import dumps -try:from machine import reset -except Q:pass -try:from collections import OrderedDict as e -except Q:from ucollections import OrderedDict as e -__version__='v1.16.2' -y=2 -z=2 -f=[L,'/lib','/sd/lib','/flash/lib','lib'] +""" +Create stubs for (all) modules on a MicroPython board. + + This variant of the createstubs.py script is optimized for use on very-low-memory devices. + Note: this version has undergone limited testing. + + 1) reads the list of modules from a text file `modulelist.txt` that should be uploaded to the device. + 2) stored the already processed modules in a text file `modulelist.done` + 3) process the modules in the database: + - stub the module + - update the modulelist.done file + - reboots the device if it runs out of memory + 4) creates the modules.json + + If that cannot be found then only a single module (micropython) is stubbed. + In order to run this on low-memory devices two additional steps are recommended: + - minification, using python-minifierto reduce overall size, and remove logging overhead. + - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device + + +This variant was generated from createstubs.py by micropython-stubber v1.16.2 +""" +# Copyright (c) 2019-2023 Jos Verlinde + +import gc +# import logging +import os +import sys + +try: + from ujson import dumps +except: + from json import dumps + +try: + from machine import reset # type: ignore +except ImportError: + pass + +try: + from collections import OrderedDict +except ImportError: + from ucollections import OrderedDict # type: ignore + +__version__ = "v1.16.2" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] from time import sleep + + class Stubber: - def __init__(C,path=F,firmware_id=F): - D=firmware_id - try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') - except I:pass - C._report=[];C.info=_info();B.collect() - if D:C._fwid=D.lower() - elif C.info[P]==Y:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info) - else:C._fwid='{family}-v{version}-{port}'.format(**C.info) - C._start_free=B.mem_free() - if path: - if path.endswith(G):path=path[:-1] - else:path=get_root() - C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) - try:g(path+G) - except A:O('error creating stub folder {}'.format(path)) - C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] - def get_obj_attributes(L,item_instance): - H=item_instance;D=[];J=[] - for A in M(H): - if A.startswith(T)and not A in L.modules:continue - try: - E=getattr(H,A) - try:F=W(type(E)).split("'")[1] - except R:F=C - if F in{p,q,r,s,Z,a,b}:G=1 - elif F in{t,u}:G=2 - elif F in'class':G=3 - else:G=4 - D.append((A,W(E),W(type(E)),E,G)) - except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) - except l as K:sleep(1);reset() - D=m([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=m(set(A.modules)|set(modules)) - def create_all_stubs(A): - B.collect() - for C in A.modules:A.create_one_stub(C) - def create_one_stub(C,module_name): - D=module_name - if D in C.problematic:return E - if D in C.excluded:return E - H='{}/{}.py'.format(C.path,D.replace(L,G));B.collect();F=E - try:F=C.create_module_stub(D,H) - except A:return E - B.collect();return F - def create_module_stub(I,module_name,file_name=F): - H=file_name;D=module_name - if H is F:O=D.replace(L,T)+'.py';H=I.path+G+O - else:O=H.split(G)[-1] - if G in D:D=D.replace(G,L) - M=F - try:M=__import__(D,F,F,'*');U=B.mem_free() - except Q:return E - g(H) - with K(H,'w')as N:P=X(I.info).replace('OrderedDict(',C).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,P,__version__);N.write(R);N.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,D,C) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: - try:del M - except(A,S):pass - try:del sys.modules[D] - except S:pass - B.collect();return J - def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;M='Exception';H=fp;E=indent;B.collect() - if P in K.problematic:return - R,L=K.get_obj_attributes(P) - if L:O(L) - for(F,J,G,T,f)in R: - if F in['classmethod','staticmethod','BaseException',M]:continue - if F[0].isdigit():continue - if G==""and N(E)<=z*4: - U=C;V=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=M - D='\n{}class {}({}):\n'.format(E,F,U) - if V:D+=E+' ...\n';H.write(D);return - H.write(D);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,F),E+' ',Q+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';H.write(D) - elif any(A in G for A in[u,t,'closure']): - W=Y;X=C - if Q>0:X='self, ' - if c in G or c in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,W) - else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,X,W) - D+=E+' ...\n\n';H.write(D) - elif G=="":0 - elif G.startswith("='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if J in A and A[J]: - K=int(A[J]);N=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if N:A[T]=N - A[J]='v{}.{}'.format(K&255,K>>8&3) - if A[E]and not A[D].endswith(c):A[D]=A[D]+c - A[O]=f"{A[D]}-{A[E]}"if A[E]else f"{A[D]}";return A -def A0(version): - A=version;B=L.join([X(A)for A in A[:3]]) - if N(A)>3 and A[3]:B+=d+A[3] - return B -def A1(info,desc=C): - L='with ';A=info;F=E - for G in[A+'/board_info.csv'for A in f]: - if h(G): - D=desc or A[H].strip();I=D.rfind(' with') - if I!=-1:K=D[:I].strip() - else:K=C - if A2(A,D,G,K):F=J;break - if not F: - D=desc or A[H].strip() - if L+A[U].upper()in D:D=D.split(L+A[U].upper())[0].strip() - A[H]=D - A[H]=A[H].replace(' ',T);B.collect() -def A2(info,descr,filename,short_descr): - B=short_descr;A=info;D=C - with K(filename,'r')as L: - while 1: - F=L.readline() - if not F:break - I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:A[H]=G;return J - elif B and I==B: - if x in B:A[H]=G;return J - D=G - if D:A[H]=D;return J - return E -def get_root(): - try:B=os.getcwd() - except(A,I):B=L - C=B - for C in[B,'/sd','/flash',G,L]: - try:D=os.stat(C);break - except A:continue - return C -def h(filename): - try: - if os.stat(filename)[0]>>14:return J - return E - except A:return E -def i():sys.exit(1) -def read_path(): - path=C - if N(sys.argv)==3: - A=sys.argv[1].lower() - if A in('--path','-p'):path=sys.argv[2] - else:i() - elif N(sys.argv)==2:i() - return path -def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return E - except(k,I):return J + "Generate stubs for modules in firmware" + + def __init__(self, path: str = None, firmware_id: str = None): # type: ignore + try: + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore + raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") + except AttributeError: + pass + # self.log = logging.getLogger("stubber") + self._report = [] # type: list[str] + self.info = _info() + # self.log.info("Port: {}".format(self.info["port"])) + # self.log.info("Board: {}".format(self.info["board"])) + gc.collect() + if firmware_id: + self._fwid = firmware_id.lower() + else: + if self.info["family"] == "micropython": + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + else: + self._fwid = "{family}-v{version}-{port}".format(**self.info) + self._start_free = gc.mem_free() # type: ignore + + if path: + if path.endswith("/"): + path = path[:-1] + else: + path = get_root() + + self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") + # self.log.debug(self.path) + try: + ensure_folder(path + "/") + except OSError: + print("error creating stub folder {}".format(path)) + self.problematic = [ + "upip", + "upysh", + "webrepl_setup", + "http_client", + "http_client_ssl", + "http_server", + "http_server_ssl", + ] + self.excluded = [ + "webrepl", + "_webrepl", + "port_diag", + "example_sub_led.py", + "example_pub_button.py", + ] + # there is no option to discover modules from micropython, list is read from an external file. + self.modules = [] # type: list[str] + + def get_obj_attributes(self, item_instance: object): + "extract information of the objects members and attributes" + # name_, repr_(value), type as text, item_instance + _result = [] + _errors = [] + # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + for name in dir(item_instance): + if name.startswith("_") and not name in self.modules: + continue + # self.log.debug("get attribute {}".format(name)) + try: + val = getattr(item_instance, name) + # name , item_repr(value) , type as text, item_instance, order + try: + type_text = repr(type(val)).split("'")[1] + except IndexError: + type_text = "" + if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: + order = 1 + elif type_text in {"function", "method"}: + order = 2 + elif type_text in ("class"): + order = 3 + else: + order = 4 + _result.append((name, repr(val), repr(type(val)), val, order)) + except AttributeError as e: + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) + except MemoryError as e: + # print("MemoryError: {}".format(e)) + sleep(1) + reset() + + # remove internal __ + # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) + _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) + gc.collect() + return _result, _errors + + def add_modules(self, modules): + "Add additional modules to be exported" + self.modules = sorted(set(self.modules) | set(modules)) + + def create_all_stubs(self): + "Create stubs for all configured modules" + # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + gc.collect() + for module_name in self.modules: + self.create_one_stub(module_name) + # self.log.info("Finally done") + + def create_one_stub(self, module_name: str): + if module_name in self.problematic: + # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + return False + if module_name in self.excluded: + # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + return False + + file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + gc.collect() + result = False + try: + result = self.create_module_stub(module_name, file_name) + except OSError: + return False + gc.collect() + return result + + def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore + """Create a Stub of a single python module + + Args: + - module_name (str): name of the module to document. This module will be imported. + - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + """ + if file_name is None: + fname = module_name.replace(".", "_") + ".py" + file_name = self.path + "/" + fname + else: + fname = file_name.split("/")[-1] + + if "/" in module_name: + # for nested modules + module_name = module_name.replace("/", ".") + + # import the module (as new_module) to examine it + new_module = None + try: + new_module = __import__(module_name, None, None, ("*")) + m1 = gc.mem_free() # type: ignore + # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + + except ImportError: + # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + return False + + # Start a new file + ensure_folder(file_name) + with open(file_name, "w") as fp: + # todo: improve header + info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) + fp.write(s) + fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + self.write_object_stub(fp, new_module, module_name, "") + + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + + if module_name not in {"os", "sys", "logging", "gc"}: + # try to unload the module unless we use it + try: + del new_module + except (OSError, KeyError): # lgtm [py/unreachable-statement] + pass + try: + del sys.modules[module_name] + except KeyError: + pass + gc.collect() + return True + + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): + "Write a module/object stub to an open file. Can be called recursive." + gc.collect() + if object_expr in self.problematic: + # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + return + + # # self.log.debug("DUMP : {}".format(object_expr)) + items, errors = self.get_obj_attributes(object_expr) + + if errors: + print(errors) + + for item_name, item_repr, item_type_txt, item_instance, _ in items: + # name_, repr_(value), type as text, item_instance, order + if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: + # do not create stubs for these primitives + continue + if item_name[0].isdigit(): + # self.log.warning("NameError: invalid name {}".format(item_name)) + continue + # Class expansion only on first 3 levels (bit of a hack) + if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: + # self.log.debug("{0}class {1}:".format(indent, item_name)) + superclass = "" + is_exception = ( + item_name.endswith("Exception") + or item_name.endswith("Error") + or item_name + in [ + "KeyboardInterrupt", + "StopIteration", + "SystemExit", + ] + ) + if is_exception: + superclass = "Exception" + s = "\n{}class {}({}):\n".format(indent, item_name, superclass) + # s += indent + " ''\n" + if is_exception: + s += indent + " ...\n" + fp.write(s) + return + # write classdef + fp.write(s) + # first write the class literals and methods + # self.log.debug("# recursion over class {0}".format(item_name)) + self.write_object_stub( + fp, + item_instance, + "{0}.{1}".format(obj_name, item_name), + indent + " ", + in_class + 1, + ) + # end with the __init__ method to make sure that the literals are defined + # Add __init__ + s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" + s += indent + " ...\n\n" + fp.write(s) + elif any(word in item_type_txt for word in ["method", "function", "closure"]): + # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # module Function or class method + # will accept any number of params + # return type Any/Incomplete + ret = "Incomplete" + first = "" + # Self parameter only on class methods/functions + if in_class > 0: + first = "self, " + # class method - add function decoration + if "bound_method" in item_type_txt or "bound_method" in item_repr: + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) + s += indent + " ...\n\n" + fp.write(s) + # self.log.debug("\n" + s) + elif item_type_txt == "": + # Skip imported modules + # fp.write("# import {}\n".format(item_name)) + pass + + elif item_type_txt.startswith(" dict[str, str] + info = OrderedDict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "UNKNOWN", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" + try: + info["version"] = version_str(sys.implementation.version) # type: ignore + except AttributeError: + pass + try: + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine + info["cpu"] = _machine.split("with")[-1].strip() + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + gc.collect() + read_boardname(info) + gc.collect() + + try: + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): + pass + # avoid build hashes + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() # type: ignore + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + info["version"] + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # versions from 1.10.0 to 1.20.0 do not have a micro .0 + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" + # simple to use version[-build] string + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" + + return info + + +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): + found = True + break + if not found: + # print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + +def find_board(info: dict, descr: str, filename: str, short_descr: str): + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + info["board"] = board_ + return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True + return False + + +def get_root() -> str: # sourcery skip: use-assigned-variable + "Determine the root folder of the device" + try: + c = os.getcwd() + except (OSError, AttributeError): + # unix port + c = "." + r = c + for r in [c, "/sd", "/flash", "/", "."]: + try: + _ = os.stat(r) + break + except OSError: + continue + return r + + +def file_exists(filename: str): + try: + if os.stat(filename)[0] >> 14: + return True + return False + except OSError: + return False + + +def show_help(): + # print("-p, --path path to store the stubs in, defaults to '.'") + sys.exit(1) + + +def read_path() -> str: + "get --path from cmdline. [unix/win]" + path = "" + if len(sys.argv) == 3: + cmd = (sys.argv[1]).lower() + if cmd in ("--path", "-p"): + path = sys.argv[2] + else: + show_help() + elif len(sys.argv) == 2: + show_help() + return path + + +def is_micropython() -> bool: + "runtime test to determine full or micropython" + # pylint: disable=unused-variable,eval-used + try: + # either test should fail on micropython + # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces + # Micropython : SyntaxError + # a = eval("1and 0") # lgtm [py/unused-local-variable] + # Eval blocks some minification aspects + + # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented + # Micropython: NotImplementedError + b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] + + # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute + # Micropython: AttributeError + c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] + return False + except (NotImplementedError, AttributeError): + return True + + def main(): - L='failed';G='modulelist.done';import machine as O - try:C=K(G,'r+b');M=J - except A:C=K(G,'w+b');M=E - stubber=Stubber(path=read_path()) - if not M:stubber.clean() - A3(stubber);D={} - try: - with K(G)as C: - for F in C.read().split('\n'): - F=F.strip();B.collect() - if N(F)>0:P,Q=F.split('=',1);D[P]=Q - except(A,SyntaxError):pass - B.collect();R=[A for A in stubber.modules if A not in D.keys()];B.collect() - for H in R: - I=E - try:I=stubber.create_one_stub(H) - except l:O.reset() - B.collect();D[H]=X(stubber._report[-1]if I else L) - with K(G,'a')as C:C.write('{}={}\n'.format(H,'ok'if I else L)) - if D:stubber._report=[A for(B,A)in D.items()if A!=L];stubber.report() -def A3(stubber): - E='/modulelist.txt';stubber.modules=[] - for D in f: - try: - with K(D+E)as F: - O('DEBUG: list of modules: '+D+E) - for C in F.read().split('\n'): - C=C.strip() - if N(C)>0 and C[0]!='#':stubber.modules.append(C) - B.collect();break - except A:pass - if not stubber.modules:stubber.modules=[Y];_log.warn('Could not find modulelist.txt, using default modules') - B.collect() -if __name__=='__main__'or j(): - try:A4=logging.getLogger(w);logging.basicConfig(level=logging.INFO) - except n:pass - if not h('no_auto_stubber.txt'): - try:B.threshold(4*1024);B.enable() - except BaseException:pass - main() \ No newline at end of file + import machine # type: ignore + + try: + f = open("modulelist.done", "r+b") + was_running = True + # print("Opened existing db") + except OSError: + f = open("modulelist.done", "w+b") + # print("created new db") + was_running = False + stubber = Stubber(path=read_path()) + + # f_name = "{}/{}".format(stubber.path, "modules.json") + if not was_running: + # Only clean folder if this is a first run + stubber.clean() + # get list of modules to process + get_modulelist(stubber) + # remove the ones that are already done + modules_done = {} # type: dict[str, str] + try: + with open("modulelist.done") as f: + # not optimal , but works on mpremote and esp8266 + for line in f.read().split("\n"): + line = line.strip() + gc.collect() + if len(line) > 0: + key, value = line.split("=", 1) + modules_done[key] = value + except (OSError, SyntaxError): + pass + gc.collect() + # see if we can continue from where we left off + modules = [m for m in stubber.modules if m not in modules_done.keys()] + gc.collect() + for modulename in modules: + # ------------------------------------ + # do epic shit + # but sometimes things fail / run out of memory and reboot + ok = False + try: + ok = stubber.create_one_stub(modulename) + except MemoryError: + # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER + machine.reset() + # ------------------------------------- + gc.collect() + modules_done[modulename] = str(stubber._report[-1] if ok else "failed") + with open("modulelist.done", "a") as f: + f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) + + # Finished processing - load all the results , and remove the failed ones + if modules_done: + # stubber.write_json_end(mod_fp) + stubber._report = [v for _, v in modules_done.items() if v != "failed"] + stubber.report() + + +def get_modulelist(stubber): + stubber.modules = [] # avoid duplicates + for p in LIBS: + try: + with open(p + "/modulelist.txt") as f: + print ("DEBUG: list of modules: " + p + "/modulelist.txt") + for line in f.read().split("\n"): + line = line.strip() + if len(line) > 0 and line[0] != "#": + stubber.modules.append(line) + gc.collect() + break + except OSError: + pass + if not stubber.modules: + stubber.modules = ["micropython"] + _log.warn("Could not find modulelist.txt, using default modules") + gc.collect() + + +if __name__ == "__main__" or is_micropython(): + try: + log = logging.getLogger("stubber") + logging.basicConfig(level=logging.INFO) + # logging.basicConfig(level=logging.DEBUG) + except NameError: + pass + if not file_exists("no_auto_stubber.txt"): + try: + gc.threshold(4 * 1024) # type: ignore + gc.enable() + except BaseException: + pass + main() diff --git a/mip/v6/createstubs_db_mpy.mpy b/mip/v6/createstubs_db_mpy.mpy index 99bab72bda685bd3acdc692e67aaef17fb5a7cfa..2ff08f91e6a973188423633a2ff7a05f25669664 100644 GIT binary patch literal 8492 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 pn"and R(C)<=x*4: - U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=M - A='\n{}class {}({}):\n'.format(C,E,U) - if V:A+=C+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),C+' ',P+1);A=C+' def __init__(self, *argv, **kwargs) -> None:\n';A+=C+' ...\n\n';H.write(A) - elif any(A in G for A in[s,r,'closure']): - W=b;a=B - if P>0:a='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(C)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(C,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(C,E,a,W) - A+=C+' ...\n\n';H.write(A) - elif G=="":0 - elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] - if J in A and A[J]: - K=int(A[J]);R=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if R:A[V]=R - A[J]='v{}.{}'.format(K&255,K>>8&3) - if A[F]and not A[C].endswith(b):A[C]=A[C]+b - A[S]=f"{A[C]}-{A[F]}"if A[F]else f"{A[C]}";return A -def z(version): - A=version;B=J.join([str(A)for A in A[:3]]) - if R(A)>3 and A[3]:B+=b+A[3] - return B -def A0(info,desc=B): - L='with ';C=info;F=A - for G in[A+'/board_info.csv'for A in y]: - if e(G): - E=desc or C[H].strip();I=E.rfind(' with') - if I!=-1:J=E[:I].strip() - else:J=B - if A1(C,E,G,J):F=K;break - if not F: - E=desc or C[H].strip() - if L+C[T].upper()in E:E=E.split(L+C[T].upper())[0].strip() - C[H]=E - C[H]=C[H].replace(' ',S);D.collect() -def A1(info,descr,filename,short_descr): - D=short_descr;C=info;E=B - with W(filename,'r')as J: - while 1: - F=J.readline() - if not F:break - I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:C[H]=G;return K - elif D and I==D: - if v in D:C[H]=G;return K - E=G - if E:C[H]=E;return K - return A -def get_root(): - try:A=os.getcwd() - except(F,I):A=J - B=A - for B in[A,'/sd','/flash',G,J]: - try:C=os.stat(B);break - except F:continue - return B -def e(filename): - try: - if os.stat(filename)[0]>>14:return K - return A - except F:return A -def f():sys.exit(1) -def read_path(): - path=B - if R(sys.argv)==3: - A=sys.argv[1].lower() - if A in('--path','-p'):path=sys.argv[2] - else:f() - elif R(sys.argv)==2:f() - return path -def g(): - try:B=bytes('abc',encoding='utf8');C=g.__module__;return A - except(h,I):return K + "Generate stubs for modules in firmware" + + def __init__(self, path: str = None, firmware_id: str = None): # type: ignore + try: + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore + raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") + except AttributeError: + pass + # self.log = logging.getLogger("stubber") + self._report = [] # type: list[str] + self.info = _info() + # self.log.info("Port: {}".format(self.info["port"])) + # self.log.info("Board: {}".format(self.info["board"])) + gc.collect() + if firmware_id: + self._fwid = firmware_id.lower() + else: + if self.info["family"] == "micropython": + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + else: + self._fwid = "{family}-v{version}-{port}".format(**self.info) + self._start_free = gc.mem_free() # type: ignore + + if path: + if path.endswith("/"): + path = path[:-1] + else: + path = get_root() + + self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") + # self.log.debug(self.path) + try: + ensure_folder(path + "/") + except OSError: + print("error creating stub folder {}".format(path)) + self.problematic = [ + "upip", + "upysh", + "webrepl_setup", + "http_client", + "http_client_ssl", + "http_server", + "http_server_ssl", + ] + self.excluded = [ + "webrepl", + "_webrepl", + "port_diag", + "example_sub_led.py", + "example_pub_button.py", + ] + # there is no option to discover modules from micropython, list is read from an external file. + self.modules = [] # type: list[str] + + def get_obj_attributes(self, item_instance: object): + "extract information of the objects members and attributes" + # name_, repr_(value), type as text, item_instance + _result = [] + _errors = [] + # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + for name in dir(item_instance): + if name.startswith("_") and not name in self.modules: + continue + # self.log.debug("get attribute {}".format(name)) + try: + val = getattr(item_instance, name) + # name , item_repr(value) , type as text, item_instance, order + try: + type_text = repr(type(val)).split("'")[1] + except IndexError: + type_text = "" + if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: + order = 1 + elif type_text in {"function", "method"}: + order = 2 + elif type_text in ("class"): + order = 3 + else: + order = 4 + _result.append((name, repr(val), repr(type(val)), val, order)) + except AttributeError as e: + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) + except MemoryError as e: + # print("MemoryError: {}".format(e)) + sleep(1) + reset() + + # remove internal __ + # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) + _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) + gc.collect() + return _result, _errors + + def add_modules(self, modules): + "Add additional modules to be exported" + self.modules = sorted(set(self.modules) | set(modules)) + + def create_all_stubs(self): + "Create stubs for all configured modules" + # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + gc.collect() + for module_name in self.modules: + self.create_one_stub(module_name) + # self.log.info("Finally done") + + def create_one_stub(self, module_name: str): + if module_name in self.problematic: + # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + return False + if module_name in self.excluded: + # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + return False + + file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + gc.collect() + result = False + try: + result = self.create_module_stub(module_name, file_name) + except OSError: + return False + gc.collect() + return result + + def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore + """Create a Stub of a single python module + + Args: + - module_name (str): name of the module to document. This module will be imported. + - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + """ + if file_name is None: + fname = module_name.replace(".", "_") + ".py" + file_name = self.path + "/" + fname + else: + fname = file_name.split("/")[-1] + + if "/" in module_name: + # for nested modules + module_name = module_name.replace("/", ".") + + # import the module (as new_module) to examine it + new_module = None + try: + new_module = __import__(module_name, None, None, ("*")) + m1 = gc.mem_free() # type: ignore + # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + + except ImportError: + # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + return False + + # Start a new file + ensure_folder(file_name) + with open(file_name, "w") as fp: + # todo: improve header + info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) + fp.write(s) + fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + self.write_object_stub(fp, new_module, module_name, "") + + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + + if module_name not in {"os", "sys", "logging", "gc"}: + # try to unload the module unless we use it + try: + del new_module + except (OSError, KeyError): # lgtm [py/unreachable-statement] + pass + try: + del sys.modules[module_name] + except KeyError: + pass + gc.collect() + return True + + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): + "Write a module/object stub to an open file. Can be called recursive." + gc.collect() + if object_expr in self.problematic: + # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + return + + # # self.log.debug("DUMP : {}".format(object_expr)) + items, errors = self.get_obj_attributes(object_expr) + + if errors: + print(errors) + + for item_name, item_repr, item_type_txt, item_instance, _ in items: + # name_, repr_(value), type as text, item_instance, order + if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: + # do not create stubs for these primitives + continue + if item_name[0].isdigit(): + # self.log.warning("NameError: invalid name {}".format(item_name)) + continue + # Class expansion only on first 3 levels (bit of a hack) + if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: + # self.log.debug("{0}class {1}:".format(indent, item_name)) + superclass = "" + is_exception = ( + item_name.endswith("Exception") + or item_name.endswith("Error") + or item_name + in [ + "KeyboardInterrupt", + "StopIteration", + "SystemExit", + ] + ) + if is_exception: + superclass = "Exception" + s = "\n{}class {}({}):\n".format(indent, item_name, superclass) + # s += indent + " ''\n" + if is_exception: + s += indent + " ...\n" + fp.write(s) + return + # write classdef + fp.write(s) + # first write the class literals and methods + # self.log.debug("# recursion over class {0}".format(item_name)) + self.write_object_stub( + fp, + item_instance, + "{0}.{1}".format(obj_name, item_name), + indent + " ", + in_class + 1, + ) + # end with the __init__ method to make sure that the literals are defined + # Add __init__ + s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" + s += indent + " ...\n\n" + fp.write(s) + elif any(word in item_type_txt for word in ["method", "function", "closure"]): + # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # module Function or class method + # will accept any number of params + # return type Any/Incomplete + ret = "Incomplete" + first = "" + # Self parameter only on class methods/functions + if in_class > 0: + first = "self, " + # class method - add function decoration + if "bound_method" in item_type_txt or "bound_method" in item_repr: + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) + s += indent + " ...\n\n" + fp.write(s) + # self.log.debug("\n" + s) + elif item_type_txt == "": + # Skip imported modules + # fp.write("# import {}\n".format(item_name)) + pass + + elif item_type_txt.startswith(" dict[str, str] + info = OrderedDict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "UNKNOWN", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" + try: + info["version"] = version_str(sys.implementation.version) # type: ignore + except AttributeError: + pass + try: + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine + info["cpu"] = _machine.split("with")[-1].strip() + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + gc.collect() + read_boardname(info) + gc.collect() + + try: + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): + pass + # avoid build hashes + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() # type: ignore + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + info["version"] + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # versions from 1.10.0 to 1.20.0 do not have a micro .0 + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" + # simple to use version[-build] string + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" + + return info + + +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): + found = True + break + if not found: + # print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + +def find_board(info: dict, descr: str, filename: str, short_descr: str): + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + info["board"] = board_ + return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True + return False + + +def get_root() -> str: # sourcery skip: use-assigned-variable + "Determine the root folder of the device" + try: + c = os.getcwd() + except (OSError, AttributeError): + # unix port + c = "." + r = c + for r in [c, "/sd", "/flash", "/", "."]: + try: + _ = os.stat(r) + break + except OSError: + continue + return r + + +def file_exists(filename: str): + try: + if os.stat(filename)[0] >> 14: + return True + return False + except OSError: + return False + + +def show_help(): + # print("-p, --path path to store the stubs in, defaults to '.'") + sys.exit(1) + + +def read_path() -> str: + "get --path from cmdline. [unix/win]" + path = "" + if len(sys.argv) == 3: + cmd = (sys.argv[1]).lower() + if cmd in ("--path", "-p"): + path = sys.argv[2] + else: + show_help() + elif len(sys.argv) == 2: + show_help() + return path + + +def is_micropython() -> bool: + "runtime test to determine full or micropython" + # pylint: disable=unused-variable,eval-used + try: + # either test should fail on micropython + # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces + # Micropython : SyntaxError + # a = eval("1and 0") # lgtm [py/unused-local-variable] + # Eval blocks some minification aspects + + # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented + # Micropython: NotImplementedError + b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] + + # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute + # Micropython: AttributeError + c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] + return False + except (NotImplementedError, AttributeError): + return True + + def main(): - C='lvgl' - try:import lvgl as A - except l:return - B=C - try:B='lvgl-{0}_{1}_{2}-{3}-{4}'.format(A.version_major(),A.version_minor(),A.version_patch(),A.version_info(),sys.platform) - except l:B='lvgl-{0}_{1}_{2}_{3}-{4}'.format(8,1,0,'dev',sys.platform) - finally:stubber=Stubber(firmware_id=B) - stubber.clean();stubber.modules=['io','lodepng','rtch',C];D.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or g(): - try:A2=logging.getLogger(u);logging.basicConfig(level=logging.INFO) - except j:pass - if not e('no_auto_stubber.txt'): - try:D.threshold(4*1024);D.enable() - except BaseException:pass - main() \ No newline at end of file + try: + import lvgl # type: ignore + except Exception: + # print("\n\nNOTE: The `lvgl` module could not be found on this firmware\n\n") + return + # Specify firmware name & version + fw_id = "lvgl" + try: + fw_id = "lvgl-{0}_{1}_{2}-{3}-{4}".format( + lvgl.version_major(), + lvgl.version_minor(), + lvgl.version_patch(), + lvgl.version_info(), + sys.platform, + ) + except Exception: + fw_id = "lvgl-{0}_{1}_{2}_{3}-{4}".format(8, 1, 0, "dev", sys.platform) + finally: + stubber = Stubber(firmware_id=fw_id) + stubber.clean() + # modules to stub : only lvgl specifics + stubber.modules = ["io", "lodepng", "rtch", "lvgl"] # spell-checker: enable + + gc.collect() + + stubber.create_all_stubs() + stubber.report() + + +if __name__ == "__main__" or is_micropython(): + try: + log = logging.getLogger("stubber") + logging.basicConfig(level=logging.INFO) + # logging.basicConfig(level=logging.DEBUG) + except NameError: + pass + if not file_exists("no_auto_stubber.txt"): + try: + gc.threshold(4 * 1024) # type: ignore + gc.enable() + except BaseException: + pass + main() diff --git a/mip/v6/createstubs_lvgl_mpy.mpy b/mip/v6/createstubs_lvgl_mpy.mpy index e84a7d7d40a8b25390838d57be36781d5a8835af..244d66abd892f932c6e7a6235247e88239bb0f41 100644 GIT binary patch literal 7990 zcmZ`-TWlNIc|N2_nWAXe0c9#nU1eltf7>mS!f39r*>c%P=J)L#~MGiwi|$PR?ZV z@S3?=%w>^DeVPkOQ7NIOOhTScWfjDpEhLqKl9W<%39)i6omS*hDwi#yJu~mlnr6E@ zx&s|Pr0+nc&U9)5HFXw~>cG}HnNAd^)p0%Ln2Tve$s%1$JTDLI(SPNt@iIjzhpX=EBW(|;B*rD>3LI+so&i;_)Dq!qMJ$rfh{ zN_-NCu$MS@nu?`F2`!p4*ODn9xGnLCnH20Wak(sqDuUqycslj7NZ*dk@lnN)fKHO(r8A|;!(gX&?9a6X+VP38(2WXk6XV7=&>p)+UC zpMgcWL?Mal<@^k)&wv9=iGnhlZK3Z+bs51HpuS$H+UE18=EZ=_S%nR#TI$)@HJ zj&J+HJfn(XnoE_YQKj1yr>8a5Jb;=CN?J)26=e2xbaiwgGDQv=;B5h?&^dh{>o|t$ z=Z^;95%42(qL7&lAdC9SXzwE#)I{e;lni2OgJS;8Fqub|`4X5off(%#G9%0E;!?-r z62k5If-;*@=8$=DsT~Lg_+x9k;Z9V~(1N%?SA`)*&72}zdT*&1YO4H!Y`ox5cu#%N?$y9aT#Vcgy5)hfGBr?n3sw^_3a;PbtODcJK zUxDsy%H)zWX{CrbEp6k8bQ&xNxr;0XMU51l|>?GZx-i6>KuDKOZ)oSsQ4No1$~$xU31CrYJ4YGMX32kD)Nd}y9b=O6BUJmV<$jv~w)|6qk&oCo=LI&6? za$p4=F&ZvjMh2G~k!zK`%w!>V1M&!P7IPggcju+!b`T7Lmx2_e59o<1I&&dI=QTYj zIzvz=D6k#SR8vV=2qDz+4nfH#k$w^3?U+LbF9<`!sI-t*P`&x`60)73w^3bAB11e5 zvZfQ6iDcp=VoppcS!F(7IEhBsczipSSwW<;Vyt`^s~lo$u2;7)YVxZ?!(<+@HIGvz5T-Gy zvMc~9fawUQvT@ZhXih(g^Z?{wsA37}=aJEx&BYTlrJNcqP<=W|^Ce`o)IzdDEs(~2 zlL-(w$(3@oH088%!-3PxdZR%FZlh6yb#t8&z+MKJL2m~}8R};V0nbQz8T95|*MI69 zrCXHQo^~h_g_L})h>Sb8haJ-t42-6}@g9-#K)C<267H{WZ&!2LsBh0B;~t7%?GVm! z276s1!iBZN4_s_>3~2pxGQR&P>F?r4&MpySIsXAOet;a#@vrIGCGB zC$r8H2T;eofjQ2(xa8y@p);HocPhcl0jeCQ5n;5v(?Ge9@d(fJ<`EU=kHgX~*bJQr zILAyG0yh$j!am;;3?o_#1k;`+Gcq1iFM%AUrqQyAJC$89tK>M%?cy|qWsUO|sm!pK zTU_L|DCUoI{NfVt<#?Jkwb>HL*|ZH;^d#p=WNZc?(hzKM$+fuTJ`U$}Q+P`%lN{u8 zHU-)2(onFCmQ^p;)^-i5+*HxcwV&k90CLkkJLw+!L!lMsyB3#v)pIq-1WN1T5hEP)(8{2gI>syShF*b-}+H{9D)m^51 z6Yv{aOspw3*m%B~#J`k+u|bVx23BK>nKj1--_uxU;RH&xXjI*0ypttYDlAFB-vn;L zyD-MhnDH1{BA2lhmfBjZtTlGdhwyH{p55)!u?Ky6w$)e1w)+h1CCs+zB0Wa-V_!Wx z>D$3x^_keLuYt|^%lXYd7M6E@<~JSPeb>=@ z*Z+xA;XW~a!hC-C^O?Km&)K`SPfSWLNW#wJ-7J|3huid#9>fw8s6_UGPQ(RDk$TXI zxWk%O#8ak&dY1T_$+T~WAC_X3XJUy?&{1XsOLl;=Bm&x!bD%DXf*{}N`dL{wMoeUZ zFa(ud{E4w(>$FoC@3An+BQXD@WYGvwdVgOlBW76c`!a+Eo zx5=0^!x}wY$AlW0gH?QJ%dd+K?g2SdUrM7fhFleP!TNxXk|ExR6%(6)g=T>ftb)z6 z1GetQgvHQal0Cw1f%O=Hv{%*67?!_%Vuk4^`@oDh%9nbDpr>0DLVUdS1H0Gml=y># z2j$l5T({GMHazGlLo!vrE%dkpzH zLzW)+K`@&Oll=i5iM|+Y0>QIiO8qg+z5sC_V$y=i`(z1;Y(g#tbiwXwr%m+ASDG#4a;33+bNNnGu5`6A z#07>nmTz-#G((1|<*4+-VATKe>%cGIkxJJohSZaV@~6E{SM5f+Fh10{zHB3I@O4b= z3CrIY9d9LWvQRn8&hAY~9F^&4uR6k{&E|j^Q-z3Xq5&1qZ!0tU zG}H*kda5e{{nNpnU=#?fzSyV??y23rDu3t7x0=U@hhA3EmH+a}6-USLVENv9w6>-MW5nB)lF%T zt~`XB0{Zpvvk=RWd^H@#q}^|LR?C;?s#t)$+hQFAr$Fe>tzgpO*PkAG!H@%Rg9SoO z7WQCP%bZS3x&r!_!d@+(c0OXrm4M;ZLmTOS3^t^1VIK@Yd*8#gDr_^v!j~??L5(zG z_QSRnnt?rYax8#gyxUmPHVR?H*JyHEzOulAwtUeCtVO{Um1F{t` z#@2)bTVMQWO*r_@KJkYYrn19s6F875pc4*J(S97L+xkKr7I-?b;~xhMa2qCl?_T!>0ZRz4rJ(o> zMl{v?0sp=SL@g_{+8hpRKt}@@rfZM41m_k^#NRKv>RmfRW|zs;;I_KVgVtIoGi0)@t`@an zSx2sH^kVWcX(#RXaHJZE3^i=5IMC))Ogs#D)fvfD<~o=>H!z6H!s|6Al~dkPms zR^fuNXRxd>KD6sOP|mGBSPRs}MxTkDFpE;Y1}wX3i1yzvG+Tcu4XGvErB&~+{OM7# zg+u@tO!scJ9dA46XrnH}WE_s5BgW{}!9^BK&QJJtg!TRTrIx_f0v_T|8lqr zT09MzsoTL+&jv>{7dn07#VzzekldZ>iM zFI@GP!Li}+bC;10s$^>e?hO9nCe%#M&9;(j_x?%{{QiTks5IbeGf0|+wZOLyxZY$ zIN@)a^Sa#d%U=-qxC1^F1KcgI;A}n34|nzZhPylE-X7lB)*0k@ewc4_@U7lHcfZ@g zwR+vDOvm6{xxpdy`F%qN`xvvg0SZiqwG($uV3sYQVU_STO6XMyy&=q8Qt#`A4h45>HEp{| z4y7=3D;di7>o%d2rh=UkL*OaeZ8xk}m+_JDDi|k7E51#F?iU{&$9;dasZYFskNpw# zm?&a)86O*0%WN8&$2VoRR_U0JmuWMgwdbKxEYdUTs4&w^t?9oVrIP!`;V&8--KJJ* zRPiI+t=>!boB^)Es%q*R7kkw#rMEI9_XZKc2vN+wmU6JtFHj6tz(%UV8!Oh+s*Na; z!Y0`IcAsDnj6%JqEqNV*#1cw ztQwUz$_#0tBfsut7@xss@hA@CF&x3?a1@W@^Pa{>cYhmw^;qhAyo`^J;|n&&Bc9y) z&7;qLd;2%=VFIq9W|hv^o%dd zx9!K8E_L7cc6YjQlkKt(Er)M|w0@{r>(F+9hj0HvI8DKp zQzp9#9m8U^&jhimhA4d8#POAY?)d}2s*$zu1CWJ=?h6s{;srCgytew#Z;(P`8!`A1 zgHS|Pf^+X4fD;hrQQJfSZLMue=hq+s-ckZO=&sr<5~sbLqHlwze8*j96V;9sdZ`!8sy0H z2exSt|6wpFJ}*B6VN%;N)Fwm~=%bgf9#vmUr@_@n#>eDUY5dXZYblI_tDA3#kDrOX z;@{kYdbTE=RuveNN9AvzWXsk2(;VM6+{$v=f%os=v`2A?jx$6zTq0uU$ur^nt2enLo^A$;|x)zMUV|dW2=F z#Gn0E5~&1V`E&`(^SC~D|2AW=<%wFKK5^~YbN&9OoY3xR9dNcgG5Z8U3v##s(e+wN z&=HscKJLNJrcG&p5-QOr@L8UN4@2?Xo7ELCkw)u<&<#m!>HeShRvI##!{Mb#9l|qs z7SF*K;}fQ2onHsxXah43c%U^fW3+(@%XcsQyWX{M|NDHdPq5pm@2;QooDQFMhIYXJ zr*1q^RXX~nqfLB=lU!G?_ Ac>n+a literal 8275 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 JdUyq*{|5lhfe!!x diff --git a/mip/v6/createstubs_mem_min.py b/mip/v6/createstubs_mem_min.py index ef72491b9..1f76a726c 100644 --- a/mip/v6/createstubs_mem_min.py +++ b/mip/v6/createstubs_mem_min.py @@ -1,303 +1,737 @@ -w='with' -v='stubber' -u='{}/{}' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n=TypeError -m=NameError -l=sorted -k=NotImplementedError -d='-' -c=',\n' -b='dict' -a='list' -Z='tuple' -Y='micropython' -X=str -W=repr -U='cpu' -T='_' -S=KeyError -R=open -Q=IndexError -P=ImportError -O='family' -N=len -M=dir -L=print -K=True -J='.' -I=AttributeError -H='board' -A=False -G='/' -E=None -F=OSError -D='version' -C='' -import gc as B,os,sys -try:from ujson import dumps -except:from json import dumps -try:from machine import reset -except P:pass -try:from collections import OrderedDict as e -except P:from ucollections import OrderedDict as e -__version__='v1.16.2' -x=2 -y=2 -f=[J,'/lib','/sd/lib','/flash/lib','lib'] +"""Create stubs for (all) modules on a MicroPython board. + + This variant of the createstubs.py script is optimised for use on low-memory devices, and reads the list of modules from a text file + `modulelist.txt` in the root or `libs` folder that should be uploaded to the device. + If that cannot be found then only a single module (micropython) is stubbed. + In order to run this on low-memory devices two additional steps are recommended: + - minifification, using python-minifier + to reduce overall size, and remove logging overhead. + - cross compilation, using mpy-cross, + to avoid the compilation step on the micropython device + +This variant was generated from createstubs.py by micropython-stubber v1.16.2 +""" +# Copyright (c) 2019-2023 Jos Verlinde + +import gc +# import logging +import os +import sys + +try: + from ujson import dumps +except: + from json import dumps + +try: + from machine import reset # type: ignore +except ImportError: + pass + +try: + from collections import OrderedDict +except ImportError: + from ucollections import OrderedDict # type: ignore + +__version__ = "v1.16.2" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] from time import sleep + + class Stubber: - def __init__(A,path=E,firmware_id=E): - C=firmware_id - try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') - except I:pass - A._report=[];A.info=_info();B.collect() - if C:A._fwid=C.lower() - elif A.info[O]==Y:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-v{version}-{port}'.format(**A.info) - A._start_free=B.mem_free() - if path: - if path.endswith(G):path=path[:-1] - else:path=get_root() - A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:g(path+G) - except F:L('error creating stub folder {}'.format(path)) - A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] - def get_obj_attributes(L,item_instance): - H=item_instance;D=[];J=[] - for A in M(H): - if A.startswith(T)and not A in L.modules:continue - try: - E=getattr(H,A) - try:F=W(type(E)).split("'")[1] - except Q:F=C - if F in{o,p,q,r,Z,a,b}:G=1 - elif F in{s,t}:G=2 - elif F in'class':G=3 - else:G=4 - D.append((A,W(E),W(type(E)),E,G)) - except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) - except MemoryError as K:sleep(1);reset() - D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return D,J - def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) - def create_all_stubs(A): - B.collect() - for C in A.modules:A.create_one_stub(C) - def create_one_stub(C,module_name): - D=module_name - if D in C.problematic:return A - if D in C.excluded:return A - H='{}/{}.py'.format(C.path,D.replace(J,G));B.collect();E=A - try:E=C.create_module_stub(D,H) - except F:return A - B.collect();return E - def create_module_stub(I,module_name,file_name=E): - H=file_name;D=module_name - if H is E:N=D.replace(J,T)+'.py';H=I.path+G+N - else:N=H.split(G)[-1] - if G in D:D=D.replace(G,J) - L=E - try:L=__import__(D,E,E,'*');U=B.mem_free() - except P:return A - g(H) - with R(H,'w')as M:O=X(I.info).replace('OrderedDict(',C).replace('})','}');Q='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,I._fwid,O,__version__);M.write(Q);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,D,C) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: - try:del L - except(F,S):pass - try:del sys.modules[D] - except S:pass - B.collect();return K - def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';Y='Incomplete';Q=in_class;P=object_expr;O='Exception';H=fp;D=indent;B.collect() - if P in K.problematic:return - R,M=K.get_obj_attributes(P) - if M:L(M) - for(E,J,G,T,f)in R: - if E in['classmethod','staticmethod','BaseException',O]:continue - if E[0].isdigit():continue - if G==""and N(D)<=y*4: - U=C;V=E.endswith(O)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=O - A='\n{}class {}({}):\n'.format(D,E,U) - if V:A+=D+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),D+' ',Q+1);A=D+' def __init__(self, *argv, **kwargs) -> None:\n';A+=D+' ...\n\n';H.write(A) - elif any(A in G for A in[t,s,'closure']): - W=Y;X=C - if Q>0:X='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W) - A+=D+' ...\n\n';H.write(A) - elif G=="":0 - elif G.startswith("='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if J in A and A[J]: - K=int(A[J]);N=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if N:A[T]=N - A[J]='v{}.{}'.format(K&255,K>>8&3) - if A[F]and not A[D].endswith(c):A[D]=A[D]+c - A[R]=f"{A[D]}-{A[F]}"if A[F]else f"{A[D]}";return A -def z(version): - A=version;B=J.join([X(A)for A in A[:3]]) - if N(A)>3 and A[3]:B+=d+A[3] - return B -def A0(info,desc=C): - L='with ';D=info;F=A - for G in[A+'/board_info.csv'for A in f]: - if h(G): - E=desc or D[H].strip();I=E.rfind(' with') - if I!=-1:J=E[:I].strip() - else:J=C - if A1(D,E,G,J):F=K;break - if not F: - E=desc or D[H].strip() - if L+D[U].upper()in E:E=E.split(L+D[U].upper())[0].strip() - D[H]=E - D[H]=D[H].replace(' ',T);B.collect() -def A1(info,descr,filename,short_descr): - D=short_descr;B=info;E=C - with R(filename,'r')as J: - while 1: - F=J.readline() - if not F:break - I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:B[H]=G;return K - elif D and I==D: - if w in D:B[H]=G;return K - E=G - if E:B[H]=E;return K - return A -def get_root(): - try:A=os.getcwd() - except(F,I):A=J - B=A - for B in[A,'/sd','/flash',G,J]: - try:C=os.stat(B);break - except F:continue - return B -def h(filename): - try: - if os.stat(filename)[0]>>14:return K - return A - except F:return A -def i():sys.exit(1) -def read_path(): - path=C - if N(sys.argv)==3: - A=sys.argv[1].lower() - if A in('--path','-p'):path=sys.argv[2] - else:i() - elif N(sys.argv)==2:i() - return path -def j(): - try:B=bytes('abc',encoding='utf8');C=j.__module__;return A - except(k,I):return K + "Generate stubs for modules in firmware" + + def __init__(self, path: str = None, firmware_id: str = None): # type: ignore + try: + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore + raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") + except AttributeError: + pass + # self.log = logging.getLogger("stubber") + self._report = [] # type: list[str] + self.info = _info() + # self.log.info("Port: {}".format(self.info["port"])) + # self.log.info("Board: {}".format(self.info["board"])) + gc.collect() + if firmware_id: + self._fwid = firmware_id.lower() + else: + if self.info["family"] == "micropython": + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + else: + self._fwid = "{family}-v{version}-{port}".format(**self.info) + self._start_free = gc.mem_free() # type: ignore + + if path: + if path.endswith("/"): + path = path[:-1] + else: + path = get_root() + + self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") + # self.log.debug(self.path) + try: + ensure_folder(path + "/") + except OSError: + print("error creating stub folder {}".format(path)) + self.problematic = [ + "upip", + "upysh", + "webrepl_setup", + "http_client", + "http_client_ssl", + "http_server", + "http_server_ssl", + ] + self.excluded = [ + "webrepl", + "_webrepl", + "port_diag", + "example_sub_led.py", + "example_pub_button.py", + ] + # there is no option to discover modules from micropython, list is read from an external file. + self.modules = [] # type: list[str] + + def get_obj_attributes(self, item_instance: object): + "extract information of the objects members and attributes" + # name_, repr_(value), type as text, item_instance + _result = [] + _errors = [] + # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + for name in dir(item_instance): + if name.startswith("_") and not name in self.modules: + continue + # self.log.debug("get attribute {}".format(name)) + try: + val = getattr(item_instance, name) + # name , item_repr(value) , type as text, item_instance, order + try: + type_text = repr(type(val)).split("'")[1] + except IndexError: + type_text = "" + if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: + order = 1 + elif type_text in {"function", "method"}: + order = 2 + elif type_text in ("class"): + order = 3 + else: + order = 4 + _result.append((name, repr(val), repr(type(val)), val, order)) + except AttributeError as e: + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) + except MemoryError as e: + # print("MemoryError: {}".format(e)) + sleep(1) + reset() + + # remove internal __ + # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) + _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) + gc.collect() + return _result, _errors + + def add_modules(self, modules): + "Add additional modules to be exported" + self.modules = sorted(set(self.modules) | set(modules)) + + def create_all_stubs(self): + "Create stubs for all configured modules" + # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + gc.collect() + for module_name in self.modules: + self.create_one_stub(module_name) + # self.log.info("Finally done") + + def create_one_stub(self, module_name: str): + if module_name in self.problematic: + # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + return False + if module_name in self.excluded: + # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + return False + + file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + gc.collect() + result = False + try: + result = self.create_module_stub(module_name, file_name) + except OSError: + return False + gc.collect() + return result + + def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore + """Create a Stub of a single python module + + Args: + - module_name (str): name of the module to document. This module will be imported. + - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + """ + if file_name is None: + fname = module_name.replace(".", "_") + ".py" + file_name = self.path + "/" + fname + else: + fname = file_name.split("/")[-1] + + if "/" in module_name: + # for nested modules + module_name = module_name.replace("/", ".") + + # import the module (as new_module) to examine it + new_module = None + try: + new_module = __import__(module_name, None, None, ("*")) + m1 = gc.mem_free() # type: ignore + # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + + except ImportError: + # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + return False + + # Start a new file + ensure_folder(file_name) + with open(file_name, "w") as fp: + # todo: improve header + info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) + fp.write(s) + fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + self.write_object_stub(fp, new_module, module_name, "") + + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + + if module_name not in {"os", "sys", "logging", "gc"}: + # try to unload the module unless we use it + try: + del new_module + except (OSError, KeyError): # lgtm [py/unreachable-statement] + pass + try: + del sys.modules[module_name] + except KeyError: + pass + gc.collect() + return True + + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): + "Write a module/object stub to an open file. Can be called recursive." + gc.collect() + if object_expr in self.problematic: + # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + return + + # # self.log.debug("DUMP : {}".format(object_expr)) + items, errors = self.get_obj_attributes(object_expr) + + if errors: + print(errors) + + for item_name, item_repr, item_type_txt, item_instance, _ in items: + # name_, repr_(value), type as text, item_instance, order + if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: + # do not create stubs for these primitives + continue + if item_name[0].isdigit(): + # self.log.warning("NameError: invalid name {}".format(item_name)) + continue + # Class expansion only on first 3 levels (bit of a hack) + if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: + # self.log.debug("{0}class {1}:".format(indent, item_name)) + superclass = "" + is_exception = ( + item_name.endswith("Exception") + or item_name.endswith("Error") + or item_name + in [ + "KeyboardInterrupt", + "StopIteration", + "SystemExit", + ] + ) + if is_exception: + superclass = "Exception" + s = "\n{}class {}({}):\n".format(indent, item_name, superclass) + # s += indent + " ''\n" + if is_exception: + s += indent + " ...\n" + fp.write(s) + return + # write classdef + fp.write(s) + # first write the class literals and methods + # self.log.debug("# recursion over class {0}".format(item_name)) + self.write_object_stub( + fp, + item_instance, + "{0}.{1}".format(obj_name, item_name), + indent + " ", + in_class + 1, + ) + # end with the __init__ method to make sure that the literals are defined + # Add __init__ + s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" + s += indent + " ...\n\n" + fp.write(s) + elif any(word in item_type_txt for word in ["method", "function", "closure"]): + # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # module Function or class method + # will accept any number of params + # return type Any/Incomplete + ret = "Incomplete" + first = "" + # Self parameter only on class methods/functions + if in_class > 0: + first = "self, " + # class method - add function decoration + if "bound_method" in item_type_txt or "bound_method" in item_repr: + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) + s += indent + " ...\n\n" + fp.write(s) + # self.log.debug("\n" + s) + elif item_type_txt == "": + # Skip imported modules + # fp.write("# import {}\n".format(item_name)) + pass + + elif item_type_txt.startswith(" dict[str, str] + info = OrderedDict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "UNKNOWN", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" + try: + info["version"] = version_str(sys.implementation.version) # type: ignore + except AttributeError: + pass + try: + _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine + info["cpu"] = _machine.split("with")[-1].strip() + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + gc.collect() + read_boardname(info) + gc.collect() + + try: + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): + pass + # avoid build hashes + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() # type: ignore + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + info["version"] + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # versions from 1.10.0 to 1.20.0 do not have a micro .0 + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" + # simple to use version[-build] string + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" + + return info + + +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): + found = True + break + if not found: + # print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + +def find_board(info: dict, descr: str, filename: str, short_descr: str): + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + info["board"] = board_ + return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True + return False + + +def get_root() -> str: # sourcery skip: use-assigned-variable + "Determine the root folder of the device" + try: + c = os.getcwd() + except (OSError, AttributeError): + # unix port + c = "." + r = c + for r in [c, "/sd", "/flash", "/", "."]: + try: + _ = os.stat(r) + break + except OSError: + continue + return r + + +def file_exists(filename: str): + try: + if os.stat(filename)[0] >> 14: + return True + return False + except OSError: + return False + + +def show_help(): + # print("-p, --path path to store the stubs in, defaults to '.'") + sys.exit(1) + + +def read_path() -> str: + "get --path from cmdline. [unix/win]" + path = "" + if len(sys.argv) == 3: + cmd = (sys.argv[1]).lower() + if cmd in ("--path", "-p"): + path = sys.argv[2] + else: + show_help() + elif len(sys.argv) == 2: + show_help() + return path + + +def is_micropython() -> bool: + "runtime test to determine full or micropython" + # pylint: disable=unused-variable,eval-used + try: + # either test should fail on micropython + # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces + # Micropython : SyntaxError + # a = eval("1and 0") # lgtm [py/unused-local-variable] + # Eval blocks some minification aspects + + # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented + # Micropython: NotImplementedError + b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] + + # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute + # Micropython: AttributeError + c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] + return False + except (NotImplementedError, AttributeError): + return True + + def main(): - E='/modulelist.txt';stubber=Stubber(path=read_path());stubber.clean();stubber.modules=[] - for C in f: - try: - F=B.mem_free() - with R(C+E)as D: - L('Debug: List of modules: '+C+E);A=D.readline() - while A: - A=A.strip() - if N(A)>0 and A[0]!='#':stubber.modules.append(A) - A=D.readline() - B.collect();L('Debug: Used memory to load modulelist.txt: '+X(F-B.mem_free())+' bytes');break - except Exception:pass - if not stubber.modules:stubber.modules=[Y] - B.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or j(): - try:A2=logging.getLogger(v);logging.basicConfig(level=logging.INFO) - except m:pass - if not h('no_auto_stubber.txt'): - try:B.threshold(4*1024);B.enable() - except BaseException:pass - main() \ No newline at end of file + stubber = Stubber(path=read_path()) + # stubber = Stubber(path="/sd") + # Option: Specify a firmware name & version + # stubber = Stubber(firmware_id='HoverBot v1.2.1') + stubber.clean() + # Read stubs from modulelist in the current folder or in /libs + # fall back to default modules + stubber.modules = [] # avoid duplicates + for p in LIBS: + try: + _1 = gc.mem_free() # type: ignore + with open(p + "/modulelist.txt") as f: + print ("Debug: List of modules: " + p + "/modulelist.txt") + line = f.readline() + while line: + line = line.strip() + if len(line) > 0 and line[0] != "#": + stubber.modules.append(line) + line = f.readline() + gc.collect() # type: ignore + print ("Debug: Used memory to load modulelist.txt: " + str(_1 - gc.mem_free()) + " bytes") # type: ignore + break + except Exception: + pass + if not stubber.modules: + stubber.modules = ["micropython"] + # print("Could not find modulelist.txt, using default modules") + + gc.collect() + + stubber.create_all_stubs() + stubber.report() + + +if __name__ == "__main__" or is_micropython(): + try: + log = logging.getLogger("stubber") + logging.basicConfig(level=logging.INFO) + # logging.basicConfig(level=logging.DEBUG) + except NameError: + pass + if not file_exists("no_auto_stubber.txt"): + try: + gc.threshold(4 * 1024) # type: ignore + gc.enable() + except BaseException: + pass + main() diff --git a/mip/v6/createstubs_mem_mpy.mpy b/mip/v6/createstubs_mem_mpy.mpy index bee999ab59698d1bb2b50c1e594a53677a6f0684..50f1357ea753c5c39a3380e756ae91770e3c2dc5 100644 GIT binary patch literal 7988 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 literal 8310 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 HA@TnKSfh%2 diff --git a/mip/v6/createstubs_min.py b/mip/v6/createstubs_min.py index e01b97706..ad7e11574 100644 --- a/mip/v6/createstubs_min.py +++ b/mip/v6/createstubs_min.py @@ -1,292 +1,954 @@ -y='with' -x='pyb' -w='stubber' -v='{}/{}' -u='logging' -t='sys' -s='method' -r='function' -q='bool' -p='str' -o='float' -n='int' -m=TypeError -l=NameError -k=sorted -j=NotImplementedError -d='pycom' -c='-' -b=',\n' -a='dict' -Z='list' -Y='tuple' -X='micropython' -W=open -V=repr -T='cpu' -S='_' -R=len -Q=KeyError -P=IndexError -O=print -N=ImportError -M='family' -L=dir -K=True -J='.' -I=AttributeError -H='board' -A=False -G='/' -E=None -F=OSError -C='version' -B='' -import gc as D,os,sys -try:from ujson import dumps -except:from json import dumps -try:from machine import reset -except N:pass -try:from collections import OrderedDict as e -except N:from ucollections import OrderedDict as e -__version__='v1.16.2' -z=2 -A0=2 -A1=[J,'/lib','/sd/lib','/flash/lib','lib'] +""" +Create stubs for (all) modules on a MicroPython board +""" +# Copyright (c) 2019-2023 Jos Verlinde + +import gc +# import logging +import os +import sys + +try: + from ujson import dumps +except: + from json import dumps + +try: + from machine import reset # type: ignore +except ImportError: + pass + +try: + from collections import OrderedDict +except ImportError: + from ucollections import OrderedDict # type: ignore + +__version__ = "v1.16.2" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] from time import sleep + + class Stubber: - def __init__(A,path=E,firmware_id=E): - B=firmware_id - try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') - except I:pass - A._report=[];A.info=_info();D.collect() - if B:A._fwid=B.lower() - elif A.info[M]==X:A._fwid='{family}-v{version}-{port}-{board}'.format(**A.info) - else:A._fwid='{family}-v{version}-{port}'.format(**A.info) - A._start_free=D.mem_free() - if path: - if path.endswith(G):path=path[:-1] - else:path=get_root() - A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G) - try:f(path+G) - except F:O('error creating stub folder {}'.format(path)) - A.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];A.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];A.modules=[] - def get_obj_attributes(M,item_instance): - H=item_instance;C=[];J=[] - for A in L(H): - if A.startswith(S)and not A in M.modules:continue - try: - E=getattr(H,A) - try:F=V(type(E)).split("'")[1] - except P:F=B - if F in{n,o,p,q,Y,Z,a}:G=1 - elif F in{r,s}:G=2 - elif F in'class':G=3 - else:G=4 - C.append((A,V(E),V(type(E)),E,G)) - except I as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,K)) - except MemoryError as K:sleep(1);reset() - C=k([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,J - def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) - def create_all_stubs(A): - D.collect() - for B in A.modules:A.create_one_stub(B) - def create_one_stub(B,module_name): - C=module_name - if C in B.problematic:return A - if C in B.excluded:return A - H='{}/{}.py'.format(B.path,C.replace(J,G));D.collect();E=A - try:E=B.create_module_stub(C,H) - except F:return A - D.collect();return E - def create_module_stub(I,module_name,file_name=E): - H=file_name;C=module_name - if H is E:O=C.replace(J,S)+'.py';H=I.path+G+O - else:O=H.split(G)[-1] - if G in C:C=C.replace(G,J) - L=E - try:L=__import__(C,E,E,'*');T=D.mem_free() - except N:return A - f(H) - with W(H,'w')as M:P=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,I._fwid,P,__version__);M.write(R);M.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(M,L,C,B) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) - if C not in{'os',t,u,'gc'}: - try:del L - except(F,Q):pass - try:del sys.modules[C] - except Q:pass - D.collect();return K - def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - d='{0}{1} = {2} # type: {3}\n';c='bound_method';b='Incomplete';P=in_class;N=object_expr;M='Exception';H=fp;C=indent;D.collect() - if N in K.problematic:return - S,L=K.get_obj_attributes(N) - if L:O(L) - for(E,J,G,T,f)in S: - if E in['classmethod','staticmethod','BaseException',M]:continue - if E[0].isdigit():continue - if G==""and R(C)<=A0*4: - U=B;V=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if V:U=M - A='\n{}class {}({}):\n'.format(C,E,U) - if V:A+=C+' ...\n';H.write(A);return - H.write(A);K.write_object_stub(H,T,'{0}.{1}'.format(obj_name,E),C+' ',P+1);A=C+' def __init__(self, *argv, **kwargs) -> None:\n';A+=C+' ...\n\n';H.write(A) - elif any(A in G for A in[s,r,'closure']): - W=b;X=B - if P>0:X='self, ' - if c in G or c in J:A='{}@classmethod\n'.format(C)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(C,E,W) - else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(C,E,X,W) - A+=C+' ...\n\n';H.write(A) - elif G=="":0 - elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] - if J in A and A[J]: - K=int(A[J]);R=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][K>>10] - if R:A[V]=R - A[J]='v{}.{}'.format(K&255,K>>8&3) - if A[F]and not A[C].endswith(b):A[C]=A[C]+b - A[S]=f"{A[C]}-{A[F]}"if A[F]else f"{A[C]}";return A -def A2(version): - A=version;B=J.join([str(A)for A in A[:3]]) - if R(A)>3 and A[3]:B+=c+A[3] - return B -def A3(info,desc=B): - L='with ';C=info;F=A - for G in[A+'/board_info.csv'for A in A1]: - if g(G): - E=desc or C[H].strip();I=E.rfind(' with') - if I!=-1:J=E[:I].strip() - else:J=B - if A4(C,E,G,J):F=K;break - if not F: - E=desc or C[H].strip() - if L+C[T].upper()in E:E=E.split(L+C[T].upper())[0].strip() - C[H]=E - C[H]=C[H].replace(' ',S);D.collect() -def A4(info,descr,filename,short_descr): - D=short_descr;C=info;E=B - with W(filename,'r')as J: - while 1: - F=J.readline() - if not F:break - I,G=F.split(',')[0].strip(),F.split(',')[1].strip() - if I==descr:C[H]=G;return K - elif D and I==D: - if y in D:C[H]=G;return K - E=G - if E:C[H]=E;return K - return A -def get_root(): - try:A=os.getcwd() - except(F,I):A=J - B=A - for B in[A,'/sd','/flash',G,J]: - try:C=os.stat(B);break - except F:continue - return B -def g(filename): - try: - if os.stat(filename)[0]>>14:return K - return A - except F:return A -def h():sys.exit(1) -def read_path(): - path=B - if R(sys.argv)==3: - A=sys.argv[1].lower() - if A in('--path','-p'):path=sys.argv[2] - else:h() - elif R(sys.argv)==2:h() - return path -def i(): - try:B=bytes('abc',encoding='utf8');C=i.__module__;return A - except(j,I):return K -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',u,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',X,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',x,d,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',t,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];D.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or i(): - try:A5=logging.getLogger(w);logging.basicConfig(level=logging.INFO) - except l:pass - if not g('no_auto_stubber.txt'): - try:D.threshold(4*1024);D.enable() - except BaseException:pass - main() \ No newline at end of file + "Generate stubs for modules in firmware" + + def __init__(self, path: str = None, firmware_id: str = None): # type: ignore + try: + if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore + raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") + except AttributeError: + pass + # self.log = logging.getLogger("stubber") + self._report = [] # type: list[str] + self.info = _info() + # self.log.info("Port: {}".format(self.info["port"])) + # self.log.info("Board: {}".format(self.info["board"])) + gc.collect() + if firmware_id: + self._fwid = firmware_id.lower() + else: + if self.info["family"] == "micropython": + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + else: + self._fwid = "{family}-v{version}-{port}".format(**self.info) + self._start_free = gc.mem_free() # type: ignore + + if path: + if path.endswith("/"): + path = path[:-1] + else: + path = get_root() + + self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") + # self.log.debug(self.path) + try: + ensure_folder(path + "/") + except OSError: + print("error creating stub folder {}".format(path)) + self.problematic = [ + "upip", + "upysh", + "webrepl_setup", + "http_client", + "http_client_ssl", + "http_server", + "http_server_ssl", + ] + self.excluded = [ + "webrepl", + "_webrepl", + "port_diag", + "example_sub_led.py", + "example_pub_button.py", + ] + # there is no option to discover modules from micropython, list is read from an external file. + self.modules = [] # type: list[str] + + def get_obj_attributes(self, item_instance: object): + "extract information of the objects members and attributes" + # name_, repr_(value), type as text, item_instance + _result = [] + _errors = [] + # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + for name in dir(item_instance): + if name.startswith("_") and not name in self.modules: + continue + # self.log.debug("get attribute {}".format(name)) + try: + val = getattr(item_instance, name) + # name , item_repr(value) , type as text, item_instance, order + try: + type_text = repr(type(val)).split("'")[1] + except IndexError: + type_text = "" + if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: + order = 1 + elif type_text in {"function", "method"}: + order = 2 + elif type_text in ("class"): + order = 3 + else: + order = 4 + _result.append((name, repr(val), repr(type(val)), val, order)) + except AttributeError as e: + _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) + except MemoryError as e: + # print("MemoryError: {}".format(e)) + sleep(1) + reset() + + # remove internal __ + # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) + _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) + gc.collect() + return _result, _errors + + def add_modules(self, modules): + "Add additional modules to be exported" + self.modules = sorted(set(self.modules) | set(modules)) + + def create_all_stubs(self): + "Create stubs for all configured modules" + # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + gc.collect() + for module_name in self.modules: + self.create_one_stub(module_name) + # self.log.info("Finally done") + + def create_one_stub(self, module_name: str): + if module_name in self.problematic: + # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + return False + if module_name in self.excluded: + # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + return False + + file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + gc.collect() + result = False + try: + result = self.create_module_stub(module_name, file_name) + except OSError: + return False + gc.collect() + return result + + def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore + """Create a Stub of a single python module + + Args: + - module_name (str): name of the module to document. This module will be imported. + - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + """ + if file_name is None: + fname = module_name.replace(".", "_") + ".py" + file_name = self.path + "/" + fname + else: + fname = file_name.split("/")[-1] + + if "/" in module_name: + # for nested modules + module_name = module_name.replace("/", ".") + + # import the module (as new_module) to examine it + new_module = None + try: + new_module = __import__(module_name, None, None, ("*")) + m1 = gc.mem_free() # type: ignore + # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + + except ImportError: + # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + return False + + # Start a new file + ensure_folder(file_name) + with open(file_name, "w") as fp: + # todo: improve header + info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format( + module_name, self._fwid, info_, __version__ + ) + fp.write(s) + fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + self.write_object_stub(fp, new_module, module_name, "") + + self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + + if module_name not in {"os", "sys", "logging", "gc"}: + # try to unload the module unless we use it + try: + del new_module + except (OSError, KeyError): # lgtm [py/unreachable-statement] + pass + try: + del sys.modules[module_name] + except KeyError: + pass + gc.collect() + return True + + def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): + "Write a module/object stub to an open file. Can be called recursive." + gc.collect() + if object_expr in self.problematic: + # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + return + + # # self.log.debug("DUMP : {}".format(object_expr)) + items, errors = self.get_obj_attributes(object_expr) + + if errors: + print(errors) + + for item_name, item_repr, item_type_txt, item_instance, _ in items: + # name_, repr_(value), type as text, item_instance, order + if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: + # do not create stubs for these primitives + continue + if item_name[0].isdigit(): + # self.log.warning("NameError: invalid name {}".format(item_name)) + continue + # Class expansion only on first 3 levels (bit of a hack) + if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: + # self.log.debug("{0}class {1}:".format(indent, item_name)) + superclass = "" + is_exception = ( + item_name.endswith("Exception") + or item_name.endswith("Error") + or item_name + in [ + "KeyboardInterrupt", + "StopIteration", + "SystemExit", + ] + ) + if is_exception: + superclass = "Exception" + s = "\n{}class {}({}):\n".format(indent, item_name, superclass) + # s += indent + " ''\n" + if is_exception: + s += indent + " ...\n" + fp.write(s) + return + # write classdef + fp.write(s) + # first write the class literals and methods + # self.log.debug("# recursion over class {0}".format(item_name)) + self.write_object_stub( + fp, + item_instance, + "{0}.{1}".format(obj_name, item_name), + indent + " ", + in_class + 1, + ) + # end with the __init__ method to make sure that the literals are defined + # Add __init__ + s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" + s += indent + " ...\n\n" + fp.write(s) + elif any(word in item_type_txt for word in ["method", "function", "closure"]): + # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # module Function or class method + # will accept any number of params + # return type Any/Incomplete + ret = "Incomplete" + first = "" + # Self parameter only on class methods/functions + if in_class > 0: + first = "self, " + # class method - add function decoration + if "bound_method" in item_type_txt or "bound_method" in item_repr: + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format( + indent, item_name, ret + ) + else: + s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) + s += indent + " ...\n\n" + fp.write(s) + # self.log.debug("\n" + s) + elif item_type_txt == "": + # Skip imported modules + # fp.write("# import {}\n".format(item_name)) + pass + + elif item_type_txt.startswith(" dict[str, str] + info = OrderedDict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "UNKNOWN", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + # change port names to be consistent with the repo + if info["port"].startswith("pyb"): + info["port"] = "stm32" + elif info["port"] == "win32": + info["port"] = "windows" + elif info["port"] == "linux": + info["port"] = "unix" + try: + info["version"] = version_str(sys.implementation.version) # type: ignore + except AttributeError: + pass + try: + _machine = ( + sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore + ) + # info["board"] = "with".join(_machine.split("with")[:-1]).strip() + info["board"] = _machine + info["cpu"] = _machine.split("with")[-1].strip() + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + gc.collect() + read_boardname(info) + gc.collect() + + try: + if "uname" in dir(os): # old + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) # type: ignore + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) # type: ignore + elif "version" in dir(sys): # new + # extract build from sys.version if available + info["build"] = _build(sys.version) + except (AttributeError, IndexError, TypeError): + pass + # avoid build hashes + # if info["build"] and len(info["build"]) > 5: + # info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() # type: ignore + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + info["version"] + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # versions from 1.10.0 to 1.20.0 do not have a micro .0 + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + if info["build"] and not info["version"].endswith("-preview"): + info["version"] = info["version"] + "-preview" + # simple to use version[-build] string + info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" + + return info + + +def version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def read_boardname(info, desc: str = ""): + found = False + for filename in [d + "/board_info.csv" for d in LIBS]: + # # print("look up the board name in the file", filename) + if file_exists(filename): + descr = desc or info["board"].strip() + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) + if find_board(info, descr, filename, short_descr): + found = True + break + if not found: + # print("Board not found, guessing board name") + descr = desc or info["board"].strip() + if "with " + info["cpu"].upper() in descr: + # remove the with cpu part + descr = descr.split("with " + info["cpu"].upper())[0].strip() + info["board"] = descr + info["board"] = info["board"].replace(" ", "_") + gc.collect() + + +def find_board(info: dict, descr: str, filename: str, short_descr: str): + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + info["board"] = board_ + return True + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + info["board"] = board_ + return True + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + info["board"] = short_hit + return True + return False + + +def get_root() -> str: # sourcery skip: use-assigned-variable + "Determine the root folder of the device" + try: + c = os.getcwd() + except (OSError, AttributeError): + # unix port + c = "." + r = c + for r in [c, "/sd", "/flash", "/", "."]: + try: + _ = os.stat(r) + break + except OSError: + continue + return r + + +def file_exists(filename: str): + try: + if os.stat(filename)[0] >> 14: + return True + return False + except OSError: + return False + + +def show_help(): + # print("-p, --path path to store the stubs in, defaults to '.'") + sys.exit(1) + + +def read_path() -> str: + "get --path from cmdline. [unix/win]" + path = "" + if len(sys.argv) == 3: + cmd = (sys.argv[1]).lower() + if cmd in ("--path", "-p"): + path = sys.argv[2] + else: + show_help() + elif len(sys.argv) == 2: + show_help() + return path + + +def is_micropython() -> bool: + "runtime test to determine full or micropython" + # pylint: disable=unused-variable,eval-used + try: + # either test should fail on micropython + # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces + # Micropython : SyntaxError + # a = eval("1and 0") # lgtm [py/unused-local-variable] + # Eval blocks some minification aspects + + # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented + # Micropython: NotImplementedError + b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] + + # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute + # Micropython: AttributeError + c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] + return False + except (NotImplementedError, AttributeError): + return True + + +def main(): + stubber = Stubber(path=read_path()) + # stubber = Stubber(path="/sd") + # Option: Specify a firmware name & version + # stubber = Stubber(firmware_id='HoverBot v1.2.1') + stubber.clean() + # there is no option to discover modules from micropython, need to hardcode + # below contains combined modules from Micropython ESP8622, ESP32, Loboris, Pycom and ulab , lvgl + # spell-checker: disable + # modules to stub : 131 + stubber.modules = [ + "WM8960", + "_OTA", + "_asyncio", + "_boot_fat", + "_coap", + "_espnow", + "_flash_control_OTA", + "_main_pybytes", + "_mqtt", + "_mqtt_core", + "_msg_handl", + "_onewire", + "_periodical_pin", + "_pybytes", + "_pybytes_ca", + "_pybytes_config", + "_pybytes_config_reader", + "_pybytes_connection", + "_pybytes_constants", + "_pybytes_debug", + "_pybytes_library", + "_pybytes_machine_learning", + "_pybytes_main", + "_pybytes_protocol", + "_pybytes_pyconfig", + "_pybytes_pymesh_config", + "_rp2", + "_terminal", + "_thread", + "_uasyncio", + "_urequest", + "adcfft", + "aioble/__init__", + "aioble/central", + "aioble/client", + "aioble/core", + "aioble/device", + "aioble/l2cap", + "aioble/peripheral", + "aioble/security", + "aioble/server", + "aioespnow", + "ak8963", + "apa102", + "apa106", + "argparse", + "array", + "asyncio/__init__", + "asyncio/core", + "asyncio/event", + "asyncio/funcs", + "asyncio/lock", + "asyncio/stream", + "binascii", + "bluetooth", + "breakout_as7262", + "breakout_bh1745", + "breakout_bme280", + "breakout_bme68x", + "breakout_bmp280", + "breakout_dotmatrix", + "breakout_encoder", + "breakout_icp10125", + "breakout_ioexpander", + "breakout_ltr559", + "breakout_matrix11x7", + "breakout_mics6814", + "breakout_msa301", + "breakout_paa5100", + "breakout_pmw3901", + "breakout_potentiometer", + "breakout_rgbmatrix5x5", + "breakout_rtc", + "breakout_scd41", + "breakout_sgp30", + "breakout_trackball", + "breakout_vl53l5cx", + "btree", + "cmath", + "collections", + "crypto", + "cryptolib", + "curl", + "deflate", + "dht", + "display", + "display_driver_utils", + "ds18x20", + "encoder", + "errno", + "esp", + "esp32", + "espidf", + "espnow", + "ffi", + "flashbdev", + "framebuf", + "freesans20", + "fs_driver", + "functools", + "galactic", + "gc", + "gfx_pack", + "gsm", + "hashlib", + "heapq", + "hub75", + "ili9341", + "ili9XXX", + "imagetools", + "inisetup", + "interstate75", + "io", + "jpegdec", + "json", + "lcd160cr", + "lodepng", + "logging", + "lsm6dsox", + "lv_colors", + "lv_utils", + "lvgl", + "lwip", + "machine", + "math", + "microWebSocket", + "microWebSrv", + "microWebTemplate", + "micropython", + "mip", + "mip/__init__", + "mip/__main__", + "motor", + "mpu6500", + "mpu9250", + "neopixel", + "network", + "ntptime", + "onewire", + "os", + "pcf85063a", + "picoexplorer", + "picographics", + "picokeypad", + "picoscroll", + "picounicorn", + "picowireless", + "pimoroni", + "pimoroni_bus", + "pimoroni_i2c", + "plasma", + "platform", + "pyb", + "pycom", + "pye", + "qrcode", + "queue", + "random", + "requests", + "requests/__init__", + "rp2", + "rtch", + "samd", + "select", + "servo", + "socket", + "ssd1306", + "ssh", + "ssl", + "stm", + "struct", + "sys", + "termios", + "time", + "tpcalib", + "uarray", + "uasyncio/__init__", + "uasyncio/core", + "uasyncio/event", + "uasyncio/funcs", + "uasyncio/lock", + "uasyncio/stream", + "uasyncio/tasks", + "ubinascii", + "ubluetooth", + "ucollections", + "ucrypto", + "ucryptolib", + "uctypes", + "uerrno", + "uftpd", + "uhashlib", + "uheapq", + "uio", + "ujson", + "ulab", + "ulab/approx", + "ulab/compare", + "ulab/fft", + "ulab/filter", + "ulab/linalg", + "ulab/numerical", + "ulab/poly", + "ulab/user", + "ulab/vector", + "umachine", + "umqtt/__init__", + "umqtt/robust", + "umqtt/simple", + "uos", + "uplatform", + "uqueue", + "urandom", + "ure", + "urequests", + "urllib/urequest", + "uselect", + "usocket", + "ussl", + "ustruct", + "usys", + "utelnetserver", + "utime", + "utimeq", + "uwebsocket", + "uzlib", + "version", + "websocket", + "websocket_helper", + "wipy", + "writer", + "xpt2046", + "ymodem", + "zephyr", + "zlib", + ] # spell-checker: enable + + gc.collect() + + stubber.create_all_stubs() + stubber.report() + + +if __name__ == "__main__" or is_micropython(): + try: + log = logging.getLogger("stubber") + logging.basicConfig(level=logging.INFO) + # logging.basicConfig(level=logging.DEBUG) + except NameError: + pass + if not file_exists("no_auto_stubber.txt"): + try: + gc.threshold(4 * 1024) # type: ignore + gc.enable() + except BaseException: + pass + main() diff --git a/mip/v6/createstubs_mpy.mpy b/mip/v6/createstubs_mpy.mpy index 4307abc5a4b28003a9be2e0a221147d403eee6b3..1cf9adba9bb65d449e220ddbb3853f68190ab479 100644 GIT binary patch delta 6389 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 delta 6652 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 Date: Sun, 21 Jan 2024 22:36:50 +0100 Subject: [PATCH 38/68] Use fw_info script to retrieve port and board information to MPRemoteBoard class Signed-off-by: Jos Verlinde --- scripts/board_stubber.py | 43 ++++------- src/stubber/board/fw_info.py | 135 +++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 30 deletions(-) create mode 100644 src/stubber/board/fw_info.py diff --git a/scripts/board_stubber.py b/scripts/board_stubber.py index 041b84b46..67133e72a 100644 --- a/scripts/board_stubber.py +++ b/scripts/board_stubber.py @@ -177,6 +177,8 @@ def __init__(self, serialport: str = ""): self.path: Optional[Path] = None self.description = "" self.version = "" + self.port = "" + self.board = "" @staticmethod def connected_boards(): @@ -188,22 +190,16 @@ def connected_boards(): def get_mcu_info(self): # switched from uname to sys.implementation as the primary source of info rc, result = self.run_command( - [ - "exec", - "import sys;print(repr(sys.implementation) if 'implementation' in dir(sys) else 'no.implementation');print(sys.platform)", - ], + ["run", "src/stubber/board/fw_info.py"], no_info=True, ) if rc == OK: - s = result[0] - if "name=" in s: - implementation = eval(f"dict{s}") - self.version = ".".join([str(n) for n in implementation["version"]]) - self.description = implementation["_machine"] - if len(result) > 1: - self.port = result[1].strip() - else: - self.port = "unknown" + s = result[0].strip() + if s.startswith("{") and s.endswith("}"): + info = eval(s) + self.version = info["version"] + self.port = info["port"] + self.description = info["board"] def disconnect(self) -> bool: """Disconnect from a board""" @@ -356,9 +352,7 @@ def run_createstubs(dest: Path, board: MPRemoteBoard, variant: Variant = Variant board.run_command("reset", timeout=5) time.sleep(2) - log.info( - f"Running createstubs {variant} on {board.serialport} {board.description} using temp path: {dest}" - ) + log.info(f"Running createstubs {variant} on {board.serialport} {board.description} using temp path: {dest}") cmd = build_cmd(dest, variant) board.run_command.retry.wait = wait_fixed(15) @@ -368,12 +362,7 @@ def run_createstubs(dest: Path, board: MPRemoteBoard, variant: Variant = Variant timeout = 60 if board.port == "esp8266" else 6 * 60 # type: ignore rc, out = board.run_command(cmd, timeout=timeout) # check last line for exception or error and raise that if found - if ( - rc != OK - and ":" in out[-1] - and not out[-1].startswith("INFO") - and not out[-1].startswith("WARN") - ): + if rc != OK and ":" in out[-1] and not out[-1].startswith("INFO") and not out[-1].startswith("WARN"): log.warning(f"createstubs: {out[-1]}") raise RuntimeError(out[-1]) from eval(out[-1].split(":")[0]) @@ -478,11 +467,7 @@ def generate_board_stubs( def get_stubfolder(out: List[str]): - return ( - lines[-1].split("/remote/")[-1].strip() - if (lines := [l for l in out if l.startswith("Path: ")]) - else "" - ) + return lines[-1].split("/remote/")[-1].strip() if (lines := [l for l in out if l.startswith("Path: ")]) else "" # def get_port_board(out: List[str]): @@ -527,9 +512,7 @@ def set_loglevel(verbose: int) -> str: else: format_str = "{time:YYYY-MM-DD HH:mm:ss.SSS}|{level: <8}|{name}:{function}:{line} - {message}" - log.add( - sys.stderr, level=level, backtrace=True, diagnose=True, colorize=True, format=format_str - ) + log.add(sys.stderr, level=level, backtrace=True, diagnose=True, colorize=True, format=format_str) # log.info(f"micropython-stubber {__version__}") return level diff --git a/src/stubber/board/fw_info.py b/src/stubber/board/fw_info.py new file mode 100644 index 000000000..1dc082953 --- /dev/null +++ b/src/stubber/board/fw_info.py @@ -0,0 +1,135 @@ +# %%micropython +import os +import sys + + +def _build(s): + # extract a build nr from a string + if not s: + return "" + if " on " in s: + s = s.split(" on ", 1)[0] + return s.split("-")[1] if "-" in s else "" + + +def _version_str(version: tuple): # -> str: + v_str = ".".join([str(n) for n in version[:3]]) + if len(version) > 3 and version[3]: + v_str += "-" + version[3] + return v_str + + +def _info(): # type:() -> dict[str, str] + # sourcery skip: use-contextlib-suppress, use-fstring-for-formatting, use-named-expression + info = dict( + { + "family": sys.implementation.name, + "version": "", + "build": "", + "ver": "", + "port": "stm32" if sys.platform.startswith("pyb") else sys.platform, # port: esp32 / win32 / linux / stm32 + "board": "GENERIC", + "cpu": "", + "mpy": "", + "arch": "", + } + ) + try: + info["version"] = _version_str(sys.implementation.version) + except AttributeError: + pass + try: + machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine + info["board"] = machine.strip() + info["cpu"] = machine.split("with")[-1].strip() if "with" in machine else "" + info["mpy"] = ( + sys.implementation._mpy + if "_mpy" in dir(sys.implementation) + else sys.implementation.mpy + if "mpy" in dir(sys.implementation) + else "" + ) + except (AttributeError, IndexError): + pass + + try: + # extract build from uname().version if available + info["build"] = _build(os.uname()[3]) + if not info["build"]: + # extract build from uname().release if available + info["build"] = _build(os.uname()[2]) + if not info["build"] and ";" in sys.version: + # extract build from uname().release if available + info["build"] = _build(sys.version.split(";")[1]) + except (AttributeError, IndexError): + pass + # avoid build hashes + if info["build"] and len(info["build"]) > 5: + info["build"] = "" + + if info["version"] == "" and sys.platform not in ("unix", "win32"): + try: + u = os.uname() + info["version"] = u.release + except (IndexError, AttributeError, TypeError): + pass + # detect families + for fam_name, mod_name, mod_thing in [ + ("pycopy", "pycopy", "const"), + ("pycom", "pycom", "FAT"), + ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), + ]: + try: + _t = __import__(mod_name, None, None, (mod_thing)) + info["family"] = fam_name + del _t + break + except (ImportError, KeyError): + pass + + if info["family"] == "ev3-pybricks": + info["release"] = "2.0.0" + + if info["family"] == "micropython": + if ( + info["version"] + and info["version"].endswith(".0") + and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 + and info["version"] <= "1.19.9" + ): + # drop the .0 for newer releases + info["version"] = info["version"][:-2] + + # spell-checker: disable + if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds + sys_mpy = int(info["mpy"]) + # .mpy architecture + arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + ][sys_mpy >> 10] + if arch: + info["arch"] = arch + # .mpy version.minor + info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) + # simple to use version[-build] string avoiding f-strings for backward compat + info["ver"] = ( + "v{version}-{build}".format(version=info["version"], build=info["build"]) + if info["build"] + else "v{version}".format(version=info["version"]) + ) + + return info + + +print(_info()) +# del _info, _build, _version_str From e4032275c4963a0e9ebe18cc4cb4cf93c8298cb0 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 23 Jan 2024 00:34:21 +0100 Subject: [PATCH 39/68] fix: Onewire stub missing parts https://github.com/Josverl/micropython-stubs/issues/748 Signed-off-by: Jos Verlinde --- src/stubber/board/createstubs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index 9f29cb4c9..3ae80a57e 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -251,7 +251,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods From ca82c373ceb47924e265b404b195cbe017911a09 Mon Sep 17 00:00:00 2001 From: Josverl Date: Mon, 22 Jan 2024 23:35:44 +0000 Subject: [PATCH 40/68] Update mip packages --- mip/v5/createstubs.py | 2 +- mip/v5/createstubs_db.py | 2 +- mip/v5/createstubs_db_min.py | 2 +- mip/v5/createstubs_db_mpy.mpy | Bin 9168 -> 9169 bytes mip/v5/createstubs_lvgl.py | 2 +- mip/v5/createstubs_lvgl_min.py | 2 +- mip/v5/createstubs_lvgl_mpy.mpy | Bin 8527 -> 8528 bytes mip/v5/createstubs_mem.py | 2 +- mip/v5/createstubs_mem_min.py | 2 +- mip/v5/createstubs_mem_mpy.mpy | Bin 8585 -> 8586 bytes mip/v5/createstubs_min.py | 2 +- mip/v5/createstubs_mpy.mpy | Bin 11249 -> 11250 bytes mip/v6/createstubs.py | 2 +- mip/v6/createstubs_db.py | 2 +- mip/v6/createstubs_db_min.py | 2 +- mip/v6/createstubs_db_mpy.mpy | Bin 8492 -> 8493 bytes mip/v6/createstubs_lvgl.py | 2 +- mip/v6/createstubs_lvgl_min.py | 2 +- mip/v6/createstubs_lvgl_mpy.mpy | Bin 7990 -> 7991 bytes mip/v6/createstubs_mem.py | 2 +- mip/v6/createstubs_mem_min.py | 2 +- mip/v6/createstubs_mem_mpy.mpy | Bin 7988 -> 7989 bytes mip/v6/createstubs_min.py | 2 +- mip/v6/createstubs_mpy.mpy | Bin 11115 -> 11116 bytes src/stubber/board/createstubs_db.py | 2 +- src/stubber/board/createstubs_db_min.py | 2 +- src/stubber/board/createstubs_db_mpy.mpy | Bin 8470 -> 8471 bytes src/stubber/board/createstubs_lvgl.py | 2 +- src/stubber/board/createstubs_lvgl_min.py | 2 +- src/stubber/board/createstubs_lvgl_mpy.mpy | Bin 7967 -> 7968 bytes src/stubber/board/createstubs_mem.py | 2 +- src/stubber/board/createstubs_mem_min.py | 2 +- src/stubber/board/createstubs_mem_mpy.mpy | Bin 7966 -> 7967 bytes src/stubber/board/createstubs_min.py | 2 +- src/stubber/board/createstubs_mpy.mpy | Bin 11094 -> 11095 bytes 35 files changed, 23 insertions(+), 23 deletions(-) diff --git a/mip/v5/createstubs.py b/mip/v5/createstubs.py index 9f29cb4c9..3ae80a57e 100644 --- a/mip/v5/createstubs.py +++ b/mip/v5/createstubs.py @@ -251,7 +251,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v5/createstubs_db.py b/mip/v5/createstubs_db.py index d176f3714..9ea3a8d12 100644 --- a/mip/v5/createstubs_db.py +++ b/mip/v5/createstubs_db.py @@ -268,7 +268,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v5/createstubs_db_min.py b/mip/v5/createstubs_db_min.py index 50065e687..1c40ecbed 100644 --- a/mip/v5/createstubs_db_min.py +++ b/mip/v5/createstubs_db_min.py @@ -268,7 +268,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v5/createstubs_db_mpy.mpy b/mip/v5/createstubs_db_mpy.mpy index 4d892daed7e6d4c237264a607ded044a9d38f9fe..877627e9053ab64ba4a581ba88fe4063614e42d8 100644 GIT binary patch delta 78 zcmccMe$jmcBQK-PWF}rEM(4?@yy=W;lY4oM8Rt$u$Scd(H~BuVi;Qr?zAXX*3P7Nz ir^of_>A8&}3`_QzF-AJ2)o-@ryTizMeY3Q{R$&0b9vOxJ delta 77 zcmccUe!+bMBQK-HWF}rEMyJWDyy=XplY4oM8Rtws$Scd(JNZ7Zi?mR~zAXX*3P7Nz hr^of_>A8&}3`_QzF-8U^Z?@;V!^n7Jvy8x2VF0Ct84Lgb diff --git a/mip/v5/createstubs_lvgl.py b/mip/v5/createstubs_lvgl.py index 7e0fd913c..52a2375ea 100644 --- a/mip/v5/createstubs_lvgl.py +++ b/mip/v5/createstubs_lvgl.py @@ -253,7 +253,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v5/createstubs_lvgl_min.py b/mip/v5/createstubs_lvgl_min.py index cc2548419..d3b5468e3 100644 --- a/mip/v5/createstubs_lvgl_min.py +++ b/mip/v5/createstubs_lvgl_min.py @@ -253,7 +253,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v5/createstubs_lvgl_mpy.mpy b/mip/v5/createstubs_lvgl_mpy.mpy index 6d349d2f9f00a1e9b02d7918b1620743d349f119..76d37d58bf8e18972aa1a79c88f2fdceba6fd87d 100644 GIT binary patch delta 59 zcmV-B0L1^#LeN66?F<1tlkN;60Yj4!4QBx+lX(p@0iBbr4IKfFlgkZ60TYuD4j2PM RW`DCP4%`6&*Rux@ND*9K5|{u0 delta 58 zcmV-A0LA~%LeE05?F<1plkN;60YZ}z4QBx*lX(p@0i2Vq4IKfElgkZ60TPoC4j2Ma QW3wv`+yMdDvj`AK5k}w=9smFU diff --git a/mip/v5/createstubs_mem.py b/mip/v5/createstubs_mem.py index 7e521e4ec..34cd9f060 100644 --- a/mip/v5/createstubs_mem.py +++ b/mip/v5/createstubs_mem.py @@ -259,7 +259,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v5/createstubs_mem_min.py b/mip/v5/createstubs_mem_min.py index 1f76a726c..f7fb6c093 100644 --- a/mip/v5/createstubs_mem_min.py +++ b/mip/v5/createstubs_mem_min.py @@ -259,7 +259,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v5/createstubs_mem_mpy.mpy b/mip/v5/createstubs_mem_mpy.mpy index 08653556ced1e52895b80d28ad396af8af3cc02b..8a60fad97f3c0fac1a0681c9b4c4550a5ec0682c 100644 GIT binary patch delta 59 zcmV-B0L1@^LyAMN?F<1tlkN;60Yj4!4QBx+lX(p@0iBbr4IKfFlgkZ60TYuD4j2PM RW`DCP4%`6&*Rux@f)PE85=a05 delta 58 zcmV-A0LA}`Ly1GM?F<1plkN;60YZ}z4QBx*lX(p@0i2Vq4IKfElgkZ60TPoC4j2Ma QW3wv`+yMdDvj`A^5h$1u&Hw-a diff --git a/mip/v5/createstubs_min.py b/mip/v5/createstubs_min.py index ad7e11574..f2fd2cf66 100644 --- a/mip/v5/createstubs_min.py +++ b/mip/v5/createstubs_min.py @@ -251,7 +251,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v5/createstubs_mpy.mpy b/mip/v5/createstubs_mpy.mpy index caa5d220dc6788f801dd5acdd623a5d2157d72d7..b778346b504145e2a3d79aadbb7d7088b08b03a1 100644 GIT binary patch delta 78 zcmewu{waLJJ03=d$?tiT7@a2z@n$fpO|IrOW}G{DJ+CZd-{iBrE;7Om`?d%OC;)+; io*vhyr{^|`Ff7?;#u(|8R=-(??+zp5_060DFQfre6C0BN delta 77 zcmewq{xN*RJ03=x$?tiT7@Z~y@n$fpPOj!PW}Gv5J+CZd@8q+*F495``?d%OC;)+; ho*vhyr{^|`Ff7?;#uyoxyjhp;4kP1@&0GR6qyaR98yNrq diff --git a/mip/v6/createstubs.py b/mip/v6/createstubs.py index 9f29cb4c9..3ae80a57e 100644 --- a/mip/v6/createstubs.py +++ b/mip/v6/createstubs.py @@ -251,7 +251,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v6/createstubs_db.py b/mip/v6/createstubs_db.py index d176f3714..9ea3a8d12 100644 --- a/mip/v6/createstubs_db.py +++ b/mip/v6/createstubs_db.py @@ -268,7 +268,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v6/createstubs_db_min.py b/mip/v6/createstubs_db_min.py index 50065e687..1c40ecbed 100644 --- a/mip/v6/createstubs_db_min.py +++ b/mip/v6/createstubs_db_min.py @@ -268,7 +268,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v6/createstubs_db_mpy.mpy b/mip/v6/createstubs_db_mpy.mpy index 2ff08f91e6a973188423633a2ff7a05f25669664..bcb0e20866ea699fc986a1b6cf2d56d56c5bdde0 100644 GIT binary patch delta 79 zcmV-V0I>h8Lajouwh{q!leZEs0Yj7K5>x?%lRFbH5R`!ufp)Ys0TO{`g!I}(g_C*{ lITTaAv=D(o^5xF46oCf5HUU{e@_w_%6L$dt`LjM1?hD@RASwU= delta 78 zcmV-U0I~nALaaitwh{qsleZEs0Ya1J5>x?$lRFbH5R-utfp)Ys0TO{`g!I}(gp+y` kITKR8v=D(o^5xF46oCf5HUU{tW3$H-cL4$Vvp*H?3$!~QApigX diff --git a/mip/v6/createstubs_lvgl.py b/mip/v6/createstubs_lvgl.py index 7e0fd913c..52a2375ea 100644 --- a/mip/v6/createstubs_lvgl.py +++ b/mip/v6/createstubs_lvgl.py @@ -253,7 +253,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v6/createstubs_lvgl_min.py b/mip/v6/createstubs_lvgl_min.py index cc2548419..d3b5468e3 100644 --- a/mip/v6/createstubs_lvgl_min.py +++ b/mip/v6/createstubs_lvgl_min.py @@ -253,7 +253,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v6/createstubs_lvgl_mpy.mpy b/mip/v6/createstubs_lvgl_mpy.mpy index 244d66abd892f932c6e7a6235247e88239bb0f41..a97a8ac879c07a2d2219154a66cb55eb7a28eade 100644 GIT binary patch delta 79 zcmV-V0I>hIKDR!wf)W9AlYx?%lLr$o5R`!ufpWAo0TO{?g!I}(g_A}T lITTaAv=D(l^5xF46oE0mHUU{e@_w_D6L$dt`LhZYEDECP9wz_* delta 78 zcmV-U0I~nKKDIuvf)W92lYx?$lLr$o5R-utfpWAo0TO{?g!I}(gp)=S kITKR8v=D(l^5xF46oE0mHUU{tW3!VJcL4$VvkMh03V9J79smFU diff --git a/mip/v6/createstubs_mem.py b/mip/v6/createstubs_mem.py index 7e521e4ec..34cd9f060 100644 --- a/mip/v6/createstubs_mem.py +++ b/mip/v6/createstubs_mem.py @@ -259,7 +259,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v6/createstubs_mem_min.py b/mip/v6/createstubs_mem_min.py index 1f76a726c..f7fb6c093 100644 --- a/mip/v6/createstubs_mem_min.py +++ b/mip/v6/createstubs_mem_min.py @@ -259,7 +259,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v6/createstubs_mem_mpy.mpy b/mip/v6/createstubs_mem_mpy.mpy index 50f1357ea753c5c39a3380e756ae91770e3c2dc5..d35e79d5a731cc31d1c6bc5a5b687b0d43526566 100644 GIT binary patch delta 79 zcmV-V0I>hGKD9ouND={blSvXT0Yj5`5>x?%lg$z@5R`!ufoilg0TO{)g!I}(g_8^u lITTaAv=D(d^5xF46oDzeHUU{e@_w^e6L$dt`LoazWD1jO9-{yN delta 78 zcmV-U0I~nIKD0itND={TlSvXT0YZ~_5>x?$lg$z@5R-utfoilg0TO{)g!I}(gp&*t kITKR8v=D(d^5xF46oDzeHUU{tW3yQkcL4$Vv(Xe}3TfFLng9R* diff --git a/mip/v6/createstubs_min.py b/mip/v6/createstubs_min.py index ad7e11574..f2fd2cf66 100644 --- a/mip/v6/createstubs_min.py +++ b/mip/v6/createstubs_min.py @@ -251,7 +251,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/mip/v6/createstubs_mpy.mpy b/mip/v6/createstubs_mpy.mpy index 1cf9adba9bb65d449e220ddbb3853f68190ab479..d59f272e75a27dad866b5a34c6fd26e756e6e1a5 100644 GIT binary patch delta 79 zcmV-V0I>h-R_s==SsVd;lUf`u0Yj6C9902?liwUK5R`!uf^f7n0TO~>g!I}(g_9l~ lITTaAv=D+k^5xF46oN3mHUU{e@_w^w9d`i%`Lp64i45yWAWr}Q delta 78 zcmV-U0I~nliwUK5R-utf^f7n0TO~>g!I}(gp(c} kITKR8v=D+k^5xF46oN3mHUU{tW3y`=cL4$Vv*R9#48Uq1MgRZ+ diff --git a/src/stubber/board/createstubs_db.py b/src/stubber/board/createstubs_db.py index d176f3714..9ea3a8d12 100644 --- a/src/stubber/board/createstubs_db.py +++ b/src/stubber/board/createstubs_db.py @@ -268,7 +268,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/src/stubber/board/createstubs_db_min.py b/src/stubber/board/createstubs_db_min.py index 50065e687..1c40ecbed 100644 --- a/src/stubber/board/createstubs_db_min.py +++ b/src/stubber/board/createstubs_db_min.py @@ -268,7 +268,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/src/stubber/board/createstubs_db_mpy.mpy b/src/stubber/board/createstubs_db_mpy.mpy index 197a518cd2030081db916e1046014dd715f6b3f8..5a6627742a3cc4240f301602eb0b796c6257ad49 100644 GIT binary patch delta 79 zcmV-V0I>g-LYG3YvJwGwld}>o0Yj7G5>x?%lQ$DD5R`!ufp)Ys0TO{`g!I}(g_Cv@ lITTaAv=D(o^5xF46oCf5HUU{e@_w_z6L$dt`Lj9|+zZTjAJ6~* delta 78 zcmV-U0I~mo0Ya1F5>x?$lQ$DD5R-utfp)Ys0TO{`g!I}(gp+m? kITKR8v=D(o^5xF46oCf5HUU{tW3$5(cL4$VvpW^s3!(=e#{d8T diff --git a/src/stubber/board/createstubs_lvgl.py b/src/stubber/board/createstubs_lvgl.py index 7e0fd913c..52a2375ea 100644 --- a/src/stubber/board/createstubs_lvgl.py +++ b/src/stubber/board/createstubs_lvgl.py @@ -253,7 +253,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/src/stubber/board/createstubs_lvgl_min.py b/src/stubber/board/createstubs_lvgl_min.py index cc2548419..d3b5468e3 100644 --- a/src/stubber/board/createstubs_lvgl_min.py +++ b/src/stubber/board/createstubs_lvgl_min.py @@ -253,7 +253,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/src/stubber/board/createstubs_lvgl_mpy.mpy b/src/stubber/board/createstubs_lvgl_mpy.mpy index 6209ee7c37f829980409815c77dfdb8fa9c0a394..ee3c7c6265faa4115a85a9f7fbeac1ee938eb17c 100644 GIT binary patch delta 79 zcmV-V0I>g`KA=9Zei8w6lYbH}0Yj6n5>x?%lLHek5R`!ufpWAo0TO{?g!I}(g_A-P lITTaAv=D(l^5xF46oE0mHUU{e@_w_96L$dt`LhNU848cs9m)Uz delta 78 zcmV-U0I~m|KA%3Yei8v}lYbH}0Ya0m5>x?$lLHek5R-utfpWAo0TO{?g!I}(gp)!O kITKR8v=D(l^5xF46oE0mHUU{tW3!JFcL4$Vvj-I!3T8nZ!2kdN diff --git a/src/stubber/board/createstubs_mem.py b/src/stubber/board/createstubs_mem.py index 7e521e4ec..34cd9f060 100644 --- a/src/stubber/board/createstubs_mem.py +++ b/src/stubber/board/createstubs_mem.py @@ -259,7 +259,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/src/stubber/board/createstubs_mem_min.py b/src/stubber/board/createstubs_mem_min.py index 1f76a726c..f7fb6c093 100644 --- a/src/stubber/board/createstubs_mem_min.py +++ b/src/stubber/board/createstubs_mem_min.py @@ -259,7 +259,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/src/stubber/board/createstubs_mem_mpy.mpy b/src/stubber/board/createstubs_mem_mpy.mpy index 66f04ca0cb160398f948ed9e2cd0b5be2c0edaa6..3b02097290bcea7935539c50c22be9fe8181fcc1 100644 GIT binary patch delta 79 zcmV-V0I>g_KA%3YL=pjXlSL9P0Yj5?5>x?%lgSb<5R`!ufoilg0TO{)g!I}(g_8&q lITTaAv=D(d^5xF46oDzeHUU{e@_w^a6L$dt`LoOvQVM|g9!UTI delta 78 zcmV-U0I~m{KAt|XL=pjPlSL9P0YZ~>5>x?$lgSb<5R-utfoilg0TO{)g!I}(gp&vp kITKR8v=D(d^5xF46oDzeHUU{tW3yEgcL4$Vv&|Gz3Rk5aKmY&$ diff --git a/src/stubber/board/createstubs_min.py b/src/stubber/board/createstubs_min.py index ad7e11574..f2fd2cf66 100644 --- a/src/stubber/board/createstubs_min.py +++ b/src/stubber/board/createstubs_min.py @@ -251,7 +251,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, if is_exception: s += indent + " ...\n" fp.write(s) - return + continue # write classdef fp.write(s) # first write the class literals and methods diff --git a/src/stubber/board/createstubs_mpy.mpy b/src/stubber/board/createstubs_mpy.mpy index f70b1bb14b9983575ecda7ac0ba57e9fd5f362c9..e75d7e7d4f3de55928a9b7004738db99b4485306 100644 GIT binary patch delta 79 zcmV-V0I>hoR@YXrRU83)lU5uq0Yj689902?liM6G5R`!uf^f7n0TO~>g!I}(g_9Z` lITTaAv=D+k^5xF46oN3mHUU{e@_w^s9d`i%`Lo_0cnsNdANT+O delta 78 zcmV-U0I~nqR@PRqRU83ylU5uq0Ya079902>liM6G5R-utf^f7n0TO~>g!I}(gp(Q_ kITKR8v=D+k^5xF46oN3mHUU{tW3y)+cL4$Vv)>+g46f21?*IS* From cb108fb2c68c61ba6301936d0a4d8c001f2ac6c4 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 23 Jan 2024 18:03:47 +0100 Subject: [PATCH 41/68] fix: extract build from version Signed-off-by: Jos Verlinde --- src/stubber/board/createstubs.py | 171 ++++++++++++++-------- tests/createstubs/createstubs_all_test.py | 6 + 2 files changed, 119 insertions(+), 58 deletions(-) diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index 3ae80a57e..25dabbf72 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -7,6 +7,7 @@ import logging import os import sys +from time import sleep try: from ujson import dumps @@ -23,11 +24,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -45,11 +61,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self.log.info("Port: {}".format(self.info["port"])) self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -98,6 +115,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -137,6 +155,7 @@ def create_all_stubs(self): self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -202,10 +221,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -231,8 +251,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -321,12 +346,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -340,6 +365,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path self.log.info("Clean/remove files in folder: {}".format(path)) @@ -362,6 +388,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() self.log.info( "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) ) @@ -423,13 +450,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -565,56 +598,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/tests/createstubs/createstubs_all_test.py b/tests/createstubs/createstubs_all_test.py index 5ba22d1b8..b236f99a3 100644 --- a/tests/createstubs/createstubs_all_test.py +++ b/tests/createstubs/createstubs_all_test.py @@ -354,11 +354,17 @@ def test_unavailable_modules( "input, expected", [ ("", ""), + ("v1.13 on 2020-10-09", ""), ("v1.13-103-gb137d064e on 2020-10-09", "103"), ("3.4.0; MicroPython v1.23.0-preview.6.g3d0b6276f on 2024-01-02", "6"), + ("3.4.0; MicroPython v1.22.0 on 2023-12-27", ""), ], ) def test_build(input: str, expected: str): + """build function should be able to extract from + - sys.version + - sys.implementation.version + """ variant = "createstubs" location = "board" createstubs = import_variant(location, variant) From a1f6df71d88398c3c8b805ef9e47e8ba1edc835e Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 23 Jan 2024 21:48:35 +0100 Subject: [PATCH 42/68] createstubs: Add type information for machine.Pin.cpu.xx and FileIO Signed-off-by: Jos Verlinde --- src/stubber/board/createstubs.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index 25dabbf72..71c910a58 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -210,7 +210,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: module_name, self._fwid, info_, __version__ ) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -331,12 +331,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: From 14f055c0cca05c430a39204cb47c3f41d3cb5edf Mon Sep 17 00:00:00 2001 From: Josverl Date: Tue, 23 Jan 2024 20:50:31 +0000 Subject: [PATCH 43/68] Update mip packages --- mip/v5/createstubs.py | 183 ++++++++++++++------- mip/v5/createstubs_db.py | 183 ++++++++++++++------- mip/v5/createstubs_db_min.py | 183 ++++++++++++++------- mip/v5/createstubs_db_mpy.mpy | Bin 9169 -> 9118 bytes mip/v5/createstubs_lvgl.py | 183 ++++++++++++++------- mip/v5/createstubs_lvgl_min.py | 183 ++++++++++++++------- mip/v5/createstubs_lvgl_mpy.mpy | Bin 8528 -> 8477 bytes mip/v5/createstubs_mem.py | 183 ++++++++++++++------- mip/v5/createstubs_mem_min.py | 183 ++++++++++++++------- mip/v5/createstubs_mem_mpy.mpy | Bin 8586 -> 8535 bytes mip/v5/createstubs_min.py | 183 ++++++++++++++------- mip/v5/createstubs_mpy.mpy | Bin 11250 -> 11199 bytes mip/v6/createstubs.py | 183 ++++++++++++++------- mip/v6/createstubs_db.py | 183 ++++++++++++++------- mip/v6/createstubs_db_min.py | 183 ++++++++++++++------- mip/v6/createstubs_db_mpy.mpy | Bin 8493 -> 8410 bytes mip/v6/createstubs_lvgl.py | 183 ++++++++++++++------- mip/v6/createstubs_lvgl_min.py | 183 ++++++++++++++------- mip/v6/createstubs_lvgl_mpy.mpy | Bin 7991 -> 7923 bytes mip/v6/createstubs_mem.py | 183 ++++++++++++++------- mip/v6/createstubs_mem_min.py | 183 ++++++++++++++------- mip/v6/createstubs_mem_mpy.mpy | Bin 7989 -> 7927 bytes mip/v6/createstubs_min.py | 183 ++++++++++++++------- mip/v6/createstubs_mpy.mpy | Bin 11116 -> 11052 bytes src/stubber/board/createstubs_db.py | 183 ++++++++++++++------- src/stubber/board/createstubs_db_min.py | 183 ++++++++++++++------- src/stubber/board/createstubs_db_mpy.mpy | Bin 8471 -> 8388 bytes src/stubber/board/createstubs_lvgl.py | 183 ++++++++++++++------- src/stubber/board/createstubs_lvgl_min.py | 183 ++++++++++++++------- src/stubber/board/createstubs_lvgl_mpy.mpy | Bin 7968 -> 7900 bytes src/stubber/board/createstubs_mem.py | 183 ++++++++++++++------- src/stubber/board/createstubs_mem_min.py | 183 ++++++++++++++------- src/stubber/board/createstubs_mem_mpy.mpy | Bin 7967 -> 7905 bytes src/stubber/board/createstubs_min.py | 183 ++++++++++++++------- src/stubber/board/createstubs_mpy.mpy | Bin 11095 -> 11031 bytes 35 files changed, 2760 insertions(+), 1449 deletions(-) diff --git a/mip/v5/createstubs.py b/mip/v5/createstubs.py index 3ae80a57e..71c910a58 100644 --- a/mip/v5/createstubs.py +++ b/mip/v5/createstubs.py @@ -7,6 +7,7 @@ import logging import os import sys +from time import sleep try: from ujson import dumps @@ -23,11 +24,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -45,11 +61,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self.log.info("Port: {}".format(self.info["port"])) self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -98,6 +115,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -137,6 +155,7 @@ def create_all_stubs(self): self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -191,7 +210,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: module_name, self._fwid, info_, __version__ ) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -202,10 +221,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -231,8 +251,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -306,12 +331,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -321,12 +348,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -340,6 +367,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path self.log.info("Clean/remove files in folder: {}".format(path)) @@ -362,6 +390,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() self.log.info( "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) ) @@ -423,13 +452,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -565,56 +600,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v5/createstubs_db.py b/mip/v5/createstubs_db.py index 9ea3a8d12..6904d4caa 100644 --- a/mip/v5/createstubs_db.py +++ b/mip/v5/createstubs_db.py @@ -26,6 +26,7 @@ import logging import os import sys +from time import sleep try: from ujson import dumps @@ -42,11 +43,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -64,11 +80,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self.log.info("Port: {}".format(self.info["port"])) self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -117,6 +134,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -156,6 +174,7 @@ def create_all_stubs(self): self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -208,7 +227,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -219,10 +238,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -248,8 +268,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -321,12 +346,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -336,12 +363,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -355,6 +382,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path self.log.info("Clean/remove files in folder: {}".format(path)) @@ -377,6 +405,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) self.log.info("Report file: {}".format(f_name)) @@ -436,13 +465,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -576,56 +611,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v5/createstubs_db_min.py b/mip/v5/createstubs_db_min.py index 1c40ecbed..05817f711 100644 --- a/mip/v5/createstubs_db_min.py +++ b/mip/v5/createstubs_db_min.py @@ -26,6 +26,7 @@ # import logging import os import sys +from time import sleep try: from ujson import dumps @@ -42,11 +43,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -64,11 +80,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore # self.log.info("Port: {}".format(self.info["port"])) # self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -117,6 +134,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + # self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -156,6 +174,7 @@ def create_all_stubs(self): # self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -208,7 +227,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -219,10 +238,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] pass - try: - del sys.modules[module_name] - except KeyError: - pass + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + pass gc.collect() return True @@ -248,8 +268,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - # self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + # self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -321,12 +346,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # self.log.debug("\n" + s) else: @@ -336,12 +363,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -355,6 +382,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path # self.log.info("Clean/remove files in folder: {}".format(path)) @@ -377,6 +405,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() # self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) # self.log.info("Report file: {}".format(f_name)) @@ -436,13 +465,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -576,56 +611,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: # print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# # print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v5/createstubs_db_mpy.mpy b/mip/v5/createstubs_db_mpy.mpy index 877627e9053ab64ba4a581ba88fe4063614e42d8..78198f80d54528a032aa6b2ca48b947fd968d51b 100644 GIT binary patch delta 1686 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 bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -204,10 +223,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -233,8 +253,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -306,12 +331,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -321,12 +348,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -340,6 +367,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path self.log.info("Clean/remove files in folder: {}".format(path)) @@ -362,6 +390,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) self.log.info("Report file: {}".format(f_name)) @@ -421,13 +450,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -561,56 +596,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v5/createstubs_lvgl_min.py b/mip/v5/createstubs_lvgl_min.py index d3b5468e3..cdab9a5ad 100644 --- a/mip/v5/createstubs_lvgl_min.py +++ b/mip/v5/createstubs_lvgl_min.py @@ -11,6 +11,7 @@ # import logging import os import sys +from time import sleep try: from ujson import dumps @@ -27,11 +28,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -49,11 +65,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore # self.log.info("Port: {}".format(self.info["port"])) # self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -102,6 +119,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + # self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -141,6 +159,7 @@ def create_all_stubs(self): # self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -193,7 +212,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -204,10 +223,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] pass - try: - del sys.modules[module_name] - except KeyError: - pass + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + pass gc.collect() return True @@ -233,8 +253,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - # self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + # self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -306,12 +331,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # self.log.debug("\n" + s) else: @@ -321,12 +348,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -340,6 +367,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path # self.log.info("Clean/remove files in folder: {}".format(path)) @@ -362,6 +390,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() # self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) # self.log.info("Report file: {}".format(f_name)) @@ -421,13 +450,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -561,56 +596,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: # print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# # print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v5/createstubs_lvgl_mpy.mpy b/mip/v5/createstubs_lvgl_mpy.mpy index 76d37d58bf8e18972aa1a79c88f2fdceba6fd87d..120b0c085dbd43f311bb9abd65c98e496267d51b 100644 GIT binary patch delta 1599 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 diff --git a/mip/v5/createstubs_mem.py b/mip/v5/createstubs_mem.py index 34cd9f060..81164f7d6 100644 --- a/mip/v5/createstubs_mem.py +++ b/mip/v5/createstubs_mem.py @@ -17,6 +17,7 @@ import logging import os import sys +from time import sleep try: from ujson import dumps @@ -33,11 +34,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -55,11 +71,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self.log.info("Port: {}".format(self.info["port"])) self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -108,6 +125,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -147,6 +165,7 @@ def create_all_stubs(self): self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -199,7 +218,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -210,10 +229,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -239,8 +259,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -312,12 +337,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -327,12 +354,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -346,6 +373,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path self.log.info("Clean/remove files in folder: {}".format(path)) @@ -368,6 +396,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) self.log.info("Report file: {}".format(f_name)) @@ -427,13 +456,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -567,56 +602,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v5/createstubs_mem_min.py b/mip/v5/createstubs_mem_min.py index f7fb6c093..d610d52be 100644 --- a/mip/v5/createstubs_mem_min.py +++ b/mip/v5/createstubs_mem_min.py @@ -17,6 +17,7 @@ # import logging import os import sys +from time import sleep try: from ujson import dumps @@ -33,11 +34,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -55,11 +71,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore # self.log.info("Port: {}".format(self.info["port"])) # self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -108,6 +125,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + # self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -147,6 +165,7 @@ def create_all_stubs(self): # self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -199,7 +218,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -210,10 +229,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] pass - try: - del sys.modules[module_name] - except KeyError: - pass + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + pass gc.collect() return True @@ -239,8 +259,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - # self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + # self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -312,12 +337,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # self.log.debug("\n" + s) else: @@ -327,12 +354,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -346,6 +373,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path # self.log.info("Clean/remove files in folder: {}".format(path)) @@ -368,6 +396,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() # self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) # self.log.info("Report file: {}".format(f_name)) @@ -427,13 +456,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -567,56 +602,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: # print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# # print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v5/createstubs_mem_mpy.mpy b/mip/v5/createstubs_mem_mpy.mpy index 8a60fad97f3c0fac1a0681c9b4c4550a5ec0682c..14b67b80ca1335bbcaa7a173341cf8ca24de299a 100644 GIT binary patch delta 1599 zcmZWpZ%i9y7=PdXfwn;V_U?LRbij=}y8fk5pk)7CS2{<>m>n%lgmEkFbu=q2w#T21 zHM>Pfgl!S>W@_9AiBXsN#ji#|u=u;~indJ+vc?GE48P5qZQOJu^WBHcJbCRLQW(%{?C_55lN1|+4 zWX>|_kd@=a>$3~=08H_rhr8bkD6!?i)d_0vA zb}DH&WP}}nu9!)PM;UO^2&_K_&C*cR3z3GGOF9%Z+&ZB=3c)EOq%=uENcg}Irr@dJ zs8@mX5gFK+kSm|`D(N~Qlb^~7d@`F(2sy8cuI9(4Qt54FfDRaGucUX%T_*UkY%G_^#3qE&Z;*r|lR&=(V;cuoT)+s-G@y}^26bLQZ=pI7 z2hgR}L$%}vaty%Ye5=OqQC`{SU+P@23Cx0Kfn4-0URcsCnwLx^x6%U5>2D+$2F7~n z1-7v{8nmYDcCODej7L>h$Ga$fJey7naZzrVD04)0$iFbLDiPQ# z70D`8os3PS(&q*c$Uh2NBvwU%XrxFgy8s1VM+&zO7Hca5NMhB`66!Ab3rfO(52-`2 zy>waq6Wp<_Qz`FfyPcig?09LmG6FTv0pW+5G599-Xxrp_OlyJHaY5S!-^F*d-dE;T zgI1`OZrDRjp}-z{6FXqFgJ<}k%ePh}_dE_Nq;Oo0+Mh)T%@sUz1=(XVydv4TMuAI6 z(SksQPvKK+5N67Zy}CZ@(#vlck5-zcPfwq=wjDp#GttDlru@m>eFxiY_V8$wwYn32 zru3mM0%09~T4m7_kaEk!^~Y7RC~o{hbw4+f%w;DSo=;ARWxMc9YGN{*6PZ{hlNDp4 z?2fz+uT&4$T@#<0t|>^j^gCk@jrDRz`XX#^H)G5Cv9iWR&E%RrXZ>M75>-@HSsWQS z?x|^o2k^O?O>OED0rqhuLt#6H> zd2rc-zcM=D1pd?5=?X8AExLGGh-E65ry0BTFzaaPvs#_(AZr`kCMP~j%s?Z)N3=R8 zmq=T6PAHRUTE5DJj@!H4wkEry*?AriCdwppgp6APS7AgxQPwZNhyNni;Yau`<%S>Q zpD70{VT0)aJc#>D@6=wfbN`NT&GJKz+vBovt|lAj!%t1zp<)ElL~t;? z;Z+ctW1&E#1MZd0J(17DsP zIdvyUNp~plwmko+YOsG}NWKEHrPeRr>eiLpe{i?_!}2=PlsBFxA>`xfLwXarI*Oh3 zOl^6;wTQFgYl#Gh&Ilr(%VtI8>J7ZBp%w1J{S6V7#jv`LZ#J~zr)LoQTU|vOXCOdA5j^{%K!iX delta 1654 zcmZ8hTTB~A6rEYyU>gj>?s`dhTHeL+1F++mMT8`xW+@Ot3fPcRKo;0bV#Q!;o4lmT zi-J`_k`^**(l#IEqYtI3ngx@DpQ>$M?O!WJYKj`ts#2?}KW$LI`cZWpXc}d{=AJuq z=bpLe-Ut5q*5+;U5PVZt zj%T<`VdhLG|6Ez7e9`Y&eEllUz>&0qjLDcRPdQ<^J{6siD>NJ&40<6d3Xo`Ha>7S( z&`WV;@?>&4A&17}v51`TYPiDC*mN`&@oG6^C^|VF_v$$Agq%o5(RHko+EMI)iUqP?2;`ReTJTEn46wA z&T;c>_7hDxvaD)oGIO;EB$9YVJ|fFEfu827M6;dm@2hf_GM<3z8bGWn=* zd~_ljJKc{!a$RB+Udw`DKxH(IK;5D9BZb#J188UizOU*n|(8hDtB(`^WqaWp*nMEsoByE}^|Uz<0GC!M9DdI}>g0 z<1IZsRx4lY0SsNh7LX7tD$|HHMILCwzM@S--wX|!1;)Z)ckz&*+9q`#e)?49Dcr$^3;Oi>-}!)_2=%E`ETw4**=n zoP;KPiSh6q^Ng)9Ay35+DvCv&MA>AQMTDXbV4Pe%I_=$lyop8Y%W= za~-^h@0y+P68_V?pNOTNdzYDVlx_EmY2lh6G&NOw@lTwvA8DH{>V{OTs4Q4Sa7LtN z`u$K*zaTb7)Cux+MO!|qPK3nA{eLoz+e$5PEjwPy>!26USG1?Szy;J$S0VV42A7w8 z(9QZEr-?d&?sfDx^gP#!nx!V|A&1*(dr7LbIwf~tpRED(-11Vi{!phs;De#AAh=C) zM5#GI?en?2I_Fk{2 zwhr9$YZWpQ?$OUQzq*>e;nPY6rSH}tS$?9OtLc?iX*<4dJ2W!pf?8CR7oM6X*pdh~ zS2v^zg}k|lG%C_;gW`)&*}k)?BHe(BATehU&?2B0DPj)L+N0s8^MPo(Hw>UYH@)-` zIT?<;o8(AGTze})L0ikq<1}9b! zMdoCC7~H+ig0u+k-Do9b0?LhChE%QiUtUjaqUf2eG++7Z>zm8#l3rO;5i`&i&PwIV z&Fs2lR?rcBj&yco%c&vGwL5;G_}@$S4v(x7lrV$@?IG1IG3Js_pj@4DBbG}ZBYF)z z0nbJv0y-+ELWy`h#Vk$YUn@Ou4=$|=Xm=McrSW8yr^FmYMKrl{GIUIiO&ONv@XacL VNcmxv0L6Usu2g>j{{{3Q bool: module_name, self._fwid, info_, __version__ ) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -202,10 +221,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] pass - try: - del sys.modules[module_name] - except KeyError: - pass + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + pass gc.collect() return True @@ -231,8 +251,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - # self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + # self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -306,12 +331,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # self.log.debug("\n" + s) else: @@ -321,12 +348,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -340,6 +367,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path # self.log.info("Clean/remove files in folder: {}".format(path)) @@ -362,6 +390,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() # self.log.info( # "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) # ) @@ -423,13 +452,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -565,56 +600,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: # print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# # print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v5/createstubs_mpy.mpy b/mip/v5/createstubs_mpy.mpy index b778346b504145e2a3d79aadbb7d7088b08b03a1..0bd6b3d252a4b7d0368c0d92b039bfe3b0b9cd2f 100644 GIT binary patch delta 1623 zcmZWpUrbw77(b_fpe;~N@4dZcbikE+DQ%(rDNtk^Sywt4W6W+X5H?0v+S}2rw5+}S z*%)#cAqv9?J1!cHhKH#!#@Maf!X9*UPGgMG#22%N#l)8_YBVA7MWgXt<{pOk;pDsL zJLlft_xpa|Z*%bWps!D>s^V79*Dt6*;m&AAj7VZunjFnGOq@OGJz%#7_)v%+_VdFb zJ|J6mno1A``D`_XTaheB?MbYXI(RmH-s6Y7HyoG?K~7Z=5t2Ml2b zo;V(ItB^5BfQ^b7<)mB9mW!$EWJV0f)5(~aackJ(@aSYB8FOn{LpYI&r`-iCJ0)ha ziF7KQl`;rGCk(a}vO7tYvG8a*l8L1v<6{1INWD-^nll zOcin~UsV(G+Y%0k(ARhzk7!;QYiEqnbTTPMB~mb@aKyBe=$gMozQ%yG2jt2O;rMhS z=G!Ib=ps}ckBldhXZsPz-uGK&Uc-P;Fh{G~0Rvt}DwhZ5$_jl*=CzL#+II2C1Z)wOl;WBHlFAk;kpgul^^!WG=8ZzgL*Z-r}kPTvkM;~RSS zu?5Y54eI5$9X-`Oz79t<-*0n($M~PL?`n?jc;HvbfhdVu9!Chx&Na@?5seXeIlApC z11=y{0|Esel}B}#vM?6xHuTjl55Hd{Rb(|%kZ}>_jz%@4D=xgZ_^2=(&!oq>a5z3GDS8QWiSdbaM&cr= zR9cEiL>^fKzEpg?{PN77=GRrUOMb*TdPaMN?!F-3+r`<_UaTo`G1Hlv#?#&aps6CJ zNa+qijt`bJ!A?9|vZ+s8pulc{<`_I>T<13B8k#S;?^nydha_YGMrcno8Odh3S`YMp zf<2|X;4D5<>YeYD1rq|32&^EAKs`rvElQ{$kVv88=MqV==lMGA13xA6h_H2iLon6Q zw>;W!eTwF@>R%6$WtU+Lwg|EQr@p`Z1VJ`lD{)|Bx;0UNt5qD zEzr!)HqFg8&vCoBS@#^r^IRu4+lmvW5%u2HTKu)i2~XiaOl|dnWxBx-O^T6J;pznE zu~Qgl|(#_0lr!EY64u@8;E)xCD3D(dDvNJDfFj=Ky79 z%!E&*R6^8^Y5He%#p*kkm<{+IzQwrUhxj4mgdbzd+zI#Mfced`^A6#^aW7f@N)S5g z?LvLEUGU()&BDH%!nSIP&|EH)VaPq`(#T}`qhx;#5hgD5e|9yBkZU3%P9?_feNtgX7f$Ki4cb=6LP%nNeJuw^d&imHJI z0i8#cLvSE)*R7&-hkAU$Rv7Nx4?cf-P$)J|njIEr5?LvmZ-xFwnF3RJq#}mbtq1q6 zGk!4V0bd*$K5@g($Tt}92Jr<{G;s9p5P5t=X&dv`x(rIGU*1%HsMwTFaY9{8%tn*@ zjAnX$7&lgMWs2`LNHfxlv6z5PiBdR|PD|?bcX3T+6MO~_R0cKH()FA8qspcoNP(qX p2q7bt9ZOG#$He4>e*F&qtx|yZFkL0X@9}F@1MpG)m#V_ze*qDz&n^G} delta 1683 zcmZ8hT~HHO6ux(pKoSUEc9ZpozcjnXB>W^qSZYy+hIIr11rmZ(oESEXW({ti|3=Yjry1q0F+~3zKK5dq0`Gxt>b;V=R5bF zd%knOb8h!8_cnGIs0#aqgHAanx&Dxo=j%qU zyqRUQh1s{V`O{mnB^Lv}i|4N5EIgc1ky%N|@`wkP7}N0~xm3r(zK|cHq9BPjAgAgm z7Wyf6i#)81rsT+AG7*zgejQsF85oTxVtzeqj>LxtlYRrsj>#z{o*a%S=@bIc1B2W1 z*iw>OEHaRcreedxe(Mo1$UmS)Z|~@+A`IUul}E%WjkHS!0%-Y?wST zWu9cG*xWT;31srOLYC4vV_*fpsxkSf za4I2B2*+1dz%ZUI28o2|qHl!s=XE-tVwrmwK>?Yp$$s z=2~)_j6nz+v0@s49>hjtvB*#|HkyzXgPOs-xdEQR{bs-8 zOn;b%CUv^i(Hhv{c5ppTH<;6y`X!N4J0-I7;@f7MwRX-5CJUuvS>&Zm|H`z%q8(xDkT!oq(PL(f4U=)G#h#pKO$BD4ybfs?Tk!Vm6<1FS7 zzJ|*76q6s>$_P+^eWWO#%r7i+^fEC5Kb&^ux$;{IfXnDIxfz#vpKXP*kFcgewMX}y zdY5F${fQbN7U)B|#+f4g9_@kc_%>Z%=9*%v%u+&*4(HGG*qwVgPfdr@S;>VtR~TSB za{^lMCC10MPcg2-lsuA5rHf~dAF=OuH&?qHZqL@raeyo&Ln1ExjCrivJTrlRvo63% zeA!kFFW`qZ4}2Ftwe2Emsbw!SBknEh4P%-4jOTaksPN-ISbi7MH`=u&af7N^!9@fo z1Ztuu09EZvVq-*&k=hll`KW3E5+D2j$qa7UXovH;_(t9UefUD@-i!}a0xi;32=36} zgSk5BwFaJKh&+Me9QqsjUg|~NY=fiS?e#bhh*b`c=nd|4)`QNweu_4>w+4cBFwzzR zU(xJfJRwKqlW`@j+ucip^tz(MD7!7 z6yEsy;jOtv(WowHhzWN~Ik7~&m0J{TDl)FrBe%5X(-Ggoy#P=HA7^%V^&g%mFkue~ z+(~}E*t|k4g;xG>W&X0tF(T&3DtIOq|p=^ diff --git a/mip/v6/createstubs.py b/mip/v6/createstubs.py index 3ae80a57e..71c910a58 100644 --- a/mip/v6/createstubs.py +++ b/mip/v6/createstubs.py @@ -7,6 +7,7 @@ import logging import os import sys +from time import sleep try: from ujson import dumps @@ -23,11 +24,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -45,11 +61,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self.log.info("Port: {}".format(self.info["port"])) self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -98,6 +115,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -137,6 +155,7 @@ def create_all_stubs(self): self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -191,7 +210,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: module_name, self._fwid, info_, __version__ ) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -202,10 +221,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -231,8 +251,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -306,12 +331,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -321,12 +348,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -340,6 +367,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path self.log.info("Clean/remove files in folder: {}".format(path)) @@ -362,6 +390,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() self.log.info( "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) ) @@ -423,13 +452,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -565,56 +600,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v6/createstubs_db.py b/mip/v6/createstubs_db.py index 9ea3a8d12..6904d4caa 100644 --- a/mip/v6/createstubs_db.py +++ b/mip/v6/createstubs_db.py @@ -26,6 +26,7 @@ import logging import os import sys +from time import sleep try: from ujson import dumps @@ -42,11 +43,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -64,11 +80,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self.log.info("Port: {}".format(self.info["port"])) self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -117,6 +134,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -156,6 +174,7 @@ def create_all_stubs(self): self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -208,7 +227,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -219,10 +238,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -248,8 +268,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -321,12 +346,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -336,12 +363,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -355,6 +382,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path self.log.info("Clean/remove files in folder: {}".format(path)) @@ -377,6 +405,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) self.log.info("Report file: {}".format(f_name)) @@ -436,13 +465,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -576,56 +611,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v6/createstubs_db_min.py b/mip/v6/createstubs_db_min.py index 1c40ecbed..05817f711 100644 --- a/mip/v6/createstubs_db_min.py +++ b/mip/v6/createstubs_db_min.py @@ -26,6 +26,7 @@ # import logging import os import sys +from time import sleep try: from ujson import dumps @@ -42,11 +43,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -64,11 +80,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore # self.log.info("Port: {}".format(self.info["port"])) # self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -117,6 +134,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + # self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -156,6 +174,7 @@ def create_all_stubs(self): # self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -208,7 +227,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -219,10 +238,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] pass - try: - del sys.modules[module_name] - except KeyError: - pass + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + pass gc.collect() return True @@ -248,8 +268,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - # self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + # self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -321,12 +346,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # self.log.debug("\n" + s) else: @@ -336,12 +363,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -355,6 +382,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path # self.log.info("Clean/remove files in folder: {}".format(path)) @@ -377,6 +405,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() # self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) # self.log.info("Report file: {}".format(f_name)) @@ -436,13 +465,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -576,56 +611,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: # print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# # print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v6/createstubs_db_mpy.mpy b/mip/v6/createstubs_db_mpy.mpy index bcb0e20866ea699fc986a1b6cf2d56d56c5bdde0..c1d3ab0c8c833f3d6f9544ed4a1207e82c366b4d 100644 GIT binary patch delta 5090 zcmZuVTWlNIbu&Xfsn_LjJd$PEre{P_eCT0%H1_(jOAkj9MM{wiP+S5{QTr}f~txUSk>7?;>?4~?GJu9Z%WyjIf`kgQ2XVpiMh$d_542iJv#j% zaA+dFwF(La>FTfS6YasA9Jl@=>v zwRj4h1^D#%RD#O?Sw-B?dgAQWnJG&wcJ|urwX2C(%rZH3dFJY@Wqf*iW_Emba%TDi zW4^*TMsMS9cip+Y_m1VD<+kUJMHDSZEVrd}wC0axvR%jQjalluweBQCC!2b0wgF*i zNQn4^$dE8_#WHER;J3E6&V2jEJ^mhh@7BG_kArEh)~O{?xs%>e(NfNrNB#9lR0*@H zmP)=d8bHzFw7NK@PZGQl@HH()-WUzkjG6Gn8`T#L6j8N+s%xp`Yome2B5DYBAkg|E z6v(zEQ3C)_O9S5!H8n^Y#p8HjN0EFqddx#1lf>{QlS$Gs^hpzrbF557k(tM5Qanz; z?=0fbHpHVw)Z{AX@wsCj8f}MV+dT{~dJMeNQ^xQ0l=Csv?4(EcRq*4UO8%UuiofWo z<}Z1S{IsWrzv8Lo=QK|pk1I|1Jle7D>oZ-EDE0HCf0qeMTnpMM(>$Ie<6USsyv!Ck zMHSC|p>%H3MUj$dU&3!TG29+uiIV9kj06x^*U$bfx;cr8hT`?uO;wl{x`82o4VieX zUGz{q8;aBZY9ov1lX58jQESzK?F*`Rq5FPY!g9arp7~?>;|~{%A2lv)yI+;?7T0d) z@x@Tc$&Bs;J=J(X&=xp6cEIT|IsSZzoE((nP8L;wJtlm~Qz-$ZS;tlJw?tYa$Z8%} zfKqT6w1Oj`7CaV;*L@3pmZV2;4W7S=wPc@gc*JKtZ*LQW?&EudqNBfOOc?DtE5M(B z(juJq+gJnFD^unm!nNyaq%`YBxbB}-KZ|dPbrPKbrLg#NNhvNWqcv&lUWv*y;d++g z0-!dwWbd3B%yE}xf@)B%XUw=BNntd&t{xZbImajgB=@H%4kOel(>hg1Z1@U>fM8E- z()VDq>PVLR8nVi?+LsM!9Za~O^sw4Fi7JSQb7Wydv&?W42y;NhWSVaJYgjRhteX-Y z4K#t+Q*YE^5N}#E0l7>QFnto?Z3y!sE1E@4+$Qp_O5odwa1+AY5pEV6MQ~97?SR8J z-3i6hQjYD#EqFdfB|r3v6+Ty&BA!pb->^sfHT`UvYe#25!v5uq`ObzpbXYXT)c>+Pb%M;XH#V!Dksqhw|QtOMX#1DoXb0z zIFqXCuf->ENAmlinOKl5WRqbyJ&wt=Z*R7fQ{3^>rdoVDg_7F$Gxx&rRFe~72cEx^ z{BsLz&Ef&j5r~NgvJ(9t61V`UH)T1>VkZRBUwG~I5m94Dh48yXoR?BX05^UW-{i0&aWvvr{1HGfTp z!|rTOX4V3AMOW#G4#&Y7B^mPZbk#Ra!`Mx@rYe$ar%ziuf`Q%(g5bXDP1ptwceOc& zjt>h~cid~S=R*IgMvI)z$c%ChH5VhH3*o&o z^YXa3qZl9!k6C<1E_?Ne!^{fklDx$h7{KX0kCwBrt}GflaWZ4pz>mb8uqsC)Y9EOx z_@|>;WI$yIONePN+xQ1HlAdSz&XSHs;(s~&-`jq`U=Jv%GF6qTP8m}*$^Ww0{S!g4 zZ*W8iD3-PvZ~AlA9iF>v?YQ6_GMCooN+t`%L6nx9Om{IaUOra)AY32ANgu_6-!AJa zfAy)|{Ij30APiYaMtDEM2V7-fXl2g|I3Io|eagH`YyQOwLijz- zkzbJ+AoOlN#G7(?bXl})zW!uc-1By!1}pzQ#inXo%@zt`$EL^YQJ3Kq348S)lL#xH zp=KL;nEYJrLD*+Q2&-1}hOZCaPd3zJq5x9Kv?vncekvO_Un>J*E19&SpUP#x4&k1+ z{D9rBvDGYE*Hxdgj;)%RL}4!^p)7zunukPbGoj|!ttLIA6jKZ272xJ~Rcxq3qK$0* zq}2plD_mkUzZfC=^IMzc^>(^PqFL)k)Ni@cXa_ z8L^dan&cFOqZ1O1Ny#l?5I+7T4daF!eg<_wqu|qt48RPDSw0%iwS! z8%JGV0d^4}Ah{AUPkk3$&b7+izpKWhK{ZSK+ypq9pEDX zRR?(eh>hv|x}gH2?uhn(Iz0a*0uQ`G2qby~+CU;%kKzYKl2);%kjX96|kmu&7^oA07Dv=n+Lh%^7qg5_E4k8;fnHavTvvP1 zKn4Xtuwv^wM|O^qhkB7bp-v5fxng9DhW|wcLKuX8sSc7sh~#blNzE6{&r?9%3 zWbrOCk~I2d2#ugobPR=21dXBhQ4}3VUw73!Uif|Z)r#7)l0olA&s~swx6^?*?sWR^cI?tRGk3$AzXk87@$gZ-J6t-YcZW3v=ue={gSK#A{2M3!hjxzR zdVGB;(IvS2c9%nR2yMPNIPIY@^c!)Kqlse;uX-pJpOffV@Zj23nq)8Lp^l!1#F$43 z=zXf7>pm+}&qF7)lMmIl4$32(W(nsv3(N+ z>yG~sb*AOqQpO@U2W&^FlSuLiT9m#L@4911QM4uW>L%@^A6-Qspjk;v(NEbc=4%D$Y*}#HTcz{#L`O)g8;buamtjM5OJDQ| z&PxI7C0}n}s}Sh4*`4lox7g>jCoF<+rQa^M?;ck>jLFcBny3DHFoal*u1ic|WEDOf z==ZE4s5At61E9mJq>bK=ZnE06L`f-XE$8dabGP)nVkOuz>Za^QKU^_kg+%uqDrAX0 zA*bAy!SF6HFQgUH2^X)IbITG9ty5?jC_aR2+{HY9@yKd?7*Whn`SfUQJqW0y@nif`k z2vZVmHLgU8N5nMvU<=4hikE?NtUMuIU71d&x6B}v@-5A3RKuDF)^WI8h7IyfTAsrd zz$OHDsiqM`?ozlT!?~y|+@?rN!{Jjh1<7Y`PQOjz8^sG(#-aNy>S7A3(Ed}uQuh&p zj`+e2%(mgmotX}+U2wN|+V;8a!#1nk1@ujKAdaACm@4>BfZSQpxCyErTqV`7CcCLm zqq(o@-L{q|dWW!^0~>+DNAt-r!d1Ug18^aO>j5dGN>fRf-eW1EeDZYwuG#u0CFOwz aguW3p=puJJ7T+;(*eKS*veKeZ{C@$77rHh8 delta 5165 zcmZ`-TTmNWdhTv<6&N42ng-k0h;FqcBw;|vjc>DqTMY=w3=*=0AwY=tUG=lthC=lqxNzZ^c_^HZg~zl>_stu6P<8}E07@Bf9j+I;c!*w{I$VsiY< z*!>q;Rmmbxsm#xr?=bjUCTY5p|7X(=>CCrFf0Su08@8E8$1bKWQ0Vyh z>9L7pXT~W0;)$~tCWnh;d?x?BvXqJ5k#8~&(V6>IcU#9Nj-TC{x_F8DbGvtvPS^K1 zdW3-iArTM~1Crg|diuMkZu7URZ@+uH{Jo90H)RH@-JQXjG%9t|o5~tW`O;(vC5zMY z;*>s2)+=DWvY~>nNQSD0EI9Q_4P<^?ZPn_ElL6Rc2A1juGjC3Y=)-6ok4JSLkHP0S zszK`!LKeh&N_qTt8d-srYq0Xx!bNbAHzF*Cced2!XHAsn~rsq@<)7S z{Bd77f6`aMPxvbNvpzF_-dDv>`l|V>J`Jv^vfvY_ZYj`fneoS}}{-;;3&)jfpj! z6eEOmr(Rr+itGOm2@b)WvAH&<4(7NJYLaQSHy72mGVy}a&7SmA1rc#l4i4gFM&nWl z*8vlgt-l_uVjFX)X~j<`L-j)}KJ!YABw0KmT7X}s2^m0!>k-}{vZ7Vw#9EQ}l!K%j z5#EGw1HzldIZ7J-AV)bS8bOOAL706)`9bJ9gQ!oXaAuJps)4Z~afb49uRe1^m8 zX5kvRqj*{7r)ZP5PTasrv$;9h1R#w@U$`m`hql12H(#lV7k$;N6@yXO3If#PB7Io- z?oC!N^HDQ?8exx*_UrWgnrriJCdKF#ebx8~Zco1t78(w-gf@s_9ca(Ba*8)~ z)KZO)>1!*u`*4y^5xJ9SZA9Xoh zt5*`n;c!(U%V7pwm{dBVsc!}o4$Oc*%F{m#3PHv16oi=MB#79!tSXTd8EqjWJAh*= zCuObIbAXc?0uz~8(JjojrO~+8Pe^oD>A_ zg|0Ej-ra4k=7EC|LGp@1Omxmff1@Ug2am}N!fh)Ha1-D!zcR0cX28*aT`j(VnsUo( zh%h#x8ks3X7lS;DCv(v#!tMT&MNm~Epnn=#2d;rE*`17}01s><_yF*GZ3bbVpXm)h zW3dRTu>hi!xDf&T3Hmz__RGw3aZ@oUtdCecDwn)?$lS-sl%?yV=g1|pDW zJgwF>XstRgngTH!XJopKdG`E~+6&S92#oM>IDEULt@OobPV3MAZVut?2=736C&Ift zCE#eKX$~-mcgqxvYbC3=Wl8-Iv-r|10on1}fB0OzgAxCWImjni+a=T8b;j@w7_Ecj zzJc(Y2zPl*%YXlgs=}$i5E~(G=KfYTz5GOteL9Qqo|P|O=D?Jn5)iK3TpJRj<~~MP z;iUYW%m8CxsvtrZNH-4hCx>jSi+9(LFW+R|gkLd`>3+g|n5$^sa z;vMKg`d4Z1C=+R4O@ekPZ|bqEK) ze&0(B#*miOfU*c95~Y2zMyo%7$=#cfQ5_bD( z(5~BI5uJwU7RmZpE`4p?L&UhEi<2a)OcON1bark5aB&3JK>z@K; zDF0wqHYFpAN-NCvll5ZE*FwONWb^OOiiUfohK&-bxr^m7n)=pur2!`(h}Td3se7lp zQF0RpAe@9V$cQcV(r^=t@PQFOjY(l%T|xNZYaYf6p*M=!N6-d<#sP#6{lDCz2l6De zN_tneqyZ0+t97JXraltg`2ZwNa{JoJkQ#s!w+RUEH)Q;Nas9ACzgK~$7@_g{)Q@a- zvDpz7-th?gTK1)f3iHZ;r?Z?5HO+uqbJ`c`zov8PCAB-7jw?OcXf6P1ECkKOk6^6D zP=C=?i|MC*J0DoZbezRwOX`HdVJGGc2}O0RJ|}EmSF@`*BX8)|%-%}K)myEtsBHxC#0Na`k*|&sp!?Cb z5hSBdLfB5ec95@~;GQR0w2jnq$dGCf?S@%G86h5g>Q?rn9e+gKp(u#Yq8*740*{=7mMU{~W3^Gy*&|s}L5q!PFoG1a*+ir`!LD|< zx8g)*UjjbyKxB=ouTqr*sNJ}b?0E}TORR>DzJ$_c#1FZS#TUOyJfMCY@k{F24Z!Lb zO_1xxz&wVk^E1|7SkG+Uv`uSExXQZXkZM8X6eKS*?Q2X?*_SR-p z!yV2XZrGxEv$x_aUjnvi9NA+unA5wA2D7RFZ4dN`&{=k*{-or;=(Z!6#h0fQA?)I;FPAypLk>+kWU6dluM!?0kp3vG7U`# zoVPej0BziwLZhUPkohVKNoDF<)h}S^2LT{@S2R#>Tk7tWKa}h~4(eUOSMj^khiu|0 zn?n@efcTbrB*iUC0^%2q?Ef}>4a&xD%kj!$3fJntlkClS2cExplv`4J z!Ks~z!Bk#NJjySrQ5488uMt~QbBjus@;4fkiCMMRP+>3?Nqv(VZ8$l7*(SL6I)qli z)$a;c0-R4}qMNM^HBX>T%@(rgG&)0?TTkh5*j5OxBUv<)-rTr;0$-iJE3^oEixo2S z*PENPv(q22CEPh|BrM`mraPMYv)x%XdUg8aZoz#zB%KcQ^xB0`tHbGTY4M7^9(cnG z!i7F(XG`NTwbh)CZmN6|tO1vZmFQhRQy82N)fFql0O{R(|lc9qAR|6z3rcemP$7&F^o3uCt4KDH1l6fvsR1=p1A{#(%Qm)H6Y3?y; z^C}EJcy}2Mh?3DX$*d-Pu#dx)GUcc9_1FYAo8h7;JTB`85qVtV_UT`Hs2n^mNz=yR zVVQzd+CF1EFY%S)3v~M5i~vGyOksWor1?VaAPiem--drjxNy~m>Hlyz1#e5Mqoc(c zaX4Ha;6DP7dPow(;fX@$u x9O3FOpiqM;;T1(10;P^vDf44noqb9p^gs;td5pI$i!~0{h}FQgYRPEoe*qJ!-P-^F diff --git a/mip/v6/createstubs_lvgl.py b/mip/v6/createstubs_lvgl.py index 52a2375ea..58b23e701 100644 --- a/mip/v6/createstubs_lvgl.py +++ b/mip/v6/createstubs_lvgl.py @@ -11,6 +11,7 @@ import logging import os import sys +from time import sleep try: from ujson import dumps @@ -27,11 +28,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -49,11 +65,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self.log.info("Port: {}".format(self.info["port"])) self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -102,6 +119,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -141,6 +159,7 @@ def create_all_stubs(self): self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -193,7 +212,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -204,10 +223,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -233,8 +253,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -306,12 +331,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -321,12 +348,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -340,6 +367,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path self.log.info("Clean/remove files in folder: {}".format(path)) @@ -362,6 +390,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) self.log.info("Report file: {}".format(f_name)) @@ -421,13 +450,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -561,56 +596,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v6/createstubs_lvgl_min.py b/mip/v6/createstubs_lvgl_min.py index d3b5468e3..cdab9a5ad 100644 --- a/mip/v6/createstubs_lvgl_min.py +++ b/mip/v6/createstubs_lvgl_min.py @@ -11,6 +11,7 @@ # import logging import os import sys +from time import sleep try: from ujson import dumps @@ -27,11 +28,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -49,11 +65,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore # self.log.info("Port: {}".format(self.info["port"])) # self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -102,6 +119,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + # self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -141,6 +159,7 @@ def create_all_stubs(self): # self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -193,7 +212,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -204,10 +223,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] pass - try: - del sys.modules[module_name] - except KeyError: - pass + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + pass gc.collect() return True @@ -233,8 +253,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - # self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + # self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -306,12 +331,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # self.log.debug("\n" + s) else: @@ -321,12 +348,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -340,6 +367,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path # self.log.info("Clean/remove files in folder: {}".format(path)) @@ -362,6 +390,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() # self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) # self.log.info("Report file: {}".format(f_name)) @@ -421,13 +450,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -561,56 +596,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: # print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# # print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v6/createstubs_lvgl_mpy.mpy b/mip/v6/createstubs_lvgl_mpy.mpy index a97a8ac879c07a2d2219154a66cb55eb7a28eade..ec7b3c33a489a17a9fa2523fc79525c44229ad54 100644 GIT binary patch delta 4839 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 bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -210,10 +229,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -239,8 +259,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -312,12 +337,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -327,12 +354,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -346,6 +373,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path self.log.info("Clean/remove files in folder: {}".format(path)) @@ -368,6 +396,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) self.log.info("Report file: {}".format(f_name)) @@ -427,13 +456,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -567,56 +602,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v6/createstubs_mem_min.py b/mip/v6/createstubs_mem_min.py index f7fb6c093..d610d52be 100644 --- a/mip/v6/createstubs_mem_min.py +++ b/mip/v6/createstubs_mem_min.py @@ -17,6 +17,7 @@ # import logging import os import sys +from time import sleep try: from ujson import dumps @@ -33,11 +34,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -55,11 +71,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore # self.log.info("Port: {}".format(self.info["port"])) # self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -108,6 +125,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + # self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -147,6 +165,7 @@ def create_all_stubs(self): # self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -199,7 +218,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -210,10 +229,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] pass - try: - del sys.modules[module_name] - except KeyError: - pass + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + pass gc.collect() return True @@ -239,8 +259,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - # self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + # self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -312,12 +337,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # self.log.debug("\n" + s) else: @@ -327,12 +354,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -346,6 +373,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path # self.log.info("Clean/remove files in folder: {}".format(path)) @@ -368,6 +396,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() # self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) # self.log.info("Report file: {}".format(f_name)) @@ -427,13 +456,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -567,56 +602,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: # print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# # print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v6/createstubs_mem_mpy.mpy b/mip/v6/createstubs_mem_mpy.mpy index d35e79d5a731cc31d1c6bc5a5b687b0d43526566..520ab82c725f16ef691a08deb58fcb941ca24afd 100644 GIT binary patch delta 4913 zcmZWMZERCncJIB|`Gy=nKTHS#Jn#A22}z9ehL3?U&o9Jr5{Q%7j2VID+2!s%Z zkLPQk3$)$MC_AgJX4OXhGwSw7?KnVKb!SNkAKOmZs$Hp*-KL|e-9IZ;+sRa_RH>_; z`(83bHId?X?m6e)bME=R4-fqJ{*umOW=Gas|6$3Fipv)U1}-wC<3qy(A38d>7avu7 znd*_zivy|QQ|YrqBLhrnisDKK2L?`mc(MM&AK$WM-P{Dj)iY3k@zTJ=(7@HgF7{n^ z`UdAOEh@8cml$$=`tP|v;fOYUwy2BCS_<<;AF-9iT|*;G<)NVq18qm9JIsG-F1~tt zoSFWuIaNu9VG!{nr-lcZ!cg(SBFFK;OQXZ~RBG_b_?1fosg!+a_~PiLar>!}koPe#%;a1C7kWoL+M7CRqU#Nv`GHW9#3U7xU z__5mMEMr{x0GM1^2rSCaPcW-&HFZ7`Ku4ll0r}VD%zI^}2gYtWuA8fi? zIuJ7UZo$2=n2+n(g(hMHs3?#3COh!r8eW{(WAxH!7cpbpo_H;!KTr}x&N7`=YMYc; zN-NWBgh6|d4m1eqM2nEasOm@XiwxUMSTc5%T*@2}-{}s!&bmEPd)=|7sN`*HIV$!v z4vP2}8M2FKBQCy3I3zRHb|Bocnpj&k11b6^HNumNQe}`GK%?+vaLp)wCRa^Ne3KTW zfSKonDB6u*^YyISJ}X?5DXCbwnzIr!1mn=TtR9m#2;Lrw$h@6p1X2PGGOKgNq>XP- zC<@Q~KtG~1uXg8!!{C%zwKX5pc5?9rrG-BeWELc?O7Q0KyfT>+`hk=q6PK&L8mZu= zJUCZ_Y%*GnYNx+YyHLB+5+J+GQZ(BKqyk8#WRZBuDhbjie+i1+0AwSODj*=)q|JUa zqAc{X*J9~u$1Hz{psUH{%;k_2_BSe$c2-Qe_BrYtZdKgTwxi!QW^Z!)nMFVIj3;OE zK{nO?uk6yCP!Fe3`?k59_1a2UQGAj6EKkPsb3yKTWHV2$@MPj)5cLx3fLLXg#9u@= zqTXk}P!A=c<^^i|2#5e=6A&Aa%|NPwYync^tuI+oRq|4y^sPW@>p5I!Un-rr-iF}q zmx^-d<*aaX`s1qY8oKY;t2QVIH>GO9JC~oAi!kbAu~(kbzUX!oc=Zc4@v5zoHxslG zUrr<6AhLbRk8bf~GQi9RSs>d3Y%t3%uK9ho;N#L(4@N_nJ85O0`!kk9XLLne;3ErIbY92#JppheU>o@9p7OBAV#r&+yJ&SHILZ~I#l}1mjX;DZ| zGvBjx5s^wIA7p+qU1_P&(jmKhHuf)S(m3?A%mI;BpP>{C$HMBO5}idKV<>C!XW-1Q zs8P!31VQE&VoQ-tJUN$-#eg`1rX?c-p6lYVP_K)Z&;uCEBeOu9L9Vs^1y5`=r7(K> zHE9df7`fmA;+DCWQjL)z#gBP%Og6oGBoNO$T8)0Ctq9;Xy^rSdxXqM|9q+@FOc)-u zxNDZCl+Q2>GUlNOOhEj=)tgrSQB6cl9#a&kX?Swp$LW=!>1*?Jr~hL7e>Q!>5ii>3 zI=Mk^l3PT}{HNU=>2H@>JG;fGV)u-OrqA(p+QdcY&U2w7*7bPOy`?I#G%Cl>%4{R| z;^kwt6*KrT-u+Rk{fDMT^Q)h`t$*{k^FT0XFwAxWY4DrSvC3QX7;e+>7p?r=PgNCJK9ja% zvdsUrT=e>Mt`u_WS~BT<|dSx!M9`uM2?eb6Quz zt@wSiqV`G{y>l`viB!3t$wjNLl@3Xw3kUp6Hla8m@4PAR-v}DRv8;xbWrS#I?#H5( zCr-_J?-o{7mj!BGJ1lyMF=`DKngc-I^%t+GMbbfi zIDr_9m=I#|a}bMEzl%4vIe3R9Zfw0qcPc=_K+w2&vqOH(yrOnVE?sqt)A~dAVzH#5iOae9RmrSy^;vkNxhMs&+PkY(o ztdm(elT@0qs)Ul*Ov%{Pu)W3M)chE5#S1`M7iUxLmCrCG3s|tZ1tpMA-#_`lS~rQU zbZWxxajK%HuEXi{i9MpbhhOV=c}#c}Q+y#}#opJfg?v@K3C3rwgKG?wj%!Y5Asp_@3o7fpip5Quh+g{#1L_bByH9 z!oxYaDA~27G~ntmr5oj;)Tm2ey@*;3ecJWb>NC13*5chtE$JX*S$68reS3X7oIdIv zAV=^73h^a%EXpwh>FN)%1pB#$EkY*&iG9Pw)nU3GgXVtNhT+r&qMN>bPe1$L;SSo$}V5}y{Ng72UhjktQDlgPih8~^ppp;B;qI7ktV0TDf zS4_O(7kle_Ge;K|mH*A;1P3^$_ieWCb)h|$qMe2TmNL)V_CB<_GjX20zpRc#%F$;Y zYO$zja2$Kl26X=51n=}mo88)OuiZxmraqITpw}h&M3)rEg~L#j27hiv?Z{z|@DrKK z#Fc}&r#Vd3otUX{XvnSTT$GNLi^Lc5X=r={*+`K{6xN6Z=0}j@nx=j&ie9JF>Bj%F z_Bzk>?&^qESy#rJtO4sT2=+q_wQ~)~^ylq<#P5bZ{jeAIQN%m+XFvTpfG&8NgFUpd zzl$nGAcU)g(ob=4a2XMbj)>`qFh!_3A`}5WrORu^&JN89?f(swks-jCJVP0R>Q^z>)7lXR>5G^1=Br;k!rH) zca;-LNY522mM25LBAUYi%wV)b9BP);QDogM6=7E$Kr`uAUYxbIQ#0usaTo3#nr^7s zrk$IM#U2JtFA6ybCOpNVIMJ{4-ZxDcD?=3$<5J18dI&ml(2fcl1Na1$n4~}IdHRbj z5YtjkQ5d>@ts)}=v0tg36o}ETfItHFV^sb;gZ7JS>SBf`0tJKY%NTS+5A;GD5^xmW zgCrb-_x%-*AAA{qHLteJ=iopBjtkz$BGG>L_}-Vde~0rqdVv~HJxXPu1{kzqde=BK zu2N|_u?zYHFGbRo%qdYgp|5GJ$idr*T>7?S&&E{qOuVVV3xaSmz~o}LQQsgogaz#O z=*-)ntA}&9<7!(TGv{`E^*5LGvQCc`tw z8%2M_?e|Jv(GyN%l<$kYd5(qip&EN=MD4yr_hJ(N6h$%3h9fxMKcWZHo)ubC?S!sc*+O2bTSdj1(|^F6 zu01pJiCy$*9WJp!^mKY6Wf&-DW#*|-hA~2DK;v^kcuFH{AqPWnj!u?-bE@6G5ZQq2 zv^6b;dWinGz)o@~8FH|+lWfnYvy;vIc``aPFV>44MkC9~Y$pEQFIA;Gjgzl21#9bb zXe>Pm#TRB4d6O_q^xApXQ(ZkW^TICG`(17BdNVywNyjbaq z+C~xC_)~n$UBH)y()%@cb{U5~9T!4BM^xL`%r8UPvSGW^sntbnJb4!`!DSf7H^@_d z%z9-3)uVm(;+hp&lHIh=#?s#nW%%I4%x^E)2b~_#U03fCT>-Dxy{F6NJk#ppx4>0? zB*+A_3|84me8TE)J@jj;{SVoN$OlHNTSSNErLxr^+j?3iHAH+BWLM!9N=Sx!vluRV jaco%Y^*CbUIXL)r`q?e`Dq1@tCupcKHfIJuvGo4|nFE%V delta 4936 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 diff --git a/mip/v6/createstubs_min.py b/mip/v6/createstubs_min.py index f2fd2cf66..7b134cbf9 100644 --- a/mip/v6/createstubs_min.py +++ b/mip/v6/createstubs_min.py @@ -7,6 +7,7 @@ # import logging import os import sys +from time import sleep try: from ujson import dumps @@ -23,11 +24,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -45,11 +61,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore # self.log.info("Port: {}".format(self.info["port"])) # self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -98,6 +115,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + # self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -137,6 +155,7 @@ def create_all_stubs(self): # self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -191,7 +210,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: module_name, self._fwid, info_, __version__ ) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -202,10 +221,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] pass - try: - del sys.modules[module_name] - except KeyError: - pass + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + pass gc.collect() return True @@ -231,8 +251,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - # self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + # self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -306,12 +331,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # self.log.debug("\n" + s) else: @@ -321,12 +348,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -340,6 +367,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path # self.log.info("Clean/remove files in folder: {}".format(path)) @@ -362,6 +390,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() # self.log.info( # "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) # ) @@ -423,13 +452,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -565,56 +600,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: # print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# # print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/mip/v6/createstubs_mpy.mpy b/mip/v6/createstubs_mpy.mpy index d59f272e75a27dad866b5a34c6fd26e756e6e1a5..db5b7968408be9b32d320122a1162073156cde21 100644 GIT binary patch delta 5260 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 pKnKkdRD2!i4WKuHW`LQ130^wFUoq-Cs delta 5319 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 QfCF3!#sPjx@e@t`FV;g0M*si- diff --git a/src/stubber/board/createstubs_db.py b/src/stubber/board/createstubs_db.py index 9ea3a8d12..6904d4caa 100644 --- a/src/stubber/board/createstubs_db.py +++ b/src/stubber/board/createstubs_db.py @@ -26,6 +26,7 @@ import logging import os import sys +from time import sleep try: from ujson import dumps @@ -42,11 +43,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -64,11 +80,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self.log.info("Port: {}".format(self.info["port"])) self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -117,6 +134,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -156,6 +174,7 @@ def create_all_stubs(self): self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -208,7 +227,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -219,10 +238,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -248,8 +268,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -321,12 +346,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -336,12 +363,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -355,6 +382,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path self.log.info("Clean/remove files in folder: {}".format(path)) @@ -377,6 +405,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) self.log.info("Report file: {}".format(f_name)) @@ -436,13 +465,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -576,56 +611,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/src/stubber/board/createstubs_db_min.py b/src/stubber/board/createstubs_db_min.py index 1c40ecbed..05817f711 100644 --- a/src/stubber/board/createstubs_db_min.py +++ b/src/stubber/board/createstubs_db_min.py @@ -26,6 +26,7 @@ # import logging import os import sys +from time import sleep try: from ujson import dumps @@ -42,11 +43,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -64,11 +80,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore # self.log.info("Port: {}".format(self.info["port"])) # self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -117,6 +134,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + # self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -156,6 +174,7 @@ def create_all_stubs(self): # self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -208,7 +227,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -219,10 +238,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] pass - try: - del sys.modules[module_name] - except KeyError: - pass + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + pass gc.collect() return True @@ -248,8 +268,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - # self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + # self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -321,12 +346,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # self.log.debug("\n" + s) else: @@ -336,12 +363,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -355,6 +382,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path # self.log.info("Clean/remove files in folder: {}".format(path)) @@ -377,6 +405,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() # self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) # self.log.info("Report file: {}".format(f_name)) @@ -436,13 +465,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -576,56 +611,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: # print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# # print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/src/stubber/board/createstubs_db_mpy.mpy b/src/stubber/board/createstubs_db_mpy.mpy index 5a6627742a3cc4240f301602eb0b796c6257ad49..029c6ff35c46c024cccecb00b4c91a26dd06a4a0 100644 GIT binary patch delta 5094 zcmZ`dTTmO>mEFx-V7O{E0t2??ZoMTQmYeo_2Dcgz5)KkrV&pNFL6&W7^RNfw*O=Co z?PP}9sxVPyQ%R)~YAaRy`q2a1IF*M5e$6K9+1kz4hTS3lNU}d$Td6Q#yS0_tb6XHw*fdjhUyIb_%u6UQ5hRCT`^S)9=#h4;fc= zS&g2#M&Uc@e_+0v9xr>qr1bfJFZ&K%R~ej~rt118uOtSB()TKsD=KfCo1@Y~WvmWQ zq4NNr9-m53`M;=)mzhtWzcw>vip9=fpSyl75sR57r)Foa&6&ohr)TEI=O$;SKhWhX zb)$5n@lMy>JNxdM4x8?H?wSO_bj)-|Oh;?~Od{KL%-x)$zFp@|GIX-J&uSgyhlcow zmyZnbgI7(Hrb|AH**x>joA-_P+55NeSA85vb9GKNi7K3QYh_!7u_EfLPogTARku|c ztD=4sElz8SQ+kZxb%3vJ(;0P9f95=`F#&J)T@q(w?c-d29 zyyDRrr#-dCtDZXJyz1Fu#8rBH5w&i3`}J2vO8I%xw_A@zt_|&yXd|8^`-YFDk3U@0ebltr_@Fw`Q(U{# zh%bjiPG)33=&9BNg0{iou>($z$?+FLB<8gH~_^)PhGt@f}}BpC##GT#FZOVKv#$A075uF52uuzio*zXO0-555*psZ5D@H% z_1Ye6RvFH6UqTj%R{FCcwSx&4?_=Ue7WV`l8>5HP47a-9igm)vn2VoP!dlBXl77#YK zS8XZ^ekl{Q1z~GD1M}2N`2@^uFueD&QI_w&%yGD81=s+OBC~WoYE^55ot$GOyDF7| zdxt`=?A2rb-N5z3H%jEyKpk6wK^d%$xOfpskICO!U{mEDDksti+dZ_HqSs0m&gGp< zoJmy=)ZsDQk^C-bCKg}|*<=__k7E+;-Iwj;WOw|mz7C&Fp``lV%>8gY)$Byrffw#3 zzh{E2Sv&|j0x|JmR;2$^1Q!7HrcB3K?1Vu2s~(%J#1F_~0bL=(Er8XcvKWeg`DVnr z04AtNX6!!RCyO?o9}#TZu19>KX;YDdaWZP%RLKxw7w5Yw$=JU?scxYRRbC@s#F3>b=oaBVq>?qXiNe5~|C z@IHpKKZ*suS>9Fg>QkHH?|!n1Fytr+;R6UCbd`hI<-M!miuh3alwtSzmY=Rd*1!iP zy0=Li9fr{kSaby8qX-{!m2Lk04;2L{ek$yNAX)u^RQCFZ%E*sa5PoOt*RQjnrXLZv z+gjKj5`|^IkMO&kBfly!K-iQ1g~6y6>Haarrs~WF69sW&)nfIytLzL3dF5wGgyqjr zixoXg{#@xr*lR@yD;C41w;$e5HkFeC4>Cx!AP`Z0ER}7&mInnhnV8X!rSjKAtlqc9 z`X#m)1j~lvmDLRxk_haB1eAsGM+=Z7t$Nh*+N{^INinTJP62K{SLLQMBv{GTPt1DQ zTK*zQ=*(Ka;XyCTC3hJ*0}$|n0f55G5BX@q$`+TIS+hP|TzU&usu(KAAi^gQ289o~ zDmIm%VADj`TMSR6ir4Z8oZqS!>~90NwJM(`Bf-HrECz`t?grD9)h)rfMb!VRJ5Xft z*|i>o$8iVlSUNb89T^GKtmQ1!=7p%-9ZIW>m1hljVQJpfYqq$E%NGz1uH|BZx^;-L zJY;63AbYa$kAsT__id<)ORC9kQFyz1P_Q`p5#BcP`xF8ptU$~bdZ$DB&tHDUm4k8{4nv09vGljj!_GYx zC$Rv+@4*&i#8$a!l4iir(Fu{pqy(2x2%q``5#xrOehzg{pk3fGQH0-WZYqP~t8gVtrH-aqRYb>Qx z-vyC;s0U^dd4j;u@eKgT8X%+ryab?VfF2)WV;aA1DAA}pqW+&2&^L*|C$AC$k=}$p zkx14n`#_PTm#i&hGw4Vp3rFiG6_4{lGlz~w(7>N88j#;Z$NmI*OqNkg1|5rNg=Q8S zrAvQYY1r`$sfWex(-%a2WRo%?%|+H(l;d8Q$Sy_T8}0EK9WTgw>&ppf)pOSdXU?3Fzu7@TI}?OG`7Gtl%3 zRU1kl8qA;o2vF>S=V4(uN*>B(@`MsK1ZIhmF$(^h0)#LK{i||<3_>K4!ytl=ftP)n z1bu{+wIqvolaWZjR6}SOji8e#j3Q_hy@#Uc6nfuP`*`uU;a96l?`j6U6G5jr$73F= zzj^%8Z}0sEI%Lo)QHU~1cz^`pgkEx@FzVVO+%#kmjd2bFBr}PT{pd__4m~?M5Xr>v znGe<1#=4i!?CW$Ojys!v)w)~l%-joa{TjTS#=+xSo49;NYZGe=(5yhe2mRsx_*YK< zj&_dYdVFI!(Z#!bHkU(i@OEz;obyN+nvXb1*~Ec@YaWWl7eqQ1IJ~}{Alb`#D5@7B zCFW5A8lh@vzt2n5^U!H^?4c5RSah}{k>Rx{d}LWJ&v|{&V?QE0l4{aZ677N}T1_D< zv~Pi6-SG!!&$V4x&X{=Tpq20B?E$N=28@1DqMjC$C)|OE8$!#@J%x;(DP+(jx&t_ zyQ~AYb{lGW%Hnx&xEYbYx1o%a5o8CrOM!&do5}zIq{2_(`f~+ZcKPJ*sZ$%!BWbW6 zFpOO>UR~boN!3i5EP~s|vDk;Mp%2iUsHW(r>{Y|{LNE?4d%JWRZ*(|57K(p^%dnyO z9k5C5d&ZRxT{6^K`_xwtMi6Sy4Us7f zufeYeTD=>B`a+;L0UBHbHL*Li+9ZV6_JJ>DzpL=A410MVxGTvWYIm0$Ob5P+g<6MKh723 zhqf$lxT`|Ul(u>t3rxNWe(I~qa|^2y{i$CM!o$620QzDb`4s@f-ezigqV(qtsv4HP z2vZ_$(XB>`N5nMvUmM6wN>&-?Sbaj;yK;?A>zzR;`Rl4hr-VJQ3_9!z2{y<#t9cGr z0-F$AsG5fnxlrMb4CkV4TsN26r`PfIqgb?Zx(M|8HeVxsEaAA!99TbT-i?u zI^v77n6=}oU6~Gxjd!b!+e(!F{mu$>aOKuDpEO%RnbzoZ-ZLZl7t+p*oFt#itBfuEkHel|?R4O_Qn5oPxvduA@4f|nJm2q~w?1#+9)MlOJLsF?!{;ws& z)NWizdhh@K@BNSW`yY?R-QSa{_Eu8On#K2^s`)`z^ub?v>r9tUPfVPrs;4H;Ogwn0 z)*5%(D9y=Sp%`CbKm9IUgM8;NPF$IsxSIKx@wU~NY*#0zPEaQD4V=3*Lyg&bZ1U{* z=-9cV7sn~)B864POJ#n}e22j|GAYB|!fy>frZeBF_(`U{a@1xTpSYx4q|mX+(-UWp zo|&MyODE1Qtn5*o>9eawzlDI*YolG#P+BCSa*+GI6FMLla?(nXzu-XDE?Q!DzEs=G(E#cRfI*VoLozZ}ql@ z`+?y7z+LBr?QZp5mHlw*hnMf0?s506cdI9YpbB>lHE{S;Eaqn7T@;7cf@PSPhP_}L zCdOeVRx%E^r^%p_!&}Yxw7)6$! zu=$_lFpFV>*eYu#rg-H~p9`_qzM^7h8q!HFR+3|unG+V=cxisHz2$b z;U=*3y9 z8%=dZ6b{m&m;AqKb9a)jpe>6Ab{;SnQ>%dL*(Lq<-*PPQL7~V=Wk*!d4TYmKNy|>H8nB zTBV=L2WW&nembDh^Q%`|a5D;{RrlB7!?-j3ZSc@&lr84c2{0cY5$RB8uH7nml_Tal zd{kr8>bJ9Z5{lO0X0cbJFrEI$24}N)fOrWM#RItj{jUMKA#PTwzM;iYb4xE$P4v+(%XV$6-D!1)Mw|7n}qU80*D4c7FOn^NFHt;z^o<~ zP)lxEju6fkR4+2c*kYJt@l-ArL%1_wTr3B{GhHc?HFc$$;YI+>H}VMk1597^Ig14_ zlm$pB!UhDvKw_Z_;eg1z5H^w!Q7zc=n8o9w@#P~cuABo0l3$?-24MQuN3%KDXH3No zjlf9;fRL~W_T|YzV#!;;nL`F-M7SFUv)WdIt%(vNwm6znc2rhQDU;R&ZyHX3}c4I&Dq*E1NSs78UyT4)GCbI5TST9=Oo6 zqz%x^85RqhvakXG6(g z9KR5nA$sQiPBgswRE~c(i}3E1uU_TAgP##7u6(dMB)-gjg0N(@7v@9;7(*)$@rqcH zniXs-uRfa1LFaSrq_{e|3vaIXU) z+-J8ehaeC4Jz19b2|Q>e(t<#g`aAUMd;Pg>1zwDg-a;dAP# z$qt^9PkIgLAW+5--UC$l*$b&_%)yqnwX&_|L}}|d+4&w)@c_buu=Q8Ox*msFaO$d? z?UpBE#ar(lBF+_DR=eFI(gcMtot;||+E$3~|LcaU(p42UxvE_?Z5Ed)VkzU1#V6f{ zG9+UPjgQO+5gx;xxO2KWo{Pt$Cu-*Nc53-}O4=Gzv|tK~r$$X5wDq*wJpeLG5#iW; zel%LQ00CNntj-iAe@^+Z`o6_|3o7UIxXmu}F7F<}?&jmXGoFL6mm$uJVGEQ(lQC_c$f5i+8zOJy#Ki<4JORo7BR+Z!?5@A*)((vH${x7D;@MM%O+As16q% z&WeWA;G)zHv;AbflmHsaiRa&+m)!YUj_T#pU83`B$s|~eee2q4N2Zt<1_LMGZA^og>`$LP6POx}lNj?)c!Ckdx z&Np(jJ@d^*hiYr%9QfSyoFD`O&8}=Hgg6B`v&-_HEaZD97MXNH+MRuh+E!_8K*KsM z3y}!s$x*`UB|U*Oqz{2ZO#rQ)(26-FfBr`(%lM{?Jl|%w+nw+^Ve`7$Ty2^5^*yS| zTLZawi=`cPj3JJ=l|z2=)inn60NOf+MAS_P+sM~;^0fmz{xplWlF|*SP!6MAFiT2f zgofT(0>U?RLQE&TO9(-o5DX*skS?ziDmUs(s(QXZzgh<-5tQ)@gdspLL!(GE+bxB` zZ={*5Ddw`MJDCIPLZld4W$5covC_ukZW9U6JfCfhCQ{9@BcpWa!&4<%c31gwBKrf%wzR;kMI5d z_V1vD2Cou_$iqYiXaI2?it2(>D@2;UIEW5F)&T}G6B#Lj4wmL3c(f~-Rc^O#uU8Ls z&g|@LZ$tIg5kHlU-3EOFkj9HFz5{wUHJ+?PUFGddSf}WQ*SJ5 zfmeY35IV{((1#oh(>Yyrxs zdL!3U4M5ZJ1?~ALIwI1~9;#o;duL-0K^cO(=MqHgbM{zvw(uxml*2>wDfp8@(wv$P zUH$q2=qO+`VI32xmDy!^coxw6mLk&7T)=UQvjo|?P(?-Kq;wEM8Hc181`hh*m=Y)>Z$!W^nUSY53MIa z|3{&a^ep`dw3%F0qC8QtuF`=QFCXWYnq?o+oh!kC*zVP^q%TEIN(O zkdD?{)z$<{t0kBVjX~%x8YOX_I}`kg)};+_J0Anq;#f|lf?WCV7?V-q}Cy)5?=f|hs+ z&%|@^q>=W$;nu(hC0Y>h>5{prnZFEbHD_#g!5g-+IEpT#E9h!K)##_}l;v7+Pyvl^ zvRJnms=A&}E zDIMEb^E6x!cP7-J_XA9EXg;#8RPzUEpi`;;2vKImr$fp+aq27Y^7QCcc zTnkW6c`2tU+^_El(0#j#IqL@^1y`<$fOjuon?P?h^WiJA0U8>|Ap%iMK_Tg2o;`nL zH$6;BEL`zw-+t>4bLJ<|j20{^d6vB>ANF`Odg|ri=V4O;9$#}J{dvR;`oq()A07|Y zHMm7K6sGn-G`J> z?It;?`eC0H*N9YrE;M2TNH&3>7`!?ghY)#n;?9|0d#D_|J4qX7#iJqxDY!GQzdP}@ z($jS2-}C@O9ZYdP588YwcM*my%C`_^UAT7r%zrwZyw}(6=<+!S91fQU_~Eh7s`&V5 z^h_~)2sFi3XWa0AU^=-KLpI@tFnar_?=B bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -204,10 +223,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -233,8 +253,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -306,12 +331,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -321,12 +348,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -340,6 +367,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path self.log.info("Clean/remove files in folder: {}".format(path)) @@ -362,6 +390,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) self.log.info("Report file: {}".format(f_name)) @@ -421,13 +450,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -561,56 +596,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/src/stubber/board/createstubs_lvgl_min.py b/src/stubber/board/createstubs_lvgl_min.py index d3b5468e3..cdab9a5ad 100644 --- a/src/stubber/board/createstubs_lvgl_min.py +++ b/src/stubber/board/createstubs_lvgl_min.py @@ -11,6 +11,7 @@ # import logging import os import sys +from time import sleep try: from ujson import dumps @@ -27,11 +28,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -49,11 +65,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore # self.log.info("Port: {}".format(self.info["port"])) # self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -102,6 +119,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + # self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -141,6 +159,7 @@ def create_all_stubs(self): # self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -193,7 +212,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -204,10 +223,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] pass - try: - del sys.modules[module_name] - except KeyError: - pass + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + pass gc.collect() return True @@ -233,8 +253,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - # self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + # self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -306,12 +331,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # self.log.debug("\n" + s) else: @@ -321,12 +348,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -340,6 +367,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path # self.log.info("Clean/remove files in folder: {}".format(path)) @@ -362,6 +390,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() # self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) # self.log.info("Report file: {}".format(f_name)) @@ -421,13 +450,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -561,56 +596,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: # print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# # print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/src/stubber/board/createstubs_lvgl_mpy.mpy b/src/stubber/board/createstubs_lvgl_mpy.mpy index ee3c7c6265faa4115a85a9f7fbeac1ee938eb17c..0022ec0e3c6cfbdd92f1fb64b7a901b88a91cf08 100644 GIT binary patch delta 4814 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 bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -210,10 +229,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -239,8 +259,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -312,12 +337,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -327,12 +354,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -346,6 +373,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path self.log.info("Clean/remove files in folder: {}".format(path)) @@ -368,6 +396,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) self.log.info("Report file: {}".format(f_name)) @@ -427,13 +456,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -567,56 +602,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/src/stubber/board/createstubs_mem_min.py b/src/stubber/board/createstubs_mem_min.py index f7fb6c093..d610d52be 100644 --- a/src/stubber/board/createstubs_mem_min.py +++ b/src/stubber/board/createstubs_mem_min.py @@ -17,6 +17,7 @@ # import logging import os import sys +from time import sleep try: from ujson import dumps @@ -33,11 +34,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -55,11 +71,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore # self.log.info("Port: {}".format(self.info["port"])) # self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -108,6 +125,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + # self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -147,6 +165,7 @@ def create_all_stubs(self): # self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -199,7 +218,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -210,10 +229,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] pass - try: - del sys.modules[module_name] - except KeyError: - pass + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + pass gc.collect() return True @@ -239,8 +259,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - # self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + # self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -312,12 +337,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # self.log.debug("\n" + s) else: @@ -327,12 +354,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -346,6 +373,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path # self.log.info("Clean/remove files in folder: {}".format(path)) @@ -368,6 +396,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() # self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) # self.log.info("Report file: {}".format(f_name)) @@ -427,13 +456,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -567,56 +602,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: # print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# # print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/src/stubber/board/createstubs_mem_mpy.mpy b/src/stubber/board/createstubs_mem_mpy.mpy index 3b02097290bcea7935539c50c22be9fe8181fcc1..e3d7d717f16c08dfa0686fb0487791c9954f3bc7 100644 GIT binary patch delta 4856 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 delta 4893 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 diff --git a/src/stubber/board/createstubs_min.py b/src/stubber/board/createstubs_min.py index f2fd2cf66..7b134cbf9 100644 --- a/src/stubber/board/createstubs_min.py +++ b/src/stubber/board/createstubs_min.py @@ -7,6 +7,7 @@ # import logging import os import sys +from time import sleep try: from ujson import dumps @@ -23,11 +24,26 @@ except ImportError: from ucollections import OrderedDict # type: ignore +try: + from nope_machine import WDT + + wdt = WDT() + +except ImportError: + + class _WDT: + def feed(self): + pass + + wdt = _WDT() + + +wdt.feed() + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -45,11 +61,12 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore # self.log.info("Port: {}".format(self.info["port"])) # self.log.info("Board: {}".format(self.info["board"])) gc.collect() + wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -98,6 +115,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + # self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -137,6 +155,7 @@ def create_all_stubs(self): # self.log.info("Finally done") def create_one_stub(self, module_name: str): + wdt.feed() if module_name in self.problematic: # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -191,7 +210,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: module_name, self._fwid, info_, __version__ ) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -202,10 +221,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] pass - try: - del sys.modules[module_name] - except KeyError: - pass + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + pass gc.collect() return True @@ -231,8 +251,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - # self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + # self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -306,12 +331,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # self.log.debug("\n" + s) else: @@ -321,12 +348,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -340,6 +367,7 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" + wdt.feed() if path is None: path = self.path # self.log.info("Clean/remove files in folder: {}".format(path)) @@ -362,6 +390,7 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" + wdt.feed() # self.log.info( # "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) # ) @@ -423,13 +452,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -565,56 +600,78 @@ def version_str(version: tuple): # -> str: def read_boardname(info, desc: str = ""): + info["board"] = info["board"].replace(" ", "_") found = False - for filename in [d + "/board_info.csv" for d in LIBS]: + for filename in [d + "/board_name.txt" for d in LIBS]: + wdt.feed() # # print("look up the board name in the file", filename) if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): + with open(filename, "r") as file: + data = file.read() + if data: + info["board"] = data.strip() found = True break if not found: # print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() + descr = "" + # descr = desc or info["board"].strip() + # if "with " + info["cpu"].upper() in descr: + # # remove the with cpu part + # descr = descr.split("with " + info["cpu"].upper())[0].strip() info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False +# def read_boardname(info, desc: str = ""): +# wdt.feed() +# # # print("look up the board name in the file", filename) +# if file_exists(filename): +# descr = desc or info["board"].strip() +# pos = descr.rfind(" with") +# if pos != -1: +# short_descr = descr[:pos].strip() +# else: +# short_descr = "" +# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) +# if find_board(info, descr, filename, short_descr): +# found = True +# break +# if not found: +# # print("Board not found, guessing board name") +# descr = desc or info["board"].strip() +# if "with " + info["cpu"].upper() in descr: +# # remove the with cpu part +# descr = descr.split("with " + info["cpu"].upper())[0].strip() +# info["board"] = descr +# info["board"] = info["board"].replace(" ", "_") +# gc.collect() + + +# def find_board(info: dict, descr: str, filename: str, short_descr: str): +# "Find the board in the provided board_info.csv file" +# short_hit = "" +# with open(filename, "r") as file: +# # ugly code to make testable in python and micropython +# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) +# while 1: +# line = file.readline() +# if not line: +# break +# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() +# if descr_ == descr: +# info["board"] = board_ +# return True +# elif short_descr and descr_ == short_descr: +# if "with" in short_descr: +# # Good enough - no need to trawl the entire file +# info["board"] = board_ +# return True +# # good enough if not found in the rest of the file (but slow) +# short_hit = board_ +# if short_hit: +# info["board"] = short_hit +# return True +# return False def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/src/stubber/board/createstubs_mpy.mpy b/src/stubber/board/createstubs_mpy.mpy index e75d7e7d4f3de55928a9b7004738db99b4485306..1f7e3a6a872904de4b1c61fd593ebe7438358ca9 100644 GIT binary patch delta 5199 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 CB;8T~ delta 5303 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 Date: Wed, 24 Jan 2024 01:57:40 +0100 Subject: [PATCH 44/68] chore: remove wdt.feed() Signed-off-by: Jos Verlinde --- src/stubber/board/createstubs.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index 71c910a58..0190d87dd 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -24,21 +24,6 @@ except ImportError: from ucollections import OrderedDict # type: ignore -try: - from nope_machine import WDT - - wdt = WDT() - -except ImportError: - - class _WDT: - def feed(self): - pass - - wdt = _WDT() - - -wdt.feed() __version__ = "v1.16.2" ENOENT = 2 @@ -61,7 +46,6 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self.log.info("Port: {}".format(self.info["port"])) self.log.info("Board: {}".format(self.info["board"])) gc.collect() - wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: @@ -155,7 +139,6 @@ def create_all_stubs(self): self.log.info("Finally done") def create_one_stub(self, module_name: str): - wdt.feed() if module_name in self.problematic: self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False @@ -367,7 +350,6 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" - wdt.feed() if path is None: path = self.path self.log.info("Clean/remove files in folder: {}".format(path)) @@ -390,7 +372,6 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" - wdt.feed() self.log.info( "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) ) @@ -603,7 +584,6 @@ def read_boardname(info, desc: str = ""): info["board"] = info["board"].replace(" ", "_") found = False for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() # print("look up the board name in the file", filename) if file_exists(filename): with open(filename, "r") as file: @@ -623,7 +603,6 @@ def read_boardname(info, desc: str = ""): # def read_boardname(info, desc: str = ""): -# wdt.feed() # # print("look up the board name in the file", filename) # if file_exists(filename): # descr = desc or info["board"].strip() From 5589e9eff41bd84cfe0299857672d70e4105f658 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Wed, 24 Jan 2024 23:55:30 +0100 Subject: [PATCH 45/68] board_stubber: determine BOARDNAME on hast and pass to MCU to avoid long delays on fileaccess over mpremote Signed-off-by: Jos Verlinde --- .gitignore | 1 + scripts/board_stubber.py | 155 +++++++++++++++++++------- src/stubber/board/createstubs.py | 84 ++------------ src/stubber/board/createstubs_db.py | 125 ++++++++------------- src/stubber/board/createstubs_lvgl.py | 125 ++++++++------------- src/stubber/board/createstubs_mem.py | 125 ++++++++------------- src/stubber/minify.py | 4 +- src/stubber/update_module_list.py | 2 +- 8 files changed, 274 insertions(+), 347 deletions(-) diff --git a/.gitignore b/.gitignore index 4b6a47857..fe4b87a43 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ snippets/*/typings **/typings_* typings_test typings +.vscode/Pico-W-Stub empty **/*_lock.file diff --git a/scripts/board_stubber.py b/scripts/board_stubber.py index 67133e72a..429ba00fa 100644 --- a/scripts/board_stubber.py +++ b/scripts/board_stubber.py @@ -1,5 +1,5 @@ """ -This script creates stubs for a connected micropython MCU board. +This script creates stubs on and for a connected micropython MCU board. """ import json @@ -14,8 +14,11 @@ from threading import Timer from typing import List, NamedTuple, Optional, Tuple, Union +import rich_click as click import serial.tools.list_ports from loguru import logger as log +from rich.console import Console +from rich.table import Table from tabulate import tabulate from tenacity import retry, stop_after_attempt, wait_fixed @@ -188,18 +191,30 @@ def connected_boards(): @retry(stop=stop_after_attempt(RETRIES), wait=wait_fixed(1)) def get_mcu_info(self): - # switched from uname to sys.implementation as the primary source of info rc, result = self.run_command( ["run", "src/stubber/board/fw_info.py"], no_info=True, ) - if rc == OK: - s = result[0].strip() - if s.startswith("{") and s.endswith("}"): - info = eval(s) - self.version = info["version"] - self.port = info["port"] - self.description = info["board"] + if rc != OK: + raise RuntimeError(f"Failed to get mcu_info for {self.serialport}") + # Ok we have the info, now parse it + s = result[0].strip() + if s.startswith("{") and s.endswith("}"): + info = eval(s) + self.version = info["version"] + self.port = info["port"] + self.description = descr = info["board"] + pos = descr.rfind(" with") + if pos != -1: + short_descr = descr[:pos].strip() + else: + short_descr = "" + if board_name := find_board( + descr, short_descr, Path(__file__).parent.parent / "src/stubber/data/board_info.csv" + ): + self.board = board_name + else: + self.board = "UNKNOWN" def disconnect(self) -> bool: """Disconnect from a board""" @@ -238,7 +253,7 @@ def run_command( """ if isinstance(cmd, str): cmd = cmd.split(" ") - prefix = ["mpremote", "connect", self.serialport] if self.serialport else ["mpremote"] + prefix = [sys.executable, "-m" "mpremote", "connect", self.serialport] if self.serialport else ["mpremote"] # if connected add resume to keep state between commands if self.connected: prefix += ["resume"] @@ -334,7 +349,7 @@ def hard_reset(board: MPRemoteBoard) -> bool: @retry(stop=stop_after_attempt(10), wait=wait_fixed(15)) -def run_createstubs(dest: Path, board: MPRemoteBoard, variant: Variant = Variant.db): +def run_createstubs(dest: Path, mcu: MPRemoteBoard, variant: Variant = Variant.db): """ Run a createstubs[variant] on the provided board. Retry running the command up to 10 times, with a 15 second timeout between retries. @@ -345,22 +360,22 @@ def run_createstubs(dest: Path, board: MPRemoteBoard, variant: Variant = Variant "exec", 'import sys;sys.path.append("/lib") if "/lib" not in sys.path else "/lib already in path"', ] - board.run_command(cmd_path, timeout=5) + mcu.run_command(cmd_path, timeout=5) if reset_before: - log.info(f"Resetting {board.serialport} {board.description}") - board.run_command("reset", timeout=5) + log.info(f"Resetting {mcu.serialport} {mcu.description}") + mcu.run_command("reset", timeout=5) time.sleep(2) - log.info(f"Running createstubs {variant} on {board.serialport} {board.description} using temp path: {dest}") + log.info(f"Running createstubs {variant} on {mcu.serialport} {mcu.description} using temp path: {dest}") cmd = build_cmd(dest, variant) - board.run_command.retry.wait = wait_fixed(15) + mcu.run_command.retry.wait = wait_fixed(15) # some boards need 2-3 minutes to run createstubs - so increase the default timeout # esp32s3 > 240 seconds with mounted fs # but slows down esp8266 restarts so keep that to 60 seconds - timeout = 60 if board.port == "esp8266" else 6 * 60 # type: ignore - rc, out = board.run_command(cmd, timeout=timeout) + timeout = 60 if mcu.port == "esp8266" else 6 * 60 # type: ignore + rc, out = mcu.run_command(cmd, timeout=timeout) # check last line for exception or error and raise that if found if rc != OK and ":" in out[-1] and not out[-1].startswith("INFO") and not out[-1].startswith("WARN"): log.warning(f"createstubs: {out[-1]}") @@ -419,16 +434,14 @@ def generate_board_stubs( log.warning("Error copying createstubs to board") return ERROR, None - if host_mounted: - # HOST: remove .done file - (dest / "modulelist.done").unlink(missing_ok=True) - # HOST: copy board_info.csv to destination - shutil.copyfile(board_info_path, dest / "board_info.csv") + if mcu.board: + cmd = ["exec", f"with open('lib/boardname.py', 'w') as f: f.write('BOARDNAME=\"{mcu.board}\"')"] + log.info(f"Writing BOARDNAME='{mcu.board}' to boardname.py") else: - cmd = f"cp {board_info_path} :board_info.csv" - rc, _ = board.run_command(cmd) - if rc != OK and "rm" not in cmd: - log.error(f"Error during copy createstubs running command: {cmd}") + cmd = ["rm", "boardname.py"] + rc, _ = mcu.run_command(cmd) + if rc != OK and not "rm" in cmd: + log.error(f"Error during copy createstubs running command: {cmd}") rc, out = run_createstubs(dest, mcu, variant) # , host_mounted=host_mounted) @@ -447,7 +460,7 @@ def generate_board_stubs( stubs_path = dest / folder mcu.path = stubs_path - # read the modles.json file into a dict + # read the modules.json file into a dict try: with open(stubs_path / "modules.json") as fp: modules_json = json.load(fp) @@ -470,13 +483,6 @@ def get_stubfolder(out: List[str]): return lines[-1].split("/remote/")[-1].strip() if (lines := [l for l in out if l.startswith("Path: ")]) else "" -# def get_port_board(out: List[str]): -# return ( -# lines[-1].split("Port:")[-1].strip() if (lines := [l for l in out if l.startswith("Port: ")]) else "", -# lines[-1].split("Board:")[-1].strip() if (lines := [l for l in out if l.startswith("Board: ")]) else "", -# ) - - def scan_boards(optimistic: bool = False) -> List[MPRemoteBoard]: """ This function scans for boards and returns a list of MPRemoteBoard objects. @@ -536,11 +542,57 @@ def copy_to_repo(source: Path, fw: dict) -> Optional[Path]: return None -if __name__ == "__main__": - set_loglevel(0) +def find_board(descr: str, short_descr: str, filename: Path) -> Optional[str]: + "Find the board in the provided board_info.csv file" + short_hit = "" + with open(filename, "r") as file: + # ugly code to make testable in python and micropython + # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) + while 1: + line = file.readline() + if not line: + break + descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() + if descr_ == descr: + return board_ + elif short_descr and descr_ == short_descr: + if "with" in short_descr: + # Good enough - no need to trawl the entire file + # info["board"] = board_ + return board_ + # good enough if not found in the rest of the file (but slow) + short_hit = board_ + if short_hit: + return short_hit + return None + + +@click.command() +@click.option( + "--variant", + "-v", + type=click.Choice(["Full", "Mem", "DB"], case_sensitive=False), + default="Full", + show_default=True, + help="Variant of createstubs to run", +) +@click.option( + "--format", + "-f", + type=click.Choice(["py", "mpy"], case_sensitive=False), + default="py", + show_default=True, + help="Python source or pre-compiled.", +) +@click.option("--debug/--no-debug", default=False, show_default=True, help="Debug mode.") +def run_stubber(variant: str, format: str, debug: bool): + if debug: + set_loglevel(1) + else: + set_loglevel(0) + variant = Variant(variant.lower()) + form = Form(format.lower()) - variant = Variant.full - form = Form.py # BUG : Minified geeft problemen ? tempdir = mkdtemp(prefix="board_stubber") dest = Path(tempdir) @@ -551,11 +603,23 @@ def copy_to_repo(source: Path, fw: dict) -> Optional[Path]: log.error("No micropython boards were found") sys.exit(1) - print(tabulate([[b.serialport, b.port, b.description, b.version] for b in connected_boards])) # type: ignore - # scan boards and generate stubs + table = Table(show_header=True, header_style="bold magenta") + table.add_column("Serial Port") + table.add_column("Port") + table.add_column("Description") + table.add_column("Version") + + for b in connected_boards: + table.add_row(b.serialport, b.port, b.description, b.version) + console = Console() + console.print(table) + # scan boards and generate stubs for board in connected_boards: - log.info(f"Connecting to {board.serialport} {board.description} {board.version}") + log.info( + f"Connecting using {board.serialport} to {board.port} {board.board} {board.version}: {board.description}" + ) + rc, my_stubs = generate_board_stubs(dest, board, variant, form) if rc == OK and my_stubs: log.success(f'Stubs generated for {board.firmware["port"]}-{board.firmware["board"]}') @@ -582,7 +646,12 @@ def copy_to_repo(source: Path, fw: dict) -> Optional[Path]: boards=board.firmware["board"], ports=board.firmware["port"], ) - + # create a rich table of the results and print it' + console.print(table) log.success("Done") else: log.error(f"Failed to generate stubs for {board.serialport}") + + +if __name__ == "__main__": + run_stubber() diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index 0190d87dd..b9aff753c 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -490,9 +490,7 @@ def _info(): # type:() -> dict[str, str] ) except (AttributeError, IndexError): pass - gc.collect() - read_boardname(info) - gc.collect() + info["board"] = get_boardname() try: if "uname" in dir(os): # old @@ -580,77 +578,15 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.info("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/src/stubber/board/createstubs_db.py b/src/stubber/board/createstubs_db.py index 9ea3a8d12..96557273f 100644 --- a/src/stubber/board/createstubs_db.py +++ b/src/stubber/board/createstubs_db.py @@ -26,6 +26,7 @@ import logging import os import sys +from time import sleep try: from ujson import dumps @@ -42,11 +43,11 @@ except ImportError: from ucollections import OrderedDict # type: ignore + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -68,7 +69,7 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -117,6 +118,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -208,7 +210,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -219,10 +221,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -248,8 +251,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -321,12 +329,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -336,12 +346,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -436,13 +446,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -485,9 +501,7 @@ def _info(): # type:() -> dict[str, str] ) except (AttributeError, IndexError): pass - gc.collect() - read_boardname(info) - gc.collect() + info["board"] = get_boardname() try: if "uname" in dir(os): # old @@ -575,57 +589,16 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - found = False - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): - found = True - break - if not found: - print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() - +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.info("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/src/stubber/board/createstubs_lvgl.py b/src/stubber/board/createstubs_lvgl.py index 52a2375ea..8b6319925 100644 --- a/src/stubber/board/createstubs_lvgl.py +++ b/src/stubber/board/createstubs_lvgl.py @@ -11,6 +11,7 @@ import logging import os import sys +from time import sleep try: from ujson import dumps @@ -27,11 +28,11 @@ except ImportError: from ucollections import OrderedDict # type: ignore + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -53,7 +54,7 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -102,6 +103,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -193,7 +195,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -204,10 +206,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -233,8 +236,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -306,12 +314,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -321,12 +331,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -421,13 +431,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -470,9 +486,7 @@ def _info(): # type:() -> dict[str, str] ) except (AttributeError, IndexError): pass - gc.collect() - read_boardname(info) - gc.collect() + info["board"] = get_boardname() try: if "uname" in dir(os): # old @@ -560,57 +574,16 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - found = False - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): - found = True - break - if not found: - print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() - +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.info("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/src/stubber/board/createstubs_mem.py b/src/stubber/board/createstubs_mem.py index 34cd9f060..f21a4dfbc 100644 --- a/src/stubber/board/createstubs_mem.py +++ b/src/stubber/board/createstubs_mem.py @@ -17,6 +17,7 @@ import logging import os import sys +from time import sleep try: from ujson import dumps @@ -33,11 +34,11 @@ except ImportError: from ucollections import OrderedDict # type: ignore + __version__ = "v1.16.2" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep class Stubber: @@ -59,7 +60,7 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore self._fwid = firmware_id.lower() else: if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) + self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") else: self._fwid = "{family}-v{version}-{port}".format(**self.info) self._start_free = gc.mem_free() # type: ignore @@ -108,6 +109,7 @@ def get_obj_attributes(self, item_instance: object): try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order + self.log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -199,7 +201,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) @@ -210,10 +212,11 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] self.log.warning("could not del new_module") - try: - del sys.modules[module_name] - except KeyError: - self.log.debug("could not del sys.modules[{}]".format(module_name)) + # lets not try - most times it does not work anyway + # try: + # del sys.modules[module_name] + # except KeyError: + # self.log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -239,8 +242,13 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, self.log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - self.log.debug("{0}class {1}:".format(indent, item_name)) + if ( + item_type_txt == "" + and len(indent) <= _MAX_CLASS_LEVEL * 4 + # and not obj_name.endswith(".Pin") + # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms + ): + self.log.info("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -312,12 +320,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) else: # something else - if t not in ["object", "set", "frozenset"]: - # Possibly default others to item_instance object ? + if t in ["object", "set", "frozenset", "Pin", "FileIO"]: # https://docs.python.org/3/tutorial/classes.html#item_instance-objects + # use these types for the attribute + s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + else: + # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - # Requires Python 3.6 syntax, which is OK for the stubs/pyi - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) self.log.debug("\n" + s) else: @@ -327,12 +337,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, fp.write(indent + item_name + " # type: Incomplete\n") - del items - del errors - try: - del item_name, item_repr, item_type_txt, item_instance # type: ignore - except (OSError, KeyError, NameError): - pass + # del items + # del errors + # try: + # del item_name, item_repr, item_type_txt, item_instance # type: ignore + # except (OSError, KeyError, NameError): + # pass @property def flat_fwid(self): @@ -427,13 +437,19 @@ def ensure_folder(path: str): def _build(s): # extract build from sys.version or os.uname().version if available - # 'v1.13-103-gb137d064e' - # 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.version: 'MicroPython v1.23.0-preview.6.g3d0b6276f' + # sys.implementation.version: 'v1.13-103-gb137d064e' if not s: return "" s = s.split(" on ", 1)[0] if " on " in s else s - s = s.split("; ", 1)[1] if "; " in s else s - b = s.split("-")[1] if s.startswith("v") else s.split("-", 1)[-1].split(".")[1] + if s.startswith("v"): + if not "-" in s: + return "" + b = s.split("-")[1] + return b + if not "-preview" in s: + return "" + b = s.split("-preview")[1].split(".")[1] return b @@ -476,9 +492,7 @@ def _info(): # type:() -> dict[str, str] ) except (AttributeError, IndexError): pass - gc.collect() - read_boardname(info) - gc.collect() + info["board"] = get_boardname() try: if "uname" in dir(os): # old @@ -566,57 +580,16 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - found = False - for filename in [d + "/board_info.csv" for d in LIBS]: - # print("look up the board name in the file", filename) - if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): - found = True - break - if not found: - print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() - +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.info("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable diff --git a/src/stubber/minify.py b/src/stubber/minify.py index d0e14b8ae..dd1d55829 100644 --- a/src/stubber/minify.py +++ b/src/stubber/minify.py @@ -365,8 +365,10 @@ def cross_compile( return result.returncode -def pipx_mpy_cross(version:str, source_file, _target): +def pipx_mpy_cross(version: str, source_file, _target): """Run mpy-cross using pipx""" + + log.info(f"Compiling with mpy-cross version: {version}") if version == "latest": version = "" if version: diff --git a/src/stubber/update_module_list.py b/src/stubber/update_module_list.py index c63b5c149..214ab14f4 100644 --- a/src/stubber/update_module_list.py +++ b/src/stubber/update_module_list.py @@ -100,7 +100,7 @@ def update_module_list(): "builtins", "re", } - + log.info("Update the module list in createstubs.py") all_modules = read_modules() modules_to_stub = sorted(all_modules - set(mods_excluded | mods_problematic)) From c53d1fec32655e6812d8dcf8f25a3f34a9969927 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Wed, 24 Jan 2024 23:56:02 +0100 Subject: [PATCH 46/68] deps: Add rich-click Signed-off-by: Jos Verlinde --- poetry.lock | 39 ++++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index d9aaa49c3..6b03906ad 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2336,6 +2336,43 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "rich" +version = "13.7.0" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "rich-13.7.0-py3-none-any.whl", hash = "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235"}, + {file = "rich-13.7.0.tar.gz", hash = "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "rich-click" +version = "1.7.3" +description = "Format click help output nicely with rich" +optional = false +python-versions = ">=3.7" +files = [ + {file = "rich-click-1.7.3.tar.gz", hash = "sha256:bced1594c497dc007ab49508ff198bb437c576d01291c13a61658999066481f4"}, + {file = "rich_click-1.7.3-py3-none-any.whl", hash = "sha256:bc4163d4e2a3361e21c4d72d300eca6eb8896dfc978667923cb1d4937b8769a3"}, +] + +[package.dependencies] +click = ">=7" +rich = ">=10.7.0" +typing-extensions = "*" + +[package.extras] +dev = ["flake8", "flake8-docstrings", "mypy", "packaging", "pre-commit", "pytest", "pytest-cov", "types-setuptools"] + [[package]] name = "setuptools" version = "69.0.3" @@ -2919,4 +2956,4 @@ tools = ["esptool"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "2a91438425ed433330988080b8e4829e990e986e768de1f009de4760103ff3fe" +content-hash = "9d6854b21f2a4232f6e2bf891025fcf50ec25afc882a4213e88e330204f24971" diff --git a/pyproject.toml b/pyproject.toml index d7456a82e..1929a136c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,6 +71,7 @@ typed-config = "^1.3.0" pyserial = "^3.5" executing = "^2.0.1" mypy-gitlab-code-quality = "^1.1.0" +rich-click = "^1.7.3" [tool.poetry.extras] tools = ["esptool"] From 7dfa01b78ddf72b4027924f1097e46e8dea7c50b Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Fri, 26 Jan 2024 23:17:15 +0100 Subject: [PATCH 47/68] Fix: Allow checkkout with missing tag Bump version to 1.16.3 Signed-off-by: Jos Verlinde --- pyproject.toml | 2 +- scripts/get_firmwares.ipynb | 148 +++++++++++++++++++++-- src/stubber/__init__.py | 2 +- src/stubber/basicgit.py | 4 +- src/stubber/board/createstubs.py | 2 +- src/stubber/board/createstubs_db.py | 4 +- src/stubber/board/createstubs_db_min.py | 4 +- src/stubber/board/createstubs_mem.py | 4 +- src/stubber/board/createstubs_mem_min.py | 4 +- src/stubber/board/createstubs_min.py | 2 +- src/stubber/utils/repos.py | 6 +- 11 files changed, 158 insertions(+), 24 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1929a136c..2684138e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ repo-path = "./repos" [tool.poetry] name = "micropython-stubber" -version = "1.16.2" +version = "1.16.3" description = "Tooling to create and maintain stubs for MicroPython" authors = ["Jos Verlinde "] license = "MIT" diff --git a/scripts/get_firmwares.ipynb b/scripts/get_firmwares.ipynb index d97be2bdb..3316143c8 100644 --- a/scripts/get_firmwares.ipynb +++ b/scripts/get_firmwares.ipynb @@ -101,7 +101,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Found 169 firmwares\n" + "Found 186 firmwares\n" ] } ], @@ -178,18 +178,115 @@ } ], "source": [ - "relevant = [3````````````````\n", + "relevant = [\n", + " board\n", + " for board in board_urls\n", + " if board[\"board\"] in RELEVANT_BOARDS and (board[\"version\"] in [\"1.22.0\", \"1.22.1\"] or board[\"preview\"])\n", " # and b[\"port\"] in [\"esp32\", \"rp2\"]\n", "]\n", + "\n", "# relevant\n", + "\n", "print(f\"Found {len(relevant)} relevant firmwares\")" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Downloading https://micropython.org/resources/firmware/PYBV11-20240105-v1.22.1.hex to firmware\\stm32\\PYBV11-v1.22.1.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-20240124-v1.23.0-preview.62.g6bb446b7f.hex to firmware\\stm32\\PYBV11-v1.23.0-preview.62.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-20240123-v1.23.0-preview.60.gce2058685.hex to firmware\\stm32\\PYBV11-v1.23.0-preview.60.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-20240123-v1.23.0-preview.59.g057701a77.hex to firmware\\stm32\\PYBV11-v1.23.0-preview.59.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-20240123-v1.23.0-preview.58.gc3ca3612d.hex to firmware\\stm32\\PYBV11-v1.23.0-preview.58.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-DP-20240105-v1.22.1.hex to firmware\\stm32\\PYBV11-DP-v1.22.1.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-DP-20240124-v1.23.0-preview.62.g6bb446b7f.hex to firmware\\stm32\\PYBV11-DP-v1.23.0-preview.62.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-DP-20240123-v1.23.0-preview.60.gce2058685.hex to firmware\\stm32\\PYBV11-DP-v1.23.0-preview.60.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-DP-20240123-v1.23.0-preview.59.g057701a77.hex to firmware\\stm32\\PYBV11-DP-v1.23.0-preview.59.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-DP-20240123-v1.23.0-preview.58.gc3ca3612d.hex to firmware\\stm32\\PYBV11-DP-v1.23.0-preview.58.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-NETWORK-20240105-v1.22.1.hex to firmware\\stm32\\PYBV11-NETWORK-v1.22.1.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-NETWORK-20240124-v1.23.0-preview.62.g6bb446b7f.hex to firmware\\stm32\\PYBV11-NETWORK-v1.23.0-preview.62.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-NETWORK-20240123-v1.23.0-preview.60.gce2058685.hex to firmware\\stm32\\PYBV11-NETWORK-v1.23.0-preview.60.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-NETWORK-20240123-v1.23.0-preview.59.g057701a77.hex to firmware\\stm32\\PYBV11-NETWORK-v1.23.0-preview.59.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-NETWORK-20240123-v1.23.0-preview.58.gc3ca3612d.hex to firmware\\stm32\\PYBV11-NETWORK-v1.23.0-preview.58.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-THREAD-20240105-v1.22.1.hex to firmware\\stm32\\PYBV11-THREAD-v1.22.1.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-THREAD-20240124-v1.23.0-preview.62.g6bb446b7f.hex to firmware\\stm32\\PYBV11-THREAD-v1.23.0-preview.62.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-THREAD-20240123-v1.23.0-preview.60.gce2058685.hex to firmware\\stm32\\PYBV11-THREAD-v1.23.0-preview.60.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-THREAD-20240123-v1.23.0-preview.59.g057701a77.hex to firmware\\stm32\\PYBV11-THREAD-v1.23.0-preview.59.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-THREAD-20240123-v1.23.0-preview.58.gc3ca3612d.hex to firmware\\stm32\\PYBV11-THREAD-v1.23.0-preview.58.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-DP_THREAD-20240105-v1.22.1.hex to firmware\\stm32\\PYBV11-DP_THREAD-v1.22.1.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-DP_THREAD-20240124-v1.23.0-preview.62.g6bb446b7f.hex to firmware\\stm32\\PYBV11-DP_THREAD-v1.23.0-preview.62.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-DP_THREAD-20240123-v1.23.0-preview.60.gce2058685.hex to firmware\\stm32\\PYBV11-DP_THREAD-v1.23.0-preview.60.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-DP_THREAD-20240123-v1.23.0-preview.59.g057701a77.hex to firmware\\stm32\\PYBV11-DP_THREAD-v1.23.0-preview.59.hex\n", + "Downloading https://micropython.org/resources/firmware/PYBV11-DP_THREAD-20240123-v1.23.0-preview.58.gc3ca3612d.hex to firmware\\stm32\\PYBV11-DP_THREAD-v1.23.0-preview.58.hex\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-20240105-v1.22.1.bin to firmware\\esp32\\ESP32_GENERIC-v1.22.1.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-20240124-v1.23.0-preview.62.g6bb446b7f.bin to firmware\\esp32\\ESP32_GENERIC-v1.23.0-preview.62.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-20240123-v1.23.0-preview.60.gce2058685.bin to firmware\\esp32\\ESP32_GENERIC-v1.23.0-preview.60.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-20240123-v1.23.0-preview.59.g057701a77.bin to firmware\\esp32\\ESP32_GENERIC-v1.23.0-preview.59.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-20240123-v1.23.0-preview.58.gc3ca3612d.bin to firmware\\esp32\\ESP32_GENERIC-v1.23.0-preview.58.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-UNICORE-20240105-v1.22.1.bin to firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.22.1.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-UNICORE-20240124-v1.23.0-preview.62.g6bb446b7f.bin to firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.23.0-preview.62.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-UNICORE-20240123-v1.23.0-preview.60.gce2058685.bin to firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.23.0-preview.60.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-UNICORE-20240123-v1.23.0-preview.59.g057701a77.bin to firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.23.0-preview.59.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-UNICORE-20240123-v1.23.0-preview.58.gc3ca3612d.bin to firmware\\esp32\\ESP32_GENERIC-UNICORE-v1.23.0-preview.58.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-OTA-20240105-v1.22.1.bin to firmware\\esp32\\ESP32_GENERIC-OTA-v1.22.1.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-OTA-20240124-v1.23.0-preview.62.g6bb446b7f.bin to firmware\\esp32\\ESP32_GENERIC-OTA-v1.23.0-preview.62.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-OTA-20240123-v1.23.0-preview.60.gce2058685.bin to firmware\\esp32\\ESP32_GENERIC-OTA-v1.23.0-preview.60.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-OTA-20240123-v1.23.0-preview.59.g057701a77.bin to firmware\\esp32\\ESP32_GENERIC-OTA-v1.23.0-preview.59.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-OTA-20240123-v1.23.0-preview.58.gc3ca3612d.bin to firmware\\esp32\\ESP32_GENERIC-OTA-v1.23.0-preview.58.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-D2WD-20240105-v1.22.1.bin to firmware\\esp32\\ESP32_GENERIC-D2WD-v1.22.1.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-D2WD-20240124-v1.23.0-preview.62.g6bb446b7f.bin to firmware\\esp32\\ESP32_GENERIC-D2WD-v1.23.0-preview.62.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-D2WD-20240123-v1.23.0-preview.60.gce2058685.bin to firmware\\esp32\\ESP32_GENERIC-D2WD-v1.23.0-preview.60.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-D2WD-20240123-v1.23.0-preview.59.g057701a77.bin to firmware\\esp32\\ESP32_GENERIC-D2WD-v1.23.0-preview.59.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-D2WD-20240123-v1.23.0-preview.58.gc3ca3612d.bin to firmware\\esp32\\ESP32_GENERIC-D2WD-v1.23.0-preview.58.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-SPIRAM-20240105-v1.22.1.bin to firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.22.1.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-SPIRAM-20240124-v1.23.0-preview.62.g6bb446b7f.bin to firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.23.0-preview.62.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-SPIRAM-20240123-v1.23.0-preview.60.gce2058685.bin to firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.23.0-preview.60.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-SPIRAM-20240123-v1.23.0-preview.59.g057701a77.bin to firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.23.0-preview.59.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC-SPIRAM-20240123-v1.23.0-preview.58.gc3ca3612d.bin to firmware\\esp32\\ESP32_GENERIC-SPIRAM-v1.23.0-preview.58.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC_S3-20240105-v1.22.1.bin to firmware\\esp32\\ESP32_GENERIC_S3-v1.22.1.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC_S3-20240124-v1.23.0-preview.62.g6bb446b7f.bin to firmware\\esp32\\ESP32_GENERIC_S3-v1.23.0-preview.62.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC_S3-20240123-v1.23.0-preview.60.gce2058685.bin to firmware\\esp32\\ESP32_GENERIC_S3-v1.23.0-preview.60.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC_S3-20240123-v1.23.0-preview.59.g057701a77.bin to firmware\\esp32\\ESP32_GENERIC_S3-v1.23.0-preview.59.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC_S3-20240123-v1.23.0-preview.58.gc3ca3612d.bin to firmware\\esp32\\ESP32_GENERIC_S3-v1.23.0-preview.58.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC_S3-SPIRAM_OCT-20240105-v1.22.1.bin to firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.1.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC_S3-SPIRAM_OCT-20240124-v1.23.0-preview.62.g6bb446b7f.bin to firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.23.0-preview.62.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC_S3-SPIRAM_OCT-20240123-v1.23.0-preview.60.gce2058685.bin to firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.23.0-preview.60.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC_S3-SPIRAM_OCT-20240123-v1.23.0-preview.59.g057701a77.bin to firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.23.0-preview.59.bin\n", + "Downloading https://micropython.org/resources/firmware/ESP32_GENERIC_S3-SPIRAM_OCT-20240123-v1.23.0-preview.58.gc3ca3612d.bin to firmware\\esp32\\ESP32_GENERIC_S3-SPIRAM_OCT-v1.23.0-preview.58.bin\n", + "Downloading https://micropython.org/resources/firmware/ARDUINO_NANO_RP2040_CONNECT-20240105-v1.22.1.uf2 to firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.22.1.uf2\n", + "Downloading https://micropython.org/resources/firmware/ARDUINO_NANO_RP2040_CONNECT-20240124-v1.23.0-preview.62.g6bb446b7f.uf2 to firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.23.0-preview.62.uf2\n", + "Downloading https://micropython.org/resources/firmware/ARDUINO_NANO_RP2040_CONNECT-20240123-v1.23.0-preview.60.gce2058685.uf2 to firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.23.0-preview.60.uf2\n", + "Downloading https://micropython.org/resources/firmware/ARDUINO_NANO_RP2040_CONNECT-20240123-v1.23.0-preview.59.g057701a77.uf2 to firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.23.0-preview.59.uf2\n", + "Downloading https://micropython.org/resources/firmware/ARDUINO_NANO_RP2040_CONNECT-20240123-v1.23.0-preview.58.gc3ca3612d.uf2 to firmware\\rp2\\ARDUINO_NANO_RP2040_CONNECT-v1.23.0-preview.58.uf2\n", + "Downloading https://micropython.org/resources/firmware/PIMORONI_PICOLIPO_16MB-20240105-v1.22.1.uf2 to firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.22.1.uf2\n", + "Downloading https://micropython.org/resources/firmware/PIMORONI_PICOLIPO_16MB-20240124-v1.23.0-preview.62.g6bb446b7f.uf2 to firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.23.0-preview.62.uf2\n", + "Downloading https://micropython.org/resources/firmware/PIMORONI_PICOLIPO_16MB-20240123-v1.23.0-preview.60.gce2058685.uf2 to firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.23.0-preview.60.uf2\n", + "Downloading https://micropython.org/resources/firmware/PIMORONI_PICOLIPO_16MB-20240123-v1.23.0-preview.59.g057701a77.uf2 to firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.23.0-preview.59.uf2\n", + "Downloading https://micropython.org/resources/firmware/PIMORONI_PICOLIPO_16MB-20240123-v1.23.0-preview.58.gc3ca3612d.uf2 to firmware\\rp2\\PIMORONI_PICOLIPO_16MB-v1.23.0-preview.58.uf2\n", + "Downloading https://micropython.org/resources/firmware/RPI_PICO-20240105-v1.22.1.uf2 to firmware\\rp2\\RPI_PICO-v1.22.1.uf2\n", + "Downloading https://micropython.org/resources/firmware/RPI_PICO-20240124-v1.23.0-preview.62.g6bb446b7f.uf2 to firmware\\rp2\\RPI_PICO-v1.23.0-preview.62.uf2\n", + "Downloading https://micropython.org/resources/firmware/RPI_PICO-20240123-v1.23.0-preview.60.gce2058685.uf2 to firmware\\rp2\\RPI_PICO-v1.23.0-preview.60.uf2\n", + "Downloading https://micropython.org/resources/firmware/RPI_PICO-20240123-v1.23.0-preview.59.g057701a77.uf2 to firmware\\rp2\\RPI_PICO-v1.23.0-preview.59.uf2\n", + "Downloading https://micropython.org/resources/firmware/RPI_PICO-20240123-v1.23.0-preview.58.gc3ca3612d.uf2 to firmware\\rp2\\RPI_PICO-v1.23.0-preview.58.uf2\n", + "Downloading https://micropython.org/resources/firmware/RPI_PICO_W-20240105-v1.22.1.uf2 to firmware\\rp2\\RPI_PICO_W-v1.22.1.uf2\n", + "Downloading https://micropython.org/resources/firmware/RPI_PICO_W-20240124-v1.23.0-preview.62.g6bb446b7f.uf2 to firmware\\rp2\\RPI_PICO_W-v1.23.0-preview.62.uf2\n", + "Downloading https://micropython.org/resources/firmware/RPI_PICO_W-20240123-v1.23.0-preview.60.gce2058685.uf2 to firmware\\rp2\\RPI_PICO_W-v1.23.0-preview.60.uf2\n", + "Downloading https://micropython.org/resources/firmware/RPI_PICO_W-20240123-v1.23.0-preview.59.g057701a77.uf2 to firmware\\rp2\\RPI_PICO_W-v1.23.0-preview.59.uf2\n", + "Downloading https://micropython.org/resources/firmware/RPI_PICO_W-20240123-v1.23.0-preview.58.gc3ca3612d.uf2 to firmware\\rp2\\RPI_PICO_W-v1.23.0-preview.58.uf2\n", + "Downloading https://micropython.org/resources/firmware/SEEED_WIO_TERMINAL-20240105-v1.22.1.uf2 to firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.1.uf2\n", + "Downloading https://micropython.org/resources/firmware/SEEED_WIO_TERMINAL-20240124-v1.23.0-preview.62.g6bb446b7f.uf2 to firmware\\samd\\SEEED_WIO_TERMINAL-v1.23.0-preview.62.uf2\n", + "Downloading https://micropython.org/resources/firmware/SEEED_WIO_TERMINAL-20240123-v1.23.0-preview.60.gce2058685.uf2 to firmware\\samd\\SEEED_WIO_TERMINAL-v1.23.0-preview.60.uf2\n", + "Downloading https://micropython.org/resources/firmware/SEEED_WIO_TERMINAL-20240123-v1.23.0-preview.59.g057701a77.uf2 to firmware\\samd\\SEEED_WIO_TERMINAL-v1.23.0-preview.59.uf2\n", + "Downloading https://micropython.org/resources/firmware/SEEED_WIO_TERMINAL-20240123-v1.23.0-preview.58.gc3ca3612d.uf2 to firmware\\samd\\SEEED_WIO_TERMINAL-v1.23.0-preview.58.uf2\n" + ] + } + ], "source": [ "# download the relevant files to the firmware folder\n", "import requests\n", @@ -219,7 +316,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -234,7 +331,7 @@ "\n", " Directory of c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\esp32\n", "\n", - "03-01-2024 11:55

.\n", + "25-01-2024 00:00 .\n", "19-10-2023 14:24 ..\n", "19-10-2023 14:45 1.494.672 ESP32_GENERIC-D2WD-v1.21.0.bin\n", "19-10-2023 14:45 1.494.832 ESP32_GENERIC-D2WD-v1.22.0-preview.27.bin\n", @@ -246,7 +343,12 @@ "19-10-2023 14:45 1.494.832 ESP32_GENERIC-D2WD-v1.22.0-preview.31.bin\n", "19-10-2023 14:45 1.494.832 ESP32_GENERIC-D2WD-v1.22.0-preview.32.bin\n", "30-12-2023 00:28 1.494.112 ESP32_GENERIC-D2WD-v1.22.0.bin\n", + "25-01-2024 00:00 1.494.112 ESP32_GENERIC-D2WD-v1.22.1.bin\n", + "25-01-2024 00:00 1.494.320 ESP32_GENERIC-D2WD-v1.23.0-preview.58.bin\n", + "25-01-2024 00:00 1.494.320 ESP32_GENERIC-D2WD-v1.23.0-preview.59.bin\n", "03-01-2024 11:55 1.494.144 ESP32_GENERIC-D2WD-v1.23.0-preview.6.bin\n", + "25-01-2024 00:00 1.494.320 ESP32_GENERIC-D2WD-v1.23.0-preview.60.bin\n", + "25-01-2024 00:00 1.494.320 ESP32_GENERIC-D2WD-v1.23.0-preview.62.bin\n", "19-10-2023 14:45 1.621.792 ESP32_GENERIC-OTA-v1.21.0.bin\n", "19-10-2023 14:45 1.621.936 ESP32_GENERIC-OTA-v1.22.0-preview.27.bin\n", "30-12-2023 00:28 1.544.848 ESP32_GENERIC-OTA-v1.22.0-preview.278.bin\n", @@ -257,7 +359,12 @@ "19-10-2023 14:45 1.621.952 ESP32_GENERIC-OTA-v1.22.0-preview.31.bin\n", "19-10-2023 14:45 1.621.952 ESP32_GENERIC-OTA-v1.22.0-preview.32.bin\n", "30-12-2023 00:28 1.545.088 ESP32_GENERIC-OTA-v1.22.0.bin\n", + "25-01-2024 00:00 1.545.088 ESP32_GENERIC-OTA-v1.22.1.bin\n", + "25-01-2024 00:00 1.545.312 ESP32_GENERIC-OTA-v1.23.0-preview.58.bin\n", + "25-01-2024 00:00 1.545.312 ESP32_GENERIC-OTA-v1.23.0-preview.59.bin\n", "03-01-2024 11:55 1.545.120 ESP32_GENERIC-OTA-v1.23.0-preview.6.bin\n", + "25-01-2024 00:00 1.545.312 ESP32_GENERIC-OTA-v1.23.0-preview.60.bin\n", + "25-01-2024 00:00 1.545.312 ESP32_GENERIC-OTA-v1.23.0-preview.62.bin\n", "19-10-2023 14:45 1.601.072 ESP32_GENERIC-SPIRAM-v1.21.0.bin\n", "19-10-2023 14:45 1.601.200 ESP32_GENERIC-SPIRAM-v1.22.0-preview.27.bin\n", "30-12-2023 00:28 1.614.304 ESP32_GENERIC-SPIRAM-v1.22.0-preview.278.bin\n", @@ -268,7 +375,12 @@ "19-10-2023 14:45 1.601.200 ESP32_GENERIC-SPIRAM-v1.22.0-preview.31.bin\n", "19-10-2023 14:45 1.601.200 ESP32_GENERIC-SPIRAM-v1.22.0-preview.32.bin\n", "30-12-2023 00:28 1.614.576 ESP32_GENERIC-SPIRAM-v1.22.0.bin\n", + "25-01-2024 00:00 1.614.576 ESP32_GENERIC-SPIRAM-v1.22.1.bin\n", + "25-01-2024 00:00 1.614.832 ESP32_GENERIC-SPIRAM-v1.23.0-preview.58.bin\n", + "25-01-2024 00:00 1.614.832 ESP32_GENERIC-SPIRAM-v1.23.0-preview.59.bin\n", "03-01-2024 11:55 1.614.624 ESP32_GENERIC-SPIRAM-v1.23.0-preview.6.bin\n", + "25-01-2024 00:00 1.614.832 ESP32_GENERIC-SPIRAM-v1.23.0-preview.60.bin\n", + "25-01-2024 00:00 1.614.832 ESP32_GENERIC-SPIRAM-v1.23.0-preview.62.bin\n", "19-10-2023 14:45 1.653.872 ESP32_GENERIC-UNICORE-v1.21.0.bin\n", "19-10-2023 14:45 1.654.032 ESP32_GENERIC-UNICORE-v1.22.0-preview.27.bin\n", "30-12-2023 00:28 1.728.880 ESP32_GENERIC-UNICORE-v1.22.0-preview.278.bin\n", @@ -279,7 +391,12 @@ "19-10-2023 14:45 1.654.032 ESP32_GENERIC-UNICORE-v1.22.0-preview.31.bin\n", "19-10-2023 14:45 1.654.032 ESP32_GENERIC-UNICORE-v1.22.0-preview.32.bin\n", "30-12-2023 00:28 1.729.152 ESP32_GENERIC-UNICORE-v1.22.0.bin\n", + "25-01-2024 00:00 1.729.152 ESP32_GENERIC-UNICORE-v1.22.1.bin\n", + "25-01-2024 00:00 1.729.424 ESP32_GENERIC-UNICORE-v1.23.0-preview.58.bin\n", + "25-01-2024 00:00 1.729.424 ESP32_GENERIC-UNICORE-v1.23.0-preview.59.bin\n", "03-01-2024 11:55 1.729.232 ESP32_GENERIC-UNICORE-v1.23.0-preview.6.bin\n", + "25-01-2024 00:00 1.729.424 ESP32_GENERIC-UNICORE-v1.23.0-preview.60.bin\n", + "25-01-2024 00:00 1.729.424 ESP32_GENERIC-UNICORE-v1.23.0-preview.62.bin\n", "19-10-2023 14:45 1.661.872 ESP32_GENERIC-v1.21.0.bin\n", "19-10-2023 14:45 1.662.032 ESP32_GENERIC-v1.22.0-preview.27.bin\n", "30-12-2023 00:28 1.737.408 ESP32_GENERIC-v1.22.0-preview.278.bin\n", @@ -290,23 +407,38 @@ "19-10-2023 14:45 1.662.032 ESP32_GENERIC-v1.22.0-preview.31.bin\n", "19-10-2023 14:45 1.662.032 ESP32_GENERIC-v1.22.0-preview.32.bin\n", "30-12-2023 00:28 1.737.664 ESP32_GENERIC-v1.22.0.bin\n", + "25-01-2024 00:00 1.737.664 ESP32_GENERIC-v1.22.1.bin\n", + "25-01-2024 00:00 1.737.904 ESP32_GENERIC-v1.23.0-preview.58.bin\n", + "25-01-2024 00:00 1.737.904 ESP32_GENERIC-v1.23.0-preview.59.bin\n", "03-01-2024 11:55 1.737.728 ESP32_GENERIC-v1.23.0-preview.6.bin\n", + "25-01-2024 00:00 1.737.904 ESP32_GENERIC-v1.23.0-preview.60.bin\n", + "25-01-2024 00:00 1.737.904 ESP32_GENERIC-v1.23.0-preview.62.bin\n", "03-01-2024 11:55 1.561.184 ESP32_GENERIC_S3-SPIRAM_OCT-v1.21.0.bin\n", "30-12-2023 00:29 1.631.216 ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.278.bin\n", "30-12-2023 00:29 1.631.536 ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.281.bin\n", "30-12-2023 00:29 1.631.600 ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.283.bin\n", "30-12-2023 00:29 1.631.584 ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0-preview.289.bin\n", "30-12-2023 00:29 1.631.504 ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.0.bin\n", + "25-01-2024 00:00 1.631.504 ESP32_GENERIC_S3-SPIRAM_OCT-v1.22.1.bin\n", + "25-01-2024 00:00 1.631.728 ESP32_GENERIC_S3-SPIRAM_OCT-v1.23.0-preview.58.bin\n", + "25-01-2024 00:00 1.631.728 ESP32_GENERIC_S3-SPIRAM_OCT-v1.23.0-preview.59.bin\n", "03-01-2024 11:55 1.631.584 ESP32_GENERIC_S3-SPIRAM_OCT-v1.23.0-preview.6.bin\n", + "25-01-2024 00:00 1.631.728 ESP32_GENERIC_S3-SPIRAM_OCT-v1.23.0-preview.60.bin\n", + "25-01-2024 00:00 1.631.728 ESP32_GENERIC_S3-SPIRAM_OCT-v1.23.0-preview.62.bin\n", "03-01-2024 11:55 1.559.472 ESP32_GENERIC_S3-v1.21.0.bin\n", "30-12-2023 00:29 1.627.952 ESP32_GENERIC_S3-v1.22.0-preview.278.bin\n", "30-12-2023 00:29 1.628.272 ESP32_GENERIC_S3-v1.22.0-preview.281.bin\n", "30-12-2023 00:29 1.628.320 ESP32_GENERIC_S3-v1.22.0-preview.283.bin\n", "30-12-2023 00:28 1.628.320 ESP32_GENERIC_S3-v1.22.0-preview.289.bin\n", "30-12-2023 00:28 1.628.240 ESP32_GENERIC_S3-v1.22.0.bin\n", + "25-01-2024 00:00 1.628.240 ESP32_GENERIC_S3-v1.22.1.bin\n", + "25-01-2024 00:00 1.628.496 ESP32_GENERIC_S3-v1.23.0-preview.58.bin\n", + "25-01-2024 00:00 1.628.496 ESP32_GENERIC_S3-v1.23.0-preview.59.bin\n", "03-01-2024 11:55 1.628.304 ESP32_GENERIC_S3-v1.23.0-preview.6.bin\n", - " 69 File(s) 111.571.760 bytes\n", - " 2 Dir(s) 348.284.379.136 bytes free\n" + "25-01-2024 00:00 1.628.496 ESP32_GENERIC_S3-v1.23.0-preview.60.bin\n", + "25-01-2024 00:00 1.628.496 ESP32_GENERIC_S3-v1.23.0-preview.62.bin\n", + " 104 File(s) 168.480.160 bytes\n", + " 2 Dir(s) 355.654.905.856 bytes free\n" ] }, { diff --git a/src/stubber/__init__.py b/src/stubber/__init__.py index aed888190..c99e52374 100644 --- a/src/stubber/__init__.py +++ b/src/stubber/__init__.py @@ -1,4 +1,4 @@ """get the version""" -__version__ = "1.16.2" +__version__ = "1.16.3" diff --git a/src/stubber/basicgit.py b/src/stubber/basicgit.py index d9ecf4fd8..f132fcd16 100644 --- a/src/stubber/basicgit.py +++ b/src/stubber/basicgit.py @@ -42,7 +42,7 @@ def _run_local_git( return None except subprocess.CalledProcessError as e: # pragma: no cover # add some logging for github actions - log.error(f"{str(e)} : { e.stderr.decode('utf-8')}") + log.error(f"{str(e)} : { e.stderr}") return None if result.stderr and result.stderr != b"": stderr = result.stderr @@ -150,7 +150,7 @@ def checkout_tag(tag: str, repo: Optional[Union[str, Path]] = None) -> bool: """ checkout a specific git tag """ - cmd = ["git", "checkout", "tags/" + tag, "--detach", "--quiet", "--force"] + cmd = ["git", "checkout", tag, "--quiet", "--force"] result = _run_local_git(cmd, repo=repo, expect_stderr=True, capture_output=True) if not result: return False diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index b9aff753c..f8f45beb6 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -25,7 +25,7 @@ from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.2" +__version__ = "v1.16.3" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] diff --git a/src/stubber/board/createstubs_db.py b/src/stubber/board/createstubs_db.py index ee508f84f..392702f55 100644 --- a/src/stubber/board/createstubs_db.py +++ b/src/stubber/board/createstubs_db.py @@ -18,7 +18,7 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.2 +This variant was generated from createstubs.py by micropython-stubber v1.16.3 """ # Copyright (c) 2019-2023 Jos Verlinde @@ -59,7 +59,7 @@ def feed(self): wdt.feed() -__version__ = "v1.16.2" +__version__ = "v1.16.3" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] diff --git a/src/stubber/board/createstubs_db_min.py b/src/stubber/board/createstubs_db_min.py index 05817f711..6f1f09732 100644 --- a/src/stubber/board/createstubs_db_min.py +++ b/src/stubber/board/createstubs_db_min.py @@ -18,7 +18,7 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.2 +This variant was generated from createstubs.py by micropython-stubber v1.16.3 """ # Copyright (c) 2019-2023 Jos Verlinde @@ -59,7 +59,7 @@ def feed(self): wdt.feed() -__version__ = "v1.16.2" +__version__ = "v1.16.3" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] diff --git a/src/stubber/board/createstubs_mem.py b/src/stubber/board/createstubs_mem.py index cbdb970d1..04cc0aebf 100644 --- a/src/stubber/board/createstubs_mem.py +++ b/src/stubber/board/createstubs_mem.py @@ -9,7 +9,7 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.2 +This variant was generated from createstubs.py by micropython-stubber v1.16.3 """ # Copyright (c) 2019-2023 Jos Verlinde @@ -50,7 +50,7 @@ def feed(self): wdt.feed() -__version__ = "v1.16.2" +__version__ = "v1.16.3" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] diff --git a/src/stubber/board/createstubs_mem_min.py b/src/stubber/board/createstubs_mem_min.py index d610d52be..262820233 100644 --- a/src/stubber/board/createstubs_mem_min.py +++ b/src/stubber/board/createstubs_mem_min.py @@ -9,7 +9,7 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.2 +This variant was generated from createstubs.py by micropython-stubber v1.16.3 """ # Copyright (c) 2019-2023 Jos Verlinde @@ -50,7 +50,7 @@ def feed(self): wdt.feed() -__version__ = "v1.16.2" +__version__ = "v1.16.3" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] diff --git a/src/stubber/board/createstubs_min.py b/src/stubber/board/createstubs_min.py index 7b134cbf9..a3c386e9e 100644 --- a/src/stubber/board/createstubs_min.py +++ b/src/stubber/board/createstubs_min.py @@ -40,7 +40,7 @@ def feed(self): wdt.feed() -__version__ = "v1.16.2" +__version__ = "v1.16.3" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] diff --git a/src/stubber/utils/repos.py b/src/stubber/utils/repos.py index 82497d4a2..cec444831 100644 --- a/src/stubber/utils/repos.py +++ b/src/stubber/utils/repos.py @@ -88,8 +88,10 @@ def match_lib_with_mpy(version_tag: str, mpy_path: Path, lib_path: Path) -> bool # micropython-lib is now a submodule result = git.checkout_tag(version_tag, lib_path) if not result: - log.error("Could not checkout micropython-lib @master") - return False + log.warning(f"Could not checkout micropython-lib @{version_tag}") + if not git.checkout_tag("master", lib_path): + log.error("Could not checkout micropython-lib @master") + return False return git.sync_submodules(mpy_path) else: log.info( From 63973dc7dab4d54c3f70ba006dfc4fdab74218d0 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Sat, 27 Jan 2024 02:25:42 +0100 Subject: [PATCH 48/68] Remove unused import statement Signed-off-by: Jos Verlinde --- scripts/board_stubber.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/board_stubber.py b/scripts/board_stubber.py index 429ba00fa..718727ba3 100644 --- a/scripts/board_stubber.py +++ b/scripts/board_stubber.py @@ -19,7 +19,6 @@ from loguru import logger as log from rich.console import Console from rich.table import Table -from tabulate import tabulate from tenacity import retry, stop_after_attempt, wait_fixed from stubber import utils From 6a34f9fd0fd5565403cc480741a4f5e7a60e74bb Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Sat, 27 Jan 2024 02:25:49 +0100 Subject: [PATCH 49/68] Refactor variable names for clarity and consistency This commit refactors variable names in the codebase to improve clarity and maintain consistency. The changes made in this commit enhance the readability and maintainability of the code. Signed-off-by: Jos Verlinde --- scripts/flash.ipynb | 106 +++++++++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 41 deletions(-) diff --git a/scripts/flash.ipynb b/scripts/flash.ipynb index 619e88720..289e0ade6 100644 --- a/scripts/flash.ipynb +++ b/scripts/flash.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 29, "metadata": {}, "outputs": [], "source": [ @@ -59,7 +59,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 30, "metadata": {}, "outputs": [], "source": [ @@ -175,7 +175,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 31, "metadata": {}, "outputs": [], "source": [ @@ -188,9 +188,10 @@ " print(f\"UF2 not supported on {mcu['board']} on {mcu['serial_port']}\")\n", " return None\n", "\n", - " print(f\"Entering bootloader on {mcu['board']} on {mcu['serial_port']}\")\n", + " print(f\"Entering UF2 bootloader on {mcu['board']} on {mcu['serial_port']}\")\n", " %mpy --select {mcu['serial_port']}\n", - " %mpy --bootloader # TODO: add this to micropython-magic\n", + " # %mpy --bootloader # same as mpremote bootloader, for the current active device\n", + " !mpremote connect {mcu['serial_port']} bootloader\n", "\n", " destination = \"\"\n", " wait = 5\n", @@ -199,6 +200,14 @@ " drives = [drive.device for drive in psutil.disk_partitions()]\n", " for drive in drives:\n", " if Path(drive, \"INFO_UF2.TXT\").exists():\n", + " # Option : read Board-ID from INFO_UF2.TXT\n", + " board_id = \"Unknown\"\n", + " with open(Path(drive, \"INFO_UF2.TXT\")) as f:\n", + " data = f.readlines()\n", + " for line in data:\n", + " if line.startswith(\"Board-ID=\"):\n", + " board_id = line.split(\"=\")[1].strip()\n", + " print(f\"Found Board-ID={board_id}\")\n", " destination = drive\n", " break\n", " time.sleep(1)\n", @@ -219,7 +228,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 32, "metadata": {}, "outputs": [], "source": [ @@ -250,7 +259,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 33, "metadata": {}, "outputs": [], "source": [ @@ -268,7 +277,7 @@ " return \"\"\n", "\n", "def flash_stm32(mcu:MCUInfo, fw_file:Optional[Path]= None,*, erase_flash:bool=True) -> Optional[MCUInfo]:\n", - " print(f\"Entering bootloader on {mcu['board']} on {mcu['serial_port']}\")\n", + " print(f\"Entering STM bootloader on {mcu['board']} on {mcu['serial_port']}\")\n", " %mpy --select {mcu['serial_port']}\n", " %mpy --bootloader # TODO: add this to micropython-magic\n", "\n", @@ -303,7 +312,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 34, "metadata": {}, "outputs": [ { @@ -311,9 +320,9 @@ "output_type": "stream", "text": [ "searching info file: ../src/stubber/data/board_info.csv for: 'Wio Terminal D51R with SAMD51P19A' \n", - "| ver | version | port | mpy | build | cpu | family | board | arch | serial_port |\n", - "|-----------------|-----------|--------|-------|---------|------------|-------------|--------------------|-----------|---------------|\n", - "| v1.23.0.preview | 1...2-3 | samd | v6.2 | | SAMD51P19A | micropython | SEEED_WIO_TERMINAL | armv7emsp | COM10 |\n" + "| ver | version | port | mpy | build | cpu | family | board | arch | serial_port |\n", + "|---------|-----------|--------|-------|---------|------------|-------------|--------------------|-----------|---------------|\n", + "| v1.22.0 | 1.22.0 | samd | v6.2 | | SAMD51P19A | micropython | SEEED_WIO_TERMINAL | armv7emsp | COM3 |\n" ] } ], @@ -347,55 +356,70 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Searching for SEEED_WIO_TERMINAL-v1.23.0-preview.*.uf2 in c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\samd\n", - "c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\samd\\SEEED_WIO_TERMINAL-v1.23.0-preview.6.uf2 {'ver': 'v1.22.0', 'version': '1.22.0', 'port': 'samd', 'mpy': 'v6.2', 'build': '', 'cpu': 'SAMD51P19A', 'family': 'micropython', 'board': 'SEEED_WIO_TERMINAL', 'arch': 'armv7emsp', 'serial_port': 'COM10'}\n", - "Entering bootloader on SEEED_WIO_TERMINAL on COM10\n", + "Searching for SEEED_WIO_TERMINAL-v1.22.1.uf2 in c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\samd\n", + "c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.1.uf2 {'ver': 'v1.22.0', 'version': '1.22.0', 'port': 'samd', 'mpy': 'v6.2', 'build': '', 'cpu': 'SAMD51P19A', 'family': 'micropython', 'board': 'SEEED_WIO_TERMINAL', 'arch': 'armv7emsp', 'serial_port': 'COM3'}\n", + "Entering UF2 bootloader on SEEED_WIO_TERMINAL on COM3\n", "Waiting for mcu to mount as a drive : 5 seconds left\n", "Waiting for mcu to mount as a drive : 4 seconds left\n", + "Found Board-ID=Unknown\n", "Board is in bootloader mode\n", - "Copying c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\samd\\SEEED_WIO_TERMINAL-v1.23.0-preview.6.uf2 to E:\\\n", + "Copying c:\\develop\\MyPython\\micropython-stubber\\scripts\\firmware\\samd\\SEEED_WIO_TERMINAL-v1.22.1.uf2 to F:\\\n", "Done copying, resetting the board and wait for it to restart\n", "searching info file: ../src/stubber/data/board_info.csv for: 'Wio Terminal D51R with SAMD51P19A' \n", - "| ver | version | port | mpy | build | cpu | family | board | arch | serial_port |\n", - "|-----------------|----------------|--------|-------|---------|------------|-------------|--------------------|-----------|---------------|\n", - "| v1.23.0.preview | 1.23.0.preview | samd | v6.2 | | SAMD51P19A | micropython | SEEED_WIO_TERMINAL | armv7emsp | COM10 |\n" + "| ver | version | port | mpy | build | cpu | family | board | arch | serial_port |\n", + "|---------|-----------|--------|-------|---------|------------|-------------|--------------------|-----------|---------------|\n", + "| v1.22.1 | 1.22.1 | samd | v6.2 | | SAMD51P19A | micropython | SEEED_WIO_TERMINAL | armv7emsp | COM3 |\n" ] } ], "source": [ "target_version = \"1.23.0-preview.*\"\n", + "target_version = \"1.22.1\"\n", "updated = []\n", + "\n", + "\n", + "\n", "for mcu in dev_info:\n", " firmwares = find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"])\n", " if not firmwares:\n", " firmwares = find_firmware(target_version, port=mcu[\"port\"], board=mcu[\"board\"].split(\"_\")[0])\n", " if not firmwares:\n", " print(f\"No firmware found for {mcu['board']} on {mcu['serial_port']}\")\n", - " continue\n", "\n", + " continue\n", " fw_file = firmwares[0]\n", - " print(fw_file, mcu)\n", "\n", + " print(fw_file, mcu)\n", " new = None\n", + " try:\n", + " if mcu[\"port\"] in [\"samd\", \"rp2\"]:\n", + " new = flash_uf2(mcu, fw_file=fw_file)\n", + " elif mcu[\"port\"] in [\"esp32\"]:\n", + " new = flash_esp32(mcu, erase_flash=False, fw_file=fw_file)\n", + "\n", + "\n", + " elif mcu[\"port\"] in [\"stm32\"]:\n", + " new = flash_stm32(mcu, erase_flash=False, fw_file=fw_file)\n", + "\n", + " if new:\n", + " read_boardname(new)\n", + "\n", + "\n", + " new[\"version\"] = new[\"version\"].rstrip(\".\") # todo: update micropython-magic to do this\n", + "\n", "\n", - " if mcu[\"port\"] in [\"samd\", \"rp2\"]:\n", - " new = flash_uf2(mcu, fw_file=fw_file)\n", - " elif mcu[\"port\"] in [\"esp32\"]:\n", - " new = flash_esp32(mcu, erase_flash=False, fw_file=fw_file)\n", - " elif mcu[\"port\"] in [\"stm32\"]:\n", - " new = flash_stm32(mcu, erase_flash=False, fw_file=fw_file)\n", + " updated.append(new)\n", + " except Exception as e:\n", + " print(\"Failed to flash\", mcu[\"board\"], mcu[\"serial_port\"])\n", + " print(e)\n", "\n", - " if new:\n", - " read_boardname(new)\n", - " new[\"version\"] = new[\"version\"].rstrip(\".\") # todo: update micropython-magic to do this\n", - " updated.append(new)\n", "\n", "\n", "print(tabulate(updated, headers=\"keys\", tablefmt=\"github\"))" @@ -403,14 +427,14 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{'ver': 'v1.22.0',\n", - " 'version': '1.22.0',\n", + "{'ver': 'v1.22.1',\n", + " 'version': '1.22.1',\n", " 'port': 'samd',\n", " 'mpy': 'v6.2',\n", " 'build': '',\n", @@ -418,10 +442,10 @@ " 'family': 'micropython',\n", " 'board': 'Wio Terminal D51R with SAMD51P19A',\n", " 'arch': 'armv7emsp',\n", - " 'serial_port': 'COM10'}" + " 'serial_port': 'COM3'}" ] }, - "execution_count": 9, + "execution_count": 36, "metadata": {}, "output_type": "execute_result" } @@ -433,14 +457,14 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "(name='micropython', version=(1, 22, 0, ''), _machine='Wio Terminal D51R with SAMD51P19A', _mpy=7686)\n" + "(name='micropython', version=(1, 22, 1, ''), _machine='Wio Terminal D51R with SAMD51P19A', _mpy=7686)\n" ] } ], @@ -454,7 +478,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 38, "metadata": {}, "outputs": [ { From 0a0d2b82394c48f7c697fc09f0f6f78d09a41f41 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Sat, 27 Jan 2024 21:16:11 +0100 Subject: [PATCH 50/68] Use encoding="utf-8" when reading text Signed-off-by: Jos Verlinde --- src/stubber/codemod/_partials/__init__.py | 2 +- src/stubber/codemod/enrich.py | 2 +- src/stubber/minify.py | 2 +- src/stubber/publish/missing_class_methods.py | 4 ++-- src/stubber/variants.py | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/stubber/codemod/_partials/__init__.py b/src/stubber/codemod/_partials/__init__.py index fed7cac06..1d57d9aef 100644 --- a/src/stubber/codemod/_partials/__init__.py +++ b/src/stubber/codemod/_partials/__init__.py @@ -15,7 +15,7 @@ def _read_partial(path: Path) -> Iterator[str]: Read a partial from the file at `path` and yield only the lines between the ###PARTIAL### and ###PARTIALEND### markers """ - lines = deque(path.read_text().splitlines(keepends=True)) + lines = deque(path.read_text(encoding="utf-8").splitlines(keepends=True)) _start = False _end = False # todo: allow processing of files that do not have the markers diff --git a/src/stubber/codemod/enrich.py b/src/stubber/codemod/enrich.py index 8f3cc52f9..e3a5a98fe 100644 --- a/src/stubber/codemod/enrich.py +++ b/src/stubber/codemod/enrich.py @@ -74,7 +74,7 @@ def enrich_file( log.debug(f"Merge {target_path} from {docstub_file}") # read source file - old_code = target_path.read_text() + old_code = target_path.read_text(encoding="utf-8") codemod_instance = merge_docstub.MergeCommand(context, docstub_file=docstub_file) if not ( diff --git a/src/stubber/minify.py b/src/stubber/minify.py index dd1d55829..de280e834 100644 --- a/src/stubber/minify.py +++ b/src/stubber/minify.py @@ -192,7 +192,7 @@ def minify_script(source_script: StubSource, keep_report: bool = True, diff: boo source_content = "" if isinstance(source_script, Path): - source_content = source_script.read_text() + source_content = source_script.read_text(encoding="utf-8") elif isinstance(source_script, (StringIO, TextIOWrapper)): source_content = "".join(source_script.readlines()) elif isinstance(source_script, str): # type: ignore diff --git a/src/stubber/publish/missing_class_methods.py b/src/stubber/publish/missing_class_methods.py index fdb765ac5..4d35a8033 100644 --- a/src/stubber/publish/missing_class_methods.py +++ b/src/stubber/publish/missing_class_methods.py @@ -27,7 +27,7 @@ def add_machine_pin_call(merged_path: Path, version: str): log.error(f"no docstubs found for {version}") return False log.trace(f"Parsing {mod_path} for __call__ method") - source = mod_path.read_text() + source = mod_path.read_text(encoding="utf-8") module = cst.parse_module(source) call_finder = CallFinder() @@ -40,7 +40,7 @@ def add_machine_pin_call(merged_path: Path, version: str): # then use the CallAdder to add the __call__ method to all machine and pyb stubs mod_paths = [f for f in merged_path.rglob("*.*") if f.stem in {"machine", "umachine", "pyb"}] for mod_path in mod_paths: - source = mod_path.read_text() + source = mod_path.read_text(encoding="utf-8") machine_module = cst.parse_module(source) new_module = machine_module.visit(CallAdder(call_finder.call_meth)) mod_path.write_text(new_module.code) diff --git a/src/stubber/variants.py b/src/stubber/variants.py index ac0e1640f..ed73f15a1 100644 --- a/src/stubber/variants.py +++ b/src/stubber/variants.py @@ -50,7 +50,7 @@ def create_variants( ctx = codemod.CodemodContext() base_file = base_path / "createstubs.py" log.info(f"Reading : {base_file}") - base_txt = (base_path / "createstubs.py").read_text() + base_txt = (base_path / "createstubs.py")encoding="utf-8") base_module = cst.parse_module(base_txt) for var in make_variants: @@ -89,7 +89,7 @@ def create_variants( # str -> path # read minified file - minified_txt = minified_path.read_text() + minified_txt = minified_path.read_text(encoding="utf-8") cross_compile(minified_txt, mpy_path, version=version) From 6bf1cd903548b80c276e2f00fe080ac526cac2ed Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Sun, 28 Jan 2024 17:34:44 +0100 Subject: [PATCH 51/68] Fix encoding issue in create_variants function Signed-off-by: Jos Verlinde --- src/stubber/variants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stubber/variants.py b/src/stubber/variants.py index ed73f15a1..fe0a79d49 100644 --- a/src/stubber/variants.py +++ b/src/stubber/variants.py @@ -50,7 +50,7 @@ def create_variants( ctx = codemod.CodemodContext() base_file = base_path / "createstubs.py" log.info(f"Reading : {base_file}") - base_txt = (base_path / "createstubs.py")encoding="utf-8") + base_txt = base_path / "createstubs.py" base_module = cst.parse_module(base_txt) for var in make_variants: From 937a4cd0ff1f57cf69d731f90fc059351ac23aa0 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Sun, 28 Jan 2024 17:35:06 +0100 Subject: [PATCH 52/68] Docstubs: Add typing import and fix class inheritance. Signed-off-by: Jos Verlinde --- src/stubber/rst/lookup.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/stubber/rst/lookup.py b/src/stubber/rst/lookup.py index f090b5418..6829c56f5 100644 --- a/src/stubber/rst/lookup.py +++ b/src/stubber/rst/lookup.py @@ -20,6 +20,7 @@ # all possible Types needed for the stubs - exxess types should be removed later , and otherwise won't do much harm TYPING_IMPORT: List[str] = [ + "from __future__ import annotations", "from typing import IO, Any, Callable, Coroutine, Dict, Generator, Iterator, List, NoReturn, Optional, Tuple, Union, NamedTuple, TypeVar", "from _typeshed import Incomplete", ] @@ -483,17 +484,18 @@ class Fix: # List of classes and their parent classes that should be added to the class definition CHILD_PARENT_CLASS = { # machine - # "SoftSPI": "SPI", # BUG: SoftSPI is defined before SPI, so baseclass is not yet available + # SoftSPI is defined before SPI, so baseclass is not yet available - but in a .pyi that is OK + "SoftSPI": "SPI", "SoftI2C": "I2C", "Switch": "Pin", "Signal": "Pin", # uio # unclear regarding deprecation in python 3.12 # "IOBase": "IO", # DOCME not in documentation - "TextIOWrapper": "IO", - "FileIO": "IO", - "StringIO": "IO", - "BytesIO": "IO", - "BufferedWriter": "IOBase", # DOCME: not in documentation + "TextIOWrapper": "IO", # "TextIOBase, TextIO", # based on Stdlib + "FileIO": "IO", # "RawIOBase, BinaryIO", # based on Stdlib + "StringIO": "IO", # "BufferedIOBase, BinaryIO", # based on Stdlib + "BytesIO": "IO", # "BufferedIOBase, BinaryIO", # based on Stdlib + "BufferedWriter": "IOBase", # DOCME: not in documentation # "BufferedWriter": "BufferedIOBase", # based on Stdlib # uzlib # "DecompIO": "IO", # https://docs.python.org/3/library/typing.html#other-concrete-types # ------------------------------------------------------------------------------------- @@ -512,7 +514,7 @@ class Fix: "namedtuple": "tuple", "deque": "stdlib_deque", # ESPNow - "ESPNow": "ESPNowBase,Iterator", # causes issue with mypy + "ESPNow": "ESPNowBase,Iterator", # causes issue with mypy "AIOESPNow": "ESPNow", # array "array": "List", From ebbe95af8db94364ca4b46cf8073e6d077e5d919 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Sun, 28 Jan 2024 17:41:56 +0100 Subject: [PATCH 53/68] Update pytest workflow to trigger on pull requests Signed-off-by: Jos Verlinde --- .github/workflows/pytest.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 8226860e2..f4a71fc97 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -7,6 +7,9 @@ name: pytest on: workflow_dispatch: + pull_request: + # branches: [main] + # push: # paths: # - 'board/**' @@ -17,8 +20,6 @@ on: # - "poetry.lock" # - "pyrightconfig.json" - pull_request: - branches: [main] jobs: run_tests: From e21fdcb2536e2bd962e60054e694b6818a4aa3de Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 30 Jan 2024 22:07:19 +0100 Subject: [PATCH 54/68] Update createstubs.py and related files Signed-off-by: Jos Verlinde --- .env | 11 +- mip/v6/createstubs.py | 2 +- scripts/board_stubber.py | 99 +- src/stubber/board/createstubs.py | 127 +- src/stubber/board/createstubs_db.py | 320 ++-- src/stubber/board/createstubs_db_min.py | 1172 +++++---------- src/stubber/board/createstubs_db_mpy.mpy | Bin 8388 -> 10274 bytes src/stubber/board/createstubs_lvgl.py | 228 ++- src/stubber/board/createstubs_lvgl_min.py | 216 ++- src/stubber/board/createstubs_lvgl_mpy.mpy | Bin 7900 -> 9267 bytes src/stubber/board/createstubs_mem.py | 257 ++-- src/stubber/board/createstubs_mem_min.py | 1088 ++++---------- src/stubber/board/createstubs_mem_mpy.mpy | Bin 7905 -> 9588 bytes src/stubber/board/createstubs_min.py | 1295 ++++------------- src/stubber/board/createstubs_mpy.mpy | Bin 11031 -> 12701 bytes src/stubber/codemod/_partials/db_main.py | 108 +- .../codemod/_partials/modules_reader.py | 46 +- src/stubber/codemod/board.py | 6 +- src/stubber/minify.py | 81 +- src/stubber/variants.py | 4 +- tests/createstubs/createstubs_all_test.py | 1 - tests/createstubs/shared.py | 3 +- tests/createstubs/testcases.py | 28 +- tests/utils/repos_test.py | 1 - tmp_minified_1.py | 954 ------------ 25 files changed, 1669 insertions(+), 4378 deletions(-) delete mode 100644 tmp_minified_1.py diff --git a/.env b/.env index 60a4812aa..3661fc02e 100644 --- a/.env +++ b/.env @@ -1,8 +1,7 @@ # Python .env file .. -# Declutter Store all __pycache__ files in the .py_cache folder -PYTHONPYCACHEPREFIX = ".py_cache" - +JUPYTER_PLATFORM_DIRS=1 +PYDEVD_DISABLE_FILE_VALIDATION=1 # Allow tests to find sources PYTHONPATH = src @@ -10,4 +9,8 @@ PYTHONPATH = src PYDEVD_WARN_EVALUATION_TIMEOUT = 20 # stop nagging for updates -PIP_DISABLE_PIP_VERSION_CHECK=1 \ No newline at end of file +PIP_DISABLE_PIP_VERSION_CHECK=1 + +# stop neggin during debug +JUPYTER_PLATFORM_DIRS=1 +PYDEVD_DISABLE_FILE_VALIDATION=1 \ No newline at end of file diff --git a/mip/v6/createstubs.py b/mip/v6/createstubs.py index 71c910a58..98f6dacbf 100644 --- a/mip/v6/createstubs.py +++ b/mip/v6/createstubs.py @@ -148,7 +148,7 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + self.log.info("Start micropython-stubber {} on {}".format(__version__, self._fwid)) gc.collect() for module_name in self.modules: self.create_one_stub(module_name) diff --git a/scripts/board_stubber.py b/scripts/board_stubber.py index 718727ba3..f8ec54e8f 100644 --- a/scripts/board_stubber.py +++ b/scripts/board_stubber.py @@ -33,7 +33,7 @@ LOCAL_FILES = True ############################################################################################### -reset_before = False +reset_before = True ############################################################################################### @@ -85,7 +85,7 @@ def run( if not error_tags: error_tags = ["Traceback ", "Error: ", "Exception: ", "ERROR :", "CRIT :"] if not warning_tags: - warning_tags = ["WARN :"] # , "Module not found." + warning_tags = ["WARN :", "TRACE :"] # , "Module not found." if not success_tags: success_tags = ["Created stubs for", "Path: /remote"] if not ignore_tags: @@ -252,14 +252,14 @@ def run_command( """ if isinstance(cmd, str): cmd = cmd.split(" ") - prefix = [sys.executable, "-m" "mpremote", "connect", self.serialport] if self.serialport else ["mpremote"] + prefix = [sys.executable, "-m", "mpremote", "connect", self.serialport] if self.serialport else ["mpremote"] # if connected add resume to keep state between commands if self.connected: prefix += ["resume"] cmd = prefix + cmd log.debug(" ".join(cmd)) result = run(cmd, timeout, log_errors, no_info, **kwargs) - self.connected = True + self.connected = result[0] == OK return result @retry(stop=stop_after_attempt(RETRIES), wait=wait_fixed(1)) @@ -272,7 +272,7 @@ def mip_install(self, name: str) -> bool: return result -def copy_createstubs(board: MPRemoteBoard, variant: Variant, form: Form) -> bool: +def copy_createstubs_to_board(board: MPRemoteBoard, variant: Variant, form: Form) -> bool: # sourcery skip: assign-if-exp, boolean-if-exp-identity, remove-unnecessary-cast """Copy createstubs to the board""" # copy createstubs.py to the destination folder @@ -366,9 +366,9 @@ def run_createstubs(dest: Path, mcu: MPRemoteBoard, variant: Variant = Variant.d mcu.run_command("reset", timeout=5) time.sleep(2) - log.info(f"Running createstubs {variant} on {mcu.serialport} {mcu.description} using temp path: {dest}") + log.info(f"Running createstubs {variant.value} on {mcu.serialport} {mcu.description} using temp path: {dest}") cmd = build_cmd(dest, variant) - + log.info(f"Running : mpremote {' '.join(cmd)}") mcu.run_command.retry.wait = wait_fixed(15) # some boards need 2-3 minutes to run createstubs - so increase the default timeout # esp32s3 > 240 seconds with mounted fs @@ -406,7 +406,7 @@ def generate_board_stubs( host_mounted=True, ) -> Tuple[int, Optional[Path]]: """ - Generate the board stubs. + Generate the board stubs for this MCU board. Parameters ---------- dest : Path @@ -415,32 +415,13 @@ def generate_board_stubs( The port the board is connected to """ - board_info_path = Path(__file__).parent.parent / "src/stubber/data/board_info.csv" # HOST -> MCU : copy createstubs to board - if LOCAL_FILES: - ok = copy_createstubs(mcu, variant, form) - else: - if form == Form.min: - location = "github:josverl/micropython-stubber/mip/minified.json" - elif form == Form.mpy: - location = "github:josverl/micropython-stubber/mip/mpy_v6.json" - else: - location = "github:josverl/micropython-stubber/mip/full.json" - - ok = mcu.mip_install(location) - + ok = copy_scripts_to_board(mcu, variant, form) if not ok and not TESTING: log.warning("Error copying createstubs to board") return ERROR, None - if mcu.board: - cmd = ["exec", f"with open('lib/boardname.py', 'w') as f: f.write('BOARDNAME=\"{mcu.board}\"')"] - log.info(f"Writing BOARDNAME='{mcu.board}' to boardname.py") - else: - cmd = ["rm", "boardname.py"] - rc, _ = mcu.run_command(cmd) - if rc != OK and not "rm" in cmd: - log.error(f"Error during copy createstubs running command: {cmd}") + copy_boardname_to_board(mcu) rc, out = run_createstubs(dest, mcu, variant) # , host_mounted=host_mounted) @@ -478,6 +459,50 @@ def generate_board_stubs( return OK, stubs_path +def copy_boardname_to_board(mcu: MPRemoteBoard): + """ + Copies the board name to the board by writing it to the 'boardname.py' file. + + Args: + mcu: The MCU object representing the microcontroller. + + Returns: + None + """ + if mcu.board: + cmd = ["exec", f"with open('lib/boardname.py', 'w') as f: f.write('BOARDNAME=\"{mcu.board}\"')"] + log.info(f"Writing BOARDNAME='{mcu.board}' to boardname.py") + else: + cmd = ["rm", "boardname.py"] + rc, _ = mcu.run_command(cmd) + if rc != OK and "rm" not in cmd: + log.error(f"Error during copy createstubs running command: {cmd}") + + +def copy_scripts_to_board(mcu: MPRemoteBoard, variant: Variant, form: Form): + """ + Copy scripts to the board. + + Args: + mcu (str): The microcontroller unit. + variant (str): The variant of the board. + form (Form): The form of the scripts to be copied. + + Returns: + bool: True if the scripts are successfully copied, False otherwise. + """ + if LOCAL_FILES: + return copy_createstubs_to_board(mcu, variant, form) + if form == Form.min: + location = "github:josverl/micropython-stubber/mip/minified.json" + elif form == Form.mpy: + location = "github:josverl/micropython-stubber/mip/mpy_v6.json" + else: + location = "github:josverl/micropython-stubber/mip/full.json" + + return mcu.mip_install(location) + + def get_stubfolder(out: List[str]): return lines[-1].split("/remote/")[-1].strip() if (lines := [l for l in out if l.startswith("Path: ")]) else "" @@ -584,7 +609,19 @@ def find_board(descr: str, short_descr: str, filename: Path) -> Optional[str]: help="Python source or pre-compiled.", ) @click.option("--debug/--no-debug", default=False, show_default=True, help="Debug mode.") -def run_stubber(variant: str, format: str, debug: bool): +def run_stubber_connected_boards(variant: str, format: str, debug: bool): + """ + Runs the stubber to generate stubs for connected MicroPython boards. + + Args: + variant (str): The variant of the MicroPython board. + format (str): The format of the generated stubs. + debug (bool): Flag indicating whether to enable debug mode. + + Returns: + None + """ + if debug: set_loglevel(1) else: @@ -653,4 +690,4 @@ def run_stubber(variant: str, format: str, debug: bool): if __name__ == "__main__": - run_stubber() + run_stubber_connected_boards() diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index f8f45beb6..e72983523 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -4,7 +4,6 @@ # Copyright (c) 2019-2023 Jos Verlinde import gc -import logging import os import sys from time import sleep @@ -24,11 +23,61 @@ except ImportError: from ucollections import OrderedDict # type: ignore - __version__ = "v1.16.3" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] +LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] + + +# our own logging module to avoid dependency on and interfering with logging module +class logging: + DEBUG = 10 + TRACE = 15 + INFO = 20 + WARNING = 30 + ERROR = 40 + CRITICAL = 50 + level = INFO + prnt = print + + @staticmethod + def getLogger(name): + return logging() + + @classmethod + def basicConfig(cls, level): + cls.level = level + pass + + def trace(self, msg): + if self.level <= logging.TRACE: + self.prnt("TRACE :", msg) + + def debug(self, msg): + if self.level <= logging.DEBUG: + self.prnt("DEBUG :", msg) + + def info(self, msg): + if self.level <= logging.INFO: + self.prnt("INFO :", msg) + + def warning(self, msg): + if self.level <= logging.WARNING: + self.prnt("WARN :", msg) + + def error(self, msg): + if self.level <= logging.ERROR: + self.prnt("ERROR :", msg) + + def critical(self, msg): + if self.level <= logging.CRITICAL: + self.prnt("CRIT :", msg) + + +log = logging.getLogger("stubber") +logging.basicConfig(level=logging.INFO) +# logging.basicConfig(level=logging.TRACE) +# logging.basicConfig(level=logging.DEBUG) class Stubber: @@ -40,11 +89,10 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() - self.log.info("Port: {}".format(self.info["port"])) - self.log.info("Board: {}".format(self.info["board"])) + log.info("Port: {}".format(self.info["port"])) + log.info("Board: {}".format(self.info["board"])) gc.collect() if firmware_id: self._fwid = firmware_id.lower() @@ -62,11 +110,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore path = get_root() self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - self.log.debug(self.path) + log.debug(self.path) try: ensure_folder(path + "/") except OSError: - self.log.error("error creating stub folder {}".format(path)) + log.error("error creating stub folder {}".format(path)) self.problematic = [ "upip", "upysh", @@ -91,15 +139,15 @@ def get_obj_attributes(self, item_instance: object): # name_, repr_(value), type as text, item_instance _result = [] _errors = [] - self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): if name.startswith("_") and not name in self.modules: continue - self.log.debug("get attribute {}".format(name)) + log.debug("get attribute {}".format(name)) try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order - self.log.debug("attribute {}:{}".format(name, val)) + log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -132,18 +180,18 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) gc.collect() for module_name in self.modules: self.create_one_stub(module_name) - self.log.info("Finally done") + log.info("Finally done") def create_one_stub(self, module_name: str): if module_name in self.problematic: - self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False if module_name in self.excluded: - self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) @@ -178,10 +226,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + log.trace("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -203,12 +251,12 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] - self.log.warning("could not del new_module") + log.warning("could not del new_module") # lets not try - most times it does not work anyway # try: # del sys.modules[module_name] # except KeyError: - # self.log.warning("could not del sys.modules[{}]".format(module_name)) + # log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -216,14 +264,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: - self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # self.log.debug("DUMP : {}".format(object_expr)) + # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: - self.log.error(errors) + log.error(errors) for item_name, item_repr, item_type_txt, item_instance, _ in items: # name_, repr_(value), type as text, item_instance, order @@ -231,7 +279,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # do not create stubs for these primitives continue if item_name[0].isdigit(): - self.log.warning("NameError: invalid name {}".format(item_name)) + log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) if ( @@ -240,7 +288,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - self.log.info("{0}class {1}:".format(indent, item_name)) + log.trace("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -263,7 +311,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - self.log.debug("# recursion over class {0}".format(item_name)) + log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -277,7 +325,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -295,7 +343,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - self.log.debug("\n" + s) + log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -323,10 +371,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - self.log.debug("\n" + s) + log.debug("\n" + s) else: # keep only the name - self.log.debug("# all other, type = '{0}'".format(item_type_txt)) + log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -352,7 +400,7 @@ def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" if path is None: path = self.path - self.log.info("Clean/remove files in folder: {}".format(path)) + log.info("Clean/remove files in folder: {}".format(path)) try: os.stat(path) # TEMP workaround mpremote listdir bug - items = os.listdir(path) @@ -372,11 +420,9 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" - self.log.info( - "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) - ) + log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) - self.log.info("Report file: {}".format(f_name)) + log.info("Report file: {}".format(f_name)) gc.collect() try: # write json by node to reduce memory requirements @@ -388,9 +434,9 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - self.log.info("Memory used: {0} Kb".format(used // 1024)) + log.trace("Memory used: {0} Kb".format(used // 1024)) except OSError: - self.log.error("Failed to create the report.") + log.error("Failed to create the report.") def write_json_header(self, f): f.write("{") @@ -582,9 +628,10 @@ def get_boardname() -> str: "Read the board name from the boardname.py file that may have been created upfront" try: from boardname import BOARDNAME # type: ignore + log.info("Found BOARDNAME: {}".format(BOARDNAME)) except ImportError: - log.info("BOARDNAME not found") + log.warning("BOARDNAME not found") BOARDNAME = "" return BOARDNAME @@ -911,12 +958,6 @@ def main(): if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass if not file_exists("no_auto_stubber.txt"): try: gc.threshold(4 * 1024) # type: ignore diff --git a/src/stubber/board/createstubs_db.py b/src/stubber/board/createstubs_db.py index 392702f55..ccace6f89 100644 --- a/src/stubber/board/createstubs_db.py +++ b/src/stubber/board/createstubs_db.py @@ -23,7 +23,6 @@ # Copyright (c) 2019-2023 Jos Verlinde import gc -import logging import os import sys from time import sleep @@ -43,26 +42,61 @@ except ImportError: from ucollections import OrderedDict # type: ignore -try: - from nope_machine import WDT +__version__ = "v1.16.3" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] + + +# our own logging module to avoid dependency on and interfering with logging module +class logging: + DEBUG = 10 + TRACE = 15 + INFO = 20 + WARNING = 30 + ERROR = 40 + CRITICAL = 50 + level = INFO + prnt = print + + @staticmethod + def getLogger(name): + return logging() + + @classmethod + def basicConfig(cls, level): + cls.level = level + pass - wdt = WDT() + def trace(self, msg): + if self.level <= logging.TRACE: + self.prnt("TRACE :", msg) -except ImportError: + def debug(self, msg): + if self.level <= logging.DEBUG: + self.prnt("DEBUG :", msg) - class _WDT: - def feed(self): - pass + def info(self, msg): + if self.level <= logging.INFO: + self.prnt("INFO :", msg) - wdt = _WDT() + def warning(self, msg): + if self.level <= logging.WARNING: + self.prnt("WARN :", msg) + def error(self, msg): + if self.level <= logging.ERROR: + self.prnt("ERROR :", msg) -wdt.feed() + def critical(self, msg): + if self.level <= logging.CRITICAL: + self.prnt("CRIT :", msg) -__version__ = "v1.16.3" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] + +log = logging.getLogger("stubber") +logging.basicConfig(level=logging.INFO) +# logging.basicConfig(level=logging.TRACE) +# logging.basicConfig(level=logging.DEBUG) class Stubber: @@ -74,13 +108,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() - self.log.info("Port: {}".format(self.info["port"])) - self.log.info("Board: {}".format(self.info["board"])) + log.info("Port: {}".format(self.info["port"])) + log.info("Board: {}".format(self.info["board"])) gc.collect() - wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: @@ -97,11 +129,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore path = get_root() self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - self.log.debug(self.path) + log.debug(self.path) try: ensure_folder(path + "/") except OSError: - self.log.error("error creating stub folder {}".format(path)) + log.error("error creating stub folder {}".format(path)) self.problematic = [ "upip", "upysh", @@ -126,15 +158,15 @@ def get_obj_attributes(self, item_instance: object): # name_, repr_(value), type as text, item_instance _result = [] _errors = [] - self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): if name.startswith("_") and not name in self.modules: continue - self.log.debug("get attribute {}".format(name)) + log.debug("get attribute {}".format(name)) try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order - self.log.debug("attribute {}:{}".format(name, val)) + log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -167,19 +199,18 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) gc.collect() for module_name in self.modules: self.create_one_stub(module_name) - self.log.info("Finally done") + log.info("Finally done") def create_one_stub(self, module_name: str): - wdt.feed() if module_name in self.problematic: - self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False if module_name in self.excluded: - self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) @@ -214,10 +245,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + log.trace("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -237,12 +268,12 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] - self.log.warning("could not del new_module") + log.warning("could not del new_module") # lets not try - most times it does not work anyway # try: # del sys.modules[module_name] # except KeyError: - # self.log.warning("could not del sys.modules[{}]".format(module_name)) + # log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -250,14 +281,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: - self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # self.log.debug("DUMP : {}".format(object_expr)) + # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: - self.log.error(errors) + log.error(errors) for item_name, item_repr, item_type_txt, item_instance, _ in items: # name_, repr_(value), type as text, item_instance, order @@ -265,7 +296,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # do not create stubs for these primitives continue if item_name[0].isdigit(): - self.log.warning("NameError: invalid name {}".format(item_name)) + log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) if ( @@ -274,7 +305,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - self.log.info("{0}class {1}:".format(indent, item_name)) + log.trace("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -297,7 +328,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - self.log.debug("# recursion over class {0}".format(item_name)) + log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -311,7 +342,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -327,7 +358,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - self.log.debug("\n" + s) + log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -355,10 +386,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - self.log.debug("\n" + s) + log.debug("\n" + s) else: # keep only the name - self.log.debug("# all other, type = '{0}'".format(item_type_txt)) + log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -382,10 +413,9 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" - wdt.feed() if path is None: path = self.path - self.log.info("Clean/remove files in folder: {}".format(path)) + log.info("Clean/remove files in folder: {}".format(path)) try: os.stat(path) # TEMP workaround mpremote listdir bug - items = os.listdir(path) @@ -405,10 +435,9 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" - wdt.feed() - self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) + log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) - self.log.info("Report file: {}".format(f_name)) + log.info("Report file: {}".format(f_name)) gc.collect() try: # write json by node to reduce memory requirements @@ -420,9 +449,9 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - self.log.info("Memory used: {0} Kb".format(used // 1024)) + log.trace("Memory used: {0} Kb".format(used // 1024)) except OSError: - self.log.error("Failed to create the report.") + log.error("Failed to create the report.") def write_json_header(self, f): f.write("{") @@ -608,79 +637,16 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore + + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.warning("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable @@ -770,72 +736,86 @@ def main(): # get list of modules to process get_modulelist(stubber) # remove the ones that are already done - modules_done = {} # type: dict[str, str] - try: - with open("modulelist.done") as f: - # not optimal , but works on mpremote and esp8266 - for line in f.read().split("\n"): - line = line.strip() - gc.collect() - if len(line) > 0: - key, value = line.split("=", 1) - modules_done[key] = value - except (OSError, SyntaxError): - pass - gc.collect() + modules_done = read_done() # see if we can continue from where we left off - modules = [m for m in stubber.modules if m not in modules_done.keys()] - gc.collect() - for modulename in modules: - # ------------------------------------ - # do epic shit - # but sometimes things fail / run out of memory and reboot - ok = False - try: - ok = stubber.create_one_stub(modulename) - except MemoryError: - # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER - machine.reset() - # ------------------------------------- + modules = [m for m in stubber.modules if not m in modules_done.keys()] + if not modules: + print("All modules have been processed, exiting") + else: + del modules_done gc.collect() - modules_done[modulename] = str(stubber._report[-1] if ok else "failed") - with open("modulelist.done", "a") as f: - f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) + for modulename in modules: + # ------------------------------------ + # do epic shit + # but sometimes things fail / run out of memory and reboot + ok = False + try: + ok = stubber.create_one_stub(modulename) + except MemoryError: + # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER + machine.reset() + # ------------------------------------- + gc.collect() + # modules_done[modulename] = str(stubber._report[-1] if ok else "failed") + with open("modulelist.done", "a") as f: + f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) # Finished processing - load all the results , and remove the failed ones + modules_done = read_done() if modules_done: # stubber.write_json_end(mod_fp) - stubber._report = [v for _, v in modules_done.items() if v != "failed"] + stubber._report = [] + for k, v in modules_done.items(): + if v != "failed": + stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(k)) stubber.report() +def read_done(): + modules_done = {} # type: dict[str, str] + try: + with open("modulelist.done") as f: + while True: + line = f.readline().strip() + if not line: + break + if len(line) > 0 and line[0] != "#": + key, value = line.split("=", 1) + modules_done[key] = value + except (OSError, SyntaxError): + print("could not read modulelist.done") + finally: + gc.collect() + return modules_done + + def get_modulelist(stubber): + # new + gc.collect() stubber.modules = [] # avoid duplicates for p in LIBS: - try: - with open(p + "/modulelist.txt") as f: - print("DEBUG: list of modules: " + p + "/modulelist.txt") - for line in f.read().split("\n"): - line = line.strip() - if len(line) > 0 and line[0] != "#": - stubber.modules.append(line) - gc.collect() - break - except OSError: - pass + fname = p + "/modulelist.txt" + if not file_exists(fname): + continue + with open(fname) as f: + # print("DEBUG: list of modules: " + p + "/modulelist.txt") + while True: + line = f.readline().strip() + if not line: + break + if len(line) > 0 and line[0] != "#": + stubber.modules.append(line) + gc.collect() + print("BREAK") + break + if not stubber.modules: stubber.modules = ["micropython"] - _log.warn("Could not find modulelist.txt, using default modules") + # _log.warn("Could not find modulelist.txt, using default modules") gc.collect() if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass if not file_exists("no_auto_stubber.txt"): try: gc.threshold(4 * 1024) # type: ignore diff --git a/src/stubber/board/createstubs_db_min.py b/src/stubber/board/createstubs_db_min.py index 6f1f09732..474217d47 100644 --- a/src/stubber/board/createstubs_db_min.py +++ b/src/stubber/board/createstubs_db_min.py @@ -1,847 +1,331 @@ -""" -Create stubs for (all) modules on a MicroPython board. - - This variant of the createstubs.py script is optimized for use on very-low-memory devices. - Note: this version has undergone limited testing. - - 1) reads the list of modules from a text file `modulelist.txt` that should be uploaded to the device. - 2) stored the already processed modules in a text file `modulelist.done` - 3) process the modules in the database: - - stub the module - - update the modulelist.done file - - reboots the device if it runs out of memory - 4) creates the modules.json - - If that cannot be found then only a single module (micropython) is stubbed. - In order to run this on low-memory devices two additional steps are recommended: - - minification, using python-minifierto reduce overall size, and remove logging overhead. - - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device - - -This variant was generated from createstubs.py by micropython-stubber v1.16.3 -""" -# Copyright (c) 2019-2023 Jos Verlinde - -import gc -# import logging -import os -import sys +y='{}/{}' +x='method' +w='function' +v='bool' +u='str' +t='float' +s='int' +r='stubber' +q=TypeError +p=KeyError +o=sorted +n=MemoryError +m=NotImplementedError +g=',\n' +e='dict' +d='list' +c='tuple' +b='_' +a='micropython' +Y='modulelist.done' +X='-preview' +W='-' +V='board' +U=IndexError +T=repr +S='family' +R=ImportError +Q=dir +P=True +O=len +N=open +M='port' +L='.' +K=print +J=AttributeError +H=False +G='/' +F=None +E=OSError +D='version' +C='' +import gc as B,os,sys from time import sleep - -try: - from ujson import dumps -except: - from json import dumps - -try: - from machine import reset # type: ignore -except ImportError: - pass - -try: - from collections import OrderedDict -except ImportError: - from ucollections import OrderedDict # type: ignore - -try: - from nope_machine import WDT - - wdt = WDT() - -except ImportError: - - class _WDT: - def feed(self): - pass - - wdt = _WDT() - - -wdt.feed() - -__version__ = "v1.16.3" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] - - +try:from ujson import dumps +except:from json import dumps +try:from machine import reset +except R:pass +try:from collections import OrderedDict as f +except R:from ucollections import OrderedDict as f +__version__='v1.16.3' +z=2 +A0=2 +A1=['lib','/lib','/sd/lib','/flash/lib',L] +class I: + DEBUG=10;TRACE=15;INFO=20;WARNING=30;ERROR=40;CRITICAL=50;level=INFO;prnt=K + @staticmethod + def getLogger(name):return I() + @classmethod + def basicConfig(A,level):A.level=level + def trace(A,msg): + if A.level<=I.TRACE:A.prnt('TRACE :',msg) + def debug(A,msg): + if A.level<=I.DEBUG:A.prnt('DEBUG :',msg) + def info(A,msg): + if A.level<=I.INFO:A.prnt('INFO :',msg) + def warning(A,msg): + if A.level<=I.WARNING:A.prnt('WARN :',msg) + def error(A,msg): + if A.level<=I.ERROR:A.prnt('ERROR :',msg) + def critical(A,msg): + if A.level<=I.CRITICAL:A.prnt('CRIT :',msg) +A=I.getLogger(r) +I.basicConfig(level=I.INFO) class Stubber: - "Generate stubs for modules in firmware" - - def __init__(self, path: str = None, firmware_id: str = None): # type: ignore - try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore - raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") - except AttributeError: - pass - # self.log = logging.getLogger("stubber") - self._report = [] # type: list[str] - self.info = _info() - # self.log.info("Port: {}".format(self.info["port"])) - # self.log.info("Board: {}".format(self.info["board"])) - gc.collect() - wdt.feed() - if firmware_id: - self._fwid = firmware_id.lower() - else: - if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") - else: - self._fwid = "{family}-v{version}-{port}".format(**self.info) - self._start_free = gc.mem_free() # type: ignore - - if path: - if path.endswith("/"): - path = path[:-1] - else: - path = get_root() - - self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - # self.log.debug(self.path) - try: - ensure_folder(path + "/") - except OSError: - print("error creating stub folder {}".format(path)) - self.problematic = [ - "upip", - "upysh", - "webrepl_setup", - "http_client", - "http_client_ssl", - "http_server", - "http_server_ssl", - ] - self.excluded = [ - "webrepl", - "_webrepl", - "port_diag", - "example_sub_led.py", - "example_pub_button.py", - ] - # there is no option to discover modules from micropython, list is read from an external file. - self.modules = [] # type: list[str] - - def get_obj_attributes(self, item_instance: object): - "extract information of the objects members and attributes" - # name_, repr_(value), type as text, item_instance - _result = [] - _errors = [] - # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) - for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: - continue - # self.log.debug("get attribute {}".format(name)) - try: - val = getattr(item_instance, name) - # name , item_repr(value) , type as text, item_instance, order - # self.log.debug("attribute {}:{}".format(name, val)) - try: - type_text = repr(type(val)).split("'")[1] - except IndexError: - type_text = "" - if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: - order = 1 - elif type_text in {"function", "method"}: - order = 2 - elif type_text in ("class"): - order = 3 - else: - order = 4 - _result.append((name, repr(val), repr(type(val)), val, order)) - except AttributeError as e: - _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) - except MemoryError as e: - # print("MemoryError: {}".format(e)) - sleep(1) - reset() - - # remove internal __ - # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) - _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) - gc.collect() - return _result, _errors - - def add_modules(self, modules): - "Add additional modules to be exported" - self.modules = sorted(set(self.modules) | set(modules)) - - def create_all_stubs(self): - "Create stubs for all configured modules" - # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) - gc.collect() - for module_name in self.modules: - self.create_one_stub(module_name) - # self.log.info("Finally done") - - def create_one_stub(self, module_name: str): - wdt.feed() - if module_name in self.problematic: - # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) - return False - if module_name in self.excluded: - # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) - return False - - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) - gc.collect() - result = False - try: - result = self.create_module_stub(module_name, file_name) - except OSError: - return False - gc.collect() - return result - - def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore - """Create a Stub of a single python module - - Args: - - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. - """ - if file_name is None: - fname = module_name.replace(".", "_") + ".py" - file_name = self.path + "/" + fname - else: - fname = file_name.split("/")[-1] - - if "/" in module_name: - # for nested modules - module_name = module_name.replace("/", ".") - - # import the module (as new_module) to examine it - new_module = None - try: - new_module = __import__(module_name, None, None, ("*")) - m1 = gc.mem_free() # type: ignore - # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) - - except ImportError: - # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) - return False - - # Start a new file - ensure_folder(file_name) - with open(file_name, "w") as fp: - # todo: improve header - info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") - s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) - fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") - self.write_object_stub(fp, new_module, module_name, "") - - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) - - if module_name not in {"os", "sys", "logging", "gc"}: - # try to unload the module unless we use it - try: - del new_module - except (OSError, KeyError): # lgtm [py/unreachable-statement] - pass - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - pass - gc.collect() - return True - - def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): - "Write a module/object stub to an open file. Can be called recursive." - gc.collect() - if object_expr in self.problematic: - # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) - return - - # # self.log.debug("DUMP : {}".format(object_expr)) - items, errors = self.get_obj_attributes(object_expr) - - if errors: - print(errors) - - for item_name, item_repr, item_type_txt, item_instance, _ in items: - # name_, repr_(value), type as text, item_instance, order - if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: - # do not create stubs for these primitives - continue - if item_name[0].isdigit(): - # self.log.warning("NameError: invalid name {}".format(item_name)) - continue - # Class expansion only on first 3 levels (bit of a hack) - if ( - item_type_txt == "" - and len(indent) <= _MAX_CLASS_LEVEL * 4 - # and not obj_name.endswith(".Pin") - # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms - ): - # self.log.info("{0}class {1}:".format(indent, item_name)) - superclass = "" - is_exception = ( - item_name.endswith("Exception") - or item_name.endswith("Error") - or item_name - in [ - "KeyboardInterrupt", - "StopIteration", - "SystemExit", - ] - ) - if is_exception: - superclass = "Exception" - s = "\n{}class {}({}):\n".format(indent, item_name, superclass) - # s += indent + " ''\n" - if is_exception: - s += indent + " ...\n" - fp.write(s) - continue - # write classdef - fp.write(s) - # first write the class literals and methods - # self.log.debug("# recursion over class {0}".format(item_name)) - self.write_object_stub( - fp, - item_instance, - "{0}.{1}".format(obj_name, item_name), - indent + " ", - in_class + 1, - ) - # end with the __init__ method to make sure that the literals are defined - # Add __init__ - s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" - s += indent + " ...\n\n" - fp.write(s) - elif any(word in item_type_txt for word in ["method", "function", "closure"]): - # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) - # module Function or class method - # will accept any number of params - # return type Any/Incomplete - ret = "Incomplete" - first = "" - # Self parameter only on class methods/functions - if in_class > 0: - first = "self, " - # class method - add function decoration - if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) - else: - s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) - s += indent + " ...\n\n" - fp.write(s) - # self.log.debug("\n" + s) - elif item_type_txt == "": - # Skip imported modules - # fp.write("# import {}\n".format(item_name)) - pass - - elif item_type_txt.startswith(" dict[str, str] - info = OrderedDict( - { - "family": sys.implementation.name, - "version": "", - "build": "", - "ver": "", - "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "UNKNOWN", - "cpu": "", - "mpy": "", - "arch": "", - } - ) - # change port names to be consistent with the repo - if info["port"].startswith("pyb"): - info["port"] = "stm32" - elif info["port"] == "win32": - info["port"] = "windows" - elif info["port"] == "linux": - info["port"] = "unix" - try: - info["version"] = version_str(sys.implementation.version) # type: ignore - except AttributeError: - pass - try: - _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - # info["board"] = "with".join(_machine.split("with")[:-1]).strip() - info["board"] = _machine - info["cpu"] = _machine.split("with")[-1].strip() - info["mpy"] = ( - sys.implementation._mpy - if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy - if "mpy" in dir(sys.implementation) - else "" - ) - except (AttributeError, IndexError): - pass - gc.collect() - read_boardname(info) - gc.collect() - - try: - if "uname" in dir(os): # old - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - elif "version" in dir(sys): # new - # extract build from sys.version if available - info["build"] = _build(sys.version) - except (AttributeError, IndexError, TypeError): - pass - # avoid build hashes - # if info["build"] and len(info["build"]) > 5: - # info["build"] = "" - - if info["version"] == "" and sys.platform not in ("unix", "win32"): - try: - u = os.uname() # type: ignore - info["version"] = u.release - except (IndexError, AttributeError, TypeError): - pass - # detect families - for fam_name, mod_name, mod_thing in [ - ("pycopy", "pycopy", "const"), - ("pycom", "pycom", "FAT"), - ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), - ]: - try: - _t = __import__(mod_name, None, None, (mod_thing)) - info["family"] = fam_name - del _t - break - except (ImportError, KeyError): - pass - - if info["family"] == "ev3-pybricks": - info["release"] = "2.0.0" - - if info["family"] == "micropython": - info["version"] - if ( - info["version"] - and info["version"].endswith(".0") - and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 - and info["version"] <= "1.19.9" - ): - # versions from 1.10.0 to 1.20.0 do not have a micro .0 - info["version"] = info["version"][:-2] - - # spell-checker: disable - if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds - sys_mpy = int(info["mpy"]) - # .mpy architecture - arch = [ - None, - "x86", - "x64", - "armv6", - "armv6m", - "armv7m", - "armv7em", - "armv7emsp", - "armv7emdp", - "xtensa", - "xtensawin", - ][sys_mpy >> 10] - if arch: - info["arch"] = arch - # .mpy version.minor - info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) - if info["build"] and not info["version"].endswith("-preview"): - info["version"] = info["version"] + "-preview" - # simple to use version[-build] string - info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" - - return info - - -def version_str(version: tuple): # -> str: - v_str = ".".join([str(n) for n in version[:3]]) - if len(version) > 3 and version[3]: - v_str += "-" + version[3] - return v_str - - -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - # print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# # print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False - - -def get_root() -> str: # sourcery skip: use-assigned-variable - "Determine the root folder of the device" - try: - c = os.getcwd() - except (OSError, AttributeError): - # unix port - c = "." - r = c - for r in [c, "/sd", "/flash", "/", "."]: - try: - _ = os.stat(r) - break - except OSError: - continue - return r - - -def file_exists(filename: str): - try: - if os.stat(filename)[0] >> 14: - return True - return False - except OSError: - return False - - -def show_help(): - # print("-p, --path path to store the stubs in, defaults to '.'") - sys.exit(1) - - -def read_path() -> str: - "get --path from cmdline. [unix/win]" - path = "" - if len(sys.argv) == 3: - cmd = (sys.argv[1]).lower() - if cmd in ("--path", "-p"): - path = sys.argv[2] - else: - show_help() - elif len(sys.argv) == 2: - show_help() - return path - - -def is_micropython() -> bool: - "runtime test to determine full or micropython" - # pylint: disable=unused-variable,eval-used - try: - # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects - - # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented - # Micropython: NotImplementedError - b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] - - # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute - # Micropython: AttributeError - c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] - return False - except (NotImplementedError, AttributeError): - return True - - + def __init__(C,path=F,firmware_id=F): + D=firmware_id + try: + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') + except J:pass + C._report=[];C.info=_info();A.info('Port: {}'.format(C.info[M]));A.info('Board: {}'.format(C.info[V]));B.collect() + if D:C._fwid=D.lower() + elif C.info[S]==a:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info).rstrip(W) + else:C._fwid='{family}-v{version}-{port}'.format(**C.info) + C._start_free=B.mem_free() + if path: + if path.endswith(G):path=path[:-1] + else:path=get_root() + C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G);A.debug(C.path) + try:h(path+G) + except E:A.error('error creating stub folder {}'.format(path)) + C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] + def get_obj_attributes(N,item_instance): + E=item_instance;G=[];M=[];A.debug('get attributes {} {}'.format(T(E),E)) + for D in Q(E): + if D.startswith(b)and not D in N.modules:continue + A.debug('get attribute {}'.format(D)) + try: + F=getattr(E,D);A.debug('attribute {}:{}'.format(D,F)) + try:H=T(type(F)).split("'")[1] + except U:H=C + if H in{s,t,u,v,c,d,e}:I=1 + elif H in{w,x}:I=2 + elif H in'class':I=3 + else:I=4 + G.append((D,T(F),T(type(F)),F,I)) + except J as L:M.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(D,E,L)) + except n as L:K('MemoryError: {}'.format(L));sleep(1);reset() + G=o([A for A in G if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return G,M + def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) + def create_all_stubs(C): + A.info('Start micropython-stubber v{} on {}'.format(__version__,C._fwid));B.collect() + for D in C.modules:C.create_one_stub(D) + A.info('Finally done') + def create_one_stub(D,module_name): + C=module_name + if C in D.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(C));return H + if C in D.excluded:A.warning('Skip module: {:<25} : Excluded'.format(C));return H + I='{}/{}.py'.format(D.path,C.replace(L,G));B.collect();F=H + try:F=D.create_module_stub(C,I) + except E:return H + B.collect();return F + def create_module_stub(J,module_name,file_name=F): + I=file_name;D=module_name + if I is F:K=D.replace(L,b)+'.py';I=J.path+G+K + else:K=I.split(G)[-1] + if G in D:D=D.replace(G,L) + M=F + try:M=__import__(D,F,F,'*');Q=B.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(D,K,Q)) + except R:A.trace('Skip module: {:<25} {:<79}'.format(D,'Module not found.'));return H + h(I) + with N(I,'w')as O:S=str(J.info).replace('OrderedDict(',C).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,S,__version__);O.write(T);O.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(O,M,D,C) + J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,I.replace('\\',G))) + if D not in{'os','sys','logging','gc'}: + try:del M + except(E,p):A.warning('could not del new_module') + B.collect();return P + def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;F=indent;B.collect() + if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return + X,P=K.get_obj_attributes(L) + if P:A.error(P) + for(D,J,G,Y,a)in X: + if D in['classmethod','staticmethod','BaseException',M]:continue + if D[0].isdigit():A.warning('NameError: invalid name {}'.format(D));continue + if G==""and O(F)<=A0*4: + A.trace('{0}class {1}:'.format(F,D));Q=C;R=D.endswith(M)or D.endswith('Error')or D in['KeyboardInterrupt','StopIteration','SystemExit'] + if R:Q=M + E='\n{}class {}({}):\n'.format(F,D,Q) + if R:E+=F+' ...\n';I.write(E);continue + I.write(E);A.debug('# recursion over class {0}'.format(D));K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,D),F+' ',N+1);E=F+' def __init__(self, *argv, **kwargs) -> None:\n';E+=F+' ...\n\n';I.write(E) + elif any(A in G for A in[x,w,'closure']): + A.debug("# def {1} function/method/closure, type = '{0}'".format(G,D));S=U;T=C + if N>0:T='self, ' + if V in G or V in J:E='{}@classmethod\n'.format(F)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(F,D,S) + else:E='{}def {}({}*args, **kwargs) -> {}:\n'.format(F,D,T,S) + E+=F+' ...\n\n';I.write(E);A.debug('\n'+E) + elif G=="":0 + elif G.startswith("='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] + if E in A and A[E]: + G=int(A[E]);I=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if I:A[N]=I + A[E]='v{}.{}'.format(G&255,G>>8&3) + if A[B]and not A[D].endswith(X):A[D]=A[D]+X + A[K]=f"{A[D]}-{A[B]}"if A[B]else f"{A[D]}";return A +def A2(version): + A=version;B=L.join([str(A)for A in A[:3]]) + if O(A)>3 and A[3]:B+=W+A[3] + return B +def A3(): + try:from boardname import BOARDNAME as B;A.info('Found BOARDNAME: {}'.format(B)) + except R:A.warning('BOARDNAME not found');B=C + return B +def get_root(): + try:A=os.getcwd() + except(E,J):A=L + B=A + for B in[A,'/sd','/flash',G,L]: + try:C=os.stat(B);break + except E:continue + return B +def i(filename): + try: + if os.stat(filename)[0]>>14:return P + return H + except E:return H +def j():K("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) +def read_path(): + path=C + if O(sys.argv)==3: + A=sys.argv[1].lower() + if A in('--path','-p'):path=sys.argv[2] + else:j() + elif O(sys.argv)==2:j() + return path +def k(): + try:A=bytes('abc',encoding='utf8');B=k.__module__;return H + except(m,J):return P def main(): - import machine # type: ignore - - try: - f = open("modulelist.done", "r+b") - was_running = True - # print("Opened existing db") - except OSError: - f = open("modulelist.done", "w+b") - # print("created new db") - was_running = False - stubber = Stubber(path=read_path()) - - # f_name = "{}/{}".format(stubber.path, "modules.json") - if not was_running: - # Only clean folder if this is a first run - stubber.clean() - # get list of modules to process - get_modulelist(stubber) - # remove the ones that are already done - modules_done = {} # type: dict[str, str] - try: - with open("modulelist.done") as f: - # not optimal , but works on mpremote and esp8266 - for line in f.read().split("\n"): - line = line.strip() - gc.collect() - if len(line) > 0: - key, value = line.split("=", 1) - modules_done[key] = value - except (OSError, SyntaxError): - pass - gc.collect() - # see if we can continue from where we left off - modules = [m for m in stubber.modules if m not in modules_done.keys()] - gc.collect() - for modulename in modules: - # ------------------------------------ - # do epic shit - # but sometimes things fail / run out of memory and reboot - ok = False - try: - ok = stubber.create_one_stub(modulename) - except MemoryError: - # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER - machine.reset() - # ------------------------------------- - gc.collect() - modules_done[modulename] = str(stubber._report[-1] if ok else "failed") - with open("modulelist.done", "a") as f: - f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) - - # Finished processing - load all the results , and remove the failed ones - if modules_done: - # stubber.write_json_end(mod_fp) - stubber._report = [v for _, v in modules_done.items() if v != "failed"] - stubber.report() - - -def get_modulelist(stubber): - stubber.modules = [] # avoid duplicates - for p in LIBS: - try: - with open(p + "/modulelist.txt") as f: - print ("DEBUG: list of modules: " + p + "/modulelist.txt") - for line in f.read().split("\n"): - line = line.strip() - if len(line) > 0 and line[0] != "#": - stubber.modules.append(line) - gc.collect() - break - except OSError: - pass - if not stubber.modules: - stubber.modules = ["micropython"] - _log.warn("Could not find modulelist.txt, using default modules") - gc.collect() - - -if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass - if not file_exists("no_auto_stubber.txt"): - try: - gc.threshold(4 * 1024) # type: ignore - gc.enable() - except BaseException: - pass - main() + J='failed';import machine as L + try:C=N(Y,'r+b');D=P;K('Opened existing db') + except E:C=N(Y,'w+b');K('created new db');D=H + stubber=Stubber(path=read_path()) + if not D:stubber.clean() + A4(stubber);A=l();F=[B for B in stubber.modules if not B in A.keys()] + if not F:K('All modules have been processed, exiting') + else: + del A;B.collect() + for G in F: + I=H + try:I=stubber.create_one_stub(G) + except n:L.reset() + B.collect() + with N(Y,'a')as C:C.write('{}={}\n'.format(G,'ok'if I else J)) + A=l() + if A: + stubber._report=[] + for(M,O)in A.items(): + if O!=J:stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(M)) + stubber.report() +def l(): + C={} + try: + with N(Y)as D: + while P: + A=D.readline().strip() + if not A:break + if O(A)>0 and A[0]!='#':F,G=A.split('=',1);C[F]=G + except(E,SyntaxError):K('could not read modulelist.done') + finally:B.collect();return C +def A4(stubber): + B.collect();stubber.modules=[] + for D in A1: + C=D+'/modulelist.txt' + if not i(C):continue + with N(C)as E: + while P: + A=E.readline().strip() + if not A:break + if O(A)>0 and A[0]!='#':stubber.modules.append(A) + B.collect();K('BREAK');break + if not stubber.modules:stubber.modules=[a] + B.collect() +if __name__=='__main__'or k(): + if not i('no_auto_stubber.txt'): + try:B.threshold(4*1024);B.enable() + except BaseException:pass + main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_db_mpy.mpy b/src/stubber/board/createstubs_db_mpy.mpy index 029c6ff35c46c024cccecb00b4c91a26dd06a4a0..f7e6e9a0c753a75ace24bd3b1964c738870ab64b 100644 GIT binary patch literal 10274 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%0Ar&jf3@S4Ph5QEM-v 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 diff --git a/src/stubber/board/createstubs_lvgl.py b/src/stubber/board/createstubs_lvgl.py index 0f5624b55..c060fb810 100644 --- a/src/stubber/board/createstubs_lvgl.py +++ b/src/stubber/board/createstubs_lvgl.py @@ -3,12 +3,11 @@ Note that the stubs can be very large, and it may be best to directly store them on an SD card if your device supports this. -This variant was generated from createstubs.py by micropython-stubber v1.16.2 +This variant was generated from createstubs.py by micropython-stubber v1.16.3 """ # Copyright (c) 2019-2023 Jos Verlinde import gc -import logging import os import sys from time import sleep @@ -28,26 +27,61 @@ except ImportError: from ucollections import OrderedDict # type: ignore -try: - from nope_machine import WDT +__version__ = "v1.16.3" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] + + +# our own logging module to avoid dependency on and interfering with logging module +class logging: + DEBUG = 10 + TRACE = 15 + INFO = 20 + WARNING = 30 + ERROR = 40 + CRITICAL = 50 + level = INFO + prnt = print + + @staticmethod + def getLogger(name): + return logging() + + @classmethod + def basicConfig(cls, level): + cls.level = level + pass - wdt = WDT() + def trace(self, msg): + if self.level <= logging.TRACE: + self.prnt("TRACE :", msg) -except ImportError: + def debug(self, msg): + if self.level <= logging.DEBUG: + self.prnt("DEBUG :", msg) - class _WDT: - def feed(self): - pass + def info(self, msg): + if self.level <= logging.INFO: + self.prnt("INFO :", msg) - wdt = _WDT() + def warning(self, msg): + if self.level <= logging.WARNING: + self.prnt("WARN :", msg) + def error(self, msg): + if self.level <= logging.ERROR: + self.prnt("ERROR :", msg) -wdt.feed() + def critical(self, msg): + if self.level <= logging.CRITICAL: + self.prnt("CRIT :", msg) -__version__ = "v1.16.2" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] + +log = logging.getLogger("stubber") +logging.basicConfig(level=logging.INFO) +# logging.basicConfig(level=logging.TRACE) +# logging.basicConfig(level=logging.DEBUG) class Stubber: @@ -59,13 +93,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() - self.log.info("Port: {}".format(self.info["port"])) - self.log.info("Board: {}".format(self.info["board"])) + log.info("Port: {}".format(self.info["port"])) + log.info("Board: {}".format(self.info["board"])) gc.collect() - wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: @@ -82,11 +114,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore path = get_root() self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - self.log.debug(self.path) + log.debug(self.path) try: ensure_folder(path + "/") except OSError: - self.log.error("error creating stub folder {}".format(path)) + log.error("error creating stub folder {}".format(path)) self.problematic = [ "upip", "upysh", @@ -111,15 +143,15 @@ def get_obj_attributes(self, item_instance: object): # name_, repr_(value), type as text, item_instance _result = [] _errors = [] - self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): if name.startswith("_") and not name in self.modules: continue - self.log.debug("get attribute {}".format(name)) + log.debug("get attribute {}".format(name)) try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order - self.log.debug("attribute {}:{}".format(name, val)) + log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -152,19 +184,18 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) gc.collect() for module_name in self.modules: self.create_one_stub(module_name) - self.log.info("Finally done") + log.info("Finally done") def create_one_stub(self, module_name: str): - wdt.feed() if module_name in self.problematic: - self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False if module_name in self.excluded: - self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) @@ -199,10 +230,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + log.trace("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -210,9 +241,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: with open(file_name, "w") as fp: # todo: improve header info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") - s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format( - module_name, self._fwid, info_, __version__ - ) + s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") @@ -224,12 +253,12 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] - self.log.warning("could not del new_module") + log.warning("could not del new_module") # lets not try - most times it does not work anyway # try: # del sys.modules[module_name] # except KeyError: - # self.log.warning("could not del sys.modules[{}]".format(module_name)) + # log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -237,14 +266,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: - self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # self.log.debug("DUMP : {}".format(object_expr)) + # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: - self.log.error(errors) + log.error(errors) for item_name, item_repr, item_type_txt, item_instance, _ in items: # name_, repr_(value), type as text, item_instance, order @@ -252,7 +281,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # do not create stubs for these primitives continue if item_name[0].isdigit(): - self.log.warning("NameError: invalid name {}".format(item_name)) + log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) if ( @@ -261,7 +290,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - self.log.info("{0}class {1}:".format(indent, item_name)) + log.trace("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -284,7 +313,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - self.log.debug("# recursion over class {0}".format(item_name)) + log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -298,7 +327,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -309,14 +338,12 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, first = "self, " # class method - add function decoration if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format( - indent, item_name, ret - ) + s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) else: s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - self.log.debug("\n" + s) + log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -344,10 +371,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - self.log.debug("\n" + s) + log.debug("\n" + s) else: # keep only the name - self.log.debug("# all other, type = '{0}'".format(item_type_txt)) + log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -371,10 +398,9 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" - wdt.feed() if path is None: path = self.path - self.log.info("Clean/remove files in folder: {}".format(path)) + log.info("Clean/remove files in folder: {}".format(path)) try: os.stat(path) # TEMP workaround mpremote listdir bug - items = os.listdir(path) @@ -394,12 +420,9 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" - wdt.feed() - self.log.info( - "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) - ) + log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) - self.log.info("Report file: {}".format(f_name)) + log.info("Report file: {}".format(f_name)) gc.collect() try: # write json by node to reduce memory requirements @@ -411,9 +434,9 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - self.log.info("Memory used: {0} Kb".format(used // 1024)) + log.trace("Memory used: {0} Kb".format(used // 1024)) except OSError: - self.log.error("Failed to create the report.") + log.error("Failed to create the report.") def write_json_header(self, f): f.write("{") @@ -599,79 +622,16 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore + + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.warning("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable @@ -772,12 +732,6 @@ def main(): if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass if not file_exists("no_auto_stubber.txt"): try: gc.threshold(4 * 1024) # type: ignore diff --git a/src/stubber/board/createstubs_lvgl_min.py b/src/stubber/board/createstubs_lvgl_min.py index cdab9a5ad..827b5fb86 100644 --- a/src/stubber/board/createstubs_lvgl_min.py +++ b/src/stubber/board/createstubs_lvgl_min.py @@ -3,12 +3,11 @@ Note that the stubs can be very large, and it may be best to directly store them on an SD card if your device supports this. -This variant was generated from createstubs.py by micropython-stubber v1.16.2 +This variant was generated from createstubs.py by micropython-stubber v1.16.3 """ # Copyright (c) 2019-2023 Jos Verlinde import gc -# import logging import os import sys from time import sleep @@ -28,26 +27,61 @@ except ImportError: from ucollections import OrderedDict # type: ignore -try: - from nope_machine import WDT +__version__ = "v1.16.3" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] + + +# our own logging module to avoid dependency on and interfering with logging module +class logging: + DEBUG = 10 + TRACE = 15 + INFO = 20 + WARNING = 30 + ERROR = 40 + CRITICAL = 50 + level = INFO + prnt = print + + @staticmethod + def getLogger(name): + return logging() + + @classmethod + def basicConfig(cls, level): + cls.level = level + pass - wdt = WDT() + def trace(self, msg): + if self.level <= logging.TRACE: + self.prnt("TRACE :", msg) -except ImportError: + def debug(self, msg): + if self.level <= logging.DEBUG: + self.prnt("DEBUG :", msg) - class _WDT: - def feed(self): - pass + def info(self, msg): + if self.level <= logging.INFO: + self.prnt("INFO :", msg) - wdt = _WDT() + def warning(self, msg): + if self.level <= logging.WARNING: + self.prnt("WARN :", msg) + def error(self, msg): + if self.level <= logging.ERROR: + self.prnt("ERROR :", msg) -wdt.feed() + def critical(self, msg): + if self.level <= logging.CRITICAL: + self.prnt("CRIT :", msg) -__version__ = "v1.16.2" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] + +log = logging.getLogger("stubber") +logging.basicConfig(level=logging.INFO) +# logging.basicConfig(level=logging.TRACE) +# logging.basicConfig(level=logging.DEBUG) class Stubber: @@ -59,13 +93,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - # self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() - # self.log.info("Port: {}".format(self.info["port"])) - # self.log.info("Board: {}".format(self.info["board"])) + log.info("Port: {}".format(self.info["port"])) + log.info("Board: {}".format(self.info["board"])) gc.collect() - wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: @@ -82,7 +114,7 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore path = get_root() self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - # self.log.debug(self.path) + log.debug(self.path) try: ensure_folder(path + "/") except OSError: @@ -111,15 +143,15 @@ def get_obj_attributes(self, item_instance: object): # name_, repr_(value), type as text, item_instance _result = [] _errors = [] - # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): if name.startswith("_") and not name in self.modules: continue - # self.log.debug("get attribute {}".format(name)) + log.debug("get attribute {}".format(name)) try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order - # self.log.debug("attribute {}:{}".format(name, val)) + log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -152,19 +184,18 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) gc.collect() for module_name in self.modules: self.create_one_stub(module_name) - # self.log.info("Finally done") + log.info("Finally done") def create_one_stub(self, module_name: str): - wdt.feed() if module_name in self.problematic: - # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False if module_name in self.excluded: - # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) @@ -199,10 +230,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + log.trace("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -222,12 +253,12 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] - pass + log.warning("could not del new_module") # lets not try - most times it does not work anyway # try: # del sys.modules[module_name] # except KeyError: - pass + # log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -235,10 +266,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: - # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # # self.log.debug("DUMP : {}".format(object_expr)) + # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: @@ -250,7 +281,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # do not create stubs for these primitives continue if item_name[0].isdigit(): - # self.log.warning("NameError: invalid name {}".format(item_name)) + log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) if ( @@ -259,7 +290,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - # self.log.info("{0}class {1}:".format(indent, item_name)) + log.trace("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -282,7 +313,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - # self.log.debug("# recursion over class {0}".format(item_name)) + log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -296,7 +327,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -312,7 +343,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - # self.log.debug("\n" + s) + log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -340,10 +371,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - # self.log.debug("\n" + s) + log.debug("\n" + s) else: # keep only the name - # self.log.debug("# all other, type = '{0}'".format(item_type_txt)) + log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -367,10 +398,9 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" - wdt.feed() if path is None: path = self.path - # self.log.info("Clean/remove files in folder: {}".format(path)) + log.info("Clean/remove files in folder: {}".format(path)) try: os.stat(path) # TEMP workaround mpremote listdir bug - items = os.listdir(path) @@ -390,10 +420,9 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" - wdt.feed() - # self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) + log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) - # self.log.info("Report file: {}".format(f_name)) + log.info("Report file: {}".format(f_name)) gc.collect() try: # write json by node to reduce memory requirements @@ -405,7 +434,7 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - # self.log.info("Memory used: {0} Kb".format(used // 1024)) + log.trace("Memory used: {0} Kb".format(used // 1024)) except OSError: print("Failed to create the report.") @@ -505,9 +534,7 @@ def _info(): # type:() -> dict[str, str] ) except (AttributeError, IndexError): pass - gc.collect() - read_boardname(info) - gc.collect() + info["board"] = get_boardname() try: if "uname" in dir(os): # old @@ -595,79 +622,16 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - # print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# # print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore + + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.warning("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable @@ -768,12 +732,6 @@ def main(): if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass if not file_exists("no_auto_stubber.txt"): try: gc.threshold(4 * 1024) # type: ignore diff --git a/src/stubber/board/createstubs_lvgl_mpy.mpy b/src/stubber/board/createstubs_lvgl_mpy.mpy index 0022ec0e3c6cfbdd92f1fb64b7a901b88a91cf08..a2ddea2665bf32c15a3a89962559e2e78a59cb73 100644 GIT binary patch literal 9267 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 delta 4956 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 bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + log.trace("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -228,12 +259,12 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] - self.log.warning("could not del new_module") + log.warning("could not del new_module") # lets not try - most times it does not work anyway # try: # del sys.modules[module_name] # except KeyError: - # self.log.warning("could not del sys.modules[{}]".format(module_name)) + # log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -241,14 +272,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: - self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # self.log.debug("DUMP : {}".format(object_expr)) + # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: - self.log.error(errors) + log.error(errors) for item_name, item_repr, item_type_txt, item_instance, _ in items: # name_, repr_(value), type as text, item_instance, order @@ -256,7 +287,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # do not create stubs for these primitives continue if item_name[0].isdigit(): - self.log.warning("NameError: invalid name {}".format(item_name)) + log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) if ( @@ -265,7 +296,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - self.log.info("{0}class {1}:".format(indent, item_name)) + log.trace("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -288,7 +319,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - self.log.debug("# recursion over class {0}".format(item_name)) + log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -302,7 +333,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -318,7 +349,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - self.log.debug("\n" + s) + log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -346,10 +377,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - self.log.debug("\n" + s) + log.debug("\n" + s) else: # keep only the name - self.log.debug("# all other, type = '{0}'".format(item_type_txt)) + log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -373,10 +404,9 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" - wdt.feed() if path is None: path = self.path - self.log.info("Clean/remove files in folder: {}".format(path)) + log.info("Clean/remove files in folder: {}".format(path)) try: os.stat(path) # TEMP workaround mpremote listdir bug - items = os.listdir(path) @@ -396,10 +426,9 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" - wdt.feed() - self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) + log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) - self.log.info("Report file: {}".format(f_name)) + log.info("Report file: {}".format(f_name)) gc.collect() try: # write json by node to reduce memory requirements @@ -411,9 +440,9 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - self.log.info("Memory used: {0} Kb".format(used // 1024)) + log.trace("Memory used: {0} Kb".format(used // 1024)) except OSError: - self.log.error("Failed to create the report.") + log.error("Failed to create the report.") def write_json_header(self, f): f.write("{") @@ -599,79 +628,16 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore + + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.warning("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable @@ -749,26 +715,33 @@ def main(): stubber.clean() # Read stubs from modulelist in the current folder or in /libs # fall back to default modules - stubber.modules = [] # avoid duplicates - for p in LIBS: - try: - _1 = gc.mem_free() # type: ignore - with open(p + "/modulelist.txt") as f: - print("Debug: List of modules: " + p + "/modulelist.txt") - line = f.readline() - while line: - line = line.strip() + def get_modulelist(stubber): + # new + gc.collect() + stubber.modules = [] # avoid duplicates + for p in LIBS: + fname = p + "/modulelist.txt" + if not file_exists(fname): + continue + with open(fname) as f: + # print("DEBUG: list of modules: " + p + "/modulelist.txt") + while True: + line = f.readline().strip() + if not line: + break if len(line) > 0 and line[0] != "#": stubber.modules.append(line) - line = f.readline() - gc.collect() # type: ignore - print("Debug: Used memory to load modulelist.txt: " + str(_1 - gc.mem_free()) + " bytes") # type: ignore + gc.collect() + print("BREAK") break - except Exception: - pass - if not stubber.modules: - stubber.modules = ["micropython"] - print("Could not find modulelist.txt, using default modules") + + if not stubber.modules: + stubber.modules = ["micropython"] + # _log.warn("Could not find modulelist.txt, using default modules") + gc.collect() + + stubber.modules = [] # avoid duplicates + get_modulelist(stubber) gc.collect() @@ -777,12 +750,6 @@ def main(): if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass if not file_exists("no_auto_stubber.txt"): try: gc.threshold(4 * 1024) # type: ignore diff --git a/src/stubber/board/createstubs_mem_min.py b/src/stubber/board/createstubs_mem_min.py index 262820233..6e136fe17 100644 --- a/src/stubber/board/createstubs_mem_min.py +++ b/src/stubber/board/createstubs_mem_min.py @@ -1,794 +1,300 @@ -"""Create stubs for (all) modules on a MicroPython board. - - This variant of the createstubs.py script is optimised for use on low-memory devices, and reads the list of modules from a text file - `modulelist.txt` in the root or `libs` folder that should be uploaded to the device. - If that cannot be found then only a single module (micropython) is stubbed. - In order to run this on low-memory devices two additional steps are recommended: - - minifification, using python-minifier - to reduce overall size, and remove logging overhead. - - cross compilation, using mpy-cross, - to avoid the compilation step on the micropython device - -This variant was generated from createstubs.py by micropython-stubber v1.16.3 -""" -# Copyright (c) 2019-2023 Jos Verlinde - -import gc -# import logging -import os -import sys +v='{}/{}' +u='method' +t='function' +s='bool' +r='str' +q='float' +p='int' +o='stubber' +n=TypeError +m=KeyError +l=sorted +k=NotImplementedError +e=',\n' +d='dict' +c='list' +b='tuple' +a='_' +Z='micropython' +Y=open +W='-preview' +V='-' +U='board' +T=IndexError +S=repr +R=print +Q=True +P='family' +O=ImportError +N=len +M=dir +L='port' +K='.' +J=False +I=AttributeError +G='/' +F=None +D=OSError +C='version' +B='' +import gc as E,os,sys from time import sleep - -try: - from ujson import dumps -except: - from json import dumps - -try: - from machine import reset # type: ignore -except ImportError: - pass - -try: - from collections import OrderedDict -except ImportError: - from ucollections import OrderedDict # type: ignore - -try: - from nope_machine import WDT - - wdt = WDT() - -except ImportError: - - class _WDT: - def feed(self): - pass - - wdt = _WDT() - - -wdt.feed() - -__version__ = "v1.16.3" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] - - +try:from ujson import dumps +except:from json import dumps +try:from machine import reset +except O:pass +try:from collections import OrderedDict as f +except O:from ucollections import OrderedDict as f +__version__='v1.16.3' +w=2 +x=2 +y=['lib','/lib','/sd/lib','/flash/lib',K] +class H: + DEBUG=10;TRACE=15;INFO=20;WARNING=30;ERROR=40;CRITICAL=50;level=INFO;prnt=R + @staticmethod + def getLogger(name):return H() + @classmethod + def basicConfig(A,level):A.level=level + def trace(A,msg): + if A.level<=H.TRACE:A.prnt('TRACE :',msg) + def debug(A,msg): + if A.level<=H.DEBUG:A.prnt('DEBUG :',msg) + def info(A,msg): + if A.level<=H.INFO:A.prnt('INFO :',msg) + def warning(A,msg): + if A.level<=H.WARNING:A.prnt('WARN :',msg) + def error(A,msg): + if A.level<=H.ERROR:A.prnt('ERROR :',msg) + def critical(A,msg): + if A.level<=H.CRITICAL:A.prnt('CRIT :',msg) +A=H.getLogger(o) +H.basicConfig(level=H.INFO) class Stubber: - "Generate stubs for modules in firmware" - - def __init__(self, path: str = None, firmware_id: str = None): # type: ignore - try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore - raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") - except AttributeError: - pass - # self.log = logging.getLogger("stubber") - self._report = [] # type: list[str] - self.info = _info() - # self.log.info("Port: {}".format(self.info["port"])) - # self.log.info("Board: {}".format(self.info["board"])) - gc.collect() - wdt.feed() - if firmware_id: - self._fwid = firmware_id.lower() - else: - if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") - else: - self._fwid = "{family}-v{version}-{port}".format(**self.info) - self._start_free = gc.mem_free() # type: ignore - - if path: - if path.endswith("/"): - path = path[:-1] - else: - path = get_root() - - self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - # self.log.debug(self.path) - try: - ensure_folder(path + "/") - except OSError: - print("error creating stub folder {}".format(path)) - self.problematic = [ - "upip", - "upysh", - "webrepl_setup", - "http_client", - "http_client_ssl", - "http_server", - "http_server_ssl", - ] - self.excluded = [ - "webrepl", - "_webrepl", - "port_diag", - "example_sub_led.py", - "example_pub_button.py", - ] - # there is no option to discover modules from micropython, list is read from an external file. - self.modules = [] # type: list[str] - - def get_obj_attributes(self, item_instance: object): - "extract information of the objects members and attributes" - # name_, repr_(value), type as text, item_instance - _result = [] - _errors = [] - # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) - for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: - continue - # self.log.debug("get attribute {}".format(name)) - try: - val = getattr(item_instance, name) - # name , item_repr(value) , type as text, item_instance, order - # self.log.debug("attribute {}:{}".format(name, val)) - try: - type_text = repr(type(val)).split("'")[1] - except IndexError: - type_text = "" - if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: - order = 1 - elif type_text in {"function", "method"}: - order = 2 - elif type_text in ("class"): - order = 3 - else: - order = 4 - _result.append((name, repr(val), repr(type(val)), val, order)) - except AttributeError as e: - _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) - except MemoryError as e: - # print("MemoryError: {}".format(e)) - sleep(1) - reset() - - # remove internal __ - # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) - _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) - gc.collect() - return _result, _errors - - def add_modules(self, modules): - "Add additional modules to be exported" - self.modules = sorted(set(self.modules) | set(modules)) - - def create_all_stubs(self): - "Create stubs for all configured modules" - # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) - gc.collect() - for module_name in self.modules: - self.create_one_stub(module_name) - # self.log.info("Finally done") - - def create_one_stub(self, module_name: str): - wdt.feed() - if module_name in self.problematic: - # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) - return False - if module_name in self.excluded: - # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) - return False - - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) - gc.collect() - result = False - try: - result = self.create_module_stub(module_name, file_name) - except OSError: - return False - gc.collect() - return result - - def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore - """Create a Stub of a single python module - - Args: - - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. - """ - if file_name is None: - fname = module_name.replace(".", "_") + ".py" - file_name = self.path + "/" + fname - else: - fname = file_name.split("/")[-1] - - if "/" in module_name: - # for nested modules - module_name = module_name.replace("/", ".") - - # import the module (as new_module) to examine it - new_module = None - try: - new_module = __import__(module_name, None, None, ("*")) - m1 = gc.mem_free() # type: ignore - # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) - - except ImportError: - # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) - return False - - # Start a new file - ensure_folder(file_name) - with open(file_name, "w") as fp: - # todo: improve header - info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") - s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) - fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") - self.write_object_stub(fp, new_module, module_name, "") - - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) - - if module_name not in {"os", "sys", "logging", "gc"}: - # try to unload the module unless we use it - try: - del new_module - except (OSError, KeyError): # lgtm [py/unreachable-statement] - pass - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - pass - gc.collect() - return True - - def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): - "Write a module/object stub to an open file. Can be called recursive." - gc.collect() - if object_expr in self.problematic: - # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) - return - - # # self.log.debug("DUMP : {}".format(object_expr)) - items, errors = self.get_obj_attributes(object_expr) - - if errors: - print(errors) - - for item_name, item_repr, item_type_txt, item_instance, _ in items: - # name_, repr_(value), type as text, item_instance, order - if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: - # do not create stubs for these primitives - continue - if item_name[0].isdigit(): - # self.log.warning("NameError: invalid name {}".format(item_name)) - continue - # Class expansion only on first 3 levels (bit of a hack) - if ( - item_type_txt == "" - and len(indent) <= _MAX_CLASS_LEVEL * 4 - # and not obj_name.endswith(".Pin") - # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms - ): - # self.log.info("{0}class {1}:".format(indent, item_name)) - superclass = "" - is_exception = ( - item_name.endswith("Exception") - or item_name.endswith("Error") - or item_name - in [ - "KeyboardInterrupt", - "StopIteration", - "SystemExit", - ] - ) - if is_exception: - superclass = "Exception" - s = "\n{}class {}({}):\n".format(indent, item_name, superclass) - # s += indent + " ''\n" - if is_exception: - s += indent + " ...\n" - fp.write(s) - continue - # write classdef - fp.write(s) - # first write the class literals and methods - # self.log.debug("# recursion over class {0}".format(item_name)) - self.write_object_stub( - fp, - item_instance, - "{0}.{1}".format(obj_name, item_name), - indent + " ", - in_class + 1, - ) - # end with the __init__ method to make sure that the literals are defined - # Add __init__ - s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" - s += indent + " ...\n\n" - fp.write(s) - elif any(word in item_type_txt for word in ["method", "function", "closure"]): - # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) - # module Function or class method - # will accept any number of params - # return type Any/Incomplete - ret = "Incomplete" - first = "" - # Self parameter only on class methods/functions - if in_class > 0: - first = "self, " - # class method - add function decoration - if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) - else: - s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) - s += indent + " ...\n\n" - fp.write(s) - # self.log.debug("\n" + s) - elif item_type_txt == "": - # Skip imported modules - # fp.write("# import {}\n".format(item_name)) - pass - - elif item_type_txt.startswith(" dict[str, str] - info = OrderedDict( - { - "family": sys.implementation.name, - "version": "", - "build": "", - "ver": "", - "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "UNKNOWN", - "cpu": "", - "mpy": "", - "arch": "", - } - ) - # change port names to be consistent with the repo - if info["port"].startswith("pyb"): - info["port"] = "stm32" - elif info["port"] == "win32": - info["port"] = "windows" - elif info["port"] == "linux": - info["port"] = "unix" - try: - info["version"] = version_str(sys.implementation.version) # type: ignore - except AttributeError: - pass - try: - _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - # info["board"] = "with".join(_machine.split("with")[:-1]).strip() - info["board"] = _machine - info["cpu"] = _machine.split("with")[-1].strip() - info["mpy"] = ( - sys.implementation._mpy - if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy - if "mpy" in dir(sys.implementation) - else "" - ) - except (AttributeError, IndexError): - pass - gc.collect() - read_boardname(info) - gc.collect() - - try: - if "uname" in dir(os): # old - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - elif "version" in dir(sys): # new - # extract build from sys.version if available - info["build"] = _build(sys.version) - except (AttributeError, IndexError, TypeError): - pass - # avoid build hashes - # if info["build"] and len(info["build"]) > 5: - # info["build"] = "" - - if info["version"] == "" and sys.platform not in ("unix", "win32"): - try: - u = os.uname() # type: ignore - info["version"] = u.release - except (IndexError, AttributeError, TypeError): - pass - # detect families - for fam_name, mod_name, mod_thing in [ - ("pycopy", "pycopy", "const"), - ("pycom", "pycom", "FAT"), - ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), - ]: - try: - _t = __import__(mod_name, None, None, (mod_thing)) - info["family"] = fam_name - del _t - break - except (ImportError, KeyError): - pass - - if info["family"] == "ev3-pybricks": - info["release"] = "2.0.0" - - if info["family"] == "micropython": - info["version"] - if ( - info["version"] - and info["version"].endswith(".0") - and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 - and info["version"] <= "1.19.9" - ): - # versions from 1.10.0 to 1.20.0 do not have a micro .0 - info["version"] = info["version"][:-2] - - # spell-checker: disable - if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds - sys_mpy = int(info["mpy"]) - # .mpy architecture - arch = [ - None, - "x86", - "x64", - "armv6", - "armv6m", - "armv7m", - "armv7em", - "armv7emsp", - "armv7emdp", - "xtensa", - "xtensawin", - ][sys_mpy >> 10] - if arch: - info["arch"] = arch - # .mpy version.minor - info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) - if info["build"] and not info["version"].endswith("-preview"): - info["version"] = info["version"] + "-preview" - # simple to use version[-build] string - info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" - - return info - - -def version_str(version: tuple): # -> str: - v_str = ".".join([str(n) for n in version[:3]]) - if len(version) > 3 and version[3]: - v_str += "-" + version[3] - return v_str - - -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - # print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# # print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False - - -def get_root() -> str: # sourcery skip: use-assigned-variable - "Determine the root folder of the device" - try: - c = os.getcwd() - except (OSError, AttributeError): - # unix port - c = "." - r = c - for r in [c, "/sd", "/flash", "/", "."]: - try: - _ = os.stat(r) - break - except OSError: - continue - return r - - -def file_exists(filename: str): - try: - if os.stat(filename)[0] >> 14: - return True - return False - except OSError: - return False - - -def show_help(): - # print("-p, --path path to store the stubs in, defaults to '.'") - sys.exit(1) - - -def read_path() -> str: - "get --path from cmdline. [unix/win]" - path = "" - if len(sys.argv) == 3: - cmd = (sys.argv[1]).lower() - if cmd in ("--path", "-p"): - path = sys.argv[2] - else: - show_help() - elif len(sys.argv) == 2: - show_help() - return path - - -def is_micropython() -> bool: - "runtime test to determine full or micropython" - # pylint: disable=unused-variable,eval-used - try: - # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects - - # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented - # Micropython: NotImplementedError - b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] - - # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute - # Micropython: AttributeError - c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] - return False - except (NotImplementedError, AttributeError): - return True - - + def __init__(B,path=F,firmware_id=F): + C=firmware_id + try: + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + except I:pass + B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[L]));A.info('Board: {}'.format(B.info[U]));E.collect() + if C:B._fwid=C.lower() + elif B.info[P]==Z:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(V) + else:B._fwid='{family}-v{version}-{port}'.format(**B.info) + B._start_free=E.mem_free() + if path: + if path.endswith(G):path=path[:-1] + else:path=get_root() + B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G);A.debug(B.path) + try:g(path+G) + except D:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[] + def get_obj_attributes(N,item_instance): + D=item_instance;G=[];L=[];A.debug('get attributes {} {}'.format(S(D),D)) + for C in M(D): + if C.startswith(a)and not C in N.modules:continue + A.debug('get attribute {}'.format(C)) + try: + F=getattr(D,C);A.debug('attribute {}:{}'.format(C,F)) + try:H=S(type(F)).split("'")[1] + except T:H=B + if H in{p,q,r,s,b,c,d}:J=1 + elif H in{t,u}:J=2 + elif H in'class':J=3 + else:J=4 + G.append((C,S(F),S(type(F)),F,J)) + except I as K:L.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(C,D,K)) + except MemoryError as K:R('MemoryError: {}'.format(K));sleep(1);reset() + G=l([A for A in G if not A[0].startswith('__')],key=lambda x:x[4]);E.collect();return G,L + def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) + def create_all_stubs(B): + A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));E.collect() + for C in B.modules:B.create_one_stub(C) + A.info('Finally done') + def create_one_stub(C,module_name): + B=module_name + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return J + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return J + H='{}/{}.py'.format(C.path,B.replace(K,G));E.collect();F=J + try:F=C.create_module_stub(B,H) + except D:return J + E.collect();return F + def create_module_stub(I,module_name,file_name=F): + H=file_name;C=module_name + if H is F:L=C.replace(K,a)+'.py';H=I.path+G+L + else:L=H.split(G)[-1] + if G in C:C=C.replace(G,K) + M=F + try:M=__import__(C,F,F,'*');P=E.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) + except O:A.trace('Skip module: {:<25} {:<79}'.format(C,'Module not found.'));return J + g(H) + with Y(H,'w')as N:R=str(I.info).replace('OrderedDict(',B).replace('})','}');S='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,I._fwid,R,__version__);N.write(S);N.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,C,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + if C not in{'os','sys','logging','gc'}: + try:del M + except(D,m):A.warning('could not del new_module') + E.collect();return Q + def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';O=in_class;M='Exception';L=object_expr;I=fp;F=indent;E.collect() + if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return + X,P=K.get_obj_attributes(L) + if P:A.error(P) + for(C,J,G,Y,a)in X: + if C in['classmethod','staticmethod','BaseException',M]:continue + if C[0].isdigit():A.warning('NameError: invalid name {}'.format(C));continue + if G==""and N(F)<=x*4: + A.trace('{0}class {1}:'.format(F,C));Q=B;R=C.endswith(M)or C.endswith('Error')or C in['KeyboardInterrupt','StopIteration','SystemExit'] + if R:Q=M + D='\n{}class {}({}):\n'.format(F,C,Q) + if R:D+=F+' ...\n';I.write(D);continue + I.write(D);A.debug('# recursion over class {0}'.format(C));K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,C),F+' ',O+1);D=F+' def __init__(self, *argv, **kwargs) -> None:\n';D+=F+' ...\n\n';I.write(D) + elif any(A in G for A in[u,t,'closure']): + A.debug("# def {1} function/method/closure, type = '{0}'".format(G,C));S=U;T=B + if O>0:T='self, ' + if V in G or V in J:D='{}@classmethod\n'.format(F)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(F,C,S) + else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(F,C,T,S) + D+=F+' ...\n\n';I.write(D);A.debug('\n'+D) + elif G=="":0 + elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if E in A and A[E]: + G=int(A[E]);J=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[Q]=J + A[E]='v{}.{}'.format(G&255,G>>8&3) + if A[D]and not A[C].endswith(W):A[C]=A[C]+W + A[K]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A +def z(version): + A=version;B=K.join([str(A)for A in A[:3]]) + if N(A)>3 and A[3]:B+=V+A[3] + return B +def A0(): + try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) + except O:A.warning('BOARDNAME not found');C=B + return C +def get_root(): + try:A=os.getcwd() + except(D,I):A=K + B=A + for B in[A,'/sd','/flash',G,K]: + try:C=os.stat(B);break + except D:continue + return B +def h(filename): + try: + if os.stat(filename)[0]>>14:return Q + return J + except D:return J +def i():R("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) +def read_path(): + path=B + if N(sys.argv)==3: + A=sys.argv[1].lower() + if A in('--path','-p'):path=sys.argv[2] + else:i() + elif N(sys.argv)==2:i() + return path +def j(): + try:A=bytes('abc',encoding='utf8');B=j.__module__;return J + except(k,I):return Q def main(): - stubber = Stubber(path=read_path()) - # stubber = Stubber(path="/sd") - # Option: Specify a firmware name & version - # stubber = Stubber(firmware_id='HoverBot v1.2.1') - stubber.clean() - # Read stubs from modulelist in the current folder or in /libs - # fall back to default modules - stubber.modules = [] # avoid duplicates - for p in LIBS: - try: - _1 = gc.mem_free() # type: ignore - with open(p + "/modulelist.txt") as f: - print ("Debug: List of modules: " + p + "/modulelist.txt") - line = f.readline() - while line: - line = line.strip() - if len(line) > 0 and line[0] != "#": - stubber.modules.append(line) - line = f.readline() - gc.collect() # type: ignore - print ("Debug: Used memory to load modulelist.txt: " + str(_1 - gc.mem_free()) + " bytes") # type: ignore - break - except Exception: - pass - if not stubber.modules: - stubber.modules = ["micropython"] - # print("Could not find modulelist.txt, using default modules") - - gc.collect() - - stubber.create_all_stubs() - stubber.report() - - -if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass - if not file_exists("no_auto_stubber.txt"): - try: - gc.threshold(4 * 1024) # type: ignore - gc.enable() - except BaseException: - pass - main() + stubber=Stubber(path=read_path());stubber.clean() + def A(stubber): + E.collect();stubber.modules=[] + for C in y: + B=C+'/modulelist.txt' + if not h(B):continue + with Y(B)as D: + while Q: + A=D.readline().strip() + if not A:break + if N(A)>0 and A[0]!='#':stubber.modules.append(A) + E.collect();R('BREAK');break + if not stubber.modules:stubber.modules=[Z] + E.collect() + stubber.modules=[];A(stubber);E.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or j(): + if not h('no_auto_stubber.txt'): + try:E.threshold(4*1024);E.enable() + except BaseException:pass + main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mem_mpy.mpy b/src/stubber/board/createstubs_mem_mpy.mpy index e3d7d717f16c08dfa0686fb0487791c9954f3bc7..ed69d016ccd8f4ae74c1c76738e16560c81e24ff 100644 GIT binary patch literal 9588 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 J1IFpt{|C@+)))W) literal 7905 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 QsF`npy3iLOctxcD2i7?w1poj5 diff --git a/src/stubber/board/createstubs_min.py b/src/stubber/board/createstubs_min.py index a3c386e9e..03628c426 100644 --- a/src/stubber/board/createstubs_min.py +++ b/src/stubber/board/createstubs_min.py @@ -1,1011 +1,288 @@ -""" -Create stubs for (all) modules on a MicroPython board -""" -# Copyright (c) 2019-2023 Jos Verlinde - -import gc -# import logging -import os -import sys +x='pyb' +w='{}/{}' +v='logging' +u='sys' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n='stubber' +m=TypeError +l=KeyError +k=sorted +j=NotImplementedError +e='pycom' +d=',\n' +c='dict' +b='list' +a='tuple' +Z='_' +Y='micropython' +X=print +V='-preview' +U=True +T='-' +S='board' +R=IndexError +Q=repr +P='family' +O=len +N=ImportError +M=dir +L='port' +K='.' +J=False +I=AttributeError +G='/' +E=None +D=OSError +C='version' +B='' +import gc as F,os,sys from time import sleep - -try: - from ujson import dumps -except: - from json import dumps - -try: - from machine import reset # type: ignore -except ImportError: - pass - -try: - from collections import OrderedDict -except ImportError: - from ucollections import OrderedDict # type: ignore - -try: - from nope_machine import WDT - - wdt = WDT() - -except ImportError: - - class _WDT: - def feed(self): - pass - - wdt = _WDT() - - -wdt.feed() - -__version__ = "v1.16.3" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] - - +try:from ujson import dumps +except:from json import dumps +try:from machine import reset +except N:pass +try:from collections import OrderedDict as f +except N:from ucollections import OrderedDict as f +__version__='v1.16.3' +y=2 +z=2 +A3=['lib','/lib','/sd/lib','/flash/lib',K] +class H: + DEBUG=10;TRACE=15;INFO=20;WARNING=30;ERROR=40;CRITICAL=50;level=INFO;prnt=X + @staticmethod + def getLogger(name):return H() + @classmethod + def basicConfig(A,level):A.level=level + def trace(A,msg): + if A.level<=H.TRACE:A.prnt('TRACE :',msg) + def debug(A,msg): + if A.level<=H.DEBUG:A.prnt('DEBUG :',msg) + def info(A,msg): + if A.level<=H.INFO:A.prnt('INFO :',msg) + def warning(A,msg): + if A.level<=H.WARNING:A.prnt('WARN :',msg) + def error(A,msg): + if A.level<=H.ERROR:A.prnt('ERROR :',msg) + def critical(A,msg): + if A.level<=H.CRITICAL:A.prnt('CRIT :',msg) +A=H.getLogger(n) +H.basicConfig(level=H.INFO) class Stubber: - "Generate stubs for modules in firmware" - - def __init__(self, path: str = None, firmware_id: str = None): # type: ignore - try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore - raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") - except AttributeError: - pass - # self.log = logging.getLogger("stubber") - self._report = [] # type: list[str] - self.info = _info() - # self.log.info("Port: {}".format(self.info["port"])) - # self.log.info("Board: {}".format(self.info["board"])) - gc.collect() - wdt.feed() - if firmware_id: - self._fwid = firmware_id.lower() - else: - if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") - else: - self._fwid = "{family}-v{version}-{port}".format(**self.info) - self._start_free = gc.mem_free() # type: ignore - - if path: - if path.endswith("/"): - path = path[:-1] - else: - path = get_root() - - self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - # self.log.debug(self.path) - try: - ensure_folder(path + "/") - except OSError: - print("error creating stub folder {}".format(path)) - self.problematic = [ - "upip", - "upysh", - "webrepl_setup", - "http_client", - "http_client_ssl", - "http_server", - "http_server_ssl", - ] - self.excluded = [ - "webrepl", - "_webrepl", - "port_diag", - "example_sub_led.py", - "example_pub_button.py", - ] - # there is no option to discover modules from micropython, list is read from an external file. - self.modules = [] # type: list[str] - - def get_obj_attributes(self, item_instance: object): - "extract information of the objects members and attributes" - # name_, repr_(value), type as text, item_instance - _result = [] - _errors = [] - # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) - for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: - continue - # self.log.debug("get attribute {}".format(name)) - try: - val = getattr(item_instance, name) - # name , item_repr(value) , type as text, item_instance, order - # self.log.debug("attribute {}:{}".format(name, val)) - try: - type_text = repr(type(val)).split("'")[1] - except IndexError: - type_text = "" - if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: - order = 1 - elif type_text in {"function", "method"}: - order = 2 - elif type_text in ("class"): - order = 3 - else: - order = 4 - _result.append((name, repr(val), repr(type(val)), val, order)) - except AttributeError as e: - _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) - except MemoryError as e: - # print("MemoryError: {}".format(e)) - sleep(1) - reset() - - # remove internal __ - # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) - _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) - gc.collect() - return _result, _errors - - def add_modules(self, modules): - "Add additional modules to be exported" - self.modules = sorted(set(self.modules) | set(modules)) - - def create_all_stubs(self): - "Create stubs for all configured modules" - # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) - gc.collect() - for module_name in self.modules: - self.create_one_stub(module_name) - # self.log.info("Finally done") - - def create_one_stub(self, module_name: str): - wdt.feed() - if module_name in self.problematic: - # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) - return False - if module_name in self.excluded: - # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) - return False - - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) - gc.collect() - result = False - try: - result = self.create_module_stub(module_name, file_name) - except OSError: - return False - gc.collect() - return result - - def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore - """Create a Stub of a single python module - - Args: - - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. - """ - if file_name is None: - fname = module_name.replace(".", "_") + ".py" - file_name = self.path + "/" + fname - else: - fname = file_name.split("/")[-1] - - if "/" in module_name: - # for nested modules - module_name = module_name.replace("/", ".") - - # import the module (as new_module) to examine it - new_module = None - try: - new_module = __import__(module_name, None, None, ("*")) - m1 = gc.mem_free() # type: ignore - # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) - - except ImportError: - # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) - return False - - # Start a new file - ensure_folder(file_name) - with open(file_name, "w") as fp: - # todo: improve header - info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") - s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format( - module_name, self._fwid, info_, __version__ - ) - fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") - self.write_object_stub(fp, new_module, module_name, "") - - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) - - if module_name not in {"os", "sys", "logging", "gc"}: - # try to unload the module unless we use it - try: - del new_module - except (OSError, KeyError): # lgtm [py/unreachable-statement] - pass - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - pass - gc.collect() - return True - - def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): - "Write a module/object stub to an open file. Can be called recursive." - gc.collect() - if object_expr in self.problematic: - # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) - return - - # # self.log.debug("DUMP : {}".format(object_expr)) - items, errors = self.get_obj_attributes(object_expr) - - if errors: - print(errors) - - for item_name, item_repr, item_type_txt, item_instance, _ in items: - # name_, repr_(value), type as text, item_instance, order - if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: - # do not create stubs for these primitives - continue - if item_name[0].isdigit(): - # self.log.warning("NameError: invalid name {}".format(item_name)) - continue - # Class expansion only on first 3 levels (bit of a hack) - if ( - item_type_txt == "" - and len(indent) <= _MAX_CLASS_LEVEL * 4 - # and not obj_name.endswith(".Pin") - # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms - ): - # self.log.info("{0}class {1}:".format(indent, item_name)) - superclass = "" - is_exception = ( - item_name.endswith("Exception") - or item_name.endswith("Error") - or item_name - in [ - "KeyboardInterrupt", - "StopIteration", - "SystemExit", - ] - ) - if is_exception: - superclass = "Exception" - s = "\n{}class {}({}):\n".format(indent, item_name, superclass) - # s += indent + " ''\n" - if is_exception: - s += indent + " ...\n" - fp.write(s) - continue - # write classdef - fp.write(s) - # first write the class literals and methods - # self.log.debug("# recursion over class {0}".format(item_name)) - self.write_object_stub( - fp, - item_instance, - "{0}.{1}".format(obj_name, item_name), - indent + " ", - in_class + 1, - ) - # end with the __init__ method to make sure that the literals are defined - # Add __init__ - s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" - s += indent + " ...\n\n" - fp.write(s) - elif any(word in item_type_txt for word in ["method", "function", "closure"]): - # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) - # module Function or class method - # will accept any number of params - # return type Any/Incomplete - ret = "Incomplete" - first = "" - # Self parameter only on class methods/functions - if in_class > 0: - first = "self, " - # class method - add function decoration - if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format( - indent, item_name, ret - ) - else: - s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) - s += indent + " ...\n\n" - fp.write(s) - # self.log.debug("\n" + s) - elif item_type_txt == "": - # Skip imported modules - # fp.write("# import {}\n".format(item_name)) - pass - - elif item_type_txt.startswith(" dict[str, str] - info = OrderedDict( - { - "family": sys.implementation.name, - "version": "", - "build": "", - "ver": "", - "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "UNKNOWN", - "cpu": "", - "mpy": "", - "arch": "", - } - ) - # change port names to be consistent with the repo - if info["port"].startswith("pyb"): - info["port"] = "stm32" - elif info["port"] == "win32": - info["port"] = "windows" - elif info["port"] == "linux": - info["port"] = "unix" - try: - info["version"] = version_str(sys.implementation.version) # type: ignore - except AttributeError: - pass - try: - _machine = ( - sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - ) - # info["board"] = "with".join(_machine.split("with")[:-1]).strip() - info["board"] = _machine - info["cpu"] = _machine.split("with")[-1].strip() - info["mpy"] = ( - sys.implementation._mpy - if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy - if "mpy" in dir(sys.implementation) - else "" - ) - except (AttributeError, IndexError): - pass - gc.collect() - read_boardname(info) - gc.collect() - - try: - if "uname" in dir(os): # old - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - elif "version" in dir(sys): # new - # extract build from sys.version if available - info["build"] = _build(sys.version) - except (AttributeError, IndexError, TypeError): - pass - # avoid build hashes - # if info["build"] and len(info["build"]) > 5: - # info["build"] = "" - - if info["version"] == "" and sys.platform not in ("unix", "win32"): - try: - u = os.uname() # type: ignore - info["version"] = u.release - except (IndexError, AttributeError, TypeError): - pass - # detect families - for fam_name, mod_name, mod_thing in [ - ("pycopy", "pycopy", "const"), - ("pycom", "pycom", "FAT"), - ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), - ]: - try: - _t = __import__(mod_name, None, None, (mod_thing)) - info["family"] = fam_name - del _t - break - except (ImportError, KeyError): - pass - - if info["family"] == "ev3-pybricks": - info["release"] = "2.0.0" - - if info["family"] == "micropython": - info["version"] - if ( - info["version"] - and info["version"].endswith(".0") - and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 - and info["version"] <= "1.19.9" - ): - # versions from 1.10.0 to 1.20.0 do not have a micro .0 - info["version"] = info["version"][:-2] - - # spell-checker: disable - if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds - sys_mpy = int(info["mpy"]) - # .mpy architecture - arch = [ - None, - "x86", - "x64", - "armv6", - "armv6m", - "armv7m", - "armv7em", - "armv7emsp", - "armv7emdp", - "xtensa", - "xtensawin", - ][sys_mpy >> 10] - if arch: - info["arch"] = arch - # .mpy version.minor - info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) - if info["build"] and not info["version"].endswith("-preview"): - info["version"] = info["version"] + "-preview" - # simple to use version[-build] string - info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" - - return info - - -def version_str(version: tuple): # -> str: - v_str = ".".join([str(n) for n in version[:3]]) - if len(version) > 3 and version[3]: - v_str += "-" + version[3] - return v_str - - -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - # print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# # print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False - - -def get_root() -> str: # sourcery skip: use-assigned-variable - "Determine the root folder of the device" - try: - c = os.getcwd() - except (OSError, AttributeError): - # unix port - c = "." - r = c - for r in [c, "/sd", "/flash", "/", "."]: - try: - _ = os.stat(r) - break - except OSError: - continue - return r - - -def file_exists(filename: str): - try: - if os.stat(filename)[0] >> 14: - return True - return False - except OSError: - return False - - -def show_help(): - # print("-p, --path path to store the stubs in, defaults to '.'") - sys.exit(1) - - -def read_path() -> str: - "get --path from cmdline. [unix/win]" - path = "" - if len(sys.argv) == 3: - cmd = (sys.argv[1]).lower() - if cmd in ("--path", "-p"): - path = sys.argv[2] - else: - show_help() - elif len(sys.argv) == 2: - show_help() - return path - - -def is_micropython() -> bool: - "runtime test to determine full or micropython" - # pylint: disable=unused-variable,eval-used - try: - # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects - - # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented - # Micropython: NotImplementedError - b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] - - # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute - # Micropython: AttributeError - c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] - return False - except (NotImplementedError, AttributeError): - return True - - -def main(): - stubber = Stubber(path=read_path()) - # stubber = Stubber(path="/sd") - # Option: Specify a firmware name & version - # stubber = Stubber(firmware_id='HoverBot v1.2.1') - stubber.clean() - # there is no option to discover modules from micropython, need to hardcode - # below contains combined modules from Micropython ESP8622, ESP32, Loboris, Pycom and ulab , lvgl - # spell-checker: disable - # modules to stub : 131 - stubber.modules = [ - "WM8960", - "_OTA", - "_asyncio", - "_boot_fat", - "_coap", - "_espnow", - "_flash_control_OTA", - "_main_pybytes", - "_mqtt", - "_mqtt_core", - "_msg_handl", - "_onewire", - "_periodical_pin", - "_pybytes", - "_pybytes_ca", - "_pybytes_config", - "_pybytes_config_reader", - "_pybytes_connection", - "_pybytes_constants", - "_pybytes_debug", - "_pybytes_library", - "_pybytes_machine_learning", - "_pybytes_main", - "_pybytes_protocol", - "_pybytes_pyconfig", - "_pybytes_pymesh_config", - "_rp2", - "_terminal", - "_thread", - "_uasyncio", - "_urequest", - "adcfft", - "aioble/__init__", - "aioble/central", - "aioble/client", - "aioble/core", - "aioble/device", - "aioble/l2cap", - "aioble/peripheral", - "aioble/security", - "aioble/server", - "aioespnow", - "ak8963", - "apa102", - "apa106", - "argparse", - "array", - "asyncio/__init__", - "asyncio/core", - "asyncio/event", - "asyncio/funcs", - "asyncio/lock", - "asyncio/stream", - "binascii", - "bluetooth", - "breakout_as7262", - "breakout_bh1745", - "breakout_bme280", - "breakout_bme68x", - "breakout_bmp280", - "breakout_dotmatrix", - "breakout_encoder", - "breakout_icp10125", - "breakout_ioexpander", - "breakout_ltr559", - "breakout_matrix11x7", - "breakout_mics6814", - "breakout_msa301", - "breakout_paa5100", - "breakout_pmw3901", - "breakout_potentiometer", - "breakout_rgbmatrix5x5", - "breakout_rtc", - "breakout_scd41", - "breakout_sgp30", - "breakout_trackball", - "breakout_vl53l5cx", - "btree", - "cmath", - "collections", - "crypto", - "cryptolib", - "curl", - "deflate", - "dht", - "display", - "display_driver_utils", - "ds18x20", - "encoder", - "errno", - "esp", - "esp32", - "espidf", - "espnow", - "ffi", - "flashbdev", - "framebuf", - "freesans20", - "fs_driver", - "functools", - "galactic", - "gc", - "gfx_pack", - "gsm", - "hashlib", - "heapq", - "hub75", - "ili9341", - "ili9XXX", - "imagetools", - "inisetup", - "interstate75", - "io", - "jpegdec", - "json", - "lcd160cr", - "lodepng", - "logging", - "lsm6dsox", - "lv_colors", - "lv_utils", - "lvgl", - "lwip", - "machine", - "math", - "microWebSocket", - "microWebSrv", - "microWebTemplate", - "micropython", - "mip", - "mip/__init__", - "mip/__main__", - "motor", - "mpu6500", - "mpu9250", - "neopixel", - "network", - "ntptime", - "onewire", - "os", - "pcf85063a", - "picoexplorer", - "picographics", - "picokeypad", - "picoscroll", - "picounicorn", - "picowireless", - "pimoroni", - "pimoroni_bus", - "pimoroni_i2c", - "plasma", - "platform", - "pyb", - "pycom", - "pye", - "qrcode", - "queue", - "random", - "requests", - "requests/__init__", - "rp2", - "rtch", - "samd", - "select", - "servo", - "socket", - "ssd1306", - "ssh", - "ssl", - "stm", - "struct", - "sys", - "termios", - "time", - "tpcalib", - "uarray", - "uasyncio/__init__", - "uasyncio/core", - "uasyncio/event", - "uasyncio/funcs", - "uasyncio/lock", - "uasyncio/stream", - "uasyncio/tasks", - "ubinascii", - "ubluetooth", - "ucollections", - "ucrypto", - "ucryptolib", - "uctypes", - "uerrno", - "uftpd", - "uhashlib", - "uheapq", - "uio", - "ujson", - "ulab", - "ulab/approx", - "ulab/compare", - "ulab/fft", - "ulab/filter", - "ulab/linalg", - "ulab/numerical", - "ulab/poly", - "ulab/user", - "ulab/vector", - "umachine", - "umqtt/__init__", - "umqtt/robust", - "umqtt/simple", - "uos", - "uplatform", - "uqueue", - "urandom", - "ure", - "urequests", - "urllib/urequest", - "uselect", - "usocket", - "ussl", - "ustruct", - "usys", - "utelnetserver", - "utime", - "utimeq", - "uwebsocket", - "uzlib", - "version", - "websocket", - "websocket_helper", - "wipy", - "writer", - "xpt2046", - "ymodem", - "zephyr", - "zlib", - ] # spell-checker: enable - - gc.collect() - - stubber.create_all_stubs() - stubber.report() - - -if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass - if not file_exists("no_auto_stubber.txt"): - try: - gc.threshold(4 * 1024) # type: ignore - gc.enable() - except BaseException: - pass - main() + def __init__(B,path=E,firmware_id=E): + C=firmware_id + try: + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') + except I:pass + B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[L]));A.info('Board: {}'.format(B.info[S]));F.collect() + if C:B._fwid=C.lower() + elif B.info[P]==Y:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(T) + else:B._fwid='{family}-v{version}-{port}'.format(**B.info) + B._start_free=F.mem_free() + if path: + if path.endswith(G):path=path[:-1] + else:path=get_root() + B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G);A.debug(B.path) + try:g(path+G) + except D:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[] + def get_obj_attributes(N,item_instance): + D=item_instance;G=[];L=[];A.debug('get attributes {} {}'.format(Q(D),D)) + for C in M(D): + if C.startswith(Z)and not C in N.modules:continue + A.debug('get attribute {}'.format(C)) + try: + E=getattr(D,C);A.debug('attribute {}:{}'.format(C,E)) + try:H=Q(type(E)).split("'")[1] + except R:H=B + if H in{o,p,q,r,a,b,c}:J=1 + elif H in{s,t}:J=2 + elif H in'class':J=3 + else:J=4 + G.append((C,Q(E),Q(type(E)),E,J)) + except I as K:L.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(C,D,K)) + except MemoryError as K:X('MemoryError: {}'.format(K));sleep(1);reset() + G=k([A for A in G if not A[0].startswith('__')],key=lambda x:x[4]);F.collect();return G,L + def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) + def create_all_stubs(B): + A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));F.collect() + for C in B.modules:B.create_one_stub(C) + A.info('Finally done') + def create_one_stub(C,module_name): + B=module_name + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return J + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return J + H='{}/{}.py'.format(C.path,B.replace(K,G));F.collect();E=J + try:E=C.create_module_stub(B,H) + except D:return J + F.collect();return E + def create_module_stub(I,module_name,file_name=E): + H=file_name;C=module_name + if H is E:L=C.replace(K,Z)+'.py';H=I.path+G+L + else:L=H.split(G)[-1] + if G in C:C=C.replace(G,K) + M=E + try:M=__import__(C,E,E,'*');P=F.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) + except N:A.trace('Skip module: {:<25} {:<79}'.format(C,'Module not found.'));return J + g(H) + with open(H,'w')as O:Q=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,I._fwid,Q,__version__);O.write(R);O.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(O,M,C,B) + I._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + if C not in{'os',u,v,'gc'}: + try:del M + except(D,l):A.warning('could not del new_module') + F.collect();return U + def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;E=indent;F.collect() + if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return + X,P=K.get_obj_attributes(L) + if P:A.error(P) + for(C,J,G,Y,d)in X: + if C in['classmethod','staticmethod','BaseException',M]:continue + if C[0].isdigit():A.warning('NameError: invalid name {}'.format(C));continue + if G==""and O(E)<=z*4: + A.trace('{0}class {1}:'.format(E,C));Q=B;R=C.endswith(M)or C.endswith('Error')or C in['KeyboardInterrupt','StopIteration','SystemExit'] + if R:Q=M + D='\n{}class {}({}):\n'.format(E,C,Q) + if R:D+=E+' ...\n';I.write(D);continue + I.write(D);A.debug('# recursion over class {0}'.format(C));K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,C),E+' ',N+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';I.write(D) + elif any(A in G for A in[t,s,'closure']): + A.debug("# def {1} function/method/closure, type = '{0}'".format(G,C));S=U;T=B + if N>0:T='self, ' + if V in G or V in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,C,S) + else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,C,T,S) + D+=E+' ...\n\n';I.write(D);A.debug('\n'+D) + elif G=="":0 + elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if F in A and A[F]: + G=int(A[F]);J=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[Q]=J + A[F]='v{}.{}'.format(G&255,G>>8&3) + if A[D]and not A[C].endswith(V):A[C]=A[C]+V + A[K]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A +def A0(version): + A=version;B=K.join([str(A)for A in A[:3]]) + if O(A)>3 and A[3]:B+=T+A[3] + return B +def A1(): + try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) + except N:A.warning('BOARDNAME not found');C=B + return C +def get_root(): + try:A=os.getcwd() + except(D,I):A=K + B=A + for B in[A,'/sd','/flash',G,K]: + try:C=os.stat(B);break + except D:continue + return B +def A2(filename): + try: + if os.stat(filename)[0]>>14:return U + return J + except D:return J +def h():X("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) +def read_path(): + path=B + if O(sys.argv)==3: + A=sys.argv[1].lower() + if A in('--path','-p'):path=sys.argv[2] + else:h() + elif O(sys.argv)==2:h() + return path +def i(): + try:A=bytes('abc',encoding='utf8');B=i.__module__;return J + except(j,I):return U +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',x,e,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];F.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or i(): + if not A2('no_auto_stubber.txt'): + try:F.threshold(4*1024);F.enable() + except BaseException:pass + main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mpy.mpy b/src/stubber/board/createstubs_mpy.mpy index 1f7e3a6a872904de4b1c61fd593ebe7438358ca9..7ee1911e0cb4588bd2d14fd74b6c62ae57b86857 100644 GIT binary patch delta 8218 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⁡EuP*kKtbM&ZxRR zIy#X5V55rcT$l*7;DPfX=E1FXq~AT@6>P8#eEPx0)!f zV0jvrF8$YajsAwJ+Oc*#IUp6{0g@TFg?~xPik=-BdaZb>IwY7MpFE6>2mPQ5;>AOi zpoA{m1Ts;qwK4v$?Sgr7pFgZD3d5p3Po40TIb5L6TC{T~@b3!LWp0$FM zRB?3s_skhZrp#h%zf<`J`A@x^{YoaLAsmiuM460ZF}6_nkBX6gW-%^T`UBwe53n>{ zz+b^`(USMqVLZu=X`g|KBj7W!CSuDfNOed>cy?6jw9J>MF^r4^Sh-h5lCXhpz0cG6l`(`mO~ zwbS(J?FWJXNw3)s;`V`uz3p}NAAOlr_o#m;lbFZp z$9;!yTieoOvR3mX7}qrpiwyVEjK)hJ_E|E?laSx^tlo))KCH<*EAkk6T(de@xm*4H zYoYMB&Nmew<*D@F&}#1icfA{qZLf6&ktxFKYdhjn*0Ij~61vm5c7F{yC4iK229M=y zI~grh&=2Ws?7>D@)(XBRFA(QTp@8dDSGZ;RM>y4${@iYFZ}qC)!+0gJdm0W@);0Ls zy{$g4z4Ay?gWF|4SZA+2&||c01s{@LcwR)!E2Oo zax~D3WfWJfs!!j;F-7C=sdxlOkg8+0aX;C*Jq}pAZ;Uz}ICJ+8g#Cdo3}WlBj{Eapa!^QS+up2_4!3DYw+9bD8Oc)U1=6%TLWZxD10 zCjUN|>4x*42T$r6A+cSG*7)76o#1Ebt-E8vkJ54hK79rkhT?!Jn1(RSKm=yt0?ffY zyy7l!!p+}~xhzggu-j?bx-|}XEptL8Q-9-xH-4-A#xG&fF!{lk^=VXbWyK}ZHKe~{ z`>8&u&=>~1x9MVh^GksNz?+i(?l)}R8Q%(PM>-2*W$EAf4z1yiQ)Y{M$$CgbzkPTE ze}IQBysT)y44z!q#)ADDxJ0q>^w+pX4Xn2_b0boJr(cQ8+j2fC<4wpHzG3neE~fw6 zUftANo`y^K!&jpG(*23dUVulHwG2U*hzfiW4Cx&yn&%h%@4SxyTnoQGJR>i?E!8zw zHnq5V^AQY}{p5bX4Tn@_H#~9CEW6*YqWbn4T!E`dfGBYrCkM*6^_@>_mk&Blib~_= z7M$pC;nr5U9@a<;ENhK#n=6~@diSF3L+DX@>^r{=B4rgK|CEO_L$Ws-z$$>*SN9+AsHnLgs)1DkqrjZNs(@jCHEjo01MC2>T3~Kq zb-?O@d4M$lYXsH=%nJ;|@BwRq7l8SJwE|Xx9Rk({>@ct+z|h7~dKB0(U>$(wJAno8 z;>5au1%Y(~>rsIn2b{8(9-|$!6BjhFJ{q8?(GP3@*a={Rz=nXG1U3xlc8CTkjvN6t zN_*&WV5ev=?E^LjL&)=jYS=ii)4<`K=ERUV!MqhXo&@@c#m4P98x3 delta 6476 zcmZ`dYfPJ2cAsBh41wd%jv<5u=erne^LC6UGf8F~`-2!v0*08xd5nP%15N-FY#tes z*!PljX3|xgmAk4|?N({kR$8@EZ6K3O)!hwACdqcUv+cIhPIgO2ZFj3}rD`>7e^k|K z)pKpKGi_A^zW1Jc?s?twx_nLf?GbXSM5tdgr0bN0*jOr-Of8Nl+vcwcRoW><&?b^X zN%Gp4|L}sd5`fF zxKKHa)W%~Af~HxVilzD!Q&YI8 zDlo#D)JuZ8Re;v{h1gO&wk#N;@wv%F_ODgd>59p*+4#&g6g;+&j3?#Qjj_=*6pjF+udSJx_unVFb^@U>y)t1TlOe`8(i6>J@K}6dv zN2g;m^Vvh1+N!#EGCCVq783K^)1&X8)$Ft<~H+heYRRVyT!=k&MkuwpfLl@xT*7rI~`m5(i?t_fpwS)CM4(0!pqCeje<8Kd_K`Bi8(xjd%D7n2)`ON zJtxi}JbS*vTBGkCIqX}AD^~br&SuEL~TjXrKI#s)Gwd2NW=MC#|>#FO9l~_5-8`jmsHw@VyRUgT=*SNF) zRMVE$Rkatqt)OOGY9%H7PJhdF)u^|pv9Vto7?4K%(#U|+f7KedUJlqA8WLZHEQ3##?0*-dmLj`DMG*@(!^}&Jf9j_Ny&w{MJ}B_^q{QGoW*-_LtP@EV@Xb zG6SW!($|$*O4E@(h!odld>!diUE&A^L@2K_SPYTA^0P*E=~LPNYO4ab_S98aDk6Q= z#jOFPz@e2zC{oy)fhq(*U6rLOVytot7WQ`E{v!5p&4Rc4uS87yEy$l_0tbz>%UlNsJZY7MP4LA* zsK>!%^)R8Ra%@*+;}s&fRsLAOWK^3EN%sVgDuOc!Wi6QI@GHC}w-5;_duWSLV!R_E zN6R7@Eo{;ySj3Q`3X~Z{wv-_u<-HdDk$rbMy?459+tV@YZT)T2`$yitdB^Zx^_}Y5 z`k1$Pb|0P%g`Dc)!)QI73k9u4y_pRaXByO;HHNs>Xc&8@s6J~qvME=o8&N9@dwRJGhI|;U&?+g-0Z}(Yg zxMNbnPatlUrUQ+l#@yo(OhI5JFXfTlRTr?*AIJfbEt0q0su)^DWLI{r(k$d^m|pC3 z^RY}+oBPmi;_h9q%fa-zdEUeK48G-@iIssn45wbo=SkG;80LV?YfLb+a%lIc3RodB z`h^`1LZYmqKx0o{9?F|fgUzFoPv%4EHg$N**DX%Dg)K5>cI1&>rAKWZ2UdkR>Rioo zAYCq!JlJ;Jsz_fA%02z5Jc#ne$vEPBR2;0j1Pp)~i9#kwj7*ZL=2GM<0y6&4ET8cIvZD?s|lBN2-dZqEIwX>;NNIz~C zo``HF?^Z>FKUO{6G`GS8ir=@1!m79ZKA$6SMLD-VxdAeK$&GZUI)~ zQPJ?TzDksQ_EWhh0=3Uj-VcE716B)cKd?Gr2Y?*}R^M8>Ez9(|k8fLn9coqMI?bN@ zP9Z?T`Py@z@7D8mGb5YG26=pe+5HDj9XfuWw|KV~Ui2C_5RqIqJ2vwVJsR8#g17@2fXOcEcsCyH&s%Txpe?sUGk8#rlR*t*Dv4 zw}M5OGxH@hXEZ2oG-X{Al$6OjQqrvj6oS8M^eMfwUL(03th@CYe z!JC<{*#lC*=WdduVbb)PnLje9TtXqzJRUZbto}ERL(I;3vUDalI%;bR_Vrwrq?QG*(%65@7PLDC zE(}Vx7R76AS`Yn$94T^|@Th?~cAg+>^x}=3$G*OGbPSAubodF_^4oGBN3?<2quvTV z4Om2$$cI9}oNnz?&Yy?QM+K=0Ii5>J@NO^$lIy^l-RhIUXCm8=ik6|vjgu=-TMQxe zzE+R=IhiR2mf?ZOq8{yw56rCXAsUj8WELl=diw{Pc|4|#gf3n}LVE5vb9ijsJe~&D zQ8X8#=0O8mpk1JD)o%Z-JQC2_wS9p8G%d1ur+PP~>|WiF^7ZTgwfF04*3OpJgf-Qg zdQG#Y&HU8b6c`VZlc$EHKA+W|@Di)jd1!W&H1rX>-9J6)uuWQRP0g#`2HDo#o=#a? z?7=C2i^CsjA3U>V)eGFjif>X3qJRIhtf9qMP#AIK*$Lp(queGmE{i^$l4@jPH_pjJJn>;n95j4SD#Ro50@K z`N_w5H1#*R@9x}uHRVRn|2eRuX2-@uj~Wq=?cAq39$jRUT;2Kjo10{zcraZ&`F$p? z=^9K{0fX{TAw3*#)?hMstK`4S0DJR$P}>OiGoQ%az}{-aZ0NO_w*4n@{BT=7Ly{5y( zq4whjVjM^S)@{p!WThaw(PsM4qx;x5jQTek$+a&6 zU)kArkQE?Z><>td3vbw`Bxx#wq|rV!xpgq$LrBx#S@I(4Xg+1EuSl|ygzuy)UtxL`tH2d zZj&W@OFywWrD3UQ_*bb3GlPt|U@Kt4;#|mRII>fi+8)1(q$|Zp3MrS6MY{V5u+tce z8y@x3KsiSqz^jb(IeFN9Dvw73V$Qt6L40qpu*VC0A%|hD!C&8p>5%fi9))9C%wVaz z?^>s={Y}0WyJUAZG%vpruE2=r$j@_QAl>tMqH#V!w+(F|tD&bnO+R1TVL&@FWbH3rMw>kOs z06T*u_)IKqNvn`k8L;rUTSa-pu)76pFd~+5Z=t+~DHjrRKDC zY>2a7D_zsy{bSBo?Ix8T099D`2C};p7!+@ zZSy4aQSa;bO--4w$VOkvvjq(Mes0dbLq(Lxv)(G+`=~K%VDFQSIu4|Nc{8N^+7XA< z$u8f0L5SPYNSsn5apnAes8ygjw=MVQu;MgRj~e-($UVwoIJaRmhoL>UUBKe|*uT;6 zR$hUQF916@5I4=co9ipT3+w96yFZX5hs|bdvf0wMX-v=#{E^NP$(puxTCE;yx`i|~ zo|O7KdR+aT?TYuX)Z}dUTP3Mqa@wSZmTpIn!)9%4al~ia`j#_gHqz~O1?#)Tik31_ zYjT+mgL@om`Hj|shkv~`j_@P!`Z&A+M>*ga|2mHKsTSVE+kTXT*LfH67Ah71FRn&> z;~WMjULwF(0E7wvKL^MKfHweQw7{?nyAbFa`5(P;AP(Kw`tg0YY8xA9E?KuPfH%jR z?DDOA4$?YJTM3tjWeQ#OEWDxxg2SauomXBdq(gt>>n(GJp$W>`p!dFfiXXH8h5p(g07ws zpSKW}oUO>_oSNP8jb;c#?MpdwFBYR8aZxx+z$&5)WrQgh$h#A0%3$BPGq6 zXt1?I^W^DA0WsxD_U)FXbNS&p{B?C_XWk zxF8Y!C12s+Sb_)ea-)0>gFliH5hv-;59L#Q7UFdYCnIniUH;n{G;3IXoDtbRK69&{ zhhPYX;S7Xf1kS=ah`@Qc&|LoD&S&8l59RKMIe2pfE}9(=B%1!&gZDmL`x(AK@NT$S z<+GdxN`L|3=Oze4#|~$fOY_}9xMX&4D981veSPqDagA>xcx@!7tTnt|8ST0^+}Z8` zvw74d?svqm~cKa_}C?g41**Zd;{My z#do}TWdoZBY}}F?5W_A~k58LPY&9`;-*WJZkQYsF zQMB~Eiv`)rw({iW4ocRg+#a2%o4WT$R>|4lD78!WU}K;R{b$-EJSx@!bR6#I_!=@l z!a9)K%0V11^B%Za7Y){J70Mj1jgP$p++VPi$q{cO7BVTXuybAF6_&d9fz&GX1&nE= z+?eyIGU4C&O!f^agG%v0p??o4D^N0X?~$lA&(cEDzHP6mnY;JYN?My6dz)IDp!N~k zA3Z&RSMX9E<1@^7_~b=>^xJYT2e9xXe5KCdE6I1}SJ><&c9}EoGy=VN!FJhl_1^cr ztZde5BQ4zZWmteDr11IlNW5xV+$u=6xU0KAGNfPu%mqHV*YTg~rF%b}u}*rwR4UDS zyZLK=_mdjMlv(_|nohq0?2hT;cs)~EU;pd->ffuBq$vqk(zMhqts?Yl20{G8_mKEB z{voleqsdY0>gednCUGAui*s(l%>*nBEBM@jYw!-N!gaU-H%S>WKpLn3R0UK`%7JP~ z1=&L?NfiNNJVQicB4)CeSV%Qcd>!b3mH;gUss~y|YREoPOZJmGa)2Bp^~4I)02HZI z0Nn$$5@;1UL?l8;1F?}tpa9gE{e$+l9ucSs5XB61FHj5Me_Lq{(0$}M&|0ATfz|;% z0Q4ZxdZ0-65Ksvy0onl61{7&Efjawd?fcW@O`x4XT~G$}Fic;jNczbs za+(Z~L4rpv0eu_LQc<9zK*xZN166=d0F42i1hn%M86rq^nw%kFf>h%`FB2qvg`6W1 z5?VmnO@ str: ... - @type_check_only class _gc: def collect(self) -> None: ... @@ -78,62 +76,82 @@ def main(): # get list of modules to process get_modulelist(stubber) # remove the ones that are already done - modules_done = {} # type: dict[str, str] - try: - with open("modulelist.done") as f: - # not optimal , but works on mpremote and esp8266 - for line in f.read().split("\n"): - line = line.strip() - gc.collect() - if len(line) > 0: - key, value = line.split("=", 1) - modules_done[key] = value - except (OSError, SyntaxError): - pass - gc.collect() + modules_done = read_done() # see if we can continue from where we left off - modules = [m for m in stubber.modules if m not in modules_done.keys()] - gc.collect() - for modulename in modules: - # ------------------------------------ - # do epic shit - # but sometimes things fail / run out of memory and reboot - ok = False - try: - ok = stubber.create_one_stub(modulename) - except MemoryError: - # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER - machine.reset() - # ------------------------------------- + modules = [m for m in stubber.modules if not m in modules_done.keys()] + if not modules: + print("All modules have been processed, exiting") + else: + del modules_done gc.collect() - modules_done[modulename] = str(stubber._report[-1] if ok else "failed") - with open("modulelist.done", "a") as f: - f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) + for modulename in modules: + # ------------------------------------ + # do epic shit + # but sometimes things fail / run out of memory and reboot + ok = False + try: + ok = stubber.create_one_stub(modulename) + except MemoryError: + # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER + machine.reset() + # ------------------------------------- + gc.collect() + # modules_done[modulename] = str(stubber._report[-1] if ok else "failed") + with open("modulelist.done", "a") as f: + f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) # Finished processing - load all the results , and remove the failed ones + modules_done = read_done() if modules_done: # stubber.write_json_end(mod_fp) - stubber._report = [v for _, v in modules_done.items() if v != "failed"] + stubber._report = [] + for k, v in modules_done.items(): + if v != "failed": + stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(k)) stubber.report() +def read_done(): + modules_done = {} # type: dict[str, str] + try: + with open("modulelist.done") as f: + while True: + line = f.readline().strip() + if not line: + break + if len(line) > 0 and line[0] != "#": + key, value = line.split("=", 1) + modules_done[key] = value + except (OSError, SyntaxError): + print("could not read modulelist.done") + finally: + gc.collect() + return modules_done + + def get_modulelist(stubber): + # new + gc.collect() stubber.modules = [] # avoid duplicates for p in LIBS: - try: - with open(p + "/modulelist.txt") as f: - print("DEBUG: list of modules: " + p + "/modulelist.txt") - for line in f.read().split("\n"): - line = line.strip() - if len(line) > 0 and line[0] != "#": - stubber.modules.append(line) - gc.collect() - break - except OSError: - pass + fname = p + "/modulelist.txt" + if not file_exists(fname): + continue + with open(fname) as f: + # print("DEBUG: list of modules: " + p + "/modulelist.txt") + while True: + line = f.readline().strip() + if not line: + break + if len(line) > 0 and line[0] != "#": + stubber.modules.append(line) + gc.collect() + print("BREAK") + break + if not stubber.modules: stubber.modules = ["micropython"] - _log.warn("Could not find modulelist.txt, using default modules") + # _log.warn("Could not find modulelist.txt, using default modules") gc.collect() diff --git a/src/stubber/codemod/_partials/modules_reader.py b/src/stubber/codemod/_partials/modules_reader.py index ec33dfee2..f28ef76c3 100644 --- a/src/stubber/codemod/_partials/modules_reader.py +++ b/src/stubber/codemod/_partials/modules_reader.py @@ -30,6 +30,9 @@ def create_all_stubs(self): def read_path() -> str: ... + def file_exists(f: str) -> bool: + ... + @type_check_only class _gc: def collect(self) -> None: @@ -41,28 +44,37 @@ def collect(self) -> None: stubber: Stubber = None # type: ignore LIBS: List[str] = [".", "lib"] + # sourcery skip: use-named-expression ###PARTIAL### # Read stubs from modulelist in the current folder or in /libs # fall back to default modules -stubber.modules = [] # avoid duplicates -for p in LIBS: - try: - _1 = gc.mem_free() # type: ignore - with open(p + "/modulelist.txt") as f: - print("Debug: List of modules: " + p + "/modulelist.txt") - line = f.readline() - while line: - line = line.strip() +def get_modulelist(stubber): + # new + gc.collect() + stubber.modules = [] # avoid duplicates + for p in LIBS: + fname = p + "/modulelist.txt" + if not file_exists(fname): + continue + with open(fname) as f: + # print("DEBUG: list of modules: " + p + "/modulelist.txt") + while True: + line = f.readline().strip() + if not line: + break if len(line) > 0 and line[0] != "#": stubber.modules.append(line) - line = f.readline() - gc.collect() # type: ignore - print("Debug: Used memory to load modulelist.txt: " + str(_1 - gc.mem_free()) + " bytes") # type: ignore + gc.collect() + print("BREAK") break - except Exception: - pass -if not stubber.modules: - stubber.modules = ["micropython"] - print("Could not find modulelist.txt, using default modules") + + if not stubber.modules: + stubber.modules = ["micropython"] + # _log.warn("Could not find modulelist.txt, using default modules") + gc.collect() + + +stubber.modules = [] # avoid duplicates +get_modulelist(stubber) ###PARTIALEND### diff --git a/src/stubber/codemod/board.py b/src/stubber/codemod/board.py index 19f9b8535..6812c13aa 100644 --- a/src/stubber/codemod/board.py +++ b/src/stubber/codemod/board.py @@ -12,10 +12,10 @@ from libcst.codemod._codemod import Codemod # type: ignore from packaging.version import Version +from stubber import __version__ from stubber.codemod._partials import Partial from stubber.codemod.modify_list import ListChangeSet, ModifyListElements from stubber.cst_transformer import update_module_docstr -from stubber import __version__ # matches on `stubber = Stubber()` _STUBBER_MATCHER = m.Assign( @@ -146,9 +146,7 @@ class ModuleDocCodemod(codemod.Codemod): def __init__(self, context: codemod.CodemodContext, module_doc: str): super().__init__(context) if module_doc.endswith('"""\n'): - generated = ( - f'\nThis variant was generated from createstubs.py by micropython-stubber v{Version(__version__).base_version}\n"""\n' - ) + generated = f'\nThis variant was generated from createstubs.py by micropython-stubber v{Version(__version__).base_version}\n"""\n' module_doc = module_doc[:-4] + generated self.module_doc = module_doc diff --git a/src/stubber/minify.py b/src/stubber/minify.py index de280e834..a70472987 100644 --- a/src/stubber/minify.py +++ b/src/stubber/minify.py @@ -202,7 +202,52 @@ def minify_script(source_script: StubSource, keep_report: bool = True, diff: boo if not source_content: raise ValueError("No source content") + len_1 = len(source_content) + if 0: + min_source = reduce_log_print(keep_report, diff, source_content) + else: + min_source = source_content + len_2 = len(min_source) + + min_source = python_minifier.minify( + min_source, + filename=getattr(source_script, "name", None), + combine_imports=True, + remove_literal_statements=True, # no Docstrings + remove_annotations=True, # not used runtime anyways + hoist_literals=True, # remove redundant strings + rename_locals=True, # short names save memory + preserve_locals=["stubber", "path"], # names to keep + rename_globals=True, # short names save memory + # keep these globals to allow testing/mocking to work against the minified not compiled version + preserve_globals=[ + "main", + "Stubber", + "read_path", + "get_root", + "_info", + "os", + "sys", + "__version__", + ], + # remove_pass=True, # no dead code + # convert_posargs_to_args=True, # Does not save any space + ) + len_3 = len(min_source) + if 1: + # write to temp file for debugging + with open("tmp_minified.py", "w+") as f: + f.write(min_source) + + log.info(f"Original length : {len_1}") + log.info(f"Reduced length : {len_2}") + log.info(f"Minified length : {len_3}") + log.info(f"Reduced by : {len_1-len_3} ") + return min_source + + +def reduce_log_print(keep_report, diff, source_content): edits: LineEdits = [ ("keepprint", "print('Debug: "), ("keepprint", "print('DEBUG: "), @@ -248,41 +293,7 @@ def minify_script(source_script: StubSource, keep_report: bool = True, diff: boo ] + edits content = edit_lines(source_content, edits, diff=diff) - - if 1: - # write to temp file for debugging - with open("tmp_minified.py", "w+") as f: - f.write(content) - - # source = python_minifier.minify( - # content, - # filename=getattr(source_script, "name", None), - # combine_imports=True, - # remove_literal_statements=True, # no Docstrings - # remove_annotations=True, # not used runtime anyways - # hoist_literals=True, # remove redundant strings - # rename_locals=True, # short names save memory - # preserve_locals=["stubber", "path"], # names to keep - # rename_globals=True, # short names save memory - # # keep these globals to allow testing/mocking to work against the minified not compiled version - # preserve_globals=[ - # "main", - # "Stubber", - # "read_path", - # "get_root", - # "_info", - # "os", - # "sys", - # "__version__", - # ], - # # remove_pass=True, # no dead code - # # convert_posargs_to_args=True, # Does not save any space - # ) - source = content - log.debug(f"Original length : {len(content)}") - log.info(f"Minified length : {len(source)}") - log.info(f"Reduced by : {len(content)-len(source)} ") - return source + return content def minify( diff --git a/src/stubber/variants.py b/src/stubber/variants.py index fe0a79d49..bb50cf8b0 100644 --- a/src/stubber/variants.py +++ b/src/stubber/variants.py @@ -26,7 +26,7 @@ def create_variants( *, target_path: Optional[Path] = None, version: str = "", - make_variants: List[CreateStubsVariant] = ALL_VARIANTS, + make_variants: List[CreateStubsVariant] = ALL_VARIANTS[:3], update_modules: bool = True, ): """ @@ -50,7 +50,7 @@ def create_variants( ctx = codemod.CodemodContext() base_file = base_path / "createstubs.py" log.info(f"Reading : {base_file}") - base_txt = base_path / "createstubs.py" + base_txt = (base_path / "createstubs.py").read_text(encoding="utf-8") base_module = cst.parse_module(base_txt) for var in make_variants: diff --git a/tests/createstubs/createstubs_all_test.py b/tests/createstubs/createstubs_all_test.py index b236f99a3..85fa99237 100644 --- a/tests/createstubs/createstubs_all_test.py +++ b/tests/createstubs/createstubs_all_test.py @@ -187,7 +187,6 @@ def mock_uname(): assert Version(info["version"]), "provided version is not a valid version" assert info["port"] != "", "stubber.info() - No port detected" - assert info["board"] != "", "stubber.info() - No board detected" # TEST 2: check if the firmware id is correct new_fwid = stubber._fwid assert new_fwid != "none" diff --git a/tests/createstubs/shared.py b/tests/createstubs/shared.py index 6dc7d7a44..f077bcad1 100644 --- a/tests/createstubs/shared.py +++ b/tests/createstubs/shared.py @@ -1,6 +1,7 @@ -import pytest from importlib import import_module +import pytest + LOCATIONS = ["board", pytest.param("minified", marks=pytest.mark.minified)] VARIANTS = ["createstubs", "createstubs_mem", "createstubs_db"] diff --git a/tests/createstubs/testcases.py b/tests/createstubs/testcases.py index cffa25aa6..439c83b32 100644 --- a/tests/createstubs/testcases.py +++ b/tests/createstubs/testcases.py @@ -136,7 +136,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): # - patch input - os.uname stucture # - patch input - array of modules to mock for firmware detection ( - "micropython-v1.9.4-esp32-GENERIC", + "micropython-v1.9.4-esp32", MP_Implementation(name="micropython", version=(1, 9, 4)), "esp32", "", @@ -144,7 +144,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): [], ), ( - "micropython-v1.10-esp32-GENERIC", + "micropython-v1.10-esp32", MP_Implementation( "micropython", (1, 10, 0), @@ -155,7 +155,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): [], ), ( - "micropython-v1.13-preview-esp32-GENERIC_SPIRAM", + "micropython-v1.13-preview-esp32", MP_Implementation( "micropython", (1, 13, 0), @@ -166,7 +166,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): [], ), ( - "micropython-v1.11-esp8266-GENERIC", + "micropython-v1.11-esp8266", MP_Implementation( "micropython", (1, 11, 0), @@ -177,7 +177,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): [], ), ( - "micropython-v1.11-preview-esp8266-GENERIC", + "micropython-v1.11-preview-esp8266", MP_Implementation( "micropython", (1, 11, 0), @@ -188,7 +188,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): [], ), ( - "micropython-v1.17-esp8266-GENERIC", + "micropython-v1.17-esp8266", MP_Implementation( "micropython", (1, 17, 0), @@ -200,7 +200,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): ), # mpy pyb1 ( - "micropython-v1.13-preview-stm32-PYBV11", + "micropython-v1.13-preview-stm32", MP_Implementation( "micropython", (1, 13, 0), @@ -212,7 +212,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): ), # RP2 ( - "micropython-v1.18-preview-rp2-RPI_PICO", + "micropython-v1.18-preview-rp2", MP_Implementation( "micropython", (1, 18, 0), @@ -294,7 +294,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): ), # 1.19.1 ( - "micropython-v1.19.1-preview-rp2-RPI_PICO_W", + "micropython-v1.19.1-preview-rp2", MP_Implementation("micropython", (1, 19, 1)), "rp2", "", @@ -308,7 +308,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): [], ), ( - "micropython-v1.19.1-rp2-PIMORONI_PICOLIPO_16MB", + "micropython-v1.19.1-rp2", MP_Implementation("micropython", (1, 19, 1)), "rp2", "", @@ -324,7 +324,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): # version 1.22 ( # using uname (old) - "micropython-v1.22.0-esp32-ESP32_GENERIC", + "micropython-v1.22.0-esp32", MP_Implementation("micropython", (1, 22, 0, "")), "esp32", "", @@ -333,7 +333,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): ), ( # using _machine and uname - "micropython-v1.22.0-esp32-ESP32_GENERIC", + "micropython-v1.22.0-esp32", MP_Implementation("micropython", (1, 22, 0, ""), _machine="Generic ESP32 module with SPIRAM with ESP32"), "esp32", "", @@ -342,7 +342,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): ), ( # using _machine only (new) - "micropython-v1.22.0-samd-SEEED_WIO_TERMINAL", + "micropython-v1.22.0-samd", MP_Implementation("micropython", (1, 22, 0, ""), _machine="Wio Terminal D51R with SAMD51P19A"), "samd", "", @@ -351,7 +351,7 @@ def __init__(self, name: str, version: Tuple, *, _machine=None, _mpy=None): ), ( # using _machine only (new) - "micropython-v1.23.0-preview-samd-SEEED_WIO_TERMINAL", + "micropython-v1.23.0-preview-samd", MP_Implementation("micropython", (1, 23, 0, "preview"), _machine="Wio Terminal D51R with SAMD51P19A"), "samd", "3.4.0; MicroPython v1.23.0-preview.6.g3d0b6276f on 2024-01-02", # sys.version diff --git a/tests/utils/repos_test.py b/tests/utils/repos_test.py index 6ddfa877f..e3b9e564d 100644 --- a/tests/utils/repos_test.py +++ b/tests/utils/repos_test.py @@ -12,4 +12,3 @@ def test_stubber_switch_version_commit_list(version: str): # from version 1.12.0, the commit list is not needed as micropython-lib is a submodule of micropython assert len(mpy_lib_commits) > 0 assert version in mpy_lib_commits, "match" - # TODO : check latest / master diff --git a/tmp_minified_1.py b/tmp_minified_1.py deleted file mode 100644 index ad7e11574..000000000 --- a/tmp_minified_1.py +++ /dev/null @@ -1,954 +0,0 @@ -""" -Create stubs for (all) modules on a MicroPython board -""" -# Copyright (c) 2019-2023 Jos Verlinde - -import gc -# import logging -import os -import sys - -try: - from ujson import dumps -except: - from json import dumps - -try: - from machine import reset # type: ignore -except ImportError: - pass - -try: - from collections import OrderedDict -except ImportError: - from ucollections import OrderedDict # type: ignore - -__version__ = "v1.16.2" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] -from time import sleep - - -class Stubber: - "Generate stubs for modules in firmware" - - def __init__(self, path: str = None, firmware_id: str = None): # type: ignore - try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore - raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") - except AttributeError: - pass - # self.log = logging.getLogger("stubber") - self._report = [] # type: list[str] - self.info = _info() - # self.log.info("Port: {}".format(self.info["port"])) - # self.log.info("Board: {}".format(self.info["board"])) - gc.collect() - if firmware_id: - self._fwid = firmware_id.lower() - else: - if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info) - else: - self._fwid = "{family}-v{version}-{port}".format(**self.info) - self._start_free = gc.mem_free() # type: ignore - - if path: - if path.endswith("/"): - path = path[:-1] - else: - path = get_root() - - self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - # self.log.debug(self.path) - try: - ensure_folder(path + "/") - except OSError: - print("error creating stub folder {}".format(path)) - self.problematic = [ - "upip", - "upysh", - "webrepl_setup", - "http_client", - "http_client_ssl", - "http_server", - "http_server_ssl", - ] - self.excluded = [ - "webrepl", - "_webrepl", - "port_diag", - "example_sub_led.py", - "example_pub_button.py", - ] - # there is no option to discover modules from micropython, list is read from an external file. - self.modules = [] # type: list[str] - - def get_obj_attributes(self, item_instance: object): - "extract information of the objects members and attributes" - # name_, repr_(value), type as text, item_instance - _result = [] - _errors = [] - # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) - for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: - continue - # self.log.debug("get attribute {}".format(name)) - try: - val = getattr(item_instance, name) - # name , item_repr(value) , type as text, item_instance, order - try: - type_text = repr(type(val)).split("'")[1] - except IndexError: - type_text = "" - if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: - order = 1 - elif type_text in {"function", "method"}: - order = 2 - elif type_text in ("class"): - order = 3 - else: - order = 4 - _result.append((name, repr(val), repr(type(val)), val, order)) - except AttributeError as e: - _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) - except MemoryError as e: - # print("MemoryError: {}".format(e)) - sleep(1) - reset() - - # remove internal __ - # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) - _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) - gc.collect() - return _result, _errors - - def add_modules(self, modules): - "Add additional modules to be exported" - self.modules = sorted(set(self.modules) | set(modules)) - - def create_all_stubs(self): - "Create stubs for all configured modules" - # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) - gc.collect() - for module_name in self.modules: - self.create_one_stub(module_name) - # self.log.info("Finally done") - - def create_one_stub(self, module_name: str): - if module_name in self.problematic: - # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) - return False - if module_name in self.excluded: - # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) - return False - - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) - gc.collect() - result = False - try: - result = self.create_module_stub(module_name, file_name) - except OSError: - return False - gc.collect() - return result - - def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore - """Create a Stub of a single python module - - Args: - - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. - """ - if file_name is None: - fname = module_name.replace(".", "_") + ".py" - file_name = self.path + "/" + fname - else: - fname = file_name.split("/")[-1] - - if "/" in module_name: - # for nested modules - module_name = module_name.replace("/", ".") - - # import the module (as new_module) to examine it - new_module = None - try: - new_module = __import__(module_name, None, None, ("*")) - m1 = gc.mem_free() # type: ignore - # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) - - except ImportError: - # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) - return False - - # Start a new file - ensure_folder(file_name) - with open(file_name, "w") as fp: - # todo: improve header - info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") - s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format( - module_name, self._fwid, info_, __version__ - ) - fp.write(s) - fp.write("from typing import Any\nfrom _typeshed import Incomplete\n\n") - self.write_object_stub(fp, new_module, module_name, "") - - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) - - if module_name not in {"os", "sys", "logging", "gc"}: - # try to unload the module unless we use it - try: - del new_module - except (OSError, KeyError): # lgtm [py/unreachable-statement] - pass - try: - del sys.modules[module_name] - except KeyError: - pass - gc.collect() - return True - - def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): - "Write a module/object stub to an open file. Can be called recursive." - gc.collect() - if object_expr in self.problematic: - # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) - return - - # # self.log.debug("DUMP : {}".format(object_expr)) - items, errors = self.get_obj_attributes(object_expr) - - if errors: - print(errors) - - for item_name, item_repr, item_type_txt, item_instance, _ in items: - # name_, repr_(value), type as text, item_instance, order - if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: - # do not create stubs for these primitives - continue - if item_name[0].isdigit(): - # self.log.warning("NameError: invalid name {}".format(item_name)) - continue - # Class expansion only on first 3 levels (bit of a hack) - if item_type_txt == "" and len(indent) <= _MAX_CLASS_LEVEL * 4: - # self.log.debug("{0}class {1}:".format(indent, item_name)) - superclass = "" - is_exception = ( - item_name.endswith("Exception") - or item_name.endswith("Error") - or item_name - in [ - "KeyboardInterrupt", - "StopIteration", - "SystemExit", - ] - ) - if is_exception: - superclass = "Exception" - s = "\n{}class {}({}):\n".format(indent, item_name, superclass) - # s += indent + " ''\n" - if is_exception: - s += indent + " ...\n" - fp.write(s) - return - # write classdef - fp.write(s) - # first write the class literals and methods - # self.log.debug("# recursion over class {0}".format(item_name)) - self.write_object_stub( - fp, - item_instance, - "{0}.{1}".format(obj_name, item_name), - indent + " ", - in_class + 1, - ) - # end with the __init__ method to make sure that the literals are defined - # Add __init__ - s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" - s += indent + " ...\n\n" - fp.write(s) - elif any(word in item_type_txt for word in ["method", "function", "closure"]): - # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) - # module Function or class method - # will accept any number of params - # return type Any/Incomplete - ret = "Incomplete" - first = "" - # Self parameter only on class methods/functions - if in_class > 0: - first = "self, " - # class method - add function decoration - if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format( - indent, item_name, ret - ) - else: - s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) - s += indent + " ...\n\n" - fp.write(s) - # self.log.debug("\n" + s) - elif item_type_txt == "": - # Skip imported modules - # fp.write("# import {}\n".format(item_name)) - pass - - elif item_type_txt.startswith(" dict[str, str] - info = OrderedDict( - { - "family": sys.implementation.name, - "version": "", - "build": "", - "ver": "", - "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "UNKNOWN", - "cpu": "", - "mpy": "", - "arch": "", - } - ) - # change port names to be consistent with the repo - if info["port"].startswith("pyb"): - info["port"] = "stm32" - elif info["port"] == "win32": - info["port"] = "windows" - elif info["port"] == "linux": - info["port"] = "unix" - try: - info["version"] = version_str(sys.implementation.version) # type: ignore - except AttributeError: - pass - try: - _machine = ( - sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - ) - # info["board"] = "with".join(_machine.split("with")[:-1]).strip() - info["board"] = _machine - info["cpu"] = _machine.split("with")[-1].strip() - info["mpy"] = ( - sys.implementation._mpy - if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy - if "mpy" in dir(sys.implementation) - else "" - ) - except (AttributeError, IndexError): - pass - gc.collect() - read_boardname(info) - gc.collect() - - try: - if "uname" in dir(os): # old - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - elif "version" in dir(sys): # new - # extract build from sys.version if available - info["build"] = _build(sys.version) - except (AttributeError, IndexError, TypeError): - pass - # avoid build hashes - # if info["build"] and len(info["build"]) > 5: - # info["build"] = "" - - if info["version"] == "" and sys.platform not in ("unix", "win32"): - try: - u = os.uname() # type: ignore - info["version"] = u.release - except (IndexError, AttributeError, TypeError): - pass - # detect families - for fam_name, mod_name, mod_thing in [ - ("pycopy", "pycopy", "const"), - ("pycom", "pycom", "FAT"), - ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), - ]: - try: - _t = __import__(mod_name, None, None, (mod_thing)) - info["family"] = fam_name - del _t - break - except (ImportError, KeyError): - pass - - if info["family"] == "ev3-pybricks": - info["release"] = "2.0.0" - - if info["family"] == "micropython": - info["version"] - if ( - info["version"] - and info["version"].endswith(".0") - and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 - and info["version"] <= "1.19.9" - ): - # versions from 1.10.0 to 1.20.0 do not have a micro .0 - info["version"] = info["version"][:-2] - - # spell-checker: disable - if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds - sys_mpy = int(info["mpy"]) - # .mpy architecture - arch = [ - None, - "x86", - "x64", - "armv6", - "armv6m", - "armv7m", - "armv7em", - "armv7emsp", - "armv7emdp", - "xtensa", - "xtensawin", - ][sys_mpy >> 10] - if arch: - info["arch"] = arch - # .mpy version.minor - info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) - if info["build"] and not info["version"].endswith("-preview"): - info["version"] = info["version"] + "-preview" - # simple to use version[-build] string - info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" - - return info - - -def version_str(version: tuple): # -> str: - v_str = ".".join([str(n) for n in version[:3]]) - if len(version) > 3 and version[3]: - v_str += "-" + version[3] - return v_str - - -def read_boardname(info, desc: str = ""): - found = False - for filename in [d + "/board_info.csv" for d in LIBS]: - # # print("look up the board name in the file", filename) - if file_exists(filename): - descr = desc or info["board"].strip() - pos = descr.rfind(" with") - if pos != -1: - short_descr = descr[:pos].strip() - else: - short_descr = "" - # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) - if find_board(info, descr, filename, short_descr): - found = True - break - if not found: - # print("Board not found, guessing board name") - descr = desc or info["board"].strip() - if "with " + info["cpu"].upper() in descr: - # remove the with cpu part - descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - info["board"] = info["board"].replace(" ", "_") - gc.collect() - - -def find_board(info: dict, descr: str, filename: str, short_descr: str): - "Find the board in the provided board_info.csv file" - short_hit = "" - with open(filename, "r") as file: - # ugly code to make testable in python and micropython - # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) - while 1: - line = file.readline() - if not line: - break - descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() - if descr_ == descr: - info["board"] = board_ - return True - elif short_descr and descr_ == short_descr: - if "with" in short_descr: - # Good enough - no need to trawl the entire file - info["board"] = board_ - return True - # good enough if not found in the rest of the file (but slow) - short_hit = board_ - if short_hit: - info["board"] = short_hit - return True - return False - - -def get_root() -> str: # sourcery skip: use-assigned-variable - "Determine the root folder of the device" - try: - c = os.getcwd() - except (OSError, AttributeError): - # unix port - c = "." - r = c - for r in [c, "/sd", "/flash", "/", "."]: - try: - _ = os.stat(r) - break - except OSError: - continue - return r - - -def file_exists(filename: str): - try: - if os.stat(filename)[0] >> 14: - return True - return False - except OSError: - return False - - -def show_help(): - # print("-p, --path path to store the stubs in, defaults to '.'") - sys.exit(1) - - -def read_path() -> str: - "get --path from cmdline. [unix/win]" - path = "" - if len(sys.argv) == 3: - cmd = (sys.argv[1]).lower() - if cmd in ("--path", "-p"): - path = sys.argv[2] - else: - show_help() - elif len(sys.argv) == 2: - show_help() - return path - - -def is_micropython() -> bool: - "runtime test to determine full or micropython" - # pylint: disable=unused-variable,eval-used - try: - # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects - - # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented - # Micropython: NotImplementedError - b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] - - # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute - # Micropython: AttributeError - c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] - return False - except (NotImplementedError, AttributeError): - return True - - -def main(): - stubber = Stubber(path=read_path()) - # stubber = Stubber(path="/sd") - # Option: Specify a firmware name & version - # stubber = Stubber(firmware_id='HoverBot v1.2.1') - stubber.clean() - # there is no option to discover modules from micropython, need to hardcode - # below contains combined modules from Micropython ESP8622, ESP32, Loboris, Pycom and ulab , lvgl - # spell-checker: disable - # modules to stub : 131 - stubber.modules = [ - "WM8960", - "_OTA", - "_asyncio", - "_boot_fat", - "_coap", - "_espnow", - "_flash_control_OTA", - "_main_pybytes", - "_mqtt", - "_mqtt_core", - "_msg_handl", - "_onewire", - "_periodical_pin", - "_pybytes", - "_pybytes_ca", - "_pybytes_config", - "_pybytes_config_reader", - "_pybytes_connection", - "_pybytes_constants", - "_pybytes_debug", - "_pybytes_library", - "_pybytes_machine_learning", - "_pybytes_main", - "_pybytes_protocol", - "_pybytes_pyconfig", - "_pybytes_pymesh_config", - "_rp2", - "_terminal", - "_thread", - "_uasyncio", - "_urequest", - "adcfft", - "aioble/__init__", - "aioble/central", - "aioble/client", - "aioble/core", - "aioble/device", - "aioble/l2cap", - "aioble/peripheral", - "aioble/security", - "aioble/server", - "aioespnow", - "ak8963", - "apa102", - "apa106", - "argparse", - "array", - "asyncio/__init__", - "asyncio/core", - "asyncio/event", - "asyncio/funcs", - "asyncio/lock", - "asyncio/stream", - "binascii", - "bluetooth", - "breakout_as7262", - "breakout_bh1745", - "breakout_bme280", - "breakout_bme68x", - "breakout_bmp280", - "breakout_dotmatrix", - "breakout_encoder", - "breakout_icp10125", - "breakout_ioexpander", - "breakout_ltr559", - "breakout_matrix11x7", - "breakout_mics6814", - "breakout_msa301", - "breakout_paa5100", - "breakout_pmw3901", - "breakout_potentiometer", - "breakout_rgbmatrix5x5", - "breakout_rtc", - "breakout_scd41", - "breakout_sgp30", - "breakout_trackball", - "breakout_vl53l5cx", - "btree", - "cmath", - "collections", - "crypto", - "cryptolib", - "curl", - "deflate", - "dht", - "display", - "display_driver_utils", - "ds18x20", - "encoder", - "errno", - "esp", - "esp32", - "espidf", - "espnow", - "ffi", - "flashbdev", - "framebuf", - "freesans20", - "fs_driver", - "functools", - "galactic", - "gc", - "gfx_pack", - "gsm", - "hashlib", - "heapq", - "hub75", - "ili9341", - "ili9XXX", - "imagetools", - "inisetup", - "interstate75", - "io", - "jpegdec", - "json", - "lcd160cr", - "lodepng", - "logging", - "lsm6dsox", - "lv_colors", - "lv_utils", - "lvgl", - "lwip", - "machine", - "math", - "microWebSocket", - "microWebSrv", - "microWebTemplate", - "micropython", - "mip", - "mip/__init__", - "mip/__main__", - "motor", - "mpu6500", - "mpu9250", - "neopixel", - "network", - "ntptime", - "onewire", - "os", - "pcf85063a", - "picoexplorer", - "picographics", - "picokeypad", - "picoscroll", - "picounicorn", - "picowireless", - "pimoroni", - "pimoroni_bus", - "pimoroni_i2c", - "plasma", - "platform", - "pyb", - "pycom", - "pye", - "qrcode", - "queue", - "random", - "requests", - "requests/__init__", - "rp2", - "rtch", - "samd", - "select", - "servo", - "socket", - "ssd1306", - "ssh", - "ssl", - "stm", - "struct", - "sys", - "termios", - "time", - "tpcalib", - "uarray", - "uasyncio/__init__", - "uasyncio/core", - "uasyncio/event", - "uasyncio/funcs", - "uasyncio/lock", - "uasyncio/stream", - "uasyncio/tasks", - "ubinascii", - "ubluetooth", - "ucollections", - "ucrypto", - "ucryptolib", - "uctypes", - "uerrno", - "uftpd", - "uhashlib", - "uheapq", - "uio", - "ujson", - "ulab", - "ulab/approx", - "ulab/compare", - "ulab/fft", - "ulab/filter", - "ulab/linalg", - "ulab/numerical", - "ulab/poly", - "ulab/user", - "ulab/vector", - "umachine", - "umqtt/__init__", - "umqtt/robust", - "umqtt/simple", - "uos", - "uplatform", - "uqueue", - "urandom", - "ure", - "urequests", - "urllib/urequest", - "uselect", - "usocket", - "ussl", - "ustruct", - "usys", - "utelnetserver", - "utime", - "utimeq", - "uwebsocket", - "uzlib", - "version", - "websocket", - "websocket_helper", - "wipy", - "writer", - "xpt2046", - "ymodem", - "zephyr", - "zlib", - ] # spell-checker: enable - - gc.collect() - - stubber.create_all_stubs() - stubber.report() - - -if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass - if not file_exists("no_auto_stubber.txt"): - try: - gc.threshold(4 * 1024) # type: ignore - gc.enable() - except BaseException: - pass - main() From 2971880a95b171a0b3c6d71eedd8c16fc8421c06 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Tue, 30 Jan 2024 22:43:11 +0100 Subject: [PATCH 55/68] reduced memory uasge for esp8266 Signed-off-by: Jos Verlinde --- mip/v6/createstubs.py | 3 +- scripts/board_stubber.py | 4 +- src/stubber/board/createstubs.py | 46 ++- src/stubber/board/createstubs_db.py | 59 ++-- src/stubber/board/createstubs_db_min.py | 341 +++++++++++----------- src/stubber/board/createstubs_db_mpy.mpy | Bin 10274 -> 9556 bytes src/stubber/board/createstubs_mem.py | 46 ++- src/stubber/board/createstubs_mem_min.py | 263 ++++++++--------- src/stubber/board/createstubs_mem_mpy.mpy | Bin 9588 -> 8906 bytes src/stubber/board/createstubs_min.py | 219 +++++++------- src/stubber/board/createstubs_mpy.mpy | Bin 12701 -> 12009 bytes src/stubber/codemod/_partials/db_main.py | 13 +- 12 files changed, 467 insertions(+), 527 deletions(-) diff --git a/mip/v6/createstubs.py b/mip/v6/createstubs.py index 98f6dacbf..6d22cdbea 100644 --- a/mip/v6/createstubs.py +++ b/mip/v6/createstubs.py @@ -25,8 +25,7 @@ from ucollections import OrderedDict # type: ignore try: - from nope_machine import WDT - + from machine import WDT wdt = WDT() except ImportError: diff --git a/scripts/board_stubber.py b/scripts/board_stubber.py index f8ec54e8f..3a74429af 100644 --- a/scripts/board_stubber.py +++ b/scripts/board_stubber.py @@ -372,8 +372,8 @@ def run_createstubs(dest: Path, mcu: MPRemoteBoard, variant: Variant = Variant.d mcu.run_command.retry.wait = wait_fixed(15) # some boards need 2-3 minutes to run createstubs - so increase the default timeout # esp32s3 > 240 seconds with mounted fs - # but slows down esp8266 restarts so keep that to 60 seconds - timeout = 60 if mcu.port == "esp8266" else 6 * 60 # type: ignore + # but slows down esp8266 restarts so keep that to 90 seconds + timeout = 90 if mcu.port == "esp8266" else 6 * 60 # type: ignore rc, out = mcu.run_command(cmd, timeout=timeout) # check last line for exception or error and raise that if found if rc != OK and ":" in out[-1] and not out[-1].startswith("INFO") and not out[-1].startswith("WARN"): diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index e72983523..1f7ca21d3 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -31,12 +31,10 @@ # our own logging module to avoid dependency on and interfering with logging module class logging: - DEBUG = 10 - TRACE = 15 + # DEBUG = 10 INFO = 20 WARNING = 30 ERROR = 40 - CRITICAL = 50 level = INFO prnt = print @@ -47,15 +45,10 @@ def getLogger(name): @classmethod def basicConfig(cls, level): cls.level = level - pass - - def trace(self, msg): - if self.level <= logging.TRACE: - self.prnt("TRACE :", msg) - def debug(self, msg): - if self.level <= logging.DEBUG: - self.prnt("DEBUG :", msg) + # def debug(self, msg): + # if self.level <= logging.DEBUG: + # self.prnt("DEBUG :", msg) def info(self, msg): if self.level <= logging.INFO: @@ -69,14 +62,9 @@ def error(self, msg): if self.level <= logging.ERROR: self.prnt("ERROR :", msg) - def critical(self, msg): - if self.level <= logging.CRITICAL: - self.prnt("CRIT :", msg) - log = logging.getLogger("stubber") logging.basicConfig(level=logging.INFO) -# logging.basicConfig(level=logging.TRACE) # logging.basicConfig(level=logging.DEBUG) @@ -110,7 +98,7 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore path = get_root() self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - log.debug(self.path) + # log.debug(self.path) try: ensure_folder(path + "/") except OSError: @@ -139,15 +127,15 @@ def get_obj_attributes(self, item_instance: object): # name_, repr_(value), type as text, item_instance _result = [] _errors = [] - log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): if name.startswith("_") and not name in self.modules: continue - log.debug("get attribute {}".format(name)) + # log.debug("get attribute {}".format(name)) try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order - log.debug("attribute {}:{}".format(name, val)) + # log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -229,7 +217,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - log.trace("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + # log.debug("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -267,7 +255,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # log.debug("DUMP : {}".format(object_expr)) + # # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: @@ -288,7 +276,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - log.trace("{0}class {1}:".format(indent, item_name)) + # log.debug("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -311,7 +299,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - log.debug("# recursion over class {0}".format(item_name)) + # log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -325,7 +313,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -343,7 +331,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - log.debug("\n" + s) + # log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -371,10 +359,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - log.debug("\n" + s) + # log.debug("\n" + s) else: # keep only the name - log.debug("# all other, type = '{0}'".format(item_type_txt)) + # log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -434,7 +422,7 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - log.trace("Memory used: {0} Kb".format(used // 1024)) + # log.debug("Memory used: {0} Kb".format(used // 1024)) except OSError: log.error("Failed to create the report.") diff --git a/src/stubber/board/createstubs_db.py b/src/stubber/board/createstubs_db.py index ccace6f89..2743ac849 100644 --- a/src/stubber/board/createstubs_db.py +++ b/src/stubber/board/createstubs_db.py @@ -50,12 +50,10 @@ # our own logging module to avoid dependency on and interfering with logging module class logging: - DEBUG = 10 - TRACE = 15 + # DEBUG = 10 INFO = 20 WARNING = 30 ERROR = 40 - CRITICAL = 50 level = INFO prnt = print @@ -66,15 +64,10 @@ def getLogger(name): @classmethod def basicConfig(cls, level): cls.level = level - pass - - def trace(self, msg): - if self.level <= logging.TRACE: - self.prnt("TRACE :", msg) - def debug(self, msg): - if self.level <= logging.DEBUG: - self.prnt("DEBUG :", msg) + # def debug(self, msg): + # if self.level <= logging.DEBUG: + # self.prnt("DEBUG :", msg) def info(self, msg): if self.level <= logging.INFO: @@ -88,14 +81,9 @@ def error(self, msg): if self.level <= logging.ERROR: self.prnt("ERROR :", msg) - def critical(self, msg): - if self.level <= logging.CRITICAL: - self.prnt("CRIT :", msg) - log = logging.getLogger("stubber") logging.basicConfig(level=logging.INFO) -# logging.basicConfig(level=logging.TRACE) # logging.basicConfig(level=logging.DEBUG) @@ -129,7 +117,7 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore path = get_root() self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - log.debug(self.path) + # log.debug(self.path) try: ensure_folder(path + "/") except OSError: @@ -158,15 +146,15 @@ def get_obj_attributes(self, item_instance: object): # name_, repr_(value), type as text, item_instance _result = [] _errors = [] - log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): if name.startswith("_") and not name in self.modules: continue - log.debug("get attribute {}".format(name)) + # log.debug("get attribute {}".format(name)) try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order - log.debug("attribute {}:{}".format(name, val)) + # log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -248,7 +236,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - log.trace("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + # log.debug("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -284,7 +272,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # log.debug("DUMP : {}".format(object_expr)) + # # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: @@ -305,7 +293,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - log.trace("{0}class {1}:".format(indent, item_name)) + # log.debug("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -328,7 +316,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - log.debug("# recursion over class {0}".format(item_name)) + # log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -342,7 +330,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -358,7 +346,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - log.debug("\n" + s) + # log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -386,10 +374,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - log.debug("\n" + s) + # log.debug("\n" + s) else: # keep only the name - log.debug("# all other, type = '{0}'".format(item_type_txt)) + # log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -449,7 +437,7 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - log.trace("Memory used: {0} Kb".format(used // 1024)) + # log.debug("Memory used: {0} Kb".format(used // 1024)) except OSError: log.error("Failed to create the report.") @@ -734,17 +722,16 @@ def main(): # Only clean folder if this is a first run stubber.clean() # get list of modules to process - get_modulelist(stubber) - # remove the ones that are already done modules_done = read_done() # see if we can continue from where we left off - modules = [m for m in stubber.modules if not m in modules_done.keys()] - if not modules: + get_modulelist(stubber, modules_done) + + if not stubber.modules: print("All modules have been processed, exiting") else: del modules_done gc.collect() - for modulename in modules: + for modulename in stubber.modules: # ------------------------------------ # do epic shit # but sometimes things fail / run out of memory and reboot @@ -789,7 +776,7 @@ def read_done(): return modules_done -def get_modulelist(stubber): +def get_modulelist(stubber, modules_done): # new gc.collect() stubber.modules = [] # avoid duplicates @@ -803,7 +790,7 @@ def get_modulelist(stubber): line = f.readline().strip() if not line: break - if len(line) > 0 and line[0] != "#": + if line and line not in modules_done.keys(): stubber.modules.append(line) gc.collect() print("BREAK") diff --git a/src/stubber/board/createstubs_db_min.py b/src/stubber/board/createstubs_db_min.py index 474217d47..f61b4498f 100644 --- a/src/stubber/board/createstubs_db_min.py +++ b/src/stubber/board/createstubs_db_min.py @@ -17,29 +17,29 @@ c='tuple' b='_' a='micropython' -Y='modulelist.done' -X='-preview' -W='-' -V='board' -U=IndexError -T=repr +Z=repr +X='modulelist.done' +W='-preview' +V='-' +U='board' +T=IndexError S='family' R=ImportError -Q=dir -P=True -O=len +Q=len +P=dir +O=True N=open -M='port' -L='.' -K=print -J=AttributeError +L='port' +K='.' +J=print +I=AttributeError H=False G='/' F=None E=OSError D='version' C='' -import gc as B,os,sys +import gc as A,os,sys from time import sleep try:from ujson import dumps except:from json import dumps @@ -50,119 +50,112 @@ __version__='v1.16.3' z=2 A0=2 -A1=['lib','/lib','/sd/lib','/flash/lib',L] -class I: - DEBUG=10;TRACE=15;INFO=20;WARNING=30;ERROR=40;CRITICAL=50;level=INFO;prnt=K +A1=['lib','/lib','/sd/lib','/flash/lib',K] +class M: + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=J @staticmethod - def getLogger(name):return I() + def getLogger(name):return M() @classmethod def basicConfig(A,level):A.level=level - def trace(A,msg): - if A.level<=I.TRACE:A.prnt('TRACE :',msg) - def debug(A,msg): - if A.level<=I.DEBUG:A.prnt('DEBUG :',msg) def info(A,msg): - if A.level<=I.INFO:A.prnt('INFO :',msg) + if A.level<=M.INFO:A.prnt('INFO :',msg) def warning(A,msg): - if A.level<=I.WARNING:A.prnt('WARN :',msg) + if A.level<=M.WARNING:A.prnt('WARN :',msg) def error(A,msg): - if A.level<=I.ERROR:A.prnt('ERROR :',msg) - def critical(A,msg): - if A.level<=I.CRITICAL:A.prnt('CRIT :',msg) -A=I.getLogger(r) -I.basicConfig(level=I.INFO) + if A.level<=M.ERROR:A.prnt('ERROR :',msg) +B=M.getLogger(r) +M.basicConfig(level=M.INFO) class Stubber: def __init__(C,path=F,firmware_id=F): D=firmware_id try: if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') - except J:pass - C._report=[];C.info=_info();A.info('Port: {}'.format(C.info[M]));A.info('Board: {}'.format(C.info[V]));B.collect() + except I:pass + C._report=[];C.info=_info();B.info('Port: {}'.format(C.info[L]));B.info('Board: {}'.format(C.info[U]));A.collect() if D:C._fwid=D.lower() - elif C.info[S]==a:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info).rstrip(W) + elif C.info[S]==a:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info).rstrip(V) else:C._fwid='{family}-v{version}-{port}'.format(**C.info) - C._start_free=B.mem_free() + C._start_free=A.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() - C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G);A.debug(C.path) + C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) try:h(path+G) - except E:A.error('error creating stub folder {}'.format(path)) + except E:B.error('error creating stub folder {}'.format(path)) C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] - def get_obj_attributes(N,item_instance): - E=item_instance;G=[];M=[];A.debug('get attributes {} {}'.format(T(E),E)) - for D in Q(E): - if D.startswith(b)and not D in N.modules:continue - A.debug('get attribute {}'.format(D)) + def get_obj_attributes(M,item_instance): + H=item_instance;D=[];L=[] + for B in P(H): + if B.startswith(b)and not B in M.modules:continue try: - F=getattr(E,D);A.debug('attribute {}:{}'.format(D,F)) - try:H=T(type(F)).split("'")[1] - except U:H=C - if H in{s,t,u,v,c,d,e}:I=1 - elif H in{w,x}:I=2 - elif H in'class':I=3 - else:I=4 - G.append((D,T(F),T(type(F)),F,I)) - except J as L:M.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(D,E,L)) - except n as L:K('MemoryError: {}'.format(L));sleep(1);reset() - G=o([A for A in G if not A[0].startswith('__')],key=lambda x:x[4]);B.collect();return G,M + E=getattr(H,B) + try:F=Z(type(E)).split("'")[1] + except T:F=C + if F in{s,t,u,v,c,d,e}:G=1 + elif F in{w,x}:G=2 + elif F in'class':G=3 + else:G=4 + D.append((B,Z(E),Z(type(E)),E,G)) + except I as K:L.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(B,H,K)) + except n as K:J('MemoryError: {}'.format(K));sleep(1);reset() + D=o([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);A.collect();return D,L def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) def create_all_stubs(C): - A.info('Start micropython-stubber v{} on {}'.format(__version__,C._fwid));B.collect() + B.info('Start micropython-stubber v{} on {}'.format(__version__,C._fwid));A.collect() for D in C.modules:C.create_one_stub(D) - A.info('Finally done') + B.info('Finally done') def create_one_stub(D,module_name): C=module_name - if C in D.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(C));return H - if C in D.excluded:A.warning('Skip module: {:<25} : Excluded'.format(C));return H - I='{}/{}.py'.format(D.path,C.replace(L,G));B.collect();F=H + if C in D.problematic:B.warning('Skip module: {:<25} : Known problematic'.format(C));return H + if C in D.excluded:B.warning('Skip module: {:<25} : Excluded'.format(C));return H + I='{}/{}.py'.format(D.path,C.replace(K,G));A.collect();F=H try:F=D.create_module_stub(C,I) except E:return H - B.collect();return F + A.collect();return F def create_module_stub(J,module_name,file_name=F): I=file_name;D=module_name - if I is F:K=D.replace(L,b)+'.py';I=J.path+G+K - else:K=I.split(G)[-1] - if G in D:D=D.replace(G,L) + if I is F:L=D.replace(K,b)+'.py';I=J.path+G+L + else:L=I.split(G)[-1] + if G in D:D=D.replace(G,K) M=F - try:M=__import__(D,F,F,'*');Q=B.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(D,K,Q)) - except R:A.trace('Skip module: {:<25} {:<79}'.format(D,'Module not found.'));return H + try:M=__import__(D,F,F,'*');Q=A.mem_free();B.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(D,L,Q)) + except R:return H h(I) - with N(I,'w')as O:S=str(J.info).replace('OrderedDict(',C).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,S,__version__);O.write(T);O.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(O,M,D,C) + with N(I,'w')as P:S=str(J.info).replace('OrderedDict(',C).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(P,M,D,C) J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,I.replace('\\',G))) if D not in{'os','sys','logging','gc'}: try:del M - except(E,p):A.warning('could not del new_module') - B.collect();return P + except(E,p):B.warning('could not del new_module') + A.collect();return O def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;F=indent;B.collect() - if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return - X,P=K.get_obj_attributes(L) - if P:A.error(P) - for(D,J,G,Y,a)in X: - if D in['classmethod','staticmethod','BaseException',M]:continue - if D[0].isdigit():A.warning('NameError: invalid name {}'.format(D));continue - if G==""and O(F)<=A0*4: - A.trace('{0}class {1}:'.format(F,D));Q=C;R=D.endswith(M)or D.endswith('Error')or D in['KeyboardInterrupt','StopIteration','SystemExit'] - if R:Q=M - E='\n{}class {}({}):\n'.format(F,D,Q) - if R:E+=F+' ...\n';I.write(E);continue - I.write(E);A.debug('# recursion over class {0}'.format(D));K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,D),F+' ',N+1);E=F+' def __init__(self, *argv, **kwargs) -> None:\n';E+=F+' ...\n\n';I.write(E) + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;E=indent;A.collect() + if L in K.problematic:B.warning('SKIPPING problematic module:{}'.format(L));return + X,O=K.get_obj_attributes(L) + if O:B.error(O) + for(F,J,G,Y,a)in X: + if F in['classmethod','staticmethod','BaseException',M]:continue + if F[0].isdigit():B.warning('NameError: invalid name {}'.format(F));continue + if G==""and Q(E)<=A0*4: + P=C;R=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] + if R:P=M + D='\n{}class {}({}):\n'.format(E,F,P) + if R:D+=E+' ...\n';I.write(D);continue + I.write(D);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',N+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';I.write(D) elif any(A in G for A in[x,w,'closure']): - A.debug("# def {1} function/method/closure, type = '{0}'".format(G,D));S=U;T=C + S=U;T=C if N>0:T='self, ' - if V in G or V in J:E='{}@classmethod\n'.format(F)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(F,D,S) - else:E='{}def {}({}*args, **kwargs) -> {}:\n'.format(F,D,T,S) - E+=F+' ...\n\n';I.write(E);A.debug('\n'+E) + if V in G or V in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) + else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,T,S) + D+=E+' ...\n\n';I.write(D) elif G=="":0 elif G.startswith("='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] if E in A and A[E]: - G=int(A[E]);I=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] - if I:A[N]=I + G=int(A[E]);J=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[N]=J A[E]='v{}.{}'.format(G&255,G>>8&3) - if A[B]and not A[D].endswith(X):A[D]=A[D]+X + if A[B]and not A[D].endswith(W):A[D]=A[D]+W A[K]=f"{A[D]}-{A[B]}"if A[B]else f"{A[D]}";return A def A2(version): - A=version;B=L.join([str(A)for A in A[:3]]) - if O(A)>3 and A[3]:B+=W+A[3] + A=version;B=K.join([str(A)for A in A[:3]]) + if Q(A)>3 and A[3]:B+=V+A[3] return B def A3(): - try:from boardname import BOARDNAME as B;A.info('Found BOARDNAME: {}'.format(B)) - except R:A.warning('BOARDNAME not found');B=C - return B + try:from boardname import BOARDNAME as A;B.info('Found BOARDNAME: {}'.format(A)) + except R:B.warning('BOARDNAME not found');A=C + return A def get_root(): try:A=os.getcwd() - except(E,J):A=L + except(E,I):A=K B=A - for B in[A,'/sd','/flash',G,L]: + for B in[A,'/sd','/flash',G,K]: try:C=os.stat(B);break except E:continue return B def i(filename): try: - if os.stat(filename)[0]>>14:return P + if os.stat(filename)[0]>>14:return O return H except E:return H -def j():K("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) +def j():J("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): path=C - if O(sys.argv)==3: + if Q(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] else:j() - elif O(sys.argv)==2:j() + elif Q(sys.argv)==2:j() return path def k(): try:A=bytes('abc',encoding='utf8');B=k.__module__;return H - except(m,J):return P + except(m,I):return O def main(): - J='failed';import machine as L - try:C=N(Y,'r+b');D=P;K('Opened existing db') - except E:C=N(Y,'w+b');K('created new db');D=H + I='failed';import machine as K + try:C=N(X,'r+b');D=O;J('Opened existing db') + except E:C=N(X,'w+b');J('created new db');D=H stubber=Stubber(path=read_path()) if not D:stubber.clean() - A4(stubber);A=l();F=[B for B in stubber.modules if not B in A.keys()] - if not F:K('All modules have been processed, exiting') + B=l();A4(stubber,B) + if not stubber.modules:J('All modules have been processed, exiting') else: - del A;B.collect() - for G in F: - I=H - try:I=stubber.create_one_stub(G) - except n:L.reset() - B.collect() - with N(Y,'a')as C:C.write('{}={}\n'.format(G,'ok'if I else J)) - A=l() - if A: + del B;A.collect() + for F in stubber.modules: + G=H + try:G=stubber.create_one_stub(F) + except n:K.reset() + A.collect() + with N(X,'a')as C:C.write('{}={}\n'.format(F,'ok'if G else I)) + B=l() + if B: stubber._report=[] - for(M,O)in A.items(): - if O!=J:stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(M)) + for(L,M)in B.items(): + if M!=I:stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(L)) stubber.report() def l(): C={} try: - with N(Y)as D: - while P: - A=D.readline().strip() - if not A:break - if O(A)>0 and A[0]!='#':F,G=A.split('=',1);C[F]=G - except(E,SyntaxError):K('could not read modulelist.done') - finally:B.collect();return C -def A4(stubber): - B.collect();stubber.modules=[] + with N(X)as D: + while O: + B=D.readline().strip() + if not B:break + if Q(B)>0 and B[0]!='#':F,G=B.split('=',1);C[F]=G + except(E,SyntaxError):J('could not read modulelist.done') + finally:A.collect();return C +def A4(stubber,modules_done): + A.collect();stubber.modules=[] for D in A1: C=D+'/modulelist.txt' if not i(C):continue with N(C)as E: - while P: - A=E.readline().strip() - if not A:break - if O(A)>0 and A[0]!='#':stubber.modules.append(A) - B.collect();K('BREAK');break + while O: + B=E.readline().strip() + if not B:break + if B and B not in modules_done.keys():stubber.modules.append(B) + A.collect();J('BREAK');break if not stubber.modules:stubber.modules=[a] - B.collect() + A.collect() if __name__=='__main__'or k(): if not i('no_auto_stubber.txt'): - try:B.threshold(4*1024);B.enable() + try:A.threshold(4*1024);A.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_db_mpy.mpy b/src/stubber/board/createstubs_db_mpy.mpy index f7e6e9a0c753a75ace24bd3b1964c738870ab64b..ce39a1007ab406f7c041cc8757aeec95d3f77135 100644 GIT binary patch delta 5289 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 diff --git a/src/stubber/board/createstubs_mem.py b/src/stubber/board/createstubs_mem.py index 2fe4cc64d..124421fd3 100644 --- a/src/stubber/board/createstubs_mem.py +++ b/src/stubber/board/createstubs_mem.py @@ -41,12 +41,10 @@ # our own logging module to avoid dependency on and interfering with logging module class logging: - DEBUG = 10 - TRACE = 15 + # DEBUG = 10 INFO = 20 WARNING = 30 ERROR = 40 - CRITICAL = 50 level = INFO prnt = print @@ -57,15 +55,10 @@ def getLogger(name): @classmethod def basicConfig(cls, level): cls.level = level - pass - - def trace(self, msg): - if self.level <= logging.TRACE: - self.prnt("TRACE :", msg) - def debug(self, msg): - if self.level <= logging.DEBUG: - self.prnt("DEBUG :", msg) + # def debug(self, msg): + # if self.level <= logging.DEBUG: + # self.prnt("DEBUG :", msg) def info(self, msg): if self.level <= logging.INFO: @@ -79,14 +72,9 @@ def error(self, msg): if self.level <= logging.ERROR: self.prnt("ERROR :", msg) - def critical(self, msg): - if self.level <= logging.CRITICAL: - self.prnt("CRIT :", msg) - log = logging.getLogger("stubber") logging.basicConfig(level=logging.INFO) -# logging.basicConfig(level=logging.TRACE) # logging.basicConfig(level=logging.DEBUG) @@ -120,7 +108,7 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore path = get_root() self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - log.debug(self.path) + # log.debug(self.path) try: ensure_folder(path + "/") except OSError: @@ -149,15 +137,15 @@ def get_obj_attributes(self, item_instance: object): # name_, repr_(value), type as text, item_instance _result = [] _errors = [] - log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): if name.startswith("_") and not name in self.modules: continue - log.debug("get attribute {}".format(name)) + # log.debug("get attribute {}".format(name)) try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order - log.debug("attribute {}:{}".format(name, val)) + # log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -239,7 +227,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - log.trace("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + # log.debug("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -275,7 +263,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # log.debug("DUMP : {}".format(object_expr)) + # # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: @@ -296,7 +284,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - log.trace("{0}class {1}:".format(indent, item_name)) + # log.debug("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -319,7 +307,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - log.debug("# recursion over class {0}".format(item_name)) + # log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -333,7 +321,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -349,7 +337,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - log.debug("\n" + s) + # log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -377,10 +365,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - log.debug("\n" + s) + # log.debug("\n" + s) else: # keep only the name - log.debug("# all other, type = '{0}'".format(item_type_txt)) + # log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -440,7 +428,7 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - log.trace("Memory used: {0} Kb".format(used // 1024)) + # log.debug("Memory used: {0} Kb".format(used // 1024)) except OSError: log.error("Failed to create the report.") diff --git a/src/stubber/board/createstubs_mem_min.py b/src/stubber/board/createstubs_mem_min.py index 6e136fe17..415b4e5bd 100644 --- a/src/stubber/board/createstubs_mem_min.py +++ b/src/stubber/board/createstubs_mem_min.py @@ -17,27 +17,27 @@ a='_' Z='micropython' Y=open -W='-preview' -V='-' -U='board' -T=IndexError -S=repr +X=repr +V='-preview' +U='-' +T='board' +S=IndexError R=print Q=True P='family' O=ImportError N=len M=dir -L='port' -K='.' -J=False -I=AttributeError +K='port' +J='.' +I=False +H=AttributeError G='/' F=None -D=OSError +E=OSError C='version' B='' -import gc as E,os,sys +import gc as D,os,sys from time import sleep try:from ujson import dumps except:from json import dumps @@ -48,119 +48,112 @@ __version__='v1.16.3' w=2 x=2 -y=['lib','/lib','/sd/lib','/flash/lib',K] -class H: - DEBUG=10;TRACE=15;INFO=20;WARNING=30;ERROR=40;CRITICAL=50;level=INFO;prnt=R +y=['lib','/lib','/sd/lib','/flash/lib',J] +class L: + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=R @staticmethod - def getLogger(name):return H() + def getLogger(name):return L() @classmethod def basicConfig(A,level):A.level=level - def trace(A,msg): - if A.level<=H.TRACE:A.prnt('TRACE :',msg) - def debug(A,msg): - if A.level<=H.DEBUG:A.prnt('DEBUG :',msg) def info(A,msg): - if A.level<=H.INFO:A.prnt('INFO :',msg) + if A.level<=L.INFO:A.prnt('INFO :',msg) def warning(A,msg): - if A.level<=H.WARNING:A.prnt('WARN :',msg) + if A.level<=L.WARNING:A.prnt('WARN :',msg) def error(A,msg): - if A.level<=H.ERROR:A.prnt('ERROR :',msg) - def critical(A,msg): - if A.level<=H.CRITICAL:A.prnt('CRIT :',msg) -A=H.getLogger(o) -H.basicConfig(level=H.INFO) + if A.level<=L.ERROR:A.prnt('ERROR :',msg) +A=L.getLogger(o) +L.basicConfig(level=L.INFO) class Stubber: def __init__(B,path=F,firmware_id=F): C=firmware_id try: if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') - except I:pass - B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[L]));A.info('Board: {}'.format(B.info[U]));E.collect() + except H:pass + B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[T]));D.collect() if C:B._fwid=C.lower() - elif B.info[P]==Z:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(V) + elif B.info[P]==Z:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(U) else:B._fwid='{family}-v{version}-{port}'.format(**B.info) - B._start_free=E.mem_free() + B._start_free=D.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() - B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G);A.debug(B.path) + B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) try:g(path+G) - except D:A.error('error creating stub folder {}'.format(path)) + except E:A.error('error creating stub folder {}'.format(path)) B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[] - def get_obj_attributes(N,item_instance): - D=item_instance;G=[];L=[];A.debug('get attributes {} {}'.format(S(D),D)) - for C in M(D): - if C.startswith(a)and not C in N.modules:continue - A.debug('get attribute {}'.format(C)) + def get_obj_attributes(L,item_instance): + I=item_instance;C=[];K=[] + for A in M(I): + if A.startswith(a)and not A in L.modules:continue try: - F=getattr(D,C);A.debug('attribute {}:{}'.format(C,F)) - try:H=S(type(F)).split("'")[1] - except T:H=B - if H in{p,q,r,s,b,c,d}:J=1 - elif H in{t,u}:J=2 - elif H in'class':J=3 - else:J=4 - G.append((C,S(F),S(type(F)),F,J)) - except I as K:L.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(C,D,K)) - except MemoryError as K:R('MemoryError: {}'.format(K));sleep(1);reset() - G=l([A for A in G if not A[0].startswith('__')],key=lambda x:x[4]);E.collect();return G,L + E=getattr(I,A) + try:F=X(type(E)).split("'")[1] + except S:F=B + if F in{p,q,r,s,b,c,d}:G=1 + elif F in{t,u}:G=2 + elif F in'class':G=3 + else:G=4 + C.append((A,X(E),X(type(E)),E,G)) + except H as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,J)) + except MemoryError as J:R('MemoryError: {}'.format(J));sleep(1);reset() + C=l([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,K def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) def create_all_stubs(B): - A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));E.collect() + A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));D.collect() for C in B.modules:B.create_one_stub(C) A.info('Finally done') def create_one_stub(C,module_name): B=module_name - if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return J - if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return J - H='{}/{}.py'.format(C.path,B.replace(K,G));E.collect();F=J + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return I + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return I + H='{}/{}.py'.format(C.path,B.replace(J,G));D.collect();F=I try:F=C.create_module_stub(B,H) - except D:return J - E.collect();return F - def create_module_stub(I,module_name,file_name=F): + except E:return I + D.collect();return F + def create_module_stub(K,module_name,file_name=F): H=file_name;C=module_name - if H is F:L=C.replace(K,a)+'.py';H=I.path+G+L + if H is F:L=C.replace(J,a)+'.py';H=K.path+G+L else:L=H.split(G)[-1] - if G in C:C=C.replace(G,K) + if G in C:C=C.replace(G,J) M=F - try:M=__import__(C,F,F,'*');P=E.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) - except O:A.trace('Skip module: {:<25} {:<79}'.format(C,'Module not found.'));return J + try:M=__import__(C,F,F,'*');P=D.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) + except O:return I g(H) - with Y(H,'w')as N:R=str(I.info).replace('OrderedDict(',B).replace('})','}');S='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,I._fwid,R,__version__);N.write(S);N.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(N,M,C,B) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + with Y(H,'w')as N:R=str(K.info).replace('OrderedDict(',B).replace('})','}');S='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,R,__version__);N.write(S);N.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,M,C,B) + K._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) if C not in{'os','sys','logging','gc'}: try:del M - except(D,m):A.warning('could not del new_module') - E.collect();return Q + except(E,m):A.warning('could not del new_module') + D.collect();return Q def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';O=in_class;M='Exception';L=object_expr;I=fp;F=indent;E.collect() + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';O=in_class;M='Exception';L=object_expr;I=fp;E=indent;D.collect() if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return X,P=K.get_obj_attributes(L) if P:A.error(P) - for(C,J,G,Y,a)in X: - if C in['classmethod','staticmethod','BaseException',M]:continue - if C[0].isdigit():A.warning('NameError: invalid name {}'.format(C));continue - if G==""and N(F)<=x*4: - A.trace('{0}class {1}:'.format(F,C));Q=B;R=C.endswith(M)or C.endswith('Error')or C in['KeyboardInterrupt','StopIteration','SystemExit'] + for(F,J,G,Y,a)in X: + if F in['classmethod','staticmethod','BaseException',M]:continue + if F[0].isdigit():A.warning('NameError: invalid name {}'.format(F));continue + if G==""and N(E)<=x*4: + Q=B;R=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] if R:Q=M - D='\n{}class {}({}):\n'.format(F,C,Q) - if R:D+=F+' ...\n';I.write(D);continue - I.write(D);A.debug('# recursion over class {0}'.format(C));K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,C),F+' ',O+1);D=F+' def __init__(self, *argv, **kwargs) -> None:\n';D+=F+' ...\n\n';I.write(D) + C='\n{}class {}({}):\n'.format(E,F,Q) + if R:C+=E+' ...\n';I.write(C);continue + I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',O+1);C=E+' def __init__(self, *argv, **kwargs) -> None:\n';C+=E+' ...\n\n';I.write(C) elif any(A in G for A in[u,t,'closure']): - A.debug("# def {1} function/method/closure, type = '{0}'".format(G,C));S=U;T=B + S=U;T=B if O>0:T='self, ' - if V in G or V in J:D='{}@classmethod\n'.format(F)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(F,C,S) - else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(F,C,T,S) - D+=F+' ...\n\n';I.write(D);A.debug('\n'+D) + if V in G or V in J:C='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) + else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,T,S) + C+=E+' ...\n\n';I.write(C) elif G=="":0 elif G.startswith(">10] if J:A[Q]=J A[E]='v{}.{}'.format(G&255,G>>8&3) - if A[D]and not A[C].endswith(W):A[C]=A[C]+W - A[K]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A + if A[D]and not A[C].endswith(V):A[C]=A[C]+V + A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A def z(version): - A=version;B=K.join([str(A)for A in A[:3]]) - if N(A)>3 and A[3]:B+=V+A[3] + A=version;B=J.join([str(A)for A in A[:3]]) + if N(A)>3 and A[3]:B+=U+A[3] return B def A0(): try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) @@ -254,17 +247,17 @@ def A0(): return C def get_root(): try:A=os.getcwd() - except(D,I):A=K + except(E,H):A=J B=A - for B in[A,'/sd','/flash',G,K]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break - except D:continue + except E:continue return B def h(filename): try: if os.stat(filename)[0]>>14:return Q - return J - except D:return J + return I + except E:return I def i():R("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): path=B @@ -275,26 +268,26 @@ def read_path(): elif N(sys.argv)==2:i() return path def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return J - except(k,I):return Q + try:A=bytes('abc',encoding='utf8');B=j.__module__;return I + except(k,H):return Q def main(): stubber=Stubber(path=read_path());stubber.clean() def A(stubber): - E.collect();stubber.modules=[] + D.collect();stubber.modules=[] for C in y: B=C+'/modulelist.txt' if not h(B):continue - with Y(B)as D: + with Y(B)as E: while Q: - A=D.readline().strip() + A=E.readline().strip() if not A:break if N(A)>0 and A[0]!='#':stubber.modules.append(A) - E.collect();R('BREAK');break + D.collect();R('BREAK');break if not stubber.modules:stubber.modules=[Z] - E.collect() - stubber.modules=[];A(stubber);E.collect();stubber.create_all_stubs();stubber.report() + D.collect() + stubber.modules=[];A(stubber);D.collect();stubber.create_all_stubs();stubber.report() if __name__=='__main__'or j(): if not h('no_auto_stubber.txt'): - try:E.threshold(4*1024);E.enable() + try:D.threshold(4*1024);D.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mem_mpy.mpy b/src/stubber/board/createstubs_mem_mpy.mpy index ed69d016ccd8f4ae74c1c76738e16560c81e24ff..21f823ef6f1c9a86f0fffaa91f064d662be5b5a4 100644 GIT binary patch delta 4833 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 delta 5610 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 jX9qYhs>5%Vk9rYJPh2chdT-#$CYc=G=ML3~3b diff --git a/src/stubber/board/createstubs_min.py b/src/stubber/board/createstubs_min.py index 03628c426..0fcb07093 100644 --- a/src/stubber/board/createstubs_min.py +++ b/src/stubber/board/createstubs_min.py @@ -20,21 +20,21 @@ a='tuple' Z='_' Y='micropython' -X=print -V='-preview' -U=True -T='-' -S='board' -R=IndexError -Q=repr +X=repr +W=print +U='-preview' +T=True +S='-' +R='board' +Q=IndexError P='family' O=len N=ImportError M=dir -L='port' -K='.' -J=False -I=AttributeError +K='port' +J='.' +I=False +H=AttributeError G='/' E=None D=OSError @@ -51,62 +51,55 @@ __version__='v1.16.3' y=2 z=2 -A3=['lib','/lib','/sd/lib','/flash/lib',K] -class H: - DEBUG=10;TRACE=15;INFO=20;WARNING=30;ERROR=40;CRITICAL=50;level=INFO;prnt=X +A3=['lib','/lib','/sd/lib','/flash/lib',J] +class L: + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=W @staticmethod - def getLogger(name):return H() + def getLogger(name):return L() @classmethod def basicConfig(A,level):A.level=level - def trace(A,msg): - if A.level<=H.TRACE:A.prnt('TRACE :',msg) - def debug(A,msg): - if A.level<=H.DEBUG:A.prnt('DEBUG :',msg) def info(A,msg): - if A.level<=H.INFO:A.prnt('INFO :',msg) + if A.level<=L.INFO:A.prnt('INFO :',msg) def warning(A,msg): - if A.level<=H.WARNING:A.prnt('WARN :',msg) + if A.level<=L.WARNING:A.prnt('WARN :',msg) def error(A,msg): - if A.level<=H.ERROR:A.prnt('ERROR :',msg) - def critical(A,msg): - if A.level<=H.CRITICAL:A.prnt('CRIT :',msg) -A=H.getLogger(n) -H.basicConfig(level=H.INFO) + if A.level<=L.ERROR:A.prnt('ERROR :',msg) +A=L.getLogger(n) +L.basicConfig(level=L.INFO) class Stubber: def __init__(B,path=E,firmware_id=E): C=firmware_id try: if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') - except I:pass - B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[L]));A.info('Board: {}'.format(B.info[S]));F.collect() + except H:pass + B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[R]));F.collect() if C:B._fwid=C.lower() - elif B.info[P]==Y:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(T) + elif B.info[P]==Y:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(S) else:B._fwid='{family}-v{version}-{port}'.format(**B.info) B._start_free=F.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() - B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G);A.debug(B.path) + B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) try:g(path+G) except D:A.error('error creating stub folder {}'.format(path)) B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[] - def get_obj_attributes(N,item_instance): - D=item_instance;G=[];L=[];A.debug('get attributes {} {}'.format(Q(D),D)) - for C in M(D): - if C.startswith(Z)and not C in N.modules:continue - A.debug('get attribute {}'.format(C)) + def get_obj_attributes(L,item_instance): + I=item_instance;C=[];K=[] + for A in M(I): + if A.startswith(Z)and not A in L.modules:continue try: - E=getattr(D,C);A.debug('attribute {}:{}'.format(C,E)) - try:H=Q(type(E)).split("'")[1] - except R:H=B - if H in{o,p,q,r,a,b,c}:J=1 - elif H in{s,t}:J=2 - elif H in'class':J=3 - else:J=4 - G.append((C,Q(E),Q(type(E)),E,J)) - except I as K:L.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(C,D,K)) - except MemoryError as K:X('MemoryError: {}'.format(K));sleep(1);reset() - G=k([A for A in G if not A[0].startswith('__')],key=lambda x:x[4]);F.collect();return G,L + D=getattr(I,A) + try:E=X(type(D)).split("'")[1] + except Q:E=B + if E in{o,p,q,r,a,b,c}:G=1 + elif E in{s,t}:G=2 + elif E in'class':G=3 + else:G=4 + C.append((A,X(D),X(type(D)),D,G)) + except H as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,J)) + except MemoryError as J:W('MemoryError: {}'.format(J));sleep(1);reset() + C=k([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);F.collect();return C,K def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) def create_all_stubs(B): A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));F.collect() @@ -114,56 +107,56 @@ def create_all_stubs(B): A.info('Finally done') def create_one_stub(C,module_name): B=module_name - if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return J - if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return J - H='{}/{}.py'.format(C.path,B.replace(K,G));F.collect();E=J + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return I + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return I + H='{}/{}.py'.format(C.path,B.replace(J,G));F.collect();E=I try:E=C.create_module_stub(B,H) - except D:return J + except D:return I F.collect();return E - def create_module_stub(I,module_name,file_name=E): + def create_module_stub(K,module_name,file_name=E): H=file_name;C=module_name - if H is E:L=C.replace(K,Z)+'.py';H=I.path+G+L + if H is E:L=C.replace(J,Z)+'.py';H=K.path+G+L else:L=H.split(G)[-1] - if G in C:C=C.replace(G,K) + if G in C:C=C.replace(G,J) M=E try:M=__import__(C,E,E,'*');P=F.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) - except N:A.trace('Skip module: {:<25} {:<79}'.format(C,'Module not found.'));return J + except N:return I g(H) - with open(H,'w')as O:Q=str(I.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,I._fwid,Q,__version__);O.write(R);O.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(O,M,C,B) - I._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + with open(H,'w')as O:Q=str(K.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,Q,__version__);O.write(R);O.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(O,M,C,B) + K._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) if C not in{'os',u,v,'gc'}: try:del M except(D,l):A.warning('could not del new_module') - F.collect();return U + F.collect();return T def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;E=indent;F.collect() + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return X,P=K.get_obj_attributes(L) if P:A.error(P) - for(C,J,G,Y,d)in X: - if C in['classmethod','staticmethod','BaseException',M]:continue - if C[0].isdigit():A.warning('NameError: invalid name {}'.format(C));continue - if G==""and O(E)<=z*4: - A.trace('{0}class {1}:'.format(E,C));Q=B;R=C.endswith(M)or C.endswith('Error')or C in['KeyboardInterrupt','StopIteration','SystemExit'] + for(E,J,G,Y,d)in X: + if E in['classmethod','staticmethod','BaseException',M]:continue + if E[0].isdigit():A.warning('NameError: invalid name {}'.format(E));continue + if G==""and O(D)<=z*4: + Q=B;R=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if R:Q=M - D='\n{}class {}({}):\n'.format(E,C,Q) - if R:D+=E+' ...\n';I.write(D);continue - I.write(D);A.debug('# recursion over class {0}'.format(C));K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,C),E+' ',N+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';I.write(D) + C='\n{}class {}({}):\n'.format(D,E,Q) + if R:C+=D+' ...\n';I.write(C);continue + I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) elif any(A in G for A in[t,s,'closure']): - A.debug("# def {1} function/method/closure, type = '{0}'".format(G,C));S=U;T=B + S=U;T=B if N>0:T='self, ' - if V in G or V in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,C,S) - else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,C,T,S) - D+=E+' ...\n\n';I.write(D);A.debug('\n'+D) + if V in G or V in J:C='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,S) + else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,T,S) + C+=D+' ...\n\n';I.write(C) elif G=="":0 elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] if F in A and A[F]: G=int(A[F]);J=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] - if J:A[Q]=J + if J:A[S]=J A[F]='v{}.{}'.format(G&255,G>>8&3) - if A[D]and not A[C].endswith(V):A[C]=A[C]+V - A[K]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A + if A[D]and not A[C].endswith(U):A[C]=A[C]+U + A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A def A0(version): - A=version;B=K.join([str(A)for A in A[:3]]) - if O(A)>3 and A[3]:B+=T+A[3] + A=version;B=J.join([str(A)for A in A[:3]]) + if O(A)>3 and A[3]:B+=S+A[3] return B def A1(): try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) @@ -257,18 +250,18 @@ def A1(): return C def get_root(): try:A=os.getcwd() - except(D,I):A=K + except(D,H):A=J B=A - for B in[A,'/sd','/flash',G,K]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break except D:continue return B def A2(filename): try: - if os.stat(filename)[0]>>14:return U - return J - except D:return J -def h():X("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) + if os.stat(filename)[0]>>14:return T + return I + except D:return I +def h():W("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): path=B if O(sys.argv)==3: @@ -278,8 +271,8 @@ def read_path(): elif O(sys.argv)==2:h() return path def i(): - try:A=bytes('abc',encoding='utf8');B=i.__module__;return J - except(j,I):return U + try:A=bytes('abc',encoding='utf8');B=i.__module__;return I + except(j,H):return T def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',x,e,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];F.collect();stubber.create_all_stubs();stubber.report() if __name__=='__main__'or i(): if not A2('no_auto_stubber.txt'): diff --git a/src/stubber/board/createstubs_mpy.mpy b/src/stubber/board/createstubs_mpy.mpy index 7ee1911e0cb4588bd2d14fd74b6c62ae57b86857..a8ce4b59ba897a868e520ab5a69db41bbefec2e2 100644 GIT binary patch delta 4775 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 E0*G&C7ytkO delta 5624 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 0 and line[0] != "#": + if line and line not in modules_done.keys(): stubber.modules.append(line) gc.collect() print("BREAK") From c71be1ef74f6f2f9d16476d04ca8b680700400b9 Mon Sep 17 00:00:00 2001 From: Josverl Date: Tue, 30 Jan 2024 21:44:57 +0000 Subject: [PATCH 56/68] Update mip packages --- mip/v5/createstubs.py | 210 ++---- mip/v5/createstubs_db.py | 319 ++++---- mip/v5/createstubs_db_min.py | 1165 ++++++++--------------------- mip/v5/createstubs_db_mpy.mpy | Bin 9118 -> 9744 bytes mip/v5/createstubs_mem.py | 251 +++---- mip/v5/createstubs_mem_min.py | 1081 +++++++-------------------- mip/v5/createstubs_mem_mpy.mpy | Bin 8535 -> 9099 bytes mip/v5/createstubs_min.py | 1288 +++++++------------------------- mip/v5/createstubs_mpy.mpy | Bin 11199 -> 11732 bytes mip/v6/createstubs.py | 211 ++---- mip/v6/createstubs_db.py | 319 ++++---- mip/v6/createstubs_db_min.py | 1165 ++++++++--------------------- mip/v6/createstubs_db_mpy.mpy | Bin 8410 -> 9581 bytes mip/v6/createstubs_mem.py | 251 +++---- mip/v6/createstubs_mem_min.py | 1081 +++++++-------------------- mip/v6/createstubs_mem_mpy.mpy | Bin 7927 -> 8928 bytes mip/v6/createstubs_min.py | 1288 +++++++------------------------- mip/v6/createstubs_mpy.mpy | Bin 11052 -> 12030 bytes 18 files changed, 2423 insertions(+), 6206 deletions(-) diff --git a/mip/v5/createstubs.py b/mip/v5/createstubs.py index 71c910a58..1f7ca21d3 100644 --- a/mip/v5/createstubs.py +++ b/mip/v5/createstubs.py @@ -4,7 +4,6 @@ # Copyright (c) 2019-2023 Jos Verlinde import gc -import logging import os import sys from time import sleep @@ -24,26 +23,49 @@ except ImportError: from ucollections import OrderedDict # type: ignore -try: - from nope_machine import WDT +__version__ = "v1.16.3" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] - wdt = WDT() -except ImportError: +# our own logging module to avoid dependency on and interfering with logging module +class logging: + # DEBUG = 10 + INFO = 20 + WARNING = 30 + ERROR = 40 + level = INFO + prnt = print - class _WDT: - def feed(self): - pass + @staticmethod + def getLogger(name): + return logging() - wdt = _WDT() + @classmethod + def basicConfig(cls, level): + cls.level = level + # def debug(self, msg): + # if self.level <= logging.DEBUG: + # self.prnt("DEBUG :", msg) -wdt.feed() + def info(self, msg): + if self.level <= logging.INFO: + self.prnt("INFO :", msg) + + def warning(self, msg): + if self.level <= logging.WARNING: + self.prnt("WARN :", msg) + + def error(self, msg): + if self.level <= logging.ERROR: + self.prnt("ERROR :", msg) -__version__ = "v1.16.2" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] + +log = logging.getLogger("stubber") +logging.basicConfig(level=logging.INFO) +# logging.basicConfig(level=logging.DEBUG) class Stubber: @@ -55,13 +77,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() - self.log.info("Port: {}".format(self.info["port"])) - self.log.info("Board: {}".format(self.info["board"])) + log.info("Port: {}".format(self.info["port"])) + log.info("Board: {}".format(self.info["board"])) gc.collect() - wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: @@ -78,11 +98,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore path = get_root() self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - self.log.debug(self.path) + # log.debug(self.path) try: ensure_folder(path + "/") except OSError: - self.log.error("error creating stub folder {}".format(path)) + log.error("error creating stub folder {}".format(path)) self.problematic = [ "upip", "upysh", @@ -107,15 +127,15 @@ def get_obj_attributes(self, item_instance: object): # name_, repr_(value), type as text, item_instance _result = [] _errors = [] - self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): if name.startswith("_") and not name in self.modules: continue - self.log.debug("get attribute {}".format(name)) + # log.debug("get attribute {}".format(name)) try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order - self.log.debug("attribute {}:{}".format(name, val)) + # log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -148,19 +168,18 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) gc.collect() for module_name in self.modules: self.create_one_stub(module_name) - self.log.info("Finally done") + log.info("Finally done") def create_one_stub(self, module_name: str): - wdt.feed() if module_name in self.problematic: - self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False if module_name in self.excluded: - self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) @@ -195,10 +214,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + # log.debug("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -220,12 +239,12 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] - self.log.warning("could not del new_module") + log.warning("could not del new_module") # lets not try - most times it does not work anyway # try: # del sys.modules[module_name] # except KeyError: - # self.log.warning("could not del sys.modules[{}]".format(module_name)) + # log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -233,14 +252,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: - self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # self.log.debug("DUMP : {}".format(object_expr)) + # # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: - self.log.error(errors) + log.error(errors) for item_name, item_repr, item_type_txt, item_instance, _ in items: # name_, repr_(value), type as text, item_instance, order @@ -248,7 +267,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # do not create stubs for these primitives continue if item_name[0].isdigit(): - self.log.warning("NameError: invalid name {}".format(item_name)) + log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) if ( @@ -257,7 +276,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - self.log.info("{0}class {1}:".format(indent, item_name)) + # log.debug("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -280,7 +299,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - self.log.debug("# recursion over class {0}".format(item_name)) + # log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -294,7 +313,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -312,7 +331,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - self.log.debug("\n" + s) + # log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -340,10 +359,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - self.log.debug("\n" + s) + # log.debug("\n" + s) else: # keep only the name - self.log.debug("# all other, type = '{0}'".format(item_type_txt)) + # log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -367,10 +386,9 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" - wdt.feed() if path is None: path = self.path - self.log.info("Clean/remove files in folder: {}".format(path)) + log.info("Clean/remove files in folder: {}".format(path)) try: os.stat(path) # TEMP workaround mpremote listdir bug - items = os.listdir(path) @@ -390,12 +408,9 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" - wdt.feed() - self.log.info( - "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) - ) + log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) - self.log.info("Report file: {}".format(f_name)) + log.info("Report file: {}".format(f_name)) gc.collect() try: # write json by node to reduce memory requirements @@ -407,9 +422,9 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - self.log.info("Memory used: {0} Kb".format(used // 1024)) + # log.debug("Memory used: {0} Kb".format(used // 1024)) except OSError: - self.log.error("Failed to create the report.") + log.error("Failed to create the report.") def write_json_header(self, f): f.write("{") @@ -509,9 +524,7 @@ def _info(): # type:() -> dict[str, str] ) except (AttributeError, IndexError): pass - gc.collect() - read_boardname(info) - gc.collect() + info["board"] = get_boardname() try: if "uname" in dir(os): # old @@ -599,79 +612,16 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore + + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.warning("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable @@ -996,12 +946,6 @@ def main(): if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass if not file_exists("no_auto_stubber.txt"): try: gc.threshold(4 * 1024) # type: ignore diff --git a/mip/v5/createstubs_db.py b/mip/v5/createstubs_db.py index 6904d4caa..2743ac849 100644 --- a/mip/v5/createstubs_db.py +++ b/mip/v5/createstubs_db.py @@ -18,12 +18,11 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.2 +This variant was generated from createstubs.py by micropython-stubber v1.16.3 """ # Copyright (c) 2019-2023 Jos Verlinde import gc -import logging import os import sys from time import sleep @@ -43,26 +42,49 @@ except ImportError: from ucollections import OrderedDict # type: ignore -try: - from nope_machine import WDT +__version__ = "v1.16.3" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] - wdt = WDT() -except ImportError: +# our own logging module to avoid dependency on and interfering with logging module +class logging: + # DEBUG = 10 + INFO = 20 + WARNING = 30 + ERROR = 40 + level = INFO + prnt = print - class _WDT: - def feed(self): - pass + @staticmethod + def getLogger(name): + return logging() - wdt = _WDT() + @classmethod + def basicConfig(cls, level): + cls.level = level + # def debug(self, msg): + # if self.level <= logging.DEBUG: + # self.prnt("DEBUG :", msg) -wdt.feed() + def info(self, msg): + if self.level <= logging.INFO: + self.prnt("INFO :", msg) + + def warning(self, msg): + if self.level <= logging.WARNING: + self.prnt("WARN :", msg) + + def error(self, msg): + if self.level <= logging.ERROR: + self.prnt("ERROR :", msg) -__version__ = "v1.16.2" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] + +log = logging.getLogger("stubber") +logging.basicConfig(level=logging.INFO) +# logging.basicConfig(level=logging.DEBUG) class Stubber: @@ -74,13 +96,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() - self.log.info("Port: {}".format(self.info["port"])) - self.log.info("Board: {}".format(self.info["board"])) + log.info("Port: {}".format(self.info["port"])) + log.info("Board: {}".format(self.info["board"])) gc.collect() - wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: @@ -97,11 +117,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore path = get_root() self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - self.log.debug(self.path) + # log.debug(self.path) try: ensure_folder(path + "/") except OSError: - self.log.error("error creating stub folder {}".format(path)) + log.error("error creating stub folder {}".format(path)) self.problematic = [ "upip", "upysh", @@ -126,15 +146,15 @@ def get_obj_attributes(self, item_instance: object): # name_, repr_(value), type as text, item_instance _result = [] _errors = [] - self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): if name.startswith("_") and not name in self.modules: continue - self.log.debug("get attribute {}".format(name)) + # log.debug("get attribute {}".format(name)) try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order - self.log.debug("attribute {}:{}".format(name, val)) + # log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -167,19 +187,18 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) gc.collect() for module_name in self.modules: self.create_one_stub(module_name) - self.log.info("Finally done") + log.info("Finally done") def create_one_stub(self, module_name: str): - wdt.feed() if module_name in self.problematic: - self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False if module_name in self.excluded: - self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) @@ -214,10 +233,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + # log.debug("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -237,12 +256,12 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] - self.log.warning("could not del new_module") + log.warning("could not del new_module") # lets not try - most times it does not work anyway # try: # del sys.modules[module_name] # except KeyError: - # self.log.warning("could not del sys.modules[{}]".format(module_name)) + # log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -250,14 +269,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: - self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # self.log.debug("DUMP : {}".format(object_expr)) + # # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: - self.log.error(errors) + log.error(errors) for item_name, item_repr, item_type_txt, item_instance, _ in items: # name_, repr_(value), type as text, item_instance, order @@ -265,7 +284,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # do not create stubs for these primitives continue if item_name[0].isdigit(): - self.log.warning("NameError: invalid name {}".format(item_name)) + log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) if ( @@ -274,7 +293,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - self.log.info("{0}class {1}:".format(indent, item_name)) + # log.debug("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -297,7 +316,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - self.log.debug("# recursion over class {0}".format(item_name)) + # log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -311,7 +330,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -327,7 +346,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - self.log.debug("\n" + s) + # log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -355,10 +374,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - self.log.debug("\n" + s) + # log.debug("\n" + s) else: # keep only the name - self.log.debug("# all other, type = '{0}'".format(item_type_txt)) + # log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -382,10 +401,9 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" - wdt.feed() if path is None: path = self.path - self.log.info("Clean/remove files in folder: {}".format(path)) + log.info("Clean/remove files in folder: {}".format(path)) try: os.stat(path) # TEMP workaround mpremote listdir bug - items = os.listdir(path) @@ -405,10 +423,9 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" - wdt.feed() - self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) + log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) - self.log.info("Report file: {}".format(f_name)) + log.info("Report file: {}".format(f_name)) gc.collect() try: # write json by node to reduce memory requirements @@ -420,9 +437,9 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - self.log.info("Memory used: {0} Kb".format(used // 1024)) + # log.debug("Memory used: {0} Kb".format(used // 1024)) except OSError: - self.log.error("Failed to create the report.") + log.error("Failed to create the report.") def write_json_header(self, f): f.write("{") @@ -520,9 +537,7 @@ def _info(): # type:() -> dict[str, str] ) except (AttributeError, IndexError): pass - gc.collect() - read_boardname(info) - gc.collect() + info["board"] = get_boardname() try: if "uname" in dir(os): # old @@ -610,79 +625,16 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore + + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.warning("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable @@ -770,74 +722,87 @@ def main(): # Only clean folder if this is a first run stubber.clean() # get list of modules to process - get_modulelist(stubber) - # remove the ones that are already done - modules_done = {} # type: dict[str, str] - try: - with open("modulelist.done") as f: - # not optimal , but works on mpremote and esp8266 - for line in f.read().split("\n"): - line = line.strip() - gc.collect() - if len(line) > 0: - key, value = line.split("=", 1) - modules_done[key] = value - except (OSError, SyntaxError): - pass - gc.collect() + modules_done = read_done() # see if we can continue from where we left off - modules = [m for m in stubber.modules if m not in modules_done.keys()] - gc.collect() - for modulename in modules: - # ------------------------------------ - # do epic shit - # but sometimes things fail / run out of memory and reboot - ok = False - try: - ok = stubber.create_one_stub(modulename) - except MemoryError: - # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER - machine.reset() - # ------------------------------------- + get_modulelist(stubber, modules_done) + + if not stubber.modules: + print("All modules have been processed, exiting") + else: + del modules_done gc.collect() - modules_done[modulename] = str(stubber._report[-1] if ok else "failed") - with open("modulelist.done", "a") as f: - f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) + for modulename in stubber.modules: + # ------------------------------------ + # do epic shit + # but sometimes things fail / run out of memory and reboot + ok = False + try: + ok = stubber.create_one_stub(modulename) + except MemoryError: + # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER + machine.reset() + # ------------------------------------- + gc.collect() + # modules_done[modulename] = str(stubber._report[-1] if ok else "failed") + with open("modulelist.done", "a") as f: + f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) # Finished processing - load all the results , and remove the failed ones + modules_done = read_done() if modules_done: # stubber.write_json_end(mod_fp) - stubber._report = [v for _, v in modules_done.items() if v != "failed"] + stubber._report = [] + for k, v in modules_done.items(): + if v != "failed": + stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(k)) stubber.report() -def get_modulelist(stubber): +def read_done(): + modules_done = {} # type: dict[str, str] + try: + with open("modulelist.done") as f: + while True: + line = f.readline().strip() + if not line: + break + if len(line) > 0 and line[0] != "#": + key, value = line.split("=", 1) + modules_done[key] = value + except (OSError, SyntaxError): + print("could not read modulelist.done") + finally: + gc.collect() + return modules_done + + +def get_modulelist(stubber, modules_done): + # new + gc.collect() stubber.modules = [] # avoid duplicates for p in LIBS: - try: - with open(p + "/modulelist.txt") as f: - print("DEBUG: list of modules: " + p + "/modulelist.txt") - for line in f.read().split("\n"): - line = line.strip() - if len(line) > 0 and line[0] != "#": - stubber.modules.append(line) - gc.collect() - break - except OSError: - pass + fname = p + "/modulelist.txt" + if not file_exists(fname): + continue + with open(fname) as f: + # print("DEBUG: list of modules: " + p + "/modulelist.txt") + while True: + line = f.readline().strip() + if not line: + break + if line and line not in modules_done.keys(): + stubber.modules.append(line) + gc.collect() + print("BREAK") + break + if not stubber.modules: stubber.modules = ["micropython"] - _log.warn("Could not find modulelist.txt, using default modules") + # _log.warn("Could not find modulelist.txt, using default modules") gc.collect() if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass if not file_exists("no_auto_stubber.txt"): try: gc.threshold(4 * 1024) # type: ignore diff --git a/mip/v5/createstubs_db_min.py b/mip/v5/createstubs_db_min.py index 05817f711..f61b4498f 100644 --- a/mip/v5/createstubs_db_min.py +++ b/mip/v5/createstubs_db_min.py @@ -1,847 +1,324 @@ -""" -Create stubs for (all) modules on a MicroPython board. - - This variant of the createstubs.py script is optimized for use on very-low-memory devices. - Note: this version has undergone limited testing. - - 1) reads the list of modules from a text file `modulelist.txt` that should be uploaded to the device. - 2) stored the already processed modules in a text file `modulelist.done` - 3) process the modules in the database: - - stub the module - - update the modulelist.done file - - reboots the device if it runs out of memory - 4) creates the modules.json - - If that cannot be found then only a single module (micropython) is stubbed. - In order to run this on low-memory devices two additional steps are recommended: - - minification, using python-minifierto reduce overall size, and remove logging overhead. - - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device - - -This variant was generated from createstubs.py by micropython-stubber v1.16.2 -""" -# Copyright (c) 2019-2023 Jos Verlinde - -import gc -# import logging -import os -import sys +y='{}/{}' +x='method' +w='function' +v='bool' +u='str' +t='float' +s='int' +r='stubber' +q=TypeError +p=KeyError +o=sorted +n=MemoryError +m=NotImplementedError +g=',\n' +e='dict' +d='list' +c='tuple' +b='_' +a='micropython' +Z=repr +X='modulelist.done' +W='-preview' +V='-' +U='board' +T=IndexError +S='family' +R=ImportError +Q=len +P=dir +O=True +N=open +L='port' +K='.' +J=print +I=AttributeError +H=False +G='/' +F=None +E=OSError +D='version' +C='' +import gc as A,os,sys from time import sleep - -try: - from ujson import dumps -except: - from json import dumps - -try: - from machine import reset # type: ignore -except ImportError: - pass - -try: - from collections import OrderedDict -except ImportError: - from ucollections import OrderedDict # type: ignore - -try: - from nope_machine import WDT - - wdt = WDT() - -except ImportError: - - class _WDT: - def feed(self): - pass - - wdt = _WDT() - - -wdt.feed() - -__version__ = "v1.16.2" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] - - +try:from ujson import dumps +except:from json import dumps +try:from machine import reset +except R:pass +try:from collections import OrderedDict as f +except R:from ucollections import OrderedDict as f +__version__='v1.16.3' +z=2 +A0=2 +A1=['lib','/lib','/sd/lib','/flash/lib',K] +class M: + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=J + @staticmethod + def getLogger(name):return M() + @classmethod + def basicConfig(A,level):A.level=level + def info(A,msg): + if A.level<=M.INFO:A.prnt('INFO :',msg) + def warning(A,msg): + if A.level<=M.WARNING:A.prnt('WARN :',msg) + def error(A,msg): + if A.level<=M.ERROR:A.prnt('ERROR :',msg) +B=M.getLogger(r) +M.basicConfig(level=M.INFO) class Stubber: - "Generate stubs for modules in firmware" - - def __init__(self, path: str = None, firmware_id: str = None): # type: ignore - try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore - raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") - except AttributeError: - pass - # self.log = logging.getLogger("stubber") - self._report = [] # type: list[str] - self.info = _info() - # self.log.info("Port: {}".format(self.info["port"])) - # self.log.info("Board: {}".format(self.info["board"])) - gc.collect() - wdt.feed() - if firmware_id: - self._fwid = firmware_id.lower() - else: - if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") - else: - self._fwid = "{family}-v{version}-{port}".format(**self.info) - self._start_free = gc.mem_free() # type: ignore - - if path: - if path.endswith("/"): - path = path[:-1] - else: - path = get_root() - - self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - # self.log.debug(self.path) - try: - ensure_folder(path + "/") - except OSError: - print("error creating stub folder {}".format(path)) - self.problematic = [ - "upip", - "upysh", - "webrepl_setup", - "http_client", - "http_client_ssl", - "http_server", - "http_server_ssl", - ] - self.excluded = [ - "webrepl", - "_webrepl", - "port_diag", - "example_sub_led.py", - "example_pub_button.py", - ] - # there is no option to discover modules from micropython, list is read from an external file. - self.modules = [] # type: list[str] - - def get_obj_attributes(self, item_instance: object): - "extract information of the objects members and attributes" - # name_, repr_(value), type as text, item_instance - _result = [] - _errors = [] - # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) - for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: - continue - # self.log.debug("get attribute {}".format(name)) - try: - val = getattr(item_instance, name) - # name , item_repr(value) , type as text, item_instance, order - # self.log.debug("attribute {}:{}".format(name, val)) - try: - type_text = repr(type(val)).split("'")[1] - except IndexError: - type_text = "" - if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: - order = 1 - elif type_text in {"function", "method"}: - order = 2 - elif type_text in ("class"): - order = 3 - else: - order = 4 - _result.append((name, repr(val), repr(type(val)), val, order)) - except AttributeError as e: - _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) - except MemoryError as e: - # print("MemoryError: {}".format(e)) - sleep(1) - reset() - - # remove internal __ - # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) - _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) - gc.collect() - return _result, _errors - - def add_modules(self, modules): - "Add additional modules to be exported" - self.modules = sorted(set(self.modules) | set(modules)) - - def create_all_stubs(self): - "Create stubs for all configured modules" - # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) - gc.collect() - for module_name in self.modules: - self.create_one_stub(module_name) - # self.log.info("Finally done") - - def create_one_stub(self, module_name: str): - wdt.feed() - if module_name in self.problematic: - # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) - return False - if module_name in self.excluded: - # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) - return False - - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) - gc.collect() - result = False - try: - result = self.create_module_stub(module_name, file_name) - except OSError: - return False - gc.collect() - return result - - def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore - """Create a Stub of a single python module - - Args: - - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. - """ - if file_name is None: - fname = module_name.replace(".", "_") + ".py" - file_name = self.path + "/" + fname - else: - fname = file_name.split("/")[-1] - - if "/" in module_name: - # for nested modules - module_name = module_name.replace("/", ".") - - # import the module (as new_module) to examine it - new_module = None - try: - new_module = __import__(module_name, None, None, ("*")) - m1 = gc.mem_free() # type: ignore - # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) - - except ImportError: - # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) - return False - - # Start a new file - ensure_folder(file_name) - with open(file_name, "w") as fp: - # todo: improve header - info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") - s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) - fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") - self.write_object_stub(fp, new_module, module_name, "") - - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) - - if module_name not in {"os", "sys", "logging", "gc"}: - # try to unload the module unless we use it - try: - del new_module - except (OSError, KeyError): # lgtm [py/unreachable-statement] - pass - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - pass - gc.collect() - return True - - def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): - "Write a module/object stub to an open file. Can be called recursive." - gc.collect() - if object_expr in self.problematic: - # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) - return - - # # self.log.debug("DUMP : {}".format(object_expr)) - items, errors = self.get_obj_attributes(object_expr) - - if errors: - print(errors) - - for item_name, item_repr, item_type_txt, item_instance, _ in items: - # name_, repr_(value), type as text, item_instance, order - if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: - # do not create stubs for these primitives - continue - if item_name[0].isdigit(): - # self.log.warning("NameError: invalid name {}".format(item_name)) - continue - # Class expansion only on first 3 levels (bit of a hack) - if ( - item_type_txt == "" - and len(indent) <= _MAX_CLASS_LEVEL * 4 - # and not obj_name.endswith(".Pin") - # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms - ): - # self.log.info("{0}class {1}:".format(indent, item_name)) - superclass = "" - is_exception = ( - item_name.endswith("Exception") - or item_name.endswith("Error") - or item_name - in [ - "KeyboardInterrupt", - "StopIteration", - "SystemExit", - ] - ) - if is_exception: - superclass = "Exception" - s = "\n{}class {}({}):\n".format(indent, item_name, superclass) - # s += indent + " ''\n" - if is_exception: - s += indent + " ...\n" - fp.write(s) - continue - # write classdef - fp.write(s) - # first write the class literals and methods - # self.log.debug("# recursion over class {0}".format(item_name)) - self.write_object_stub( - fp, - item_instance, - "{0}.{1}".format(obj_name, item_name), - indent + " ", - in_class + 1, - ) - # end with the __init__ method to make sure that the literals are defined - # Add __init__ - s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" - s += indent + " ...\n\n" - fp.write(s) - elif any(word in item_type_txt for word in ["method", "function", "closure"]): - # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) - # module Function or class method - # will accept any number of params - # return type Any/Incomplete - ret = "Incomplete" - first = "" - # Self parameter only on class methods/functions - if in_class > 0: - first = "self, " - # class method - add function decoration - if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) - else: - s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) - s += indent + " ...\n\n" - fp.write(s) - # self.log.debug("\n" + s) - elif item_type_txt == "": - # Skip imported modules - # fp.write("# import {}\n".format(item_name)) - pass - - elif item_type_txt.startswith(" dict[str, str] - info = OrderedDict( - { - "family": sys.implementation.name, - "version": "", - "build": "", - "ver": "", - "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "UNKNOWN", - "cpu": "", - "mpy": "", - "arch": "", - } - ) - # change port names to be consistent with the repo - if info["port"].startswith("pyb"): - info["port"] = "stm32" - elif info["port"] == "win32": - info["port"] = "windows" - elif info["port"] == "linux": - info["port"] = "unix" - try: - info["version"] = version_str(sys.implementation.version) # type: ignore - except AttributeError: - pass - try: - _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - # info["board"] = "with".join(_machine.split("with")[:-1]).strip() - info["board"] = _machine - info["cpu"] = _machine.split("with")[-1].strip() - info["mpy"] = ( - sys.implementation._mpy - if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy - if "mpy" in dir(sys.implementation) - else "" - ) - except (AttributeError, IndexError): - pass - gc.collect() - read_boardname(info) - gc.collect() - - try: - if "uname" in dir(os): # old - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - elif "version" in dir(sys): # new - # extract build from sys.version if available - info["build"] = _build(sys.version) - except (AttributeError, IndexError, TypeError): - pass - # avoid build hashes - # if info["build"] and len(info["build"]) > 5: - # info["build"] = "" - - if info["version"] == "" and sys.platform not in ("unix", "win32"): - try: - u = os.uname() # type: ignore - info["version"] = u.release - except (IndexError, AttributeError, TypeError): - pass - # detect families - for fam_name, mod_name, mod_thing in [ - ("pycopy", "pycopy", "const"), - ("pycom", "pycom", "FAT"), - ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), - ]: - try: - _t = __import__(mod_name, None, None, (mod_thing)) - info["family"] = fam_name - del _t - break - except (ImportError, KeyError): - pass - - if info["family"] == "ev3-pybricks": - info["release"] = "2.0.0" - - if info["family"] == "micropython": - info["version"] - if ( - info["version"] - and info["version"].endswith(".0") - and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 - and info["version"] <= "1.19.9" - ): - # versions from 1.10.0 to 1.20.0 do not have a micro .0 - info["version"] = info["version"][:-2] - - # spell-checker: disable - if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds - sys_mpy = int(info["mpy"]) - # .mpy architecture - arch = [ - None, - "x86", - "x64", - "armv6", - "armv6m", - "armv7m", - "armv7em", - "armv7emsp", - "armv7emdp", - "xtensa", - "xtensawin", - ][sys_mpy >> 10] - if arch: - info["arch"] = arch - # .mpy version.minor - info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) - if info["build"] and not info["version"].endswith("-preview"): - info["version"] = info["version"] + "-preview" - # simple to use version[-build] string - info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" - - return info - - -def version_str(version: tuple): # -> str: - v_str = ".".join([str(n) for n in version[:3]]) - if len(version) > 3 and version[3]: - v_str += "-" + version[3] - return v_str - - -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - # print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# # print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False - - -def get_root() -> str: # sourcery skip: use-assigned-variable - "Determine the root folder of the device" - try: - c = os.getcwd() - except (OSError, AttributeError): - # unix port - c = "." - r = c - for r in [c, "/sd", "/flash", "/", "."]: - try: - _ = os.stat(r) - break - except OSError: - continue - return r - - -def file_exists(filename: str): - try: - if os.stat(filename)[0] >> 14: - return True - return False - except OSError: - return False - - -def show_help(): - # print("-p, --path path to store the stubs in, defaults to '.'") - sys.exit(1) - - -def read_path() -> str: - "get --path from cmdline. [unix/win]" - path = "" - if len(sys.argv) == 3: - cmd = (sys.argv[1]).lower() - if cmd in ("--path", "-p"): - path = sys.argv[2] - else: - show_help() - elif len(sys.argv) == 2: - show_help() - return path - - -def is_micropython() -> bool: - "runtime test to determine full or micropython" - # pylint: disable=unused-variable,eval-used - try: - # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects - - # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented - # Micropython: NotImplementedError - b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] - - # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute - # Micropython: AttributeError - c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] - return False - except (NotImplementedError, AttributeError): - return True - - + def __init__(C,path=F,firmware_id=F): + D=firmware_id + try: + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') + except I:pass + C._report=[];C.info=_info();B.info('Port: {}'.format(C.info[L]));B.info('Board: {}'.format(C.info[U]));A.collect() + if D:C._fwid=D.lower() + elif C.info[S]==a:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info).rstrip(V) + else:C._fwid='{family}-v{version}-{port}'.format(**C.info) + C._start_free=A.mem_free() + if path: + if path.endswith(G):path=path[:-1] + else:path=get_root() + C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) + try:h(path+G) + except E:B.error('error creating stub folder {}'.format(path)) + C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] + def get_obj_attributes(M,item_instance): + H=item_instance;D=[];L=[] + for B in P(H): + if B.startswith(b)and not B in M.modules:continue + try: + E=getattr(H,B) + try:F=Z(type(E)).split("'")[1] + except T:F=C + if F in{s,t,u,v,c,d,e}:G=1 + elif F in{w,x}:G=2 + elif F in'class':G=3 + else:G=4 + D.append((B,Z(E),Z(type(E)),E,G)) + except I as K:L.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(B,H,K)) + except n as K:J('MemoryError: {}'.format(K));sleep(1);reset() + D=o([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);A.collect();return D,L + def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) + def create_all_stubs(C): + B.info('Start micropython-stubber v{} on {}'.format(__version__,C._fwid));A.collect() + for D in C.modules:C.create_one_stub(D) + B.info('Finally done') + def create_one_stub(D,module_name): + C=module_name + if C in D.problematic:B.warning('Skip module: {:<25} : Known problematic'.format(C));return H + if C in D.excluded:B.warning('Skip module: {:<25} : Excluded'.format(C));return H + I='{}/{}.py'.format(D.path,C.replace(K,G));A.collect();F=H + try:F=D.create_module_stub(C,I) + except E:return H + A.collect();return F + def create_module_stub(J,module_name,file_name=F): + I=file_name;D=module_name + if I is F:L=D.replace(K,b)+'.py';I=J.path+G+L + else:L=I.split(G)[-1] + if G in D:D=D.replace(G,K) + M=F + try:M=__import__(D,F,F,'*');Q=A.mem_free();B.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(D,L,Q)) + except R:return H + h(I) + with N(I,'w')as P:S=str(J.info).replace('OrderedDict(',C).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(P,M,D,C) + J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,I.replace('\\',G))) + if D not in{'os','sys','logging','gc'}: + try:del M + except(E,p):B.warning('could not del new_module') + A.collect();return O + def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;E=indent;A.collect() + if L in K.problematic:B.warning('SKIPPING problematic module:{}'.format(L));return + X,O=K.get_obj_attributes(L) + if O:B.error(O) + for(F,J,G,Y,a)in X: + if F in['classmethod','staticmethod','BaseException',M]:continue + if F[0].isdigit():B.warning('NameError: invalid name {}'.format(F));continue + if G==""and Q(E)<=A0*4: + P=C;R=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] + if R:P=M + D='\n{}class {}({}):\n'.format(E,F,P) + if R:D+=E+' ...\n';I.write(D);continue + I.write(D);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',N+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';I.write(D) + elif any(A in G for A in[x,w,'closure']): + S=U;T=C + if N>0:T='self, ' + if V in G or V in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) + else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,T,S) + D+=E+' ...\n\n';I.write(D) + elif G=="":0 + elif G.startswith("='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] + if E in A and A[E]: + G=int(A[E]);J=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[N]=J + A[E]='v{}.{}'.format(G&255,G>>8&3) + if A[B]and not A[D].endswith(W):A[D]=A[D]+W + A[K]=f"{A[D]}-{A[B]}"if A[B]else f"{A[D]}";return A +def A2(version): + A=version;B=K.join([str(A)for A in A[:3]]) + if Q(A)>3 and A[3]:B+=V+A[3] + return B +def A3(): + try:from boardname import BOARDNAME as A;B.info('Found BOARDNAME: {}'.format(A)) + except R:B.warning('BOARDNAME not found');A=C + return A +def get_root(): + try:A=os.getcwd() + except(E,I):A=K + B=A + for B in[A,'/sd','/flash',G,K]: + try:C=os.stat(B);break + except E:continue + return B +def i(filename): + try: + if os.stat(filename)[0]>>14:return O + return H + except E:return H +def j():J("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) +def read_path(): + path=C + if Q(sys.argv)==3: + A=sys.argv[1].lower() + if A in('--path','-p'):path=sys.argv[2] + else:j() + elif Q(sys.argv)==2:j() + return path +def k(): + try:A=bytes('abc',encoding='utf8');B=k.__module__;return H + except(m,I):return O def main(): - import machine # type: ignore - - try: - f = open("modulelist.done", "r+b") - was_running = True - # print("Opened existing db") - except OSError: - f = open("modulelist.done", "w+b") - # print("created new db") - was_running = False - stubber = Stubber(path=read_path()) - - # f_name = "{}/{}".format(stubber.path, "modules.json") - if not was_running: - # Only clean folder if this is a first run - stubber.clean() - # get list of modules to process - get_modulelist(stubber) - # remove the ones that are already done - modules_done = {} # type: dict[str, str] - try: - with open("modulelist.done") as f: - # not optimal , but works on mpremote and esp8266 - for line in f.read().split("\n"): - line = line.strip() - gc.collect() - if len(line) > 0: - key, value = line.split("=", 1) - modules_done[key] = value - except (OSError, SyntaxError): - pass - gc.collect() - # see if we can continue from where we left off - modules = [m for m in stubber.modules if m not in modules_done.keys()] - gc.collect() - for modulename in modules: - # ------------------------------------ - # do epic shit - # but sometimes things fail / run out of memory and reboot - ok = False - try: - ok = stubber.create_one_stub(modulename) - except MemoryError: - # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER - machine.reset() - # ------------------------------------- - gc.collect() - modules_done[modulename] = str(stubber._report[-1] if ok else "failed") - with open("modulelist.done", "a") as f: - f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) - - # Finished processing - load all the results , and remove the failed ones - if modules_done: - # stubber.write_json_end(mod_fp) - stubber._report = [v for _, v in modules_done.items() if v != "failed"] - stubber.report() - - -def get_modulelist(stubber): - stubber.modules = [] # avoid duplicates - for p in LIBS: - try: - with open(p + "/modulelist.txt") as f: - print ("DEBUG: list of modules: " + p + "/modulelist.txt") - for line in f.read().split("\n"): - line = line.strip() - if len(line) > 0 and line[0] != "#": - stubber.modules.append(line) - gc.collect() - break - except OSError: - pass - if not stubber.modules: - stubber.modules = ["micropython"] - _log.warn("Could not find modulelist.txt, using default modules") - gc.collect() - - -if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass - if not file_exists("no_auto_stubber.txt"): - try: - gc.threshold(4 * 1024) # type: ignore - gc.enable() - except BaseException: - pass - main() + I='failed';import machine as K + try:C=N(X,'r+b');D=O;J('Opened existing db') + except E:C=N(X,'w+b');J('created new db');D=H + stubber=Stubber(path=read_path()) + if not D:stubber.clean() + B=l();A4(stubber,B) + if not stubber.modules:J('All modules have been processed, exiting') + else: + del B;A.collect() + for F in stubber.modules: + G=H + try:G=stubber.create_one_stub(F) + except n:K.reset() + A.collect() + with N(X,'a')as C:C.write('{}={}\n'.format(F,'ok'if G else I)) + B=l() + if B: + stubber._report=[] + for(L,M)in B.items(): + if M!=I:stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(L)) + stubber.report() +def l(): + C={} + try: + with N(X)as D: + while O: + B=D.readline().strip() + if not B:break + if Q(B)>0 and B[0]!='#':F,G=B.split('=',1);C[F]=G + except(E,SyntaxError):J('could not read modulelist.done') + finally:A.collect();return C +def A4(stubber,modules_done): + A.collect();stubber.modules=[] + for D in A1: + C=D+'/modulelist.txt' + if not i(C):continue + with N(C)as E: + while O: + B=E.readline().strip() + if not B:break + if B and B not in modules_done.keys():stubber.modules.append(B) + A.collect();J('BREAK');break + if not stubber.modules:stubber.modules=[a] + A.collect() +if __name__=='__main__'or k(): + if not i('no_auto_stubber.txt'): + try:A.threshold(4*1024);A.enable() + except BaseException:pass + main() \ No newline at end of file diff --git a/mip/v5/createstubs_db_mpy.mpy b/mip/v5/createstubs_db_mpy.mpy index 78198f80d54528a032aa6b2ca48b947fd968d51b..d7910db3d017ffcc5cce9ca96e3921ec6a2ad299 100644 GIT binary patch literal 9744 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 literal 9118 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 bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + # log.debug("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -228,12 +247,12 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] - self.log.warning("could not del new_module") + log.warning("could not del new_module") # lets not try - most times it does not work anyway # try: # del sys.modules[module_name] # except KeyError: - # self.log.warning("could not del sys.modules[{}]".format(module_name)) + # log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -241,14 +260,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: - self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # self.log.debug("DUMP : {}".format(object_expr)) + # # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: - self.log.error(errors) + log.error(errors) for item_name, item_repr, item_type_txt, item_instance, _ in items: # name_, repr_(value), type as text, item_instance, order @@ -256,7 +275,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # do not create stubs for these primitives continue if item_name[0].isdigit(): - self.log.warning("NameError: invalid name {}".format(item_name)) + log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) if ( @@ -265,7 +284,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - self.log.info("{0}class {1}:".format(indent, item_name)) + # log.debug("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -288,7 +307,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - self.log.debug("# recursion over class {0}".format(item_name)) + # log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -302,7 +321,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -318,7 +337,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - self.log.debug("\n" + s) + # log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -346,10 +365,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - self.log.debug("\n" + s) + # log.debug("\n" + s) else: # keep only the name - self.log.debug("# all other, type = '{0}'".format(item_type_txt)) + # log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -373,10 +392,9 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" - wdt.feed() if path is None: path = self.path - self.log.info("Clean/remove files in folder: {}".format(path)) + log.info("Clean/remove files in folder: {}".format(path)) try: os.stat(path) # TEMP workaround mpremote listdir bug - items = os.listdir(path) @@ -396,10 +414,9 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" - wdt.feed() - self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) + log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) - self.log.info("Report file: {}".format(f_name)) + log.info("Report file: {}".format(f_name)) gc.collect() try: # write json by node to reduce memory requirements @@ -411,9 +428,9 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - self.log.info("Memory used: {0} Kb".format(used // 1024)) + # log.debug("Memory used: {0} Kb".format(used // 1024)) except OSError: - self.log.error("Failed to create the report.") + log.error("Failed to create the report.") def write_json_header(self, f): f.write("{") @@ -511,9 +528,7 @@ def _info(): # type:() -> dict[str, str] ) except (AttributeError, IndexError): pass - gc.collect() - read_boardname(info) - gc.collect() + info["board"] = get_boardname() try: if "uname" in dir(os): # old @@ -601,79 +616,16 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore + + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.warning("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable @@ -751,26 +703,33 @@ def main(): stubber.clean() # Read stubs from modulelist in the current folder or in /libs # fall back to default modules - stubber.modules = [] # avoid duplicates - for p in LIBS: - try: - _1 = gc.mem_free() # type: ignore - with open(p + "/modulelist.txt") as f: - print("Debug: List of modules: " + p + "/modulelist.txt") - line = f.readline() - while line: - line = line.strip() + def get_modulelist(stubber): + # new + gc.collect() + stubber.modules = [] # avoid duplicates + for p in LIBS: + fname = p + "/modulelist.txt" + if not file_exists(fname): + continue + with open(fname) as f: + # print("DEBUG: list of modules: " + p + "/modulelist.txt") + while True: + line = f.readline().strip() + if not line: + break if len(line) > 0 and line[0] != "#": stubber.modules.append(line) - line = f.readline() - gc.collect() # type: ignore - print("Debug: Used memory to load modulelist.txt: " + str(_1 - gc.mem_free()) + " bytes") # type: ignore + gc.collect() + print("BREAK") break - except Exception: - pass - if not stubber.modules: - stubber.modules = ["micropython"] - print("Could not find modulelist.txt, using default modules") + + if not stubber.modules: + stubber.modules = ["micropython"] + # _log.warn("Could not find modulelist.txt, using default modules") + gc.collect() + + stubber.modules = [] # avoid duplicates + get_modulelist(stubber) gc.collect() @@ -779,12 +738,6 @@ def main(): if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass if not file_exists("no_auto_stubber.txt"): try: gc.threshold(4 * 1024) # type: ignore diff --git a/mip/v5/createstubs_mem_min.py b/mip/v5/createstubs_mem_min.py index d610d52be..415b4e5bd 100644 --- a/mip/v5/createstubs_mem_min.py +++ b/mip/v5/createstubs_mem_min.py @@ -1,794 +1,293 @@ -"""Create stubs for (all) modules on a MicroPython board. - - This variant of the createstubs.py script is optimised for use on low-memory devices, and reads the list of modules from a text file - `modulelist.txt` in the root or `libs` folder that should be uploaded to the device. - If that cannot be found then only a single module (micropython) is stubbed. - In order to run this on low-memory devices two additional steps are recommended: - - minifification, using python-minifier - to reduce overall size, and remove logging overhead. - - cross compilation, using mpy-cross, - to avoid the compilation step on the micropython device - -This variant was generated from createstubs.py by micropython-stubber v1.16.2 -""" -# Copyright (c) 2019-2023 Jos Verlinde - -import gc -# import logging -import os -import sys +v='{}/{}' +u='method' +t='function' +s='bool' +r='str' +q='float' +p='int' +o='stubber' +n=TypeError +m=KeyError +l=sorted +k=NotImplementedError +e=',\n' +d='dict' +c='list' +b='tuple' +a='_' +Z='micropython' +Y=open +X=repr +V='-preview' +U='-' +T='board' +S=IndexError +R=print +Q=True +P='family' +O=ImportError +N=len +M=dir +K='port' +J='.' +I=False +H=AttributeError +G='/' +F=None +E=OSError +C='version' +B='' +import gc as D,os,sys from time import sleep - -try: - from ujson import dumps -except: - from json import dumps - -try: - from machine import reset # type: ignore -except ImportError: - pass - -try: - from collections import OrderedDict -except ImportError: - from ucollections import OrderedDict # type: ignore - -try: - from nope_machine import WDT - - wdt = WDT() - -except ImportError: - - class _WDT: - def feed(self): - pass - - wdt = _WDT() - - -wdt.feed() - -__version__ = "v1.16.2" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] - - +try:from ujson import dumps +except:from json import dumps +try:from machine import reset +except O:pass +try:from collections import OrderedDict as f +except O:from ucollections import OrderedDict as f +__version__='v1.16.3' +w=2 +x=2 +y=['lib','/lib','/sd/lib','/flash/lib',J] +class L: + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=R + @staticmethod + def getLogger(name):return L() + @classmethod + def basicConfig(A,level):A.level=level + def info(A,msg): + if A.level<=L.INFO:A.prnt('INFO :',msg) + def warning(A,msg): + if A.level<=L.WARNING:A.prnt('WARN :',msg) + def error(A,msg): + if A.level<=L.ERROR:A.prnt('ERROR :',msg) +A=L.getLogger(o) +L.basicConfig(level=L.INFO) class Stubber: - "Generate stubs for modules in firmware" - - def __init__(self, path: str = None, firmware_id: str = None): # type: ignore - try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore - raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") - except AttributeError: - pass - # self.log = logging.getLogger("stubber") - self._report = [] # type: list[str] - self.info = _info() - # self.log.info("Port: {}".format(self.info["port"])) - # self.log.info("Board: {}".format(self.info["board"])) - gc.collect() - wdt.feed() - if firmware_id: - self._fwid = firmware_id.lower() - else: - if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") - else: - self._fwid = "{family}-v{version}-{port}".format(**self.info) - self._start_free = gc.mem_free() # type: ignore - - if path: - if path.endswith("/"): - path = path[:-1] - else: - path = get_root() - - self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - # self.log.debug(self.path) - try: - ensure_folder(path + "/") - except OSError: - print("error creating stub folder {}".format(path)) - self.problematic = [ - "upip", - "upysh", - "webrepl_setup", - "http_client", - "http_client_ssl", - "http_server", - "http_server_ssl", - ] - self.excluded = [ - "webrepl", - "_webrepl", - "port_diag", - "example_sub_led.py", - "example_pub_button.py", - ] - # there is no option to discover modules from micropython, list is read from an external file. - self.modules = [] # type: list[str] - - def get_obj_attributes(self, item_instance: object): - "extract information of the objects members and attributes" - # name_, repr_(value), type as text, item_instance - _result = [] - _errors = [] - # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) - for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: - continue - # self.log.debug("get attribute {}".format(name)) - try: - val = getattr(item_instance, name) - # name , item_repr(value) , type as text, item_instance, order - # self.log.debug("attribute {}:{}".format(name, val)) - try: - type_text = repr(type(val)).split("'")[1] - except IndexError: - type_text = "" - if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: - order = 1 - elif type_text in {"function", "method"}: - order = 2 - elif type_text in ("class"): - order = 3 - else: - order = 4 - _result.append((name, repr(val), repr(type(val)), val, order)) - except AttributeError as e: - _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) - except MemoryError as e: - # print("MemoryError: {}".format(e)) - sleep(1) - reset() - - # remove internal __ - # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) - _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) - gc.collect() - return _result, _errors - - def add_modules(self, modules): - "Add additional modules to be exported" - self.modules = sorted(set(self.modules) | set(modules)) - - def create_all_stubs(self): - "Create stubs for all configured modules" - # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) - gc.collect() - for module_name in self.modules: - self.create_one_stub(module_name) - # self.log.info("Finally done") - - def create_one_stub(self, module_name: str): - wdt.feed() - if module_name in self.problematic: - # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) - return False - if module_name in self.excluded: - # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) - return False - - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) - gc.collect() - result = False - try: - result = self.create_module_stub(module_name, file_name) - except OSError: - return False - gc.collect() - return result - - def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore - """Create a Stub of a single python module - - Args: - - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. - """ - if file_name is None: - fname = module_name.replace(".", "_") + ".py" - file_name = self.path + "/" + fname - else: - fname = file_name.split("/")[-1] - - if "/" in module_name: - # for nested modules - module_name = module_name.replace("/", ".") - - # import the module (as new_module) to examine it - new_module = None - try: - new_module = __import__(module_name, None, None, ("*")) - m1 = gc.mem_free() # type: ignore - # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) - - except ImportError: - # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) - return False - - # Start a new file - ensure_folder(file_name) - with open(file_name, "w") as fp: - # todo: improve header - info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") - s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) - fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") - self.write_object_stub(fp, new_module, module_name, "") - - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) - - if module_name not in {"os", "sys", "logging", "gc"}: - # try to unload the module unless we use it - try: - del new_module - except (OSError, KeyError): # lgtm [py/unreachable-statement] - pass - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - pass - gc.collect() - return True - - def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): - "Write a module/object stub to an open file. Can be called recursive." - gc.collect() - if object_expr in self.problematic: - # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) - return - - # # self.log.debug("DUMP : {}".format(object_expr)) - items, errors = self.get_obj_attributes(object_expr) - - if errors: - print(errors) - - for item_name, item_repr, item_type_txt, item_instance, _ in items: - # name_, repr_(value), type as text, item_instance, order - if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: - # do not create stubs for these primitives - continue - if item_name[0].isdigit(): - # self.log.warning("NameError: invalid name {}".format(item_name)) - continue - # Class expansion only on first 3 levels (bit of a hack) - if ( - item_type_txt == "" - and len(indent) <= _MAX_CLASS_LEVEL * 4 - # and not obj_name.endswith(".Pin") - # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms - ): - # self.log.info("{0}class {1}:".format(indent, item_name)) - superclass = "" - is_exception = ( - item_name.endswith("Exception") - or item_name.endswith("Error") - or item_name - in [ - "KeyboardInterrupt", - "StopIteration", - "SystemExit", - ] - ) - if is_exception: - superclass = "Exception" - s = "\n{}class {}({}):\n".format(indent, item_name, superclass) - # s += indent + " ''\n" - if is_exception: - s += indent + " ...\n" - fp.write(s) - continue - # write classdef - fp.write(s) - # first write the class literals and methods - # self.log.debug("# recursion over class {0}".format(item_name)) - self.write_object_stub( - fp, - item_instance, - "{0}.{1}".format(obj_name, item_name), - indent + " ", - in_class + 1, - ) - # end with the __init__ method to make sure that the literals are defined - # Add __init__ - s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" - s += indent + " ...\n\n" - fp.write(s) - elif any(word in item_type_txt for word in ["method", "function", "closure"]): - # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) - # module Function or class method - # will accept any number of params - # return type Any/Incomplete - ret = "Incomplete" - first = "" - # Self parameter only on class methods/functions - if in_class > 0: - first = "self, " - # class method - add function decoration - if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) - else: - s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) - s += indent + " ...\n\n" - fp.write(s) - # self.log.debug("\n" + s) - elif item_type_txt == "": - # Skip imported modules - # fp.write("# import {}\n".format(item_name)) - pass - - elif item_type_txt.startswith(" dict[str, str] - info = OrderedDict( - { - "family": sys.implementation.name, - "version": "", - "build": "", - "ver": "", - "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "UNKNOWN", - "cpu": "", - "mpy": "", - "arch": "", - } - ) - # change port names to be consistent with the repo - if info["port"].startswith("pyb"): - info["port"] = "stm32" - elif info["port"] == "win32": - info["port"] = "windows" - elif info["port"] == "linux": - info["port"] = "unix" - try: - info["version"] = version_str(sys.implementation.version) # type: ignore - except AttributeError: - pass - try: - _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - # info["board"] = "with".join(_machine.split("with")[:-1]).strip() - info["board"] = _machine - info["cpu"] = _machine.split("with")[-1].strip() - info["mpy"] = ( - sys.implementation._mpy - if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy - if "mpy" in dir(sys.implementation) - else "" - ) - except (AttributeError, IndexError): - pass - gc.collect() - read_boardname(info) - gc.collect() - - try: - if "uname" in dir(os): # old - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - elif "version" in dir(sys): # new - # extract build from sys.version if available - info["build"] = _build(sys.version) - except (AttributeError, IndexError, TypeError): - pass - # avoid build hashes - # if info["build"] and len(info["build"]) > 5: - # info["build"] = "" - - if info["version"] == "" and sys.platform not in ("unix", "win32"): - try: - u = os.uname() # type: ignore - info["version"] = u.release - except (IndexError, AttributeError, TypeError): - pass - # detect families - for fam_name, mod_name, mod_thing in [ - ("pycopy", "pycopy", "const"), - ("pycom", "pycom", "FAT"), - ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), - ]: - try: - _t = __import__(mod_name, None, None, (mod_thing)) - info["family"] = fam_name - del _t - break - except (ImportError, KeyError): - pass - - if info["family"] == "ev3-pybricks": - info["release"] = "2.0.0" - - if info["family"] == "micropython": - info["version"] - if ( - info["version"] - and info["version"].endswith(".0") - and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 - and info["version"] <= "1.19.9" - ): - # versions from 1.10.0 to 1.20.0 do not have a micro .0 - info["version"] = info["version"][:-2] - - # spell-checker: disable - if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds - sys_mpy = int(info["mpy"]) - # .mpy architecture - arch = [ - None, - "x86", - "x64", - "armv6", - "armv6m", - "armv7m", - "armv7em", - "armv7emsp", - "armv7emdp", - "xtensa", - "xtensawin", - ][sys_mpy >> 10] - if arch: - info["arch"] = arch - # .mpy version.minor - info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) - if info["build"] and not info["version"].endswith("-preview"): - info["version"] = info["version"] + "-preview" - # simple to use version[-build] string - info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" - - return info - - -def version_str(version: tuple): # -> str: - v_str = ".".join([str(n) for n in version[:3]]) - if len(version) > 3 and version[3]: - v_str += "-" + version[3] - return v_str - - -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - # print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# # print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False - - -def get_root() -> str: # sourcery skip: use-assigned-variable - "Determine the root folder of the device" - try: - c = os.getcwd() - except (OSError, AttributeError): - # unix port - c = "." - r = c - for r in [c, "/sd", "/flash", "/", "."]: - try: - _ = os.stat(r) - break - except OSError: - continue - return r - - -def file_exists(filename: str): - try: - if os.stat(filename)[0] >> 14: - return True - return False - except OSError: - return False - - -def show_help(): - # print("-p, --path path to store the stubs in, defaults to '.'") - sys.exit(1) - - -def read_path() -> str: - "get --path from cmdline. [unix/win]" - path = "" - if len(sys.argv) == 3: - cmd = (sys.argv[1]).lower() - if cmd in ("--path", "-p"): - path = sys.argv[2] - else: - show_help() - elif len(sys.argv) == 2: - show_help() - return path - - -def is_micropython() -> bool: - "runtime test to determine full or micropython" - # pylint: disable=unused-variable,eval-used - try: - # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects - - # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented - # Micropython: NotImplementedError - b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] - - # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute - # Micropython: AttributeError - c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] - return False - except (NotImplementedError, AttributeError): - return True - - + def __init__(B,path=F,firmware_id=F): + C=firmware_id + try: + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + except H:pass + B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[T]));D.collect() + if C:B._fwid=C.lower() + elif B.info[P]==Z:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(U) + else:B._fwid='{family}-v{version}-{port}'.format(**B.info) + B._start_free=D.mem_free() + if path: + if path.endswith(G):path=path[:-1] + else:path=get_root() + B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) + try:g(path+G) + except E:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[] + def get_obj_attributes(L,item_instance): + I=item_instance;C=[];K=[] + for A in M(I): + if A.startswith(a)and not A in L.modules:continue + try: + E=getattr(I,A) + try:F=X(type(E)).split("'")[1] + except S:F=B + if F in{p,q,r,s,b,c,d}:G=1 + elif F in{t,u}:G=2 + elif F in'class':G=3 + else:G=4 + C.append((A,X(E),X(type(E)),E,G)) + except H as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,J)) + except MemoryError as J:R('MemoryError: {}'.format(J));sleep(1);reset() + C=l([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,K + def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) + def create_all_stubs(B): + A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));D.collect() + for C in B.modules:B.create_one_stub(C) + A.info('Finally done') + def create_one_stub(C,module_name): + B=module_name + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return I + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return I + H='{}/{}.py'.format(C.path,B.replace(J,G));D.collect();F=I + try:F=C.create_module_stub(B,H) + except E:return I + D.collect();return F + def create_module_stub(K,module_name,file_name=F): + H=file_name;C=module_name + if H is F:L=C.replace(J,a)+'.py';H=K.path+G+L + else:L=H.split(G)[-1] + if G in C:C=C.replace(G,J) + M=F + try:M=__import__(C,F,F,'*');P=D.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) + except O:return I + g(H) + with Y(H,'w')as N:R=str(K.info).replace('OrderedDict(',B).replace('})','}');S='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,R,__version__);N.write(S);N.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,M,C,B) + K._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + if C not in{'os','sys','logging','gc'}: + try:del M + except(E,m):A.warning('could not del new_module') + D.collect();return Q + def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';O=in_class;M='Exception';L=object_expr;I=fp;E=indent;D.collect() + if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return + X,P=K.get_obj_attributes(L) + if P:A.error(P) + for(F,J,G,Y,a)in X: + if F in['classmethod','staticmethod','BaseException',M]:continue + if F[0].isdigit():A.warning('NameError: invalid name {}'.format(F));continue + if G==""and N(E)<=x*4: + Q=B;R=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] + if R:Q=M + C='\n{}class {}({}):\n'.format(E,F,Q) + if R:C+=E+' ...\n';I.write(C);continue + I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',O+1);C=E+' def __init__(self, *argv, **kwargs) -> None:\n';C+=E+' ...\n\n';I.write(C) + elif any(A in G for A in[u,t,'closure']): + S=U;T=B + if O>0:T='self, ' + if V in G or V in J:C='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) + else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,T,S) + C+=E+' ...\n\n';I.write(C) + elif G=="":0 + elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if E in A and A[E]: + G=int(A[E]);J=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[Q]=J + A[E]='v{}.{}'.format(G&255,G>>8&3) + if A[D]and not A[C].endswith(V):A[C]=A[C]+V + A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A +def z(version): + A=version;B=J.join([str(A)for A in A[:3]]) + if N(A)>3 and A[3]:B+=U+A[3] + return B +def A0(): + try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) + except O:A.warning('BOARDNAME not found');C=B + return C +def get_root(): + try:A=os.getcwd() + except(E,H):A=J + B=A + for B in[A,'/sd','/flash',G,J]: + try:C=os.stat(B);break + except E:continue + return B +def h(filename): + try: + if os.stat(filename)[0]>>14:return Q + return I + except E:return I +def i():R("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) +def read_path(): + path=B + if N(sys.argv)==3: + A=sys.argv[1].lower() + if A in('--path','-p'):path=sys.argv[2] + else:i() + elif N(sys.argv)==2:i() + return path +def j(): + try:A=bytes('abc',encoding='utf8');B=j.__module__;return I + except(k,H):return Q def main(): - stubber = Stubber(path=read_path()) - # stubber = Stubber(path="/sd") - # Option: Specify a firmware name & version - # stubber = Stubber(firmware_id='HoverBot v1.2.1') - stubber.clean() - # Read stubs from modulelist in the current folder or in /libs - # fall back to default modules - stubber.modules = [] # avoid duplicates - for p in LIBS: - try: - _1 = gc.mem_free() # type: ignore - with open(p + "/modulelist.txt") as f: - print ("Debug: List of modules: " + p + "/modulelist.txt") - line = f.readline() - while line: - line = line.strip() - if len(line) > 0 and line[0] != "#": - stubber.modules.append(line) - line = f.readline() - gc.collect() # type: ignore - print ("Debug: Used memory to load modulelist.txt: " + str(_1 - gc.mem_free()) + " bytes") # type: ignore - break - except Exception: - pass - if not stubber.modules: - stubber.modules = ["micropython"] - # print("Could not find modulelist.txt, using default modules") - - gc.collect() - - stubber.create_all_stubs() - stubber.report() - - -if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass - if not file_exists("no_auto_stubber.txt"): - try: - gc.threshold(4 * 1024) # type: ignore - gc.enable() - except BaseException: - pass - main() + stubber=Stubber(path=read_path());stubber.clean() + def A(stubber): + D.collect();stubber.modules=[] + for C in y: + B=C+'/modulelist.txt' + if not h(B):continue + with Y(B)as E: + while Q: + A=E.readline().strip() + if not A:break + if N(A)>0 and A[0]!='#':stubber.modules.append(A) + D.collect();R('BREAK');break + if not stubber.modules:stubber.modules=[Z] + D.collect() + stubber.modules=[];A(stubber);D.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or j(): + if not h('no_auto_stubber.txt'): + try:D.threshold(4*1024);D.enable() + except BaseException:pass + main() \ No newline at end of file diff --git a/mip/v5/createstubs_mem_mpy.mpy b/mip/v5/createstubs_mem_mpy.mpy index 14b67b80ca1335bbcaa7a173341cf8ca24de299a..c3acec7c4c8d58fbfdef272abee6285c6f8eb261 100644 GIT binary patch literal 9099 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 diff --git a/mip/v5/createstubs_min.py b/mip/v5/createstubs_min.py index 7b134cbf9..0fcb07093 100644 --- a/mip/v5/createstubs_min.py +++ b/mip/v5/createstubs_min.py @@ -1,1011 +1,281 @@ -""" -Create stubs for (all) modules on a MicroPython board -""" -# Copyright (c) 2019-2023 Jos Verlinde - -import gc -# import logging -import os -import sys +x='pyb' +w='{}/{}' +v='logging' +u='sys' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n='stubber' +m=TypeError +l=KeyError +k=sorted +j=NotImplementedError +e='pycom' +d=',\n' +c='dict' +b='list' +a='tuple' +Z='_' +Y='micropython' +X=repr +W=print +U='-preview' +T=True +S='-' +R='board' +Q=IndexError +P='family' +O=len +N=ImportError +M=dir +K='port' +J='.' +I=False +H=AttributeError +G='/' +E=None +D=OSError +C='version' +B='' +import gc as F,os,sys from time import sleep - -try: - from ujson import dumps -except: - from json import dumps - -try: - from machine import reset # type: ignore -except ImportError: - pass - -try: - from collections import OrderedDict -except ImportError: - from ucollections import OrderedDict # type: ignore - -try: - from nope_machine import WDT - - wdt = WDT() - -except ImportError: - - class _WDT: - def feed(self): - pass - - wdt = _WDT() - - -wdt.feed() - -__version__ = "v1.16.2" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] - - +try:from ujson import dumps +except:from json import dumps +try:from machine import reset +except N:pass +try:from collections import OrderedDict as f +except N:from ucollections import OrderedDict as f +__version__='v1.16.3' +y=2 +z=2 +A3=['lib','/lib','/sd/lib','/flash/lib',J] +class L: + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=W + @staticmethod + def getLogger(name):return L() + @classmethod + def basicConfig(A,level):A.level=level + def info(A,msg): + if A.level<=L.INFO:A.prnt('INFO :',msg) + def warning(A,msg): + if A.level<=L.WARNING:A.prnt('WARN :',msg) + def error(A,msg): + if A.level<=L.ERROR:A.prnt('ERROR :',msg) +A=L.getLogger(n) +L.basicConfig(level=L.INFO) class Stubber: - "Generate stubs for modules in firmware" - - def __init__(self, path: str = None, firmware_id: str = None): # type: ignore - try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore - raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") - except AttributeError: - pass - # self.log = logging.getLogger("stubber") - self._report = [] # type: list[str] - self.info = _info() - # self.log.info("Port: {}".format(self.info["port"])) - # self.log.info("Board: {}".format(self.info["board"])) - gc.collect() - wdt.feed() - if firmware_id: - self._fwid = firmware_id.lower() - else: - if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") - else: - self._fwid = "{family}-v{version}-{port}".format(**self.info) - self._start_free = gc.mem_free() # type: ignore - - if path: - if path.endswith("/"): - path = path[:-1] - else: - path = get_root() - - self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - # self.log.debug(self.path) - try: - ensure_folder(path + "/") - except OSError: - print("error creating stub folder {}".format(path)) - self.problematic = [ - "upip", - "upysh", - "webrepl_setup", - "http_client", - "http_client_ssl", - "http_server", - "http_server_ssl", - ] - self.excluded = [ - "webrepl", - "_webrepl", - "port_diag", - "example_sub_led.py", - "example_pub_button.py", - ] - # there is no option to discover modules from micropython, list is read from an external file. - self.modules = [] # type: list[str] - - def get_obj_attributes(self, item_instance: object): - "extract information of the objects members and attributes" - # name_, repr_(value), type as text, item_instance - _result = [] - _errors = [] - # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) - for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: - continue - # self.log.debug("get attribute {}".format(name)) - try: - val = getattr(item_instance, name) - # name , item_repr(value) , type as text, item_instance, order - # self.log.debug("attribute {}:{}".format(name, val)) - try: - type_text = repr(type(val)).split("'")[1] - except IndexError: - type_text = "" - if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: - order = 1 - elif type_text in {"function", "method"}: - order = 2 - elif type_text in ("class"): - order = 3 - else: - order = 4 - _result.append((name, repr(val), repr(type(val)), val, order)) - except AttributeError as e: - _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) - except MemoryError as e: - # print("MemoryError: {}".format(e)) - sleep(1) - reset() - - # remove internal __ - # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) - _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) - gc.collect() - return _result, _errors - - def add_modules(self, modules): - "Add additional modules to be exported" - self.modules = sorted(set(self.modules) | set(modules)) - - def create_all_stubs(self): - "Create stubs for all configured modules" - # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) - gc.collect() - for module_name in self.modules: - self.create_one_stub(module_name) - # self.log.info("Finally done") - - def create_one_stub(self, module_name: str): - wdt.feed() - if module_name in self.problematic: - # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) - return False - if module_name in self.excluded: - # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) - return False - - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) - gc.collect() - result = False - try: - result = self.create_module_stub(module_name, file_name) - except OSError: - return False - gc.collect() - return result - - def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore - """Create a Stub of a single python module - - Args: - - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. - """ - if file_name is None: - fname = module_name.replace(".", "_") + ".py" - file_name = self.path + "/" + fname - else: - fname = file_name.split("/")[-1] - - if "/" in module_name: - # for nested modules - module_name = module_name.replace("/", ".") - - # import the module (as new_module) to examine it - new_module = None - try: - new_module = __import__(module_name, None, None, ("*")) - m1 = gc.mem_free() # type: ignore - # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) - - except ImportError: - # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) - return False - - # Start a new file - ensure_folder(file_name) - with open(file_name, "w") as fp: - # todo: improve header - info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") - s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format( - module_name, self._fwid, info_, __version__ - ) - fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") - self.write_object_stub(fp, new_module, module_name, "") - - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) - - if module_name not in {"os", "sys", "logging", "gc"}: - # try to unload the module unless we use it - try: - del new_module - except (OSError, KeyError): # lgtm [py/unreachable-statement] - pass - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - pass - gc.collect() - return True - - def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): - "Write a module/object stub to an open file. Can be called recursive." - gc.collect() - if object_expr in self.problematic: - # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) - return - - # # self.log.debug("DUMP : {}".format(object_expr)) - items, errors = self.get_obj_attributes(object_expr) - - if errors: - print(errors) - - for item_name, item_repr, item_type_txt, item_instance, _ in items: - # name_, repr_(value), type as text, item_instance, order - if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: - # do not create stubs for these primitives - continue - if item_name[0].isdigit(): - # self.log.warning("NameError: invalid name {}".format(item_name)) - continue - # Class expansion only on first 3 levels (bit of a hack) - if ( - item_type_txt == "" - and len(indent) <= _MAX_CLASS_LEVEL * 4 - # and not obj_name.endswith(".Pin") - # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms - ): - # self.log.info("{0}class {1}:".format(indent, item_name)) - superclass = "" - is_exception = ( - item_name.endswith("Exception") - or item_name.endswith("Error") - or item_name - in [ - "KeyboardInterrupt", - "StopIteration", - "SystemExit", - ] - ) - if is_exception: - superclass = "Exception" - s = "\n{}class {}({}):\n".format(indent, item_name, superclass) - # s += indent + " ''\n" - if is_exception: - s += indent + " ...\n" - fp.write(s) - continue - # write classdef - fp.write(s) - # first write the class literals and methods - # self.log.debug("# recursion over class {0}".format(item_name)) - self.write_object_stub( - fp, - item_instance, - "{0}.{1}".format(obj_name, item_name), - indent + " ", - in_class + 1, - ) - # end with the __init__ method to make sure that the literals are defined - # Add __init__ - s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" - s += indent + " ...\n\n" - fp.write(s) - elif any(word in item_type_txt for word in ["method", "function", "closure"]): - # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) - # module Function or class method - # will accept any number of params - # return type Any/Incomplete - ret = "Incomplete" - first = "" - # Self parameter only on class methods/functions - if in_class > 0: - first = "self, " - # class method - add function decoration - if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format( - indent, item_name, ret - ) - else: - s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) - s += indent + " ...\n\n" - fp.write(s) - # self.log.debug("\n" + s) - elif item_type_txt == "": - # Skip imported modules - # fp.write("# import {}\n".format(item_name)) - pass - - elif item_type_txt.startswith(" dict[str, str] - info = OrderedDict( - { - "family": sys.implementation.name, - "version": "", - "build": "", - "ver": "", - "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "UNKNOWN", - "cpu": "", - "mpy": "", - "arch": "", - } - ) - # change port names to be consistent with the repo - if info["port"].startswith("pyb"): - info["port"] = "stm32" - elif info["port"] == "win32": - info["port"] = "windows" - elif info["port"] == "linux": - info["port"] = "unix" - try: - info["version"] = version_str(sys.implementation.version) # type: ignore - except AttributeError: - pass - try: - _machine = ( - sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - ) - # info["board"] = "with".join(_machine.split("with")[:-1]).strip() - info["board"] = _machine - info["cpu"] = _machine.split("with")[-1].strip() - info["mpy"] = ( - sys.implementation._mpy - if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy - if "mpy" in dir(sys.implementation) - else "" - ) - except (AttributeError, IndexError): - pass - gc.collect() - read_boardname(info) - gc.collect() - - try: - if "uname" in dir(os): # old - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - elif "version" in dir(sys): # new - # extract build from sys.version if available - info["build"] = _build(sys.version) - except (AttributeError, IndexError, TypeError): - pass - # avoid build hashes - # if info["build"] and len(info["build"]) > 5: - # info["build"] = "" - - if info["version"] == "" and sys.platform not in ("unix", "win32"): - try: - u = os.uname() # type: ignore - info["version"] = u.release - except (IndexError, AttributeError, TypeError): - pass - # detect families - for fam_name, mod_name, mod_thing in [ - ("pycopy", "pycopy", "const"), - ("pycom", "pycom", "FAT"), - ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), - ]: - try: - _t = __import__(mod_name, None, None, (mod_thing)) - info["family"] = fam_name - del _t - break - except (ImportError, KeyError): - pass - - if info["family"] == "ev3-pybricks": - info["release"] = "2.0.0" - - if info["family"] == "micropython": - info["version"] - if ( - info["version"] - and info["version"].endswith(".0") - and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 - and info["version"] <= "1.19.9" - ): - # versions from 1.10.0 to 1.20.0 do not have a micro .0 - info["version"] = info["version"][:-2] - - # spell-checker: disable - if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds - sys_mpy = int(info["mpy"]) - # .mpy architecture - arch = [ - None, - "x86", - "x64", - "armv6", - "armv6m", - "armv7m", - "armv7em", - "armv7emsp", - "armv7emdp", - "xtensa", - "xtensawin", - ][sys_mpy >> 10] - if arch: - info["arch"] = arch - # .mpy version.minor - info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) - if info["build"] and not info["version"].endswith("-preview"): - info["version"] = info["version"] + "-preview" - # simple to use version[-build] string - info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" - - return info - - -def version_str(version: tuple): # -> str: - v_str = ".".join([str(n) for n in version[:3]]) - if len(version) > 3 and version[3]: - v_str += "-" + version[3] - return v_str - - -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - # print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# # print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False - - -def get_root() -> str: # sourcery skip: use-assigned-variable - "Determine the root folder of the device" - try: - c = os.getcwd() - except (OSError, AttributeError): - # unix port - c = "." - r = c - for r in [c, "/sd", "/flash", "/", "."]: - try: - _ = os.stat(r) - break - except OSError: - continue - return r - - -def file_exists(filename: str): - try: - if os.stat(filename)[0] >> 14: - return True - return False - except OSError: - return False - - -def show_help(): - # print("-p, --path path to store the stubs in, defaults to '.'") - sys.exit(1) - - -def read_path() -> str: - "get --path from cmdline. [unix/win]" - path = "" - if len(sys.argv) == 3: - cmd = (sys.argv[1]).lower() - if cmd in ("--path", "-p"): - path = sys.argv[2] - else: - show_help() - elif len(sys.argv) == 2: - show_help() - return path - - -def is_micropython() -> bool: - "runtime test to determine full or micropython" - # pylint: disable=unused-variable,eval-used - try: - # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects - - # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented - # Micropython: NotImplementedError - b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] - - # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute - # Micropython: AttributeError - c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] - return False - except (NotImplementedError, AttributeError): - return True - - -def main(): - stubber = Stubber(path=read_path()) - # stubber = Stubber(path="/sd") - # Option: Specify a firmware name & version - # stubber = Stubber(firmware_id='HoverBot v1.2.1') - stubber.clean() - # there is no option to discover modules from micropython, need to hardcode - # below contains combined modules from Micropython ESP8622, ESP32, Loboris, Pycom and ulab , lvgl - # spell-checker: disable - # modules to stub : 131 - stubber.modules = [ - "WM8960", - "_OTA", - "_asyncio", - "_boot_fat", - "_coap", - "_espnow", - "_flash_control_OTA", - "_main_pybytes", - "_mqtt", - "_mqtt_core", - "_msg_handl", - "_onewire", - "_periodical_pin", - "_pybytes", - "_pybytes_ca", - "_pybytes_config", - "_pybytes_config_reader", - "_pybytes_connection", - "_pybytes_constants", - "_pybytes_debug", - "_pybytes_library", - "_pybytes_machine_learning", - "_pybytes_main", - "_pybytes_protocol", - "_pybytes_pyconfig", - "_pybytes_pymesh_config", - "_rp2", - "_terminal", - "_thread", - "_uasyncio", - "_urequest", - "adcfft", - "aioble/__init__", - "aioble/central", - "aioble/client", - "aioble/core", - "aioble/device", - "aioble/l2cap", - "aioble/peripheral", - "aioble/security", - "aioble/server", - "aioespnow", - "ak8963", - "apa102", - "apa106", - "argparse", - "array", - "asyncio/__init__", - "asyncio/core", - "asyncio/event", - "asyncio/funcs", - "asyncio/lock", - "asyncio/stream", - "binascii", - "bluetooth", - "breakout_as7262", - "breakout_bh1745", - "breakout_bme280", - "breakout_bme68x", - "breakout_bmp280", - "breakout_dotmatrix", - "breakout_encoder", - "breakout_icp10125", - "breakout_ioexpander", - "breakout_ltr559", - "breakout_matrix11x7", - "breakout_mics6814", - "breakout_msa301", - "breakout_paa5100", - "breakout_pmw3901", - "breakout_potentiometer", - "breakout_rgbmatrix5x5", - "breakout_rtc", - "breakout_scd41", - "breakout_sgp30", - "breakout_trackball", - "breakout_vl53l5cx", - "btree", - "cmath", - "collections", - "crypto", - "cryptolib", - "curl", - "deflate", - "dht", - "display", - "display_driver_utils", - "ds18x20", - "encoder", - "errno", - "esp", - "esp32", - "espidf", - "espnow", - "ffi", - "flashbdev", - "framebuf", - "freesans20", - "fs_driver", - "functools", - "galactic", - "gc", - "gfx_pack", - "gsm", - "hashlib", - "heapq", - "hub75", - "ili9341", - "ili9XXX", - "imagetools", - "inisetup", - "interstate75", - "io", - "jpegdec", - "json", - "lcd160cr", - "lodepng", - "logging", - "lsm6dsox", - "lv_colors", - "lv_utils", - "lvgl", - "lwip", - "machine", - "math", - "microWebSocket", - "microWebSrv", - "microWebTemplate", - "micropython", - "mip", - "mip/__init__", - "mip/__main__", - "motor", - "mpu6500", - "mpu9250", - "neopixel", - "network", - "ntptime", - "onewire", - "os", - "pcf85063a", - "picoexplorer", - "picographics", - "picokeypad", - "picoscroll", - "picounicorn", - "picowireless", - "pimoroni", - "pimoroni_bus", - "pimoroni_i2c", - "plasma", - "platform", - "pyb", - "pycom", - "pye", - "qrcode", - "queue", - "random", - "requests", - "requests/__init__", - "rp2", - "rtch", - "samd", - "select", - "servo", - "socket", - "ssd1306", - "ssh", - "ssl", - "stm", - "struct", - "sys", - "termios", - "time", - "tpcalib", - "uarray", - "uasyncio/__init__", - "uasyncio/core", - "uasyncio/event", - "uasyncio/funcs", - "uasyncio/lock", - "uasyncio/stream", - "uasyncio/tasks", - "ubinascii", - "ubluetooth", - "ucollections", - "ucrypto", - "ucryptolib", - "uctypes", - "uerrno", - "uftpd", - "uhashlib", - "uheapq", - "uio", - "ujson", - "ulab", - "ulab/approx", - "ulab/compare", - "ulab/fft", - "ulab/filter", - "ulab/linalg", - "ulab/numerical", - "ulab/poly", - "ulab/user", - "ulab/vector", - "umachine", - "umqtt/__init__", - "umqtt/robust", - "umqtt/simple", - "uos", - "uplatform", - "uqueue", - "urandom", - "ure", - "urequests", - "urllib/urequest", - "uselect", - "usocket", - "ussl", - "ustruct", - "usys", - "utelnetserver", - "utime", - "utimeq", - "uwebsocket", - "uzlib", - "version", - "websocket", - "websocket_helper", - "wipy", - "writer", - "xpt2046", - "ymodem", - "zephyr", - "zlib", - ] # spell-checker: enable - - gc.collect() - - stubber.create_all_stubs() - stubber.report() - - -if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass - if not file_exists("no_auto_stubber.txt"): - try: - gc.threshold(4 * 1024) # type: ignore - gc.enable() - except BaseException: - pass - main() + def __init__(B,path=E,firmware_id=E): + C=firmware_id + try: + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') + except H:pass + B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[R]));F.collect() + if C:B._fwid=C.lower() + elif B.info[P]==Y:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(S) + else:B._fwid='{family}-v{version}-{port}'.format(**B.info) + B._start_free=F.mem_free() + if path: + if path.endswith(G):path=path[:-1] + else:path=get_root() + B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) + try:g(path+G) + except D:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[] + def get_obj_attributes(L,item_instance): + I=item_instance;C=[];K=[] + for A in M(I): + if A.startswith(Z)and not A in L.modules:continue + try: + D=getattr(I,A) + try:E=X(type(D)).split("'")[1] + except Q:E=B + if E in{o,p,q,r,a,b,c}:G=1 + elif E in{s,t}:G=2 + elif E in'class':G=3 + else:G=4 + C.append((A,X(D),X(type(D)),D,G)) + except H as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,J)) + except MemoryError as J:W('MemoryError: {}'.format(J));sleep(1);reset() + C=k([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);F.collect();return C,K + def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) + def create_all_stubs(B): + A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));F.collect() + for C in B.modules:B.create_one_stub(C) + A.info('Finally done') + def create_one_stub(C,module_name): + B=module_name + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return I + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return I + H='{}/{}.py'.format(C.path,B.replace(J,G));F.collect();E=I + try:E=C.create_module_stub(B,H) + except D:return I + F.collect();return E + def create_module_stub(K,module_name,file_name=E): + H=file_name;C=module_name + if H is E:L=C.replace(J,Z)+'.py';H=K.path+G+L + else:L=H.split(G)[-1] + if G in C:C=C.replace(G,J) + M=E + try:M=__import__(C,E,E,'*');P=F.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) + except N:return I + g(H) + with open(H,'w')as O:Q=str(K.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,Q,__version__);O.write(R);O.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(O,M,C,B) + K._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + if C not in{'os',u,v,'gc'}: + try:del M + except(D,l):A.warning('could not del new_module') + F.collect();return T + def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() + if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return + X,P=K.get_obj_attributes(L) + if P:A.error(P) + for(E,J,G,Y,d)in X: + if E in['classmethod','staticmethod','BaseException',M]:continue + if E[0].isdigit():A.warning('NameError: invalid name {}'.format(E));continue + if G==""and O(D)<=z*4: + Q=B;R=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if R:Q=M + C='\n{}class {}({}):\n'.format(D,E,Q) + if R:C+=D+' ...\n';I.write(C);continue + I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) + elif any(A in G for A in[t,s,'closure']): + S=U;T=B + if N>0:T='self, ' + if V in G or V in J:C='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,S) + else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,T,S) + C+=D+' ...\n\n';I.write(C) + elif G=="":0 + elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if F in A and A[F]: + G=int(A[F]);J=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[S]=J + A[F]='v{}.{}'.format(G&255,G>>8&3) + if A[D]and not A[C].endswith(U):A[C]=A[C]+U + A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A +def A0(version): + A=version;B=J.join([str(A)for A in A[:3]]) + if O(A)>3 and A[3]:B+=S+A[3] + return B +def A1(): + try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) + except N:A.warning('BOARDNAME not found');C=B + return C +def get_root(): + try:A=os.getcwd() + except(D,H):A=J + B=A + for B in[A,'/sd','/flash',G,J]: + try:C=os.stat(B);break + except D:continue + return B +def A2(filename): + try: + if os.stat(filename)[0]>>14:return T + return I + except D:return I +def h():W("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) +def read_path(): + path=B + if O(sys.argv)==3: + A=sys.argv[1].lower() + if A in('--path','-p'):path=sys.argv[2] + else:h() + elif O(sys.argv)==2:h() + return path +def i(): + try:A=bytes('abc',encoding='utf8');B=i.__module__;return I + except(j,H):return T +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',x,e,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];F.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or i(): + if not A2('no_auto_stubber.txt'): + try:F.threshold(4*1024);F.enable() + except BaseException:pass + main() \ No newline at end of file diff --git a/mip/v5/createstubs_mpy.mpy b/mip/v5/createstubs_mpy.mpy index 0bd6b3d252a4b7d0368c0d92b039bfe3b0b9cd2f..0fe1b26a0d424ffe4053f0b89a45761e5ad3769a 100644 GIT binary patch delta 6686 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 delta 6190 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 bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + # log.debug("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -219,12 +239,12 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] - self.log.warning("could not del new_module") + log.warning("could not del new_module") # lets not try - most times it does not work anyway # try: # del sys.modules[module_name] # except KeyError: - # self.log.warning("could not del sys.modules[{}]".format(module_name)) + # log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -232,14 +252,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: - self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # self.log.debug("DUMP : {}".format(object_expr)) + # # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: - self.log.error(errors) + log.error(errors) for item_name, item_repr, item_type_txt, item_instance, _ in items: # name_, repr_(value), type as text, item_instance, order @@ -247,7 +267,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # do not create stubs for these primitives continue if item_name[0].isdigit(): - self.log.warning("NameError: invalid name {}".format(item_name)) + log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) if ( @@ -256,7 +276,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - self.log.info("{0}class {1}:".format(indent, item_name)) + # log.debug("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -279,7 +299,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - self.log.debug("# recursion over class {0}".format(item_name)) + # log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -293,7 +313,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -311,7 +331,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - self.log.debug("\n" + s) + # log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -339,10 +359,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - self.log.debug("\n" + s) + # log.debug("\n" + s) else: # keep only the name - self.log.debug("# all other, type = '{0}'".format(item_type_txt)) + # log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -366,10 +386,9 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" - wdt.feed() if path is None: path = self.path - self.log.info("Clean/remove files in folder: {}".format(path)) + log.info("Clean/remove files in folder: {}".format(path)) try: os.stat(path) # TEMP workaround mpremote listdir bug - items = os.listdir(path) @@ -389,12 +408,9 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" - wdt.feed() - self.log.info( - "Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path) - ) + log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) - self.log.info("Report file: {}".format(f_name)) + log.info("Report file: {}".format(f_name)) gc.collect() try: # write json by node to reduce memory requirements @@ -406,9 +422,9 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - self.log.info("Memory used: {0} Kb".format(used // 1024)) + # log.debug("Memory used: {0} Kb".format(used // 1024)) except OSError: - self.log.error("Failed to create the report.") + log.error("Failed to create the report.") def write_json_header(self, f): f.write("{") @@ -508,9 +524,7 @@ def _info(): # type:() -> dict[str, str] ) except (AttributeError, IndexError): pass - gc.collect() - read_boardname(info) - gc.collect() + info["board"] = get_boardname() try: if "uname" in dir(os): # old @@ -598,79 +612,16 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore + + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.warning("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable @@ -995,12 +946,6 @@ def main(): if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass if not file_exists("no_auto_stubber.txt"): try: gc.threshold(4 * 1024) # type: ignore diff --git a/mip/v6/createstubs_db.py b/mip/v6/createstubs_db.py index 6904d4caa..2743ac849 100644 --- a/mip/v6/createstubs_db.py +++ b/mip/v6/createstubs_db.py @@ -18,12 +18,11 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.2 +This variant was generated from createstubs.py by micropython-stubber v1.16.3 """ # Copyright (c) 2019-2023 Jos Verlinde import gc -import logging import os import sys from time import sleep @@ -43,26 +42,49 @@ except ImportError: from ucollections import OrderedDict # type: ignore -try: - from nope_machine import WDT +__version__ = "v1.16.3" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] - wdt = WDT() -except ImportError: +# our own logging module to avoid dependency on and interfering with logging module +class logging: + # DEBUG = 10 + INFO = 20 + WARNING = 30 + ERROR = 40 + level = INFO + prnt = print - class _WDT: - def feed(self): - pass + @staticmethod + def getLogger(name): + return logging() - wdt = _WDT() + @classmethod + def basicConfig(cls, level): + cls.level = level + # def debug(self, msg): + # if self.level <= logging.DEBUG: + # self.prnt("DEBUG :", msg) -wdt.feed() + def info(self, msg): + if self.level <= logging.INFO: + self.prnt("INFO :", msg) + + def warning(self, msg): + if self.level <= logging.WARNING: + self.prnt("WARN :", msg) + + def error(self, msg): + if self.level <= logging.ERROR: + self.prnt("ERROR :", msg) -__version__ = "v1.16.2" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] + +log = logging.getLogger("stubber") +logging.basicConfig(level=logging.INFO) +# logging.basicConfig(level=logging.DEBUG) class Stubber: @@ -74,13 +96,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() - self.log.info("Port: {}".format(self.info["port"])) - self.log.info("Board: {}".format(self.info["board"])) + log.info("Port: {}".format(self.info["port"])) + log.info("Board: {}".format(self.info["board"])) gc.collect() - wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: @@ -97,11 +117,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore path = get_root() self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - self.log.debug(self.path) + # log.debug(self.path) try: ensure_folder(path + "/") except OSError: - self.log.error("error creating stub folder {}".format(path)) + log.error("error creating stub folder {}".format(path)) self.problematic = [ "upip", "upysh", @@ -126,15 +146,15 @@ def get_obj_attributes(self, item_instance: object): # name_, repr_(value), type as text, item_instance _result = [] _errors = [] - self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): if name.startswith("_") and not name in self.modules: continue - self.log.debug("get attribute {}".format(name)) + # log.debug("get attribute {}".format(name)) try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order - self.log.debug("attribute {}:{}".format(name, val)) + # log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -167,19 +187,18 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) gc.collect() for module_name in self.modules: self.create_one_stub(module_name) - self.log.info("Finally done") + log.info("Finally done") def create_one_stub(self, module_name: str): - wdt.feed() if module_name in self.problematic: - self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False if module_name in self.excluded: - self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) @@ -214,10 +233,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + # log.debug("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -237,12 +256,12 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] - self.log.warning("could not del new_module") + log.warning("could not del new_module") # lets not try - most times it does not work anyway # try: # del sys.modules[module_name] # except KeyError: - # self.log.warning("could not del sys.modules[{}]".format(module_name)) + # log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -250,14 +269,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: - self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # self.log.debug("DUMP : {}".format(object_expr)) + # # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: - self.log.error(errors) + log.error(errors) for item_name, item_repr, item_type_txt, item_instance, _ in items: # name_, repr_(value), type as text, item_instance, order @@ -265,7 +284,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # do not create stubs for these primitives continue if item_name[0].isdigit(): - self.log.warning("NameError: invalid name {}".format(item_name)) + log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) if ( @@ -274,7 +293,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - self.log.info("{0}class {1}:".format(indent, item_name)) + # log.debug("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -297,7 +316,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - self.log.debug("# recursion over class {0}".format(item_name)) + # log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -311,7 +330,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -327,7 +346,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - self.log.debug("\n" + s) + # log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -355,10 +374,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - self.log.debug("\n" + s) + # log.debug("\n" + s) else: # keep only the name - self.log.debug("# all other, type = '{0}'".format(item_type_txt)) + # log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -382,10 +401,9 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" - wdt.feed() if path is None: path = self.path - self.log.info("Clean/remove files in folder: {}".format(path)) + log.info("Clean/remove files in folder: {}".format(path)) try: os.stat(path) # TEMP workaround mpremote listdir bug - items = os.listdir(path) @@ -405,10 +423,9 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" - wdt.feed() - self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) + log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) - self.log.info("Report file: {}".format(f_name)) + log.info("Report file: {}".format(f_name)) gc.collect() try: # write json by node to reduce memory requirements @@ -420,9 +437,9 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - self.log.info("Memory used: {0} Kb".format(used // 1024)) + # log.debug("Memory used: {0} Kb".format(used // 1024)) except OSError: - self.log.error("Failed to create the report.") + log.error("Failed to create the report.") def write_json_header(self, f): f.write("{") @@ -520,9 +537,7 @@ def _info(): # type:() -> dict[str, str] ) except (AttributeError, IndexError): pass - gc.collect() - read_boardname(info) - gc.collect() + info["board"] = get_boardname() try: if "uname" in dir(os): # old @@ -610,79 +625,16 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore + + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.warning("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable @@ -770,74 +722,87 @@ def main(): # Only clean folder if this is a first run stubber.clean() # get list of modules to process - get_modulelist(stubber) - # remove the ones that are already done - modules_done = {} # type: dict[str, str] - try: - with open("modulelist.done") as f: - # not optimal , but works on mpremote and esp8266 - for line in f.read().split("\n"): - line = line.strip() - gc.collect() - if len(line) > 0: - key, value = line.split("=", 1) - modules_done[key] = value - except (OSError, SyntaxError): - pass - gc.collect() + modules_done = read_done() # see if we can continue from where we left off - modules = [m for m in stubber.modules if m not in modules_done.keys()] - gc.collect() - for modulename in modules: - # ------------------------------------ - # do epic shit - # but sometimes things fail / run out of memory and reboot - ok = False - try: - ok = stubber.create_one_stub(modulename) - except MemoryError: - # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER - machine.reset() - # ------------------------------------- + get_modulelist(stubber, modules_done) + + if not stubber.modules: + print("All modules have been processed, exiting") + else: + del modules_done gc.collect() - modules_done[modulename] = str(stubber._report[-1] if ok else "failed") - with open("modulelist.done", "a") as f: - f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) + for modulename in stubber.modules: + # ------------------------------------ + # do epic shit + # but sometimes things fail / run out of memory and reboot + ok = False + try: + ok = stubber.create_one_stub(modulename) + except MemoryError: + # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER + machine.reset() + # ------------------------------------- + gc.collect() + # modules_done[modulename] = str(stubber._report[-1] if ok else "failed") + with open("modulelist.done", "a") as f: + f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) # Finished processing - load all the results , and remove the failed ones + modules_done = read_done() if modules_done: # stubber.write_json_end(mod_fp) - stubber._report = [v for _, v in modules_done.items() if v != "failed"] + stubber._report = [] + for k, v in modules_done.items(): + if v != "failed": + stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(k)) stubber.report() -def get_modulelist(stubber): +def read_done(): + modules_done = {} # type: dict[str, str] + try: + with open("modulelist.done") as f: + while True: + line = f.readline().strip() + if not line: + break + if len(line) > 0 and line[0] != "#": + key, value = line.split("=", 1) + modules_done[key] = value + except (OSError, SyntaxError): + print("could not read modulelist.done") + finally: + gc.collect() + return modules_done + + +def get_modulelist(stubber, modules_done): + # new + gc.collect() stubber.modules = [] # avoid duplicates for p in LIBS: - try: - with open(p + "/modulelist.txt") as f: - print("DEBUG: list of modules: " + p + "/modulelist.txt") - for line in f.read().split("\n"): - line = line.strip() - if len(line) > 0 and line[0] != "#": - stubber.modules.append(line) - gc.collect() - break - except OSError: - pass + fname = p + "/modulelist.txt" + if not file_exists(fname): + continue + with open(fname) as f: + # print("DEBUG: list of modules: " + p + "/modulelist.txt") + while True: + line = f.readline().strip() + if not line: + break + if line and line not in modules_done.keys(): + stubber.modules.append(line) + gc.collect() + print("BREAK") + break + if not stubber.modules: stubber.modules = ["micropython"] - _log.warn("Could not find modulelist.txt, using default modules") + # _log.warn("Could not find modulelist.txt, using default modules") gc.collect() if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass if not file_exists("no_auto_stubber.txt"): try: gc.threshold(4 * 1024) # type: ignore diff --git a/mip/v6/createstubs_db_min.py b/mip/v6/createstubs_db_min.py index 05817f711..f61b4498f 100644 --- a/mip/v6/createstubs_db_min.py +++ b/mip/v6/createstubs_db_min.py @@ -1,847 +1,324 @@ -""" -Create stubs for (all) modules on a MicroPython board. - - This variant of the createstubs.py script is optimized for use on very-low-memory devices. - Note: this version has undergone limited testing. - - 1) reads the list of modules from a text file `modulelist.txt` that should be uploaded to the device. - 2) stored the already processed modules in a text file `modulelist.done` - 3) process the modules in the database: - - stub the module - - update the modulelist.done file - - reboots the device if it runs out of memory - 4) creates the modules.json - - If that cannot be found then only a single module (micropython) is stubbed. - In order to run this on low-memory devices two additional steps are recommended: - - minification, using python-minifierto reduce overall size, and remove logging overhead. - - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device - - -This variant was generated from createstubs.py by micropython-stubber v1.16.2 -""" -# Copyright (c) 2019-2023 Jos Verlinde - -import gc -# import logging -import os -import sys +y='{}/{}' +x='method' +w='function' +v='bool' +u='str' +t='float' +s='int' +r='stubber' +q=TypeError +p=KeyError +o=sorted +n=MemoryError +m=NotImplementedError +g=',\n' +e='dict' +d='list' +c='tuple' +b='_' +a='micropython' +Z=repr +X='modulelist.done' +W='-preview' +V='-' +U='board' +T=IndexError +S='family' +R=ImportError +Q=len +P=dir +O=True +N=open +L='port' +K='.' +J=print +I=AttributeError +H=False +G='/' +F=None +E=OSError +D='version' +C='' +import gc as A,os,sys from time import sleep - -try: - from ujson import dumps -except: - from json import dumps - -try: - from machine import reset # type: ignore -except ImportError: - pass - -try: - from collections import OrderedDict -except ImportError: - from ucollections import OrderedDict # type: ignore - -try: - from nope_machine import WDT - - wdt = WDT() - -except ImportError: - - class _WDT: - def feed(self): - pass - - wdt = _WDT() - - -wdt.feed() - -__version__ = "v1.16.2" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] - - +try:from ujson import dumps +except:from json import dumps +try:from machine import reset +except R:pass +try:from collections import OrderedDict as f +except R:from ucollections import OrderedDict as f +__version__='v1.16.3' +z=2 +A0=2 +A1=['lib','/lib','/sd/lib','/flash/lib',K] +class M: + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=J + @staticmethod + def getLogger(name):return M() + @classmethod + def basicConfig(A,level):A.level=level + def info(A,msg): + if A.level<=M.INFO:A.prnt('INFO :',msg) + def warning(A,msg): + if A.level<=M.WARNING:A.prnt('WARN :',msg) + def error(A,msg): + if A.level<=M.ERROR:A.prnt('ERROR :',msg) +B=M.getLogger(r) +M.basicConfig(level=M.INFO) class Stubber: - "Generate stubs for modules in firmware" - - def __init__(self, path: str = None, firmware_id: str = None): # type: ignore - try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore - raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") - except AttributeError: - pass - # self.log = logging.getLogger("stubber") - self._report = [] # type: list[str] - self.info = _info() - # self.log.info("Port: {}".format(self.info["port"])) - # self.log.info("Board: {}".format(self.info["board"])) - gc.collect() - wdt.feed() - if firmware_id: - self._fwid = firmware_id.lower() - else: - if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") - else: - self._fwid = "{family}-v{version}-{port}".format(**self.info) - self._start_free = gc.mem_free() # type: ignore - - if path: - if path.endswith("/"): - path = path[:-1] - else: - path = get_root() - - self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - # self.log.debug(self.path) - try: - ensure_folder(path + "/") - except OSError: - print("error creating stub folder {}".format(path)) - self.problematic = [ - "upip", - "upysh", - "webrepl_setup", - "http_client", - "http_client_ssl", - "http_server", - "http_server_ssl", - ] - self.excluded = [ - "webrepl", - "_webrepl", - "port_diag", - "example_sub_led.py", - "example_pub_button.py", - ] - # there is no option to discover modules from micropython, list is read from an external file. - self.modules = [] # type: list[str] - - def get_obj_attributes(self, item_instance: object): - "extract information of the objects members and attributes" - # name_, repr_(value), type as text, item_instance - _result = [] - _errors = [] - # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) - for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: - continue - # self.log.debug("get attribute {}".format(name)) - try: - val = getattr(item_instance, name) - # name , item_repr(value) , type as text, item_instance, order - # self.log.debug("attribute {}:{}".format(name, val)) - try: - type_text = repr(type(val)).split("'")[1] - except IndexError: - type_text = "" - if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: - order = 1 - elif type_text in {"function", "method"}: - order = 2 - elif type_text in ("class"): - order = 3 - else: - order = 4 - _result.append((name, repr(val), repr(type(val)), val, order)) - except AttributeError as e: - _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) - except MemoryError as e: - # print("MemoryError: {}".format(e)) - sleep(1) - reset() - - # remove internal __ - # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) - _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) - gc.collect() - return _result, _errors - - def add_modules(self, modules): - "Add additional modules to be exported" - self.modules = sorted(set(self.modules) | set(modules)) - - def create_all_stubs(self): - "Create stubs for all configured modules" - # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) - gc.collect() - for module_name in self.modules: - self.create_one_stub(module_name) - # self.log.info("Finally done") - - def create_one_stub(self, module_name: str): - wdt.feed() - if module_name in self.problematic: - # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) - return False - if module_name in self.excluded: - # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) - return False - - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) - gc.collect() - result = False - try: - result = self.create_module_stub(module_name, file_name) - except OSError: - return False - gc.collect() - return result - - def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore - """Create a Stub of a single python module - - Args: - - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. - """ - if file_name is None: - fname = module_name.replace(".", "_") + ".py" - file_name = self.path + "/" + fname - else: - fname = file_name.split("/")[-1] - - if "/" in module_name: - # for nested modules - module_name = module_name.replace("/", ".") - - # import the module (as new_module) to examine it - new_module = None - try: - new_module = __import__(module_name, None, None, ("*")) - m1 = gc.mem_free() # type: ignore - # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) - - except ImportError: - # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) - return False - - # Start a new file - ensure_folder(file_name) - with open(file_name, "w") as fp: - # todo: improve header - info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") - s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) - fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") - self.write_object_stub(fp, new_module, module_name, "") - - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) - - if module_name not in {"os", "sys", "logging", "gc"}: - # try to unload the module unless we use it - try: - del new_module - except (OSError, KeyError): # lgtm [py/unreachable-statement] - pass - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - pass - gc.collect() - return True - - def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): - "Write a module/object stub to an open file. Can be called recursive." - gc.collect() - if object_expr in self.problematic: - # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) - return - - # # self.log.debug("DUMP : {}".format(object_expr)) - items, errors = self.get_obj_attributes(object_expr) - - if errors: - print(errors) - - for item_name, item_repr, item_type_txt, item_instance, _ in items: - # name_, repr_(value), type as text, item_instance, order - if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: - # do not create stubs for these primitives - continue - if item_name[0].isdigit(): - # self.log.warning("NameError: invalid name {}".format(item_name)) - continue - # Class expansion only on first 3 levels (bit of a hack) - if ( - item_type_txt == "" - and len(indent) <= _MAX_CLASS_LEVEL * 4 - # and not obj_name.endswith(".Pin") - # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms - ): - # self.log.info("{0}class {1}:".format(indent, item_name)) - superclass = "" - is_exception = ( - item_name.endswith("Exception") - or item_name.endswith("Error") - or item_name - in [ - "KeyboardInterrupt", - "StopIteration", - "SystemExit", - ] - ) - if is_exception: - superclass = "Exception" - s = "\n{}class {}({}):\n".format(indent, item_name, superclass) - # s += indent + " ''\n" - if is_exception: - s += indent + " ...\n" - fp.write(s) - continue - # write classdef - fp.write(s) - # first write the class literals and methods - # self.log.debug("# recursion over class {0}".format(item_name)) - self.write_object_stub( - fp, - item_instance, - "{0}.{1}".format(obj_name, item_name), - indent + " ", - in_class + 1, - ) - # end with the __init__ method to make sure that the literals are defined - # Add __init__ - s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" - s += indent + " ...\n\n" - fp.write(s) - elif any(word in item_type_txt for word in ["method", "function", "closure"]): - # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) - # module Function or class method - # will accept any number of params - # return type Any/Incomplete - ret = "Incomplete" - first = "" - # Self parameter only on class methods/functions - if in_class > 0: - first = "self, " - # class method - add function decoration - if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) - else: - s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) - s += indent + " ...\n\n" - fp.write(s) - # self.log.debug("\n" + s) - elif item_type_txt == "": - # Skip imported modules - # fp.write("# import {}\n".format(item_name)) - pass - - elif item_type_txt.startswith(" dict[str, str] - info = OrderedDict( - { - "family": sys.implementation.name, - "version": "", - "build": "", - "ver": "", - "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "UNKNOWN", - "cpu": "", - "mpy": "", - "arch": "", - } - ) - # change port names to be consistent with the repo - if info["port"].startswith("pyb"): - info["port"] = "stm32" - elif info["port"] == "win32": - info["port"] = "windows" - elif info["port"] == "linux": - info["port"] = "unix" - try: - info["version"] = version_str(sys.implementation.version) # type: ignore - except AttributeError: - pass - try: - _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - # info["board"] = "with".join(_machine.split("with")[:-1]).strip() - info["board"] = _machine - info["cpu"] = _machine.split("with")[-1].strip() - info["mpy"] = ( - sys.implementation._mpy - if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy - if "mpy" in dir(sys.implementation) - else "" - ) - except (AttributeError, IndexError): - pass - gc.collect() - read_boardname(info) - gc.collect() - - try: - if "uname" in dir(os): # old - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - elif "version" in dir(sys): # new - # extract build from sys.version if available - info["build"] = _build(sys.version) - except (AttributeError, IndexError, TypeError): - pass - # avoid build hashes - # if info["build"] and len(info["build"]) > 5: - # info["build"] = "" - - if info["version"] == "" and sys.platform not in ("unix", "win32"): - try: - u = os.uname() # type: ignore - info["version"] = u.release - except (IndexError, AttributeError, TypeError): - pass - # detect families - for fam_name, mod_name, mod_thing in [ - ("pycopy", "pycopy", "const"), - ("pycom", "pycom", "FAT"), - ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), - ]: - try: - _t = __import__(mod_name, None, None, (mod_thing)) - info["family"] = fam_name - del _t - break - except (ImportError, KeyError): - pass - - if info["family"] == "ev3-pybricks": - info["release"] = "2.0.0" - - if info["family"] == "micropython": - info["version"] - if ( - info["version"] - and info["version"].endswith(".0") - and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 - and info["version"] <= "1.19.9" - ): - # versions from 1.10.0 to 1.20.0 do not have a micro .0 - info["version"] = info["version"][:-2] - - # spell-checker: disable - if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds - sys_mpy = int(info["mpy"]) - # .mpy architecture - arch = [ - None, - "x86", - "x64", - "armv6", - "armv6m", - "armv7m", - "armv7em", - "armv7emsp", - "armv7emdp", - "xtensa", - "xtensawin", - ][sys_mpy >> 10] - if arch: - info["arch"] = arch - # .mpy version.minor - info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) - if info["build"] and not info["version"].endswith("-preview"): - info["version"] = info["version"] + "-preview" - # simple to use version[-build] string - info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" - - return info - - -def version_str(version: tuple): # -> str: - v_str = ".".join([str(n) for n in version[:3]]) - if len(version) > 3 and version[3]: - v_str += "-" + version[3] - return v_str - - -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - # print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# # print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False - - -def get_root() -> str: # sourcery skip: use-assigned-variable - "Determine the root folder of the device" - try: - c = os.getcwd() - except (OSError, AttributeError): - # unix port - c = "." - r = c - for r in [c, "/sd", "/flash", "/", "."]: - try: - _ = os.stat(r) - break - except OSError: - continue - return r - - -def file_exists(filename: str): - try: - if os.stat(filename)[0] >> 14: - return True - return False - except OSError: - return False - - -def show_help(): - # print("-p, --path path to store the stubs in, defaults to '.'") - sys.exit(1) - - -def read_path() -> str: - "get --path from cmdline. [unix/win]" - path = "" - if len(sys.argv) == 3: - cmd = (sys.argv[1]).lower() - if cmd in ("--path", "-p"): - path = sys.argv[2] - else: - show_help() - elif len(sys.argv) == 2: - show_help() - return path - - -def is_micropython() -> bool: - "runtime test to determine full or micropython" - # pylint: disable=unused-variable,eval-used - try: - # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects - - # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented - # Micropython: NotImplementedError - b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] - - # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute - # Micropython: AttributeError - c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] - return False - except (NotImplementedError, AttributeError): - return True - - + def __init__(C,path=F,firmware_id=F): + D=firmware_id + try: + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') + except I:pass + C._report=[];C.info=_info();B.info('Port: {}'.format(C.info[L]));B.info('Board: {}'.format(C.info[U]));A.collect() + if D:C._fwid=D.lower() + elif C.info[S]==a:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info).rstrip(V) + else:C._fwid='{family}-v{version}-{port}'.format(**C.info) + C._start_free=A.mem_free() + if path: + if path.endswith(G):path=path[:-1] + else:path=get_root() + C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) + try:h(path+G) + except E:B.error('error creating stub folder {}'.format(path)) + C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] + def get_obj_attributes(M,item_instance): + H=item_instance;D=[];L=[] + for B in P(H): + if B.startswith(b)and not B in M.modules:continue + try: + E=getattr(H,B) + try:F=Z(type(E)).split("'")[1] + except T:F=C + if F in{s,t,u,v,c,d,e}:G=1 + elif F in{w,x}:G=2 + elif F in'class':G=3 + else:G=4 + D.append((B,Z(E),Z(type(E)),E,G)) + except I as K:L.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(B,H,K)) + except n as K:J('MemoryError: {}'.format(K));sleep(1);reset() + D=o([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);A.collect();return D,L + def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) + def create_all_stubs(C): + B.info('Start micropython-stubber v{} on {}'.format(__version__,C._fwid));A.collect() + for D in C.modules:C.create_one_stub(D) + B.info('Finally done') + def create_one_stub(D,module_name): + C=module_name + if C in D.problematic:B.warning('Skip module: {:<25} : Known problematic'.format(C));return H + if C in D.excluded:B.warning('Skip module: {:<25} : Excluded'.format(C));return H + I='{}/{}.py'.format(D.path,C.replace(K,G));A.collect();F=H + try:F=D.create_module_stub(C,I) + except E:return H + A.collect();return F + def create_module_stub(J,module_name,file_name=F): + I=file_name;D=module_name + if I is F:L=D.replace(K,b)+'.py';I=J.path+G+L + else:L=I.split(G)[-1] + if G in D:D=D.replace(G,K) + M=F + try:M=__import__(D,F,F,'*');Q=A.mem_free();B.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(D,L,Q)) + except R:return H + h(I) + with N(I,'w')as P:S=str(J.info).replace('OrderedDict(',C).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(P,M,D,C) + J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,I.replace('\\',G))) + if D not in{'os','sys','logging','gc'}: + try:del M + except(E,p):B.warning('could not del new_module') + A.collect();return O + def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;E=indent;A.collect() + if L in K.problematic:B.warning('SKIPPING problematic module:{}'.format(L));return + X,O=K.get_obj_attributes(L) + if O:B.error(O) + for(F,J,G,Y,a)in X: + if F in['classmethod','staticmethod','BaseException',M]:continue + if F[0].isdigit():B.warning('NameError: invalid name {}'.format(F));continue + if G==""and Q(E)<=A0*4: + P=C;R=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] + if R:P=M + D='\n{}class {}({}):\n'.format(E,F,P) + if R:D+=E+' ...\n';I.write(D);continue + I.write(D);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',N+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';I.write(D) + elif any(A in G for A in[x,w,'closure']): + S=U;T=C + if N>0:T='self, ' + if V in G or V in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) + else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,T,S) + D+=E+' ...\n\n';I.write(D) + elif G=="":0 + elif G.startswith("='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] + if E in A and A[E]: + G=int(A[E]);J=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[N]=J + A[E]='v{}.{}'.format(G&255,G>>8&3) + if A[B]and not A[D].endswith(W):A[D]=A[D]+W + A[K]=f"{A[D]}-{A[B]}"if A[B]else f"{A[D]}";return A +def A2(version): + A=version;B=K.join([str(A)for A in A[:3]]) + if Q(A)>3 and A[3]:B+=V+A[3] + return B +def A3(): + try:from boardname import BOARDNAME as A;B.info('Found BOARDNAME: {}'.format(A)) + except R:B.warning('BOARDNAME not found');A=C + return A +def get_root(): + try:A=os.getcwd() + except(E,I):A=K + B=A + for B in[A,'/sd','/flash',G,K]: + try:C=os.stat(B);break + except E:continue + return B +def i(filename): + try: + if os.stat(filename)[0]>>14:return O + return H + except E:return H +def j():J("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) +def read_path(): + path=C + if Q(sys.argv)==3: + A=sys.argv[1].lower() + if A in('--path','-p'):path=sys.argv[2] + else:j() + elif Q(sys.argv)==2:j() + return path +def k(): + try:A=bytes('abc',encoding='utf8');B=k.__module__;return H + except(m,I):return O def main(): - import machine # type: ignore - - try: - f = open("modulelist.done", "r+b") - was_running = True - # print("Opened existing db") - except OSError: - f = open("modulelist.done", "w+b") - # print("created new db") - was_running = False - stubber = Stubber(path=read_path()) - - # f_name = "{}/{}".format(stubber.path, "modules.json") - if not was_running: - # Only clean folder if this is a first run - stubber.clean() - # get list of modules to process - get_modulelist(stubber) - # remove the ones that are already done - modules_done = {} # type: dict[str, str] - try: - with open("modulelist.done") as f: - # not optimal , but works on mpremote and esp8266 - for line in f.read().split("\n"): - line = line.strip() - gc.collect() - if len(line) > 0: - key, value = line.split("=", 1) - modules_done[key] = value - except (OSError, SyntaxError): - pass - gc.collect() - # see if we can continue from where we left off - modules = [m for m in stubber.modules if m not in modules_done.keys()] - gc.collect() - for modulename in modules: - # ------------------------------------ - # do epic shit - # but sometimes things fail / run out of memory and reboot - ok = False - try: - ok = stubber.create_one_stub(modulename) - except MemoryError: - # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER - machine.reset() - # ------------------------------------- - gc.collect() - modules_done[modulename] = str(stubber._report[-1] if ok else "failed") - with open("modulelist.done", "a") as f: - f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) - - # Finished processing - load all the results , and remove the failed ones - if modules_done: - # stubber.write_json_end(mod_fp) - stubber._report = [v for _, v in modules_done.items() if v != "failed"] - stubber.report() - - -def get_modulelist(stubber): - stubber.modules = [] # avoid duplicates - for p in LIBS: - try: - with open(p + "/modulelist.txt") as f: - print ("DEBUG: list of modules: " + p + "/modulelist.txt") - for line in f.read().split("\n"): - line = line.strip() - if len(line) > 0 and line[0] != "#": - stubber.modules.append(line) - gc.collect() - break - except OSError: - pass - if not stubber.modules: - stubber.modules = ["micropython"] - _log.warn("Could not find modulelist.txt, using default modules") - gc.collect() - - -if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass - if not file_exists("no_auto_stubber.txt"): - try: - gc.threshold(4 * 1024) # type: ignore - gc.enable() - except BaseException: - pass - main() + I='failed';import machine as K + try:C=N(X,'r+b');D=O;J('Opened existing db') + except E:C=N(X,'w+b');J('created new db');D=H + stubber=Stubber(path=read_path()) + if not D:stubber.clean() + B=l();A4(stubber,B) + if not stubber.modules:J('All modules have been processed, exiting') + else: + del B;A.collect() + for F in stubber.modules: + G=H + try:G=stubber.create_one_stub(F) + except n:K.reset() + A.collect() + with N(X,'a')as C:C.write('{}={}\n'.format(F,'ok'if G else I)) + B=l() + if B: + stubber._report=[] + for(L,M)in B.items(): + if M!=I:stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(L)) + stubber.report() +def l(): + C={} + try: + with N(X)as D: + while O: + B=D.readline().strip() + if not B:break + if Q(B)>0 and B[0]!='#':F,G=B.split('=',1);C[F]=G + except(E,SyntaxError):J('could not read modulelist.done') + finally:A.collect();return C +def A4(stubber,modules_done): + A.collect();stubber.modules=[] + for D in A1: + C=D+'/modulelist.txt' + if not i(C):continue + with N(C)as E: + while O: + B=E.readline().strip() + if not B:break + if B and B not in modules_done.keys():stubber.modules.append(B) + A.collect();J('BREAK');break + if not stubber.modules:stubber.modules=[a] + A.collect() +if __name__=='__main__'or k(): + if not i('no_auto_stubber.txt'): + try:A.threshold(4*1024);A.enable() + except BaseException:pass + main() \ No newline at end of file diff --git a/mip/v6/createstubs_db_mpy.mpy b/mip/v6/createstubs_db_mpy.mpy index c1d3ab0c8c833f3d6f9544ed4a1207e82c366b4d..45221f43d3581e06e61248282d2cedde5f6c9e67 100644 GIT binary patch literal 9581 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 E0VEBty8r+H diff --git a/mip/v6/createstubs_mem.py b/mip/v6/createstubs_mem.py index 81164f7d6..124421fd3 100644 --- a/mip/v6/createstubs_mem.py +++ b/mip/v6/createstubs_mem.py @@ -9,12 +9,11 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.2 +This variant was generated from createstubs.py by micropython-stubber v1.16.3 """ # Copyright (c) 2019-2023 Jos Verlinde import gc -import logging import os import sys from time import sleep @@ -34,26 +33,49 @@ except ImportError: from ucollections import OrderedDict # type: ignore -try: - from nope_machine import WDT +__version__ = "v1.16.3" +ENOENT = 2 +_MAX_CLASS_LEVEL = 2 # Max class nesting +LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] - wdt = WDT() -except ImportError: +# our own logging module to avoid dependency on and interfering with logging module +class logging: + # DEBUG = 10 + INFO = 20 + WARNING = 30 + ERROR = 40 + level = INFO + prnt = print - class _WDT: - def feed(self): - pass + @staticmethod + def getLogger(name): + return logging() - wdt = _WDT() + @classmethod + def basicConfig(cls, level): + cls.level = level + # def debug(self, msg): + # if self.level <= logging.DEBUG: + # self.prnt("DEBUG :", msg) -wdt.feed() + def info(self, msg): + if self.level <= logging.INFO: + self.prnt("INFO :", msg) -__version__ = "v1.16.2" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] + def warning(self, msg): + if self.level <= logging.WARNING: + self.prnt("WARN :", msg) + + def error(self, msg): + if self.level <= logging.ERROR: + self.prnt("ERROR :", msg) + + +log = logging.getLogger("stubber") +logging.basicConfig(level=logging.INFO) +# logging.basicConfig(level=logging.DEBUG) class Stubber: @@ -65,13 +87,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self.log = logging.getLogger("stubber") self._report = [] # type: list[str] self.info = _info() - self.log.info("Port: {}".format(self.info["port"])) - self.log.info("Board: {}".format(self.info["board"])) + log.info("Port: {}".format(self.info["port"])) + log.info("Board: {}".format(self.info["board"])) gc.collect() - wdt.feed() if firmware_id: self._fwid = firmware_id.lower() else: @@ -88,11 +108,11 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore path = get_root() self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - self.log.debug(self.path) + # log.debug(self.path) try: ensure_folder(path + "/") except OSError: - self.log.error("error creating stub folder {}".format(path)) + log.error("error creating stub folder {}".format(path)) self.problematic = [ "upip", "upysh", @@ -117,15 +137,15 @@ def get_obj_attributes(self, item_instance: object): # name_, repr_(value), type as text, item_instance _result = [] _errors = [] - self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) + # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): if name.startswith("_") and not name in self.modules: continue - self.log.debug("get attribute {}".format(name)) + # log.debug("get attribute {}".format(name)) try: val = getattr(item_instance, name) # name , item_repr(value) , type as text, item_instance, order - self.log.debug("attribute {}:{}".format(name, val)) + # log.debug("attribute {}:{}".format(name, val)) try: type_text = repr(type(val)).split("'")[1] except IndexError: @@ -158,19 +178,18 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) gc.collect() for module_name in self.modules: self.create_one_stub(module_name) - self.log.info("Finally done") + log.info("Finally done") def create_one_stub(self, module_name: str): - wdt.feed() if module_name in self.problematic: - self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) + log.warning("Skip module: {:<25} : Known problematic".format(module_name)) return False if module_name in self.excluded: - self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) + log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) @@ -205,10 +224,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: new_module = __import__(module_name, None, None, ("*")) m1 = gc.mem_free() # type: ignore - self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) + log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) except ImportError: - self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) + # log.debug("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) return False # Start a new file @@ -228,12 +247,12 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: try: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] - self.log.warning("could not del new_module") + log.warning("could not del new_module") # lets not try - most times it does not work anyway # try: # del sys.modules[module_name] # except KeyError: - # self.log.warning("could not del sys.modules[{}]".format(module_name)) + # log.warning("could not del sys.modules[{}]".format(module_name)) gc.collect() return True @@ -241,14 +260,14 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: - self.log.warning("SKIPPING problematic module:{}".format(object_expr)) + log.warning("SKIPPING problematic module:{}".format(object_expr)) return - # self.log.debug("DUMP : {}".format(object_expr)) + # # log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: - self.log.error(errors) + log.error(errors) for item_name, item_repr, item_type_txt, item_instance, _ in items: # name_, repr_(value), type as text, item_instance, order @@ -256,7 +275,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # do not create stubs for these primitives continue if item_name[0].isdigit(): - self.log.warning("NameError: invalid name {}".format(item_name)) + log.warning("NameError: invalid name {}".format(item_name)) continue # Class expansion only on first 3 levels (bit of a hack) if ( @@ -265,7 +284,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # and not obj_name.endswith(".Pin") # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms ): - self.log.info("{0}class {1}:".format(indent, item_name)) + # log.debug("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = ( item_name.endswith("Exception") @@ -288,7 +307,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, # write classdef fp.write(s) # first write the class literals and methods - self.log.debug("# recursion over class {0}".format(item_name)) + # log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, @@ -302,7 +321,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s += indent + " ...\n\n" fp.write(s) elif any(word in item_type_txt for word in ["method", "function", "closure"]): - self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) + # log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any/Incomplete @@ -318,7 +337,7 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) s += indent + " ...\n\n" fp.write(s) - self.log.debug("\n" + s) + # log.debug("\n" + s) elif item_type_txt == "": # Skip imported modules # fp.write("# import {}\n".format(item_name)) @@ -346,10 +365,10 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = "Incomplete" s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) - self.log.debug("\n" + s) + # log.debug("\n" + s) else: # keep only the name - self.log.debug("# all other, type = '{0}'".format(item_type_txt)) + # log.debug("# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Incomplete\n") @@ -373,10 +392,9 @@ def flat_fwid(self): def clean(self, path: str = None): # type: ignore "Remove all files from the stub folder" - wdt.feed() if path is None: path = self.path - self.log.info("Clean/remove files in folder: {}".format(path)) + log.info("Clean/remove files in folder: {}".format(path)) try: os.stat(path) # TEMP workaround mpremote listdir bug - items = os.listdir(path) @@ -396,10 +414,9 @@ def clean(self, path: str = None): # type: ignore def report(self, filename: str = "modules.json"): "create json with list of exported modules" - wdt.feed() - self.log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) + log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) f_name = "{}/{}".format(self.path, filename) - self.log.info("Report file: {}".format(f_name)) + log.info("Report file: {}".format(f_name)) gc.collect() try: # write json by node to reduce memory requirements @@ -411,9 +428,9 @@ def report(self, filename: str = "modules.json"): first = False self.write_json_end(f) used = self._start_free - gc.mem_free() # type: ignore - self.log.info("Memory used: {0} Kb".format(used // 1024)) + # log.debug("Memory used: {0} Kb".format(used // 1024)) except OSError: - self.log.error("Failed to create the report.") + log.error("Failed to create the report.") def write_json_header(self, f): f.write("{") @@ -511,9 +528,7 @@ def _info(): # type:() -> dict[str, str] ) except (AttributeError, IndexError): pass - gc.collect() - read_boardname(info) - gc.collect() + info["board"] = get_boardname() try: if "uname" in dir(os): # old @@ -601,79 +616,16 @@ def version_str(version: tuple): # -> str: return v_str -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False +def get_boardname() -> str: + "Read the board name from the boardname.py file that may have been created upfront" + try: + from boardname import BOARDNAME # type: ignore + + log.info("Found BOARDNAME: {}".format(BOARDNAME)) + except ImportError: + log.warning("BOARDNAME not found") + BOARDNAME = "" + return BOARDNAME def get_root() -> str: # sourcery skip: use-assigned-variable @@ -751,26 +703,33 @@ def main(): stubber.clean() # Read stubs from modulelist in the current folder or in /libs # fall back to default modules - stubber.modules = [] # avoid duplicates - for p in LIBS: - try: - _1 = gc.mem_free() # type: ignore - with open(p + "/modulelist.txt") as f: - print("Debug: List of modules: " + p + "/modulelist.txt") - line = f.readline() - while line: - line = line.strip() + def get_modulelist(stubber): + # new + gc.collect() + stubber.modules = [] # avoid duplicates + for p in LIBS: + fname = p + "/modulelist.txt" + if not file_exists(fname): + continue + with open(fname) as f: + # print("DEBUG: list of modules: " + p + "/modulelist.txt") + while True: + line = f.readline().strip() + if not line: + break if len(line) > 0 and line[0] != "#": stubber.modules.append(line) - line = f.readline() - gc.collect() # type: ignore - print("Debug: Used memory to load modulelist.txt: " + str(_1 - gc.mem_free()) + " bytes") # type: ignore + gc.collect() + print("BREAK") break - except Exception: - pass - if not stubber.modules: - stubber.modules = ["micropython"] - print("Could not find modulelist.txt, using default modules") + + if not stubber.modules: + stubber.modules = ["micropython"] + # _log.warn("Could not find modulelist.txt, using default modules") + gc.collect() + + stubber.modules = [] # avoid duplicates + get_modulelist(stubber) gc.collect() @@ -779,12 +738,6 @@ def main(): if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass if not file_exists("no_auto_stubber.txt"): try: gc.threshold(4 * 1024) # type: ignore diff --git a/mip/v6/createstubs_mem_min.py b/mip/v6/createstubs_mem_min.py index d610d52be..415b4e5bd 100644 --- a/mip/v6/createstubs_mem_min.py +++ b/mip/v6/createstubs_mem_min.py @@ -1,794 +1,293 @@ -"""Create stubs for (all) modules on a MicroPython board. - - This variant of the createstubs.py script is optimised for use on low-memory devices, and reads the list of modules from a text file - `modulelist.txt` in the root or `libs` folder that should be uploaded to the device. - If that cannot be found then only a single module (micropython) is stubbed. - In order to run this on low-memory devices two additional steps are recommended: - - minifification, using python-minifier - to reduce overall size, and remove logging overhead. - - cross compilation, using mpy-cross, - to avoid the compilation step on the micropython device - -This variant was generated from createstubs.py by micropython-stubber v1.16.2 -""" -# Copyright (c) 2019-2023 Jos Verlinde - -import gc -# import logging -import os -import sys +v='{}/{}' +u='method' +t='function' +s='bool' +r='str' +q='float' +p='int' +o='stubber' +n=TypeError +m=KeyError +l=sorted +k=NotImplementedError +e=',\n' +d='dict' +c='list' +b='tuple' +a='_' +Z='micropython' +Y=open +X=repr +V='-preview' +U='-' +T='board' +S=IndexError +R=print +Q=True +P='family' +O=ImportError +N=len +M=dir +K='port' +J='.' +I=False +H=AttributeError +G='/' +F=None +E=OSError +C='version' +B='' +import gc as D,os,sys from time import sleep - -try: - from ujson import dumps -except: - from json import dumps - -try: - from machine import reset # type: ignore -except ImportError: - pass - -try: - from collections import OrderedDict -except ImportError: - from ucollections import OrderedDict # type: ignore - -try: - from nope_machine import WDT - - wdt = WDT() - -except ImportError: - - class _WDT: - def feed(self): - pass - - wdt = _WDT() - - -wdt.feed() - -__version__ = "v1.16.2" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] - - +try:from ujson import dumps +except:from json import dumps +try:from machine import reset +except O:pass +try:from collections import OrderedDict as f +except O:from ucollections import OrderedDict as f +__version__='v1.16.3' +w=2 +x=2 +y=['lib','/lib','/sd/lib','/flash/lib',J] +class L: + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=R + @staticmethod + def getLogger(name):return L() + @classmethod + def basicConfig(A,level):A.level=level + def info(A,msg): + if A.level<=L.INFO:A.prnt('INFO :',msg) + def warning(A,msg): + if A.level<=L.WARNING:A.prnt('WARN :',msg) + def error(A,msg): + if A.level<=L.ERROR:A.prnt('ERROR :',msg) +A=L.getLogger(o) +L.basicConfig(level=L.INFO) class Stubber: - "Generate stubs for modules in firmware" - - def __init__(self, path: str = None, firmware_id: str = None): # type: ignore - try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore - raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") - except AttributeError: - pass - # self.log = logging.getLogger("stubber") - self._report = [] # type: list[str] - self.info = _info() - # self.log.info("Port: {}".format(self.info["port"])) - # self.log.info("Board: {}".format(self.info["board"])) - gc.collect() - wdt.feed() - if firmware_id: - self._fwid = firmware_id.lower() - else: - if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") - else: - self._fwid = "{family}-v{version}-{port}".format(**self.info) - self._start_free = gc.mem_free() # type: ignore - - if path: - if path.endswith("/"): - path = path[:-1] - else: - path = get_root() - - self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - # self.log.debug(self.path) - try: - ensure_folder(path + "/") - except OSError: - print("error creating stub folder {}".format(path)) - self.problematic = [ - "upip", - "upysh", - "webrepl_setup", - "http_client", - "http_client_ssl", - "http_server", - "http_server_ssl", - ] - self.excluded = [ - "webrepl", - "_webrepl", - "port_diag", - "example_sub_led.py", - "example_pub_button.py", - ] - # there is no option to discover modules from micropython, list is read from an external file. - self.modules = [] # type: list[str] - - def get_obj_attributes(self, item_instance: object): - "extract information of the objects members and attributes" - # name_, repr_(value), type as text, item_instance - _result = [] - _errors = [] - # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) - for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: - continue - # self.log.debug("get attribute {}".format(name)) - try: - val = getattr(item_instance, name) - # name , item_repr(value) , type as text, item_instance, order - # self.log.debug("attribute {}:{}".format(name, val)) - try: - type_text = repr(type(val)).split("'")[1] - except IndexError: - type_text = "" - if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: - order = 1 - elif type_text in {"function", "method"}: - order = 2 - elif type_text in ("class"): - order = 3 - else: - order = 4 - _result.append((name, repr(val), repr(type(val)), val, order)) - except AttributeError as e: - _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) - except MemoryError as e: - # print("MemoryError: {}".format(e)) - sleep(1) - reset() - - # remove internal __ - # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) - _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) - gc.collect() - return _result, _errors - - def add_modules(self, modules): - "Add additional modules to be exported" - self.modules = sorted(set(self.modules) | set(modules)) - - def create_all_stubs(self): - "Create stubs for all configured modules" - # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) - gc.collect() - for module_name in self.modules: - self.create_one_stub(module_name) - # self.log.info("Finally done") - - def create_one_stub(self, module_name: str): - wdt.feed() - if module_name in self.problematic: - # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) - return False - if module_name in self.excluded: - # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) - return False - - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) - gc.collect() - result = False - try: - result = self.create_module_stub(module_name, file_name) - except OSError: - return False - gc.collect() - return result - - def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore - """Create a Stub of a single python module - - Args: - - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. - """ - if file_name is None: - fname = module_name.replace(".", "_") + ".py" - file_name = self.path + "/" + fname - else: - fname = file_name.split("/")[-1] - - if "/" in module_name: - # for nested modules - module_name = module_name.replace("/", ".") - - # import the module (as new_module) to examine it - new_module = None - try: - new_module = __import__(module_name, None, None, ("*")) - m1 = gc.mem_free() # type: ignore - # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) - - except ImportError: - # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) - return False - - # Start a new file - ensure_folder(file_name) - with open(file_name, "w") as fp: - # todo: improve header - info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") - s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) - fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") - self.write_object_stub(fp, new_module, module_name, "") - - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) - - if module_name not in {"os", "sys", "logging", "gc"}: - # try to unload the module unless we use it - try: - del new_module - except (OSError, KeyError): # lgtm [py/unreachable-statement] - pass - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - pass - gc.collect() - return True - - def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): - "Write a module/object stub to an open file. Can be called recursive." - gc.collect() - if object_expr in self.problematic: - # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) - return - - # # self.log.debug("DUMP : {}".format(object_expr)) - items, errors = self.get_obj_attributes(object_expr) - - if errors: - print(errors) - - for item_name, item_repr, item_type_txt, item_instance, _ in items: - # name_, repr_(value), type as text, item_instance, order - if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: - # do not create stubs for these primitives - continue - if item_name[0].isdigit(): - # self.log.warning("NameError: invalid name {}".format(item_name)) - continue - # Class expansion only on first 3 levels (bit of a hack) - if ( - item_type_txt == "" - and len(indent) <= _MAX_CLASS_LEVEL * 4 - # and not obj_name.endswith(".Pin") - # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms - ): - # self.log.info("{0}class {1}:".format(indent, item_name)) - superclass = "" - is_exception = ( - item_name.endswith("Exception") - or item_name.endswith("Error") - or item_name - in [ - "KeyboardInterrupt", - "StopIteration", - "SystemExit", - ] - ) - if is_exception: - superclass = "Exception" - s = "\n{}class {}({}):\n".format(indent, item_name, superclass) - # s += indent + " ''\n" - if is_exception: - s += indent + " ...\n" - fp.write(s) - continue - # write classdef - fp.write(s) - # first write the class literals and methods - # self.log.debug("# recursion over class {0}".format(item_name)) - self.write_object_stub( - fp, - item_instance, - "{0}.{1}".format(obj_name, item_name), - indent + " ", - in_class + 1, - ) - # end with the __init__ method to make sure that the literals are defined - # Add __init__ - s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" - s += indent + " ...\n\n" - fp.write(s) - elif any(word in item_type_txt for word in ["method", "function", "closure"]): - # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) - # module Function or class method - # will accept any number of params - # return type Any/Incomplete - ret = "Incomplete" - first = "" - # Self parameter only on class methods/functions - if in_class > 0: - first = "self, " - # class method - add function decoration - if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret) - else: - s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) - s += indent + " ...\n\n" - fp.write(s) - # self.log.debug("\n" + s) - elif item_type_txt == "": - # Skip imported modules - # fp.write("# import {}\n".format(item_name)) - pass - - elif item_type_txt.startswith(" dict[str, str] - info = OrderedDict( - { - "family": sys.implementation.name, - "version": "", - "build": "", - "ver": "", - "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "UNKNOWN", - "cpu": "", - "mpy": "", - "arch": "", - } - ) - # change port names to be consistent with the repo - if info["port"].startswith("pyb"): - info["port"] = "stm32" - elif info["port"] == "win32": - info["port"] = "windows" - elif info["port"] == "linux": - info["port"] = "unix" - try: - info["version"] = version_str(sys.implementation.version) # type: ignore - except AttributeError: - pass - try: - _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - # info["board"] = "with".join(_machine.split("with")[:-1]).strip() - info["board"] = _machine - info["cpu"] = _machine.split("with")[-1].strip() - info["mpy"] = ( - sys.implementation._mpy - if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy - if "mpy" in dir(sys.implementation) - else "" - ) - except (AttributeError, IndexError): - pass - gc.collect() - read_boardname(info) - gc.collect() - - try: - if "uname" in dir(os): # old - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - elif "version" in dir(sys): # new - # extract build from sys.version if available - info["build"] = _build(sys.version) - except (AttributeError, IndexError, TypeError): - pass - # avoid build hashes - # if info["build"] and len(info["build"]) > 5: - # info["build"] = "" - - if info["version"] == "" and sys.platform not in ("unix", "win32"): - try: - u = os.uname() # type: ignore - info["version"] = u.release - except (IndexError, AttributeError, TypeError): - pass - # detect families - for fam_name, mod_name, mod_thing in [ - ("pycopy", "pycopy", "const"), - ("pycom", "pycom", "FAT"), - ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), - ]: - try: - _t = __import__(mod_name, None, None, (mod_thing)) - info["family"] = fam_name - del _t - break - except (ImportError, KeyError): - pass - - if info["family"] == "ev3-pybricks": - info["release"] = "2.0.0" - - if info["family"] == "micropython": - info["version"] - if ( - info["version"] - and info["version"].endswith(".0") - and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 - and info["version"] <= "1.19.9" - ): - # versions from 1.10.0 to 1.20.0 do not have a micro .0 - info["version"] = info["version"][:-2] - - # spell-checker: disable - if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds - sys_mpy = int(info["mpy"]) - # .mpy architecture - arch = [ - None, - "x86", - "x64", - "armv6", - "armv6m", - "armv7m", - "armv7em", - "armv7emsp", - "armv7emdp", - "xtensa", - "xtensawin", - ][sys_mpy >> 10] - if arch: - info["arch"] = arch - # .mpy version.minor - info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) - if info["build"] and not info["version"].endswith("-preview"): - info["version"] = info["version"] + "-preview" - # simple to use version[-build] string - info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" - - return info - - -def version_str(version: tuple): # -> str: - v_str = ".".join([str(n) for n in version[:3]]) - if len(version) > 3 and version[3]: - v_str += "-" + version[3] - return v_str - - -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - # print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# # print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False - - -def get_root() -> str: # sourcery skip: use-assigned-variable - "Determine the root folder of the device" - try: - c = os.getcwd() - except (OSError, AttributeError): - # unix port - c = "." - r = c - for r in [c, "/sd", "/flash", "/", "."]: - try: - _ = os.stat(r) - break - except OSError: - continue - return r - - -def file_exists(filename: str): - try: - if os.stat(filename)[0] >> 14: - return True - return False - except OSError: - return False - - -def show_help(): - # print("-p, --path path to store the stubs in, defaults to '.'") - sys.exit(1) - - -def read_path() -> str: - "get --path from cmdline. [unix/win]" - path = "" - if len(sys.argv) == 3: - cmd = (sys.argv[1]).lower() - if cmd in ("--path", "-p"): - path = sys.argv[2] - else: - show_help() - elif len(sys.argv) == 2: - show_help() - return path - - -def is_micropython() -> bool: - "runtime test to determine full or micropython" - # pylint: disable=unused-variable,eval-used - try: - # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects - - # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented - # Micropython: NotImplementedError - b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] - - # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute - # Micropython: AttributeError - c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] - return False - except (NotImplementedError, AttributeError): - return True - - + def __init__(B,path=F,firmware_id=F): + C=firmware_id + try: + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + except H:pass + B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[T]));D.collect() + if C:B._fwid=C.lower() + elif B.info[P]==Z:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(U) + else:B._fwid='{family}-v{version}-{port}'.format(**B.info) + B._start_free=D.mem_free() + if path: + if path.endswith(G):path=path[:-1] + else:path=get_root() + B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) + try:g(path+G) + except E:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[] + def get_obj_attributes(L,item_instance): + I=item_instance;C=[];K=[] + for A in M(I): + if A.startswith(a)and not A in L.modules:continue + try: + E=getattr(I,A) + try:F=X(type(E)).split("'")[1] + except S:F=B + if F in{p,q,r,s,b,c,d}:G=1 + elif F in{t,u}:G=2 + elif F in'class':G=3 + else:G=4 + C.append((A,X(E),X(type(E)),E,G)) + except H as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,J)) + except MemoryError as J:R('MemoryError: {}'.format(J));sleep(1);reset() + C=l([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,K + def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) + def create_all_stubs(B): + A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));D.collect() + for C in B.modules:B.create_one_stub(C) + A.info('Finally done') + def create_one_stub(C,module_name): + B=module_name + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return I + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return I + H='{}/{}.py'.format(C.path,B.replace(J,G));D.collect();F=I + try:F=C.create_module_stub(B,H) + except E:return I + D.collect();return F + def create_module_stub(K,module_name,file_name=F): + H=file_name;C=module_name + if H is F:L=C.replace(J,a)+'.py';H=K.path+G+L + else:L=H.split(G)[-1] + if G in C:C=C.replace(G,J) + M=F + try:M=__import__(C,F,F,'*');P=D.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) + except O:return I + g(H) + with Y(H,'w')as N:R=str(K.info).replace('OrderedDict(',B).replace('})','}');S='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,R,__version__);N.write(S);N.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,M,C,B) + K._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + if C not in{'os','sys','logging','gc'}: + try:del M + except(E,m):A.warning('could not del new_module') + D.collect();return Q + def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';O=in_class;M='Exception';L=object_expr;I=fp;E=indent;D.collect() + if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return + X,P=K.get_obj_attributes(L) + if P:A.error(P) + for(F,J,G,Y,a)in X: + if F in['classmethod','staticmethod','BaseException',M]:continue + if F[0].isdigit():A.warning('NameError: invalid name {}'.format(F));continue + if G==""and N(E)<=x*4: + Q=B;R=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] + if R:Q=M + C='\n{}class {}({}):\n'.format(E,F,Q) + if R:C+=E+' ...\n';I.write(C);continue + I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',O+1);C=E+' def __init__(self, *argv, **kwargs) -> None:\n';C+=E+' ...\n\n';I.write(C) + elif any(A in G for A in[u,t,'closure']): + S=U;T=B + if O>0:T='self, ' + if V in G or V in J:C='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) + else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,T,S) + C+=E+' ...\n\n';I.write(C) + elif G=="":0 + elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if E in A and A[E]: + G=int(A[E]);J=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[Q]=J + A[E]='v{}.{}'.format(G&255,G>>8&3) + if A[D]and not A[C].endswith(V):A[C]=A[C]+V + A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A +def z(version): + A=version;B=J.join([str(A)for A in A[:3]]) + if N(A)>3 and A[3]:B+=U+A[3] + return B +def A0(): + try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) + except O:A.warning('BOARDNAME not found');C=B + return C +def get_root(): + try:A=os.getcwd() + except(E,H):A=J + B=A + for B in[A,'/sd','/flash',G,J]: + try:C=os.stat(B);break + except E:continue + return B +def h(filename): + try: + if os.stat(filename)[0]>>14:return Q + return I + except E:return I +def i():R("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) +def read_path(): + path=B + if N(sys.argv)==3: + A=sys.argv[1].lower() + if A in('--path','-p'):path=sys.argv[2] + else:i() + elif N(sys.argv)==2:i() + return path +def j(): + try:A=bytes('abc',encoding='utf8');B=j.__module__;return I + except(k,H):return Q def main(): - stubber = Stubber(path=read_path()) - # stubber = Stubber(path="/sd") - # Option: Specify a firmware name & version - # stubber = Stubber(firmware_id='HoverBot v1.2.1') - stubber.clean() - # Read stubs from modulelist in the current folder or in /libs - # fall back to default modules - stubber.modules = [] # avoid duplicates - for p in LIBS: - try: - _1 = gc.mem_free() # type: ignore - with open(p + "/modulelist.txt") as f: - print ("Debug: List of modules: " + p + "/modulelist.txt") - line = f.readline() - while line: - line = line.strip() - if len(line) > 0 and line[0] != "#": - stubber.modules.append(line) - line = f.readline() - gc.collect() # type: ignore - print ("Debug: Used memory to load modulelist.txt: " + str(_1 - gc.mem_free()) + " bytes") # type: ignore - break - except Exception: - pass - if not stubber.modules: - stubber.modules = ["micropython"] - # print("Could not find modulelist.txt, using default modules") - - gc.collect() - - stubber.create_all_stubs() - stubber.report() - - -if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass - if not file_exists("no_auto_stubber.txt"): - try: - gc.threshold(4 * 1024) # type: ignore - gc.enable() - except BaseException: - pass - main() + stubber=Stubber(path=read_path());stubber.clean() + def A(stubber): + D.collect();stubber.modules=[] + for C in y: + B=C+'/modulelist.txt' + if not h(B):continue + with Y(B)as E: + while Q: + A=E.readline().strip() + if not A:break + if N(A)>0 and A[0]!='#':stubber.modules.append(A) + D.collect();R('BREAK');break + if not stubber.modules:stubber.modules=[Z] + D.collect() + stubber.modules=[];A(stubber);D.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or j(): + if not h('no_auto_stubber.txt'): + try:D.threshold(4*1024);D.enable() + except BaseException:pass + main() \ No newline at end of file diff --git a/mip/v6/createstubs_mem_mpy.mpy b/mip/v6/createstubs_mem_mpy.mpy index 520ab82c725f16ef691a08deb58fcb941ca24afd..430edcd3681b41267ac4389a2508d35b6a3adf57 100644 GIT binary patch literal 8928 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 Vn?C6pJJd`!Kwsz+5PZUk{|6%0COiND diff --git a/mip/v6/createstubs_min.py b/mip/v6/createstubs_min.py index 7b134cbf9..0fcb07093 100644 --- a/mip/v6/createstubs_min.py +++ b/mip/v6/createstubs_min.py @@ -1,1011 +1,281 @@ -""" -Create stubs for (all) modules on a MicroPython board -""" -# Copyright (c) 2019-2023 Jos Verlinde - -import gc -# import logging -import os -import sys +x='pyb' +w='{}/{}' +v='logging' +u='sys' +t='method' +s='function' +r='bool' +q='str' +p='float' +o='int' +n='stubber' +m=TypeError +l=KeyError +k=sorted +j=NotImplementedError +e='pycom' +d=',\n' +c='dict' +b='list' +a='tuple' +Z='_' +Y='micropython' +X=repr +W=print +U='-preview' +T=True +S='-' +R='board' +Q=IndexError +P='family' +O=len +N=ImportError +M=dir +K='port' +J='.' +I=False +H=AttributeError +G='/' +E=None +D=OSError +C='version' +B='' +import gc as F,os,sys from time import sleep - -try: - from ujson import dumps -except: - from json import dumps - -try: - from machine import reset # type: ignore -except ImportError: - pass - -try: - from collections import OrderedDict -except ImportError: - from ucollections import OrderedDict # type: ignore - -try: - from nope_machine import WDT - - wdt = WDT() - -except ImportError: - - class _WDT: - def feed(self): - pass - - wdt = _WDT() - - -wdt.feed() - -__version__ = "v1.16.2" -ENOENT = 2 -_MAX_CLASS_LEVEL = 2 # Max class nesting -LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"] - - +try:from ujson import dumps +except:from json import dumps +try:from machine import reset +except N:pass +try:from collections import OrderedDict as f +except N:from ucollections import OrderedDict as f +__version__='v1.16.3' +y=2 +z=2 +A3=['lib','/lib','/sd/lib','/flash/lib',J] +class L: + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=W + @staticmethod + def getLogger(name):return L() + @classmethod + def basicConfig(A,level):A.level=level + def info(A,msg): + if A.level<=L.INFO:A.prnt('INFO :',msg) + def warning(A,msg): + if A.level<=L.WARNING:A.prnt('WARN :',msg) + def error(A,msg): + if A.level<=L.ERROR:A.prnt('ERROR :',msg) +A=L.getLogger(n) +L.basicConfig(level=L.INFO) class Stubber: - "Generate stubs for modules in firmware" - - def __init__(self, path: str = None, firmware_id: str = None): # type: ignore - try: - if os.uname().release == "1.13.0" and os.uname().version < "v1.13-103": # type: ignore - raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") - except AttributeError: - pass - # self.log = logging.getLogger("stubber") - self._report = [] # type: list[str] - self.info = _info() - # self.log.info("Port: {}".format(self.info["port"])) - # self.log.info("Board: {}".format(self.info["board"])) - gc.collect() - wdt.feed() - if firmware_id: - self._fwid = firmware_id.lower() - else: - if self.info["family"] == "micropython": - self._fwid = "{family}-v{version}-{port}-{board}".format(**self.info).rstrip("-") - else: - self._fwid = "{family}-v{version}-{port}".format(**self.info) - self._start_free = gc.mem_free() # type: ignore - - if path: - if path.endswith("/"): - path = path[:-1] - else: - path = get_root() - - self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/") - # self.log.debug(self.path) - try: - ensure_folder(path + "/") - except OSError: - print("error creating stub folder {}".format(path)) - self.problematic = [ - "upip", - "upysh", - "webrepl_setup", - "http_client", - "http_client_ssl", - "http_server", - "http_server_ssl", - ] - self.excluded = [ - "webrepl", - "_webrepl", - "port_diag", - "example_sub_led.py", - "example_pub_button.py", - ] - # there is no option to discover modules from micropython, list is read from an external file. - self.modules = [] # type: list[str] - - def get_obj_attributes(self, item_instance: object): - "extract information of the objects members and attributes" - # name_, repr_(value), type as text, item_instance - _result = [] - _errors = [] - # self.log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) - for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: - continue - # self.log.debug("get attribute {}".format(name)) - try: - val = getattr(item_instance, name) - # name , item_repr(value) , type as text, item_instance, order - # self.log.debug("attribute {}:{}".format(name, val)) - try: - type_text = repr(type(val)).split("'")[1] - except IndexError: - type_text = "" - if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}: - order = 1 - elif type_text in {"function", "method"}: - order = 2 - elif type_text in ("class"): - order = 3 - else: - order = 4 - _result.append((name, repr(val), repr(type(val)), val, order)) - except AttributeError as e: - _errors.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(name, item_instance, e)) - except MemoryError as e: - # print("MemoryError: {}".format(e)) - sleep(1) - reset() - - # remove internal __ - # _result = sorted([i for i in _result if not (i[0].startswith("_"))], key=lambda x: x[4]) - _result = sorted([i for i in _result if not (i[0].startswith("__"))], key=lambda x: x[4]) - gc.collect() - return _result, _errors - - def add_modules(self, modules): - "Add additional modules to be exported" - self.modules = sorted(set(self.modules) | set(modules)) - - def create_all_stubs(self): - "Create stubs for all configured modules" - # self.log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) - gc.collect() - for module_name in self.modules: - self.create_one_stub(module_name) - # self.log.info("Finally done") - - def create_one_stub(self, module_name: str): - wdt.feed() - if module_name in self.problematic: - # self.log.warning("Skip module: {:<25} : Known problematic".format(module_name)) - return False - if module_name in self.excluded: - # self.log.warning("Skip module: {:<25} : Excluded".format(module_name)) - return False - - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) - gc.collect() - result = False - try: - result = self.create_module_stub(module_name, file_name) - except OSError: - return False - gc.collect() - return result - - def create_module_stub(self, module_name: str, file_name: str = None) -> bool: # type: ignore - """Create a Stub of a single python module - - Args: - - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. - """ - if file_name is None: - fname = module_name.replace(".", "_") + ".py" - file_name = self.path + "/" + fname - else: - fname = file_name.split("/")[-1] - - if "/" in module_name: - # for nested modules - module_name = module_name.replace("/", ".") - - # import the module (as new_module) to examine it - new_module = None - try: - new_module = __import__(module_name, None, None, ("*")) - m1 = gc.mem_free() # type: ignore - # self.log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1)) - - except ImportError: - # self.log.warning("Skip module: {:<25} {:<79}".format(module_name, "Module not found.")) - return False - - # Start a new file - ensure_folder(file_name) - with open(file_name, "w") as fp: - # todo: improve header - info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") - s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format( - module_name, self._fwid, info_, __version__ - ) - fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") - self.write_object_stub(fp, new_module, module_name, "") - - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) - - if module_name not in {"os", "sys", "logging", "gc"}: - # try to unload the module unless we use it - try: - del new_module - except (OSError, KeyError): # lgtm [py/unreachable-statement] - pass - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - pass - gc.collect() - return True - - def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): - "Write a module/object stub to an open file. Can be called recursive." - gc.collect() - if object_expr in self.problematic: - # self.log.warning("SKIPPING problematic module:{}".format(object_expr)) - return - - # # self.log.debug("DUMP : {}".format(object_expr)) - items, errors = self.get_obj_attributes(object_expr) - - if errors: - print(errors) - - for item_name, item_repr, item_type_txt, item_instance, _ in items: - # name_, repr_(value), type as text, item_instance, order - if item_name in ["classmethod", "staticmethod", "BaseException", "Exception"]: - # do not create stubs for these primitives - continue - if item_name[0].isdigit(): - # self.log.warning("NameError: invalid name {}".format(item_name)) - continue - # Class expansion only on first 3 levels (bit of a hack) - if ( - item_type_txt == "" - and len(indent) <= _MAX_CLASS_LEVEL * 4 - # and not obj_name.endswith(".Pin") - # avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms - ): - # self.log.info("{0}class {1}:".format(indent, item_name)) - superclass = "" - is_exception = ( - item_name.endswith("Exception") - or item_name.endswith("Error") - or item_name - in [ - "KeyboardInterrupt", - "StopIteration", - "SystemExit", - ] - ) - if is_exception: - superclass = "Exception" - s = "\n{}class {}({}):\n".format(indent, item_name, superclass) - # s += indent + " ''\n" - if is_exception: - s += indent + " ...\n" - fp.write(s) - continue - # write classdef - fp.write(s) - # first write the class literals and methods - # self.log.debug("# recursion over class {0}".format(item_name)) - self.write_object_stub( - fp, - item_instance, - "{0}.{1}".format(obj_name, item_name), - indent + " ", - in_class + 1, - ) - # end with the __init__ method to make sure that the literals are defined - # Add __init__ - s = indent + " def __init__(self, *argv, **kwargs) -> None:\n" - s += indent + " ...\n\n" - fp.write(s) - elif any(word in item_type_txt for word in ["method", "function", "closure"]): - # self.log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name)) - # module Function or class method - # will accept any number of params - # return type Any/Incomplete - ret = "Incomplete" - first = "" - # Self parameter only on class methods/functions - if in_class > 0: - first = "self, " - # class method - add function decoration - if "bound_method" in item_type_txt or "bound_method" in item_repr: - s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format( - indent, item_name, ret - ) - else: - s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret) - s += indent + " ...\n\n" - fp.write(s) - # self.log.debug("\n" + s) - elif item_type_txt == "": - # Skip imported modules - # fp.write("# import {}\n".format(item_name)) - pass - - elif item_type_txt.startswith(" dict[str, str] - info = OrderedDict( - { - "family": sys.implementation.name, - "version": "", - "build": "", - "ver": "", - "port": sys.platform, # port: esp32 / win32 / linux / stm32 - "board": "UNKNOWN", - "cpu": "", - "mpy": "", - "arch": "", - } - ) - # change port names to be consistent with the repo - if info["port"].startswith("pyb"): - info["port"] = "stm32" - elif info["port"] == "win32": - info["port"] = "windows" - elif info["port"] == "linux": - info["port"] = "unix" - try: - info["version"] = version_str(sys.implementation.version) # type: ignore - except AttributeError: - pass - try: - _machine = ( - sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore - ) - # info["board"] = "with".join(_machine.split("with")[:-1]).strip() - info["board"] = _machine - info["cpu"] = _machine.split("with")[-1].strip() - info["mpy"] = ( - sys.implementation._mpy - if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy - if "mpy" in dir(sys.implementation) - else "" - ) - except (AttributeError, IndexError): - pass - gc.collect() - read_boardname(info) - gc.collect() - - try: - if "uname" in dir(os): # old - # extract build from uname().version if available - info["build"] = _build(os.uname()[3]) # type: ignore - if not info["build"]: - # extract build from uname().release if available - info["build"] = _build(os.uname()[2]) # type: ignore - elif "version" in dir(sys): # new - # extract build from sys.version if available - info["build"] = _build(sys.version) - except (AttributeError, IndexError, TypeError): - pass - # avoid build hashes - # if info["build"] and len(info["build"]) > 5: - # info["build"] = "" - - if info["version"] == "" and sys.platform not in ("unix", "win32"): - try: - u = os.uname() # type: ignore - info["version"] = u.release - except (IndexError, AttributeError, TypeError): - pass - # detect families - for fam_name, mod_name, mod_thing in [ - ("pycopy", "pycopy", "const"), - ("pycom", "pycom", "FAT"), - ("ev3-pybricks", "pybricks.hubs", "EV3Brick"), - ]: - try: - _t = __import__(mod_name, None, None, (mod_thing)) - info["family"] = fam_name - del _t - break - except (ImportError, KeyError): - pass - - if info["family"] == "ev3-pybricks": - info["release"] = "2.0.0" - - if info["family"] == "micropython": - info["version"] - if ( - info["version"] - and info["version"].endswith(".0") - and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0 - and info["version"] <= "1.19.9" - ): - # versions from 1.10.0 to 1.20.0 do not have a micro .0 - info["version"] = info["version"][:-2] - - # spell-checker: disable - if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds - sys_mpy = int(info["mpy"]) - # .mpy architecture - arch = [ - None, - "x86", - "x64", - "armv6", - "armv6m", - "armv7m", - "armv7em", - "armv7emsp", - "armv7emdp", - "xtensa", - "xtensawin", - ][sys_mpy >> 10] - if arch: - info["arch"] = arch - # .mpy version.minor - info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3) - if info["build"] and not info["version"].endswith("-preview"): - info["version"] = info["version"] + "-preview" - # simple to use version[-build] string - info["ver"] = f"{info['version']}-{info['build']}" if info["build"] else f"{info['version']}" - - return info - - -def version_str(version: tuple): # -> str: - v_str = ".".join([str(n) for n in version[:3]]) - if len(version) > 3 and version[3]: - v_str += "-" + version[3] - return v_str - - -def read_boardname(info, desc: str = ""): - info["board"] = info["board"].replace(" ", "_") - found = False - for filename in [d + "/board_name.txt" for d in LIBS]: - wdt.feed() - # # print("look up the board name in the file", filename) - if file_exists(filename): - with open(filename, "r") as file: - data = file.read() - if data: - info["board"] = data.strip() - found = True - break - if not found: - # print("Board not found, guessing board name") - descr = "" - # descr = desc or info["board"].strip() - # if "with " + info["cpu"].upper() in descr: - # # remove the with cpu part - # descr = descr.split("with " + info["cpu"].upper())[0].strip() - info["board"] = descr - - -# def read_boardname(info, desc: str = ""): -# wdt.feed() -# # # print("look up the board name in the file", filename) -# if file_exists(filename): -# descr = desc or info["board"].strip() -# pos = descr.rfind(" with") -# if pos != -1: -# short_descr = descr[:pos].strip() -# else: -# short_descr = "" -# # print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr)) -# if find_board(info, descr, filename, short_descr): -# found = True -# break -# if not found: -# # print("Board not found, guessing board name") -# descr = desc or info["board"].strip() -# if "with " + info["cpu"].upper() in descr: -# # remove the with cpu part -# descr = descr.split("with " + info["cpu"].upper())[0].strip() -# info["board"] = descr -# info["board"] = info["board"].replace(" ", "_") -# gc.collect() - - -# def find_board(info: dict, descr: str, filename: str, short_descr: str): -# "Find the board in the provided board_info.csv file" -# short_hit = "" -# with open(filename, "r") as file: -# # ugly code to make testable in python and micropython -# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file) -# while 1: -# line = file.readline() -# if not line: -# break -# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip() -# if descr_ == descr: -# info["board"] = board_ -# return True -# elif short_descr and descr_ == short_descr: -# if "with" in short_descr: -# # Good enough - no need to trawl the entire file -# info["board"] = board_ -# return True -# # good enough if not found in the rest of the file (but slow) -# short_hit = board_ -# if short_hit: -# info["board"] = short_hit -# return True -# return False - - -def get_root() -> str: # sourcery skip: use-assigned-variable - "Determine the root folder of the device" - try: - c = os.getcwd() - except (OSError, AttributeError): - # unix port - c = "." - r = c - for r in [c, "/sd", "/flash", "/", "."]: - try: - _ = os.stat(r) - break - except OSError: - continue - return r - - -def file_exists(filename: str): - try: - if os.stat(filename)[0] >> 14: - return True - return False - except OSError: - return False - - -def show_help(): - # print("-p, --path path to store the stubs in, defaults to '.'") - sys.exit(1) - - -def read_path() -> str: - "get --path from cmdline. [unix/win]" - path = "" - if len(sys.argv) == 3: - cmd = (sys.argv[1]).lower() - if cmd in ("--path", "-p"): - path = sys.argv[2] - else: - show_help() - elif len(sys.argv) == 2: - show_help() - return path - - -def is_micropython() -> bool: - "runtime test to determine full or micropython" - # pylint: disable=unused-variable,eval-used - try: - # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects - - # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented - # Micropython: NotImplementedError - b = bytes("abc", encoding="utf8") # type: ignore # lgtm [py/unused-local-variable] - - # c) https://docs.micropython.org/en/latest/genrst/core_language.html#function-objects-do-not-have-the-module-attribute - # Micropython: AttributeError - c = is_micropython.__module__ # type: ignore # lgtm [py/unused-local-variable] - return False - except (NotImplementedError, AttributeError): - return True - - -def main(): - stubber = Stubber(path=read_path()) - # stubber = Stubber(path="/sd") - # Option: Specify a firmware name & version - # stubber = Stubber(firmware_id='HoverBot v1.2.1') - stubber.clean() - # there is no option to discover modules from micropython, need to hardcode - # below contains combined modules from Micropython ESP8622, ESP32, Loboris, Pycom and ulab , lvgl - # spell-checker: disable - # modules to stub : 131 - stubber.modules = [ - "WM8960", - "_OTA", - "_asyncio", - "_boot_fat", - "_coap", - "_espnow", - "_flash_control_OTA", - "_main_pybytes", - "_mqtt", - "_mqtt_core", - "_msg_handl", - "_onewire", - "_periodical_pin", - "_pybytes", - "_pybytes_ca", - "_pybytes_config", - "_pybytes_config_reader", - "_pybytes_connection", - "_pybytes_constants", - "_pybytes_debug", - "_pybytes_library", - "_pybytes_machine_learning", - "_pybytes_main", - "_pybytes_protocol", - "_pybytes_pyconfig", - "_pybytes_pymesh_config", - "_rp2", - "_terminal", - "_thread", - "_uasyncio", - "_urequest", - "adcfft", - "aioble/__init__", - "aioble/central", - "aioble/client", - "aioble/core", - "aioble/device", - "aioble/l2cap", - "aioble/peripheral", - "aioble/security", - "aioble/server", - "aioespnow", - "ak8963", - "apa102", - "apa106", - "argparse", - "array", - "asyncio/__init__", - "asyncio/core", - "asyncio/event", - "asyncio/funcs", - "asyncio/lock", - "asyncio/stream", - "binascii", - "bluetooth", - "breakout_as7262", - "breakout_bh1745", - "breakout_bme280", - "breakout_bme68x", - "breakout_bmp280", - "breakout_dotmatrix", - "breakout_encoder", - "breakout_icp10125", - "breakout_ioexpander", - "breakout_ltr559", - "breakout_matrix11x7", - "breakout_mics6814", - "breakout_msa301", - "breakout_paa5100", - "breakout_pmw3901", - "breakout_potentiometer", - "breakout_rgbmatrix5x5", - "breakout_rtc", - "breakout_scd41", - "breakout_sgp30", - "breakout_trackball", - "breakout_vl53l5cx", - "btree", - "cmath", - "collections", - "crypto", - "cryptolib", - "curl", - "deflate", - "dht", - "display", - "display_driver_utils", - "ds18x20", - "encoder", - "errno", - "esp", - "esp32", - "espidf", - "espnow", - "ffi", - "flashbdev", - "framebuf", - "freesans20", - "fs_driver", - "functools", - "galactic", - "gc", - "gfx_pack", - "gsm", - "hashlib", - "heapq", - "hub75", - "ili9341", - "ili9XXX", - "imagetools", - "inisetup", - "interstate75", - "io", - "jpegdec", - "json", - "lcd160cr", - "lodepng", - "logging", - "lsm6dsox", - "lv_colors", - "lv_utils", - "lvgl", - "lwip", - "machine", - "math", - "microWebSocket", - "microWebSrv", - "microWebTemplate", - "micropython", - "mip", - "mip/__init__", - "mip/__main__", - "motor", - "mpu6500", - "mpu9250", - "neopixel", - "network", - "ntptime", - "onewire", - "os", - "pcf85063a", - "picoexplorer", - "picographics", - "picokeypad", - "picoscroll", - "picounicorn", - "picowireless", - "pimoroni", - "pimoroni_bus", - "pimoroni_i2c", - "plasma", - "platform", - "pyb", - "pycom", - "pye", - "qrcode", - "queue", - "random", - "requests", - "requests/__init__", - "rp2", - "rtch", - "samd", - "select", - "servo", - "socket", - "ssd1306", - "ssh", - "ssl", - "stm", - "struct", - "sys", - "termios", - "time", - "tpcalib", - "uarray", - "uasyncio/__init__", - "uasyncio/core", - "uasyncio/event", - "uasyncio/funcs", - "uasyncio/lock", - "uasyncio/stream", - "uasyncio/tasks", - "ubinascii", - "ubluetooth", - "ucollections", - "ucrypto", - "ucryptolib", - "uctypes", - "uerrno", - "uftpd", - "uhashlib", - "uheapq", - "uio", - "ujson", - "ulab", - "ulab/approx", - "ulab/compare", - "ulab/fft", - "ulab/filter", - "ulab/linalg", - "ulab/numerical", - "ulab/poly", - "ulab/user", - "ulab/vector", - "umachine", - "umqtt/__init__", - "umqtt/robust", - "umqtt/simple", - "uos", - "uplatform", - "uqueue", - "urandom", - "ure", - "urequests", - "urllib/urequest", - "uselect", - "usocket", - "ussl", - "ustruct", - "usys", - "utelnetserver", - "utime", - "utimeq", - "uwebsocket", - "uzlib", - "version", - "websocket", - "websocket_helper", - "wipy", - "writer", - "xpt2046", - "ymodem", - "zephyr", - "zlib", - ] # spell-checker: enable - - gc.collect() - - stubber.create_all_stubs() - stubber.report() - - -if __name__ == "__main__" or is_micropython(): - try: - log = logging.getLogger("stubber") - logging.basicConfig(level=logging.INFO) - # logging.basicConfig(level=logging.DEBUG) - except NameError: - pass - if not file_exists("no_auto_stubber.txt"): - try: - gc.threshold(4 * 1024) # type: ignore - gc.enable() - except BaseException: - pass - main() + def __init__(B,path=E,firmware_id=E): + C=firmware_id + try: + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') + except H:pass + B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[R]));F.collect() + if C:B._fwid=C.lower() + elif B.info[P]==Y:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(S) + else:B._fwid='{family}-v{version}-{port}'.format(**B.info) + B._start_free=F.mem_free() + if path: + if path.endswith(G):path=path[:-1] + else:path=get_root() + B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) + try:g(path+G) + except D:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[] + def get_obj_attributes(L,item_instance): + I=item_instance;C=[];K=[] + for A in M(I): + if A.startswith(Z)and not A in L.modules:continue + try: + D=getattr(I,A) + try:E=X(type(D)).split("'")[1] + except Q:E=B + if E in{o,p,q,r,a,b,c}:G=1 + elif E in{s,t}:G=2 + elif E in'class':G=3 + else:G=4 + C.append((A,X(D),X(type(D)),D,G)) + except H as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,J)) + except MemoryError as J:W('MemoryError: {}'.format(J));sleep(1);reset() + C=k([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);F.collect();return C,K + def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) + def create_all_stubs(B): + A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));F.collect() + for C in B.modules:B.create_one_stub(C) + A.info('Finally done') + def create_one_stub(C,module_name): + B=module_name + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return I + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return I + H='{}/{}.py'.format(C.path,B.replace(J,G));F.collect();E=I + try:E=C.create_module_stub(B,H) + except D:return I + F.collect();return E + def create_module_stub(K,module_name,file_name=E): + H=file_name;C=module_name + if H is E:L=C.replace(J,Z)+'.py';H=K.path+G+L + else:L=H.split(G)[-1] + if G in C:C=C.replace(G,J) + M=E + try:M=__import__(C,E,E,'*');P=F.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) + except N:return I + g(H) + with open(H,'w')as O:Q=str(K.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,Q,__version__);O.write(R);O.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(O,M,C,B) + K._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + if C not in{'os',u,v,'gc'}: + try:del M + except(D,l):A.warning('could not del new_module') + F.collect();return T + def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() + if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return + X,P=K.get_obj_attributes(L) + if P:A.error(P) + for(E,J,G,Y,d)in X: + if E in['classmethod','staticmethod','BaseException',M]:continue + if E[0].isdigit():A.warning('NameError: invalid name {}'.format(E));continue + if G==""and O(D)<=z*4: + Q=B;R=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if R:Q=M + C='\n{}class {}({}):\n'.format(D,E,Q) + if R:C+=D+' ...\n';I.write(C);continue + I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) + elif any(A in G for A in[t,s,'closure']): + S=U;T=B + if N>0:T='self, ' + if V in G or V in J:C='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,S) + else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,T,S) + C+=D+' ...\n\n';I.write(C) + elif G=="":0 + elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if F in A and A[F]: + G=int(A[F]);J=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[S]=J + A[F]='v{}.{}'.format(G&255,G>>8&3) + if A[D]and not A[C].endswith(U):A[C]=A[C]+U + A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A +def A0(version): + A=version;B=J.join([str(A)for A in A[:3]]) + if O(A)>3 and A[3]:B+=S+A[3] + return B +def A1(): + try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) + except N:A.warning('BOARDNAME not found');C=B + return C +def get_root(): + try:A=os.getcwd() + except(D,H):A=J + B=A + for B in[A,'/sd','/flash',G,J]: + try:C=os.stat(B);break + except D:continue + return B +def A2(filename): + try: + if os.stat(filename)[0]>>14:return T + return I + except D:return I +def h():W("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) +def read_path(): + path=B + if O(sys.argv)==3: + A=sys.argv[1].lower() + if A in('--path','-p'):path=sys.argv[2] + else:h() + elif O(sys.argv)==2:h() + return path +def i(): + try:A=bytes('abc',encoding='utf8');B=i.__module__;return I + except(j,H):return T +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',x,e,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];F.collect();stubber.create_all_stubs();stubber.report() +if __name__=='__main__'or i(): + if not A2('no_auto_stubber.txt'): + try:F.threshold(4*1024);F.enable() + except BaseException:pass + main() \ No newline at end of file diff --git a/mip/v6/createstubs_mpy.mpy b/mip/v6/createstubs_mpy.mpy index db5b7968408be9b32d320122a1162073156cde21..268efa46913e0933112083cfc1f65512085abb7a 100644 GIT binary patch delta 7485 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 Wr4_9B#mx(kT7cPt4>LXjq5lW6byBGS delta 6442 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 pKCThua~ Date: Fri, 2 Feb 2024 08:17:33 +0100 Subject: [PATCH 57/68] chore: update GH token Signed-off-by: Jos Verlinde --- src/stubber/basicgit.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/stubber/basicgit.py b/src/stubber/basicgit.py index f132fcd16..c2dd8d2cf 100644 --- a/src/stubber/basicgit.py +++ b/src/stubber/basicgit.py @@ -13,9 +13,10 @@ from loguru import logger as log from packaging.version import parse -# Token with no permissions +# Token with no permissions to avoid throttling +# https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#getting-a-higher-rate-limit PAT_NO_ACCESS = ( - "github_pat" + "_11AAHPVFQ0IwtAmfc3cD5Z" + "_xOVII22ErRzzZ7xwwxRcNotUu4krMMbjinQcsMxjnWkYFBIDRWFlZMaHSqq" + "github_pat" + "_11AAHPVFQ0qAkDnSUaMKSp" + "_ZkDl5NRRwBsUN6EYg9ahp1Dvj4FDDONnXVgimxC2EtpY7Q7BUKBoQ0Jq72X" ) PAT = os.environ.get("GITHUB_TOKEN") or PAT_NO_ACCESS GH_CLIENT = Github(auth=Auth.Token(PAT)) From af5693f283b8a8f69edf2b4ad1f31c977ce7a6fb Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Fri, 2 Feb 2024 08:18:35 +0100 Subject: [PATCH 58/68] createstubs_db : Use generator to limit memory usage Signed-off-by: Jos Verlinde --- src/stubber/codemod/_partials/db_main.py | 156 ++++++++++++----------- 1 file changed, 85 insertions(+), 71 deletions(-) diff --git a/src/stubber/codemod/_partials/db_main.py b/src/stubber/codemod/_partials/db_main.py index 85a1e3615..53bee4476 100644 --- a/src/stubber/codemod/_partials/db_main.py +++ b/src/stubber/codemod/_partials/db_main.py @@ -3,11 +3,11 @@ - type_check_only is used to avoid circular imports The partial is enclosed in ###PARTIAL### and ###PARTIALEND### markers """ +# sourcery skip: require-parameter-annotation, for-append-to-extend, use-named-expression from io import TextIOWrapper from typing import TYPE_CHECKING, List, type_check_only -# sourcery skip: require-parameter-annotation if TYPE_CHECKING: import gc import logging @@ -52,10 +52,70 @@ def collect(self) -> None: gc: _gc _log = logging.getLogger("stubber") + def file_exists(filename: str) -> bool: + ... + LIBS = [".", "lib"] ###PARTIAL### +def get_modules(skip=0): + # new + for p in LIBS: + fname = p + "/modulelist.txt" + if not file_exists(fname): + continue + try: + with open(fname) as f: + # print("DEBUG: list of modules: " + p + "/modulelist.txt") + for _ in range(skip): + f.readline() + while True: + line = f.readline().strip() + if not line: + break + if len(line) > 0 and line[0] != "#": + yield line + break + except OSError: + pass + + +def write_skip(done): + # write count of modules already processed to file + with open("modulelist.skip", "w") as f: + f.write(str(done) + "\n") + + +def read_skip(): + # read count of modules already processed from file + done = 0 + try: + with open("modulelist.skip") as f: + done = int(f.readline().strip()) + except OSError: + pass + return done + + +def read_done(): + modules_done = {} # type: dict[str, str] + try: + with open("modulelist.done") as f: + while True: + line = f.readline().strip() + if not line: + break + if len(line) > 0 and line[0] != "#": + key, value = line.split("=", 1) + modules_done[key] = value + except (OSError, SyntaxError): + print("could not read modulelist.done") + finally: + gc.collect() + return modules_done + + def main(): import machine # type: ignore @@ -70,88 +130,42 @@ def main(): stubber = Stubber(path=read_path()) # f_name = "{}/{}".format(stubber.path, "modules.json") + skip = 0 if not was_running: # Only clean folder if this is a first run stubber.clean() - # get list of modules to process - modules_done = read_done() - # see if we can continue from where we left off - get_modulelist(stubber, modules_done) - - if not stubber.modules: - print("All modules have been processed, exiting") else: - del modules_done + skip = read_skip() + + for modulename in get_modules(skip): + # ------------------------------------ + # do epic shit + # but sometimes things fail / run out of memory and reboot + ok = False + try: + ok = stubber.create_one_stub(modulename) + stubber._report = [] + except MemoryError: + # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER + machine.reset() + # ------------------------------------- gc.collect() - for modulename in stubber.modules: - # ------------------------------------ - # do epic shit - # but sometimes things fail / run out of memory and reboot - ok = False - try: - ok = stubber.create_one_stub(modulename) - except MemoryError: - # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER - machine.reset() - # ------------------------------------- - gc.collect() - # modules_done[modulename] = str(stubber._report[-1] if ok else "failed") - with open("modulelist.done", "a") as f: - f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) + # modules_done[modulename] = str(stubber._report[-1] if ok else "failed") + with open("modulelist.done", "a") as f: + f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) + skip += 1 + write_skip(skip) + print("All modules have been processed, Building Report") # Finished processing - load all the results , and remove the failed ones modules_done = read_done() if modules_done: # stubber.write_json_end(mod_fp) stubber._report = [] - for k, v in modules_done.items(): - if v != "failed": - stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(k)) + stubber._report.extend( + '{{"module": "{0}", "file": "{0}.py"}}'.format(k) for k, v in modules_done.items() if v != "failed" + ) stubber.report() -def read_done(): - modules_done = {} # type: dict[str, str] - try: - with open("modulelist.done") as f: - while True: - line = f.readline().strip() - if not line: - break - if len(line) > 0 and line[0] != "#": - key, value = line.split("=", 1) - modules_done[key] = value - except (OSError, SyntaxError): - print("could not read modulelist.done") - finally: - gc.collect() - return modules_done - - -def get_modulelist(stubber, modules_done): - # new - gc.collect() - stubber.modules = [] # avoid duplicates - for p in LIBS: - fname = p + "/modulelist.txt" - if not file_exists(fname): - continue - with open(fname) as f: - # print("DEBUG: list of modules: " + p + "/modulelist.txt") - while True: - line = f.readline().strip() - if not line: - break - if line and line not in modules_done.keys(): - stubber.modules.append(line) - gc.collect() - print("BREAK") - break - - if not stubber.modules: - stubber.modules = ["micropython"] - # _log.warn("Could not find modulelist.txt, using default modules") - gc.collect() - - ###PARTIALEND### From 2c8539544c9381891a54b190a7cccd305fd35732 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Fri, 2 Feb 2024 08:20:02 +0100 Subject: [PATCH 59/68] Fix error handling in createstubs function Signed-off-by: Jos Verlinde --- scripts/board_stubber.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/board_stubber.py b/scripts/board_stubber.py index 3a74429af..7d4986bef 100644 --- a/scripts/board_stubber.py +++ b/scripts/board_stubber.py @@ -376,7 +376,7 @@ def run_createstubs(dest: Path, mcu: MPRemoteBoard, variant: Variant = Variant.d timeout = 90 if mcu.port == "esp8266" else 6 * 60 # type: ignore rc, out = mcu.run_command(cmd, timeout=timeout) # check last line for exception or error and raise that if found - if rc != OK and ":" in out[-1] and not out[-1].startswith("INFO") and not out[-1].startswith("WARN"): + if rc != OK and out and ":" in out[-1] and not out[-1].startswith("INFO") and not out[-1].startswith("WARN"): log.warning(f"createstubs: {out[-1]}") raise RuntimeError(out[-1]) from eval(out[-1].split(":")[0]) From d1f72b3439f9b2b22223a714c74b83186b727241 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Fri, 2 Feb 2024 12:43:51 +0100 Subject: [PATCH 60/68] creatstubs_db: Append to `modules.json` while stubbing, to reduce memory usage. remove logging module. Signed-off-by: Jos Verlinde --- scripts/board_stubber.py | 8 +- src/stubber/board/createstubs.py | 96 ++-- src/stubber/board/createstubs_db.py | 259 +++++------ src/stubber/board/createstubs_db_min.py | 526 +++++++++++----------- src/stubber/board/createstubs_db_mpy.mpy | Bin 9556 -> 9402 bytes src/stubber/board/createstubs_mem.py | 96 ++-- src/stubber/board/createstubs_mem_min.py | 322 ++++++------- src/stubber/board/createstubs_mem_mpy.mpy | Bin 8906 -> 8985 bytes src/stubber/board/createstubs_min.py | 346 +++++++------- src/stubber/board/createstubs_mpy.mpy | Bin 12009 -> 12087 bytes src/stubber/board/logging.py | 99 ---- src/stubber/board/modulelist.txt | 3 +- src/stubber/codemod/_partials/db_main.py | 101 ++--- 13 files changed, 885 insertions(+), 971 deletions(-) delete mode 100644 src/stubber/board/logging.py diff --git a/scripts/board_stubber.py b/scripts/board_stubber.py index 7d4986bef..020a24678 100644 --- a/scripts/board_stubber.py +++ b/scripts/board_stubber.py @@ -288,8 +288,8 @@ def copy_createstubs_to_board(board: MPRemoteBoard, variant: Variant, form: Form f"cp {origin}/createstubs.py :lib/createstubs.py", f"cp {origin}/createstubs_mem.py :lib/createstubs_mem.py", f"cp {origin}/createstubs_db.py :lib/createstubs_db.py", - f"cp {origin}/logging.py :lib/logging.py", ] + # copy createstubs*_min.py to the destination folder _min = [ f"cp {origin}/createstubs_min.py :lib/createstubs.py", @@ -446,7 +446,7 @@ def generate_board_stubs( modules_json = json.load(fp) mcu.firmware = modules_json["firmware"] except FileNotFoundError: - log.warning("Error generating stubs, modules.json not found") + log.warning("Could not load modules.json, Assuming error in createstubs") return ERROR, None # check the number of stubs generated @@ -504,7 +504,9 @@ def copy_scripts_to_board(mcu: MPRemoteBoard, variant: Variant, form: Form): def get_stubfolder(out: List[str]): - return lines[-1].split("/remote/")[-1].strip() if (lines := [l for l in out if l.startswith("Path: ")]) else "" + return ( + lines[-1].split("/remote/")[-1].strip() if (lines := [l for l in out if l.startswith("INFO : Path: ")]) else "" + ) def scan_boards(optimistic: bool = False) -> List[MPRemoteBoard]: diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index 1f7ca21d3..c8b593b85 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -77,7 +77,6 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self._report = [] # type: list[str] self.info = _info() log.info("Port: {}".format(self.info["port"])) log.info("Board: {}".format(self.info["board"])) @@ -121,6 +120,8 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore ] # there is no option to discover modules from micropython, list is read from an external file. self.modules = [] # type: list[str] + self._json_name = None + self._json_first = False def get_obj_attributes(self, item_instance: object): "extract information of the objects members and attributes" @@ -168,10 +169,12 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber {} on {}".format(__version__, self._fwid)) + self.report_start() gc.collect() for module_name in self.modules: self.create_one_stub(module_name) + self.report_end() log.info("Finally done") def create_one_stub(self, module_name: str): @@ -232,7 +235,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + self.report_add(module_name, file_name) if module_name not in {"os", "sys", "logging", "gc"}: # try to unload the module unless we use it @@ -240,11 +243,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] log.warning("could not del new_module") - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - # log.warning("could not del sys.modules[{}]".format(module_name)) + # do not try to delete from sys.modules - most times it does not work anyway gc.collect() return True @@ -406,41 +405,53 @@ def clean(self, path: str = None): # type: ignore except OSError: pass - def report(self, filename: str = "modules.json"): - "create json with list of exported modules" - log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) - f_name = "{}/{}".format(self.path, filename) - log.info("Report file: {}".format(f_name)) + def report_start(self, filename: str = "modules.json"): + """Start a report of the modules that have been stubbed + "create json with list of exported modules""" + self._json_name = "{}/{}".format(self.path, filename) + self._json_first = True + ensure_folder(self._json_name) + log.info("Report file: {}".format(self._json_name)) gc.collect() try: # write json by node to reduce memory requirements - with open(f_name, "w") as f: - self.write_json_header(f) - first = True - for n in self._report: - self.write_json_node(f, n, first) - first = False - self.write_json_end(f) - used = self._start_free - gc.mem_free() # type: ignore - # log.debug("Memory used: {0} Kb".format(used // 1024)) - except OSError: + with open(self._json_name, "w") as f: + f.write("{") + f.write(dumps({"firmware": self.info})[1:-1]) + f.write(",\n") + f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) + f.write(",\n") + f.write('"modules" :[\n') + + except OSError as e: log.error("Failed to create the report.") + self._json_name = None + raise e + + def report_add(self, module_name: str, stub_file: str): + "Add a module to the report" + # write json by node to reduce memory requirements + if not self._json_name: + raise Exception("No report file") + try: + with open(self._json_name, "a") as f: + if not self._json_first: + f.write(",\n") + else: + self._json_first = False + line = '{{"module": "{}", "file": "{}"}}'.format(module_name, stub_file.replace("\\", "/")) + f.write(line) - def write_json_header(self, f): - f.write("{") - f.write(dumps({"firmware": self.info})[1:-1]) - f.write(",\n") - f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) - f.write(",\n") - f.write('"modules" :[\n') - - def write_json_node(self, f, n, first): - if not first: - f.write(",\n") - f.write(n) + except OSError: + log.error("Failed to create the report.") - def write_json_end(self, f): - f.write("\n]}") + def report_end(self): + if not self._json_name: + raise Exception("No report file") + with open(self._json_name, "a") as f: + f.write("\n]}") + # is used as sucess indicator + log.info("Path: {}".format(self.path)) def ensure_folder(path: str): @@ -486,7 +497,7 @@ def _build(s): def _info(): # type:() -> dict[str, str] info = OrderedDict( { - "family": sys.implementation.name, + "family": sys.implementation.name, # type: ignore "version": "", "build": "", "ver": "", @@ -516,9 +527,9 @@ def _info(): # type:() -> dict[str, str] info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( - sys.implementation._mpy + sys.implementation._mpy # type: ignore if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy + else sys.implementation.mpy # type: ignore if "mpy" in dir(sys.implementation) else "" ) @@ -674,10 +685,6 @@ def is_micropython() -> bool: # pylint: disable=unused-variable,eval-used try: # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented # Micropython: NotImplementedError @@ -942,7 +949,6 @@ def main(): gc.collect() stubber.create_all_stubs() - stubber.report() if __name__ == "__main__" or is_micropython(): diff --git a/src/stubber/board/createstubs_db.py b/src/stubber/board/createstubs_db.py index 2743ac849..f5d17d802 100644 --- a/src/stubber/board/createstubs_db.py +++ b/src/stubber/board/createstubs_db.py @@ -96,7 +96,6 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self._report = [] # type: list[str] self.info = _info() log.info("Port: {}".format(self.info["port"])) log.info("Board: {}".format(self.info["board"])) @@ -140,6 +139,8 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore ] # there is no option to discover modules from micropython, list is read from an external file. self.modules = [] # type: list[str] + self._json_name = None + self._json_first = False def get_obj_attributes(self, item_instance: object): "extract information of the objects members and attributes" @@ -187,10 +188,12 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber {} on {}".format(__version__, self._fwid)) + self.report_start() gc.collect() for module_name in self.modules: self.create_one_stub(module_name) + self.report_end() log.info("Finally done") def create_one_stub(self, module_name: str): @@ -249,7 +252,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + self.report_add(module_name, file_name) if module_name not in {"os", "sys", "logging", "gc"}: # try to unload the module unless we use it @@ -257,11 +260,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] log.warning("could not del new_module") - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - # log.warning("could not del sys.modules[{}]".format(module_name)) + # do not try to delete from sys.modules - most times it does not work anyway gc.collect() return True @@ -421,41 +420,53 @@ def clean(self, path: str = None): # type: ignore except OSError: pass - def report(self, filename: str = "modules.json"): - "create json with list of exported modules" - log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) - f_name = "{}/{}".format(self.path, filename) - log.info("Report file: {}".format(f_name)) + def report_start(self, filename: str = "modules.json"): + """Start a report of the modules that have been stubbed + "create json with list of exported modules""" + self._json_name = "{}/{}".format(self.path, filename) + self._json_first = True + ensure_folder(self._json_name) + log.info("Report file: {}".format(self._json_name)) gc.collect() try: # write json by node to reduce memory requirements - with open(f_name, "w") as f: - self.write_json_header(f) - first = True - for n in self._report: - self.write_json_node(f, n, first) - first = False - self.write_json_end(f) - used = self._start_free - gc.mem_free() # type: ignore - # log.debug("Memory used: {0} Kb".format(used // 1024)) - except OSError: + with open(self._json_name, "w") as f: + f.write("{") + f.write(dumps({"firmware": self.info})[1:-1]) + f.write(",\n") + f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) + f.write(",\n") + f.write('"modules" :[\n') + + except OSError as e: log.error("Failed to create the report.") + self._json_name = None + raise e + + def report_add(self, module_name: str, stub_file: str): + "Add a module to the report" + # write json by node to reduce memory requirements + if not self._json_name: + raise Exception("No report file") + try: + with open(self._json_name, "a") as f: + if not self._json_first: + f.write(",\n") + else: + self._json_first = False + line = '{{"module": "{}", "file": "{}"}}'.format(module_name, stub_file.replace("\\", "/")) + f.write(line) - def write_json_header(self, f): - f.write("{") - f.write(dumps({"firmware": self.info})[1:-1]) - f.write(",\n") - f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) - f.write(",\n") - f.write('"modules" :[\n') - - def write_json_node(self, f, n, first): - if not first: - f.write(",\n") - f.write(n) + except OSError: + log.error("Failed to create the report.") - def write_json_end(self, f): - f.write("\n]}") + def report_end(self): + if not self._json_name: + raise Exception("No report file") + with open(self._json_name, "a") as f: + f.write("\n]}") + # is used as sucess indicator + log.info("Path: {}".format(self.path)) def ensure_folder(path: str): @@ -501,7 +512,7 @@ def _build(s): def _info(): # type:() -> dict[str, str] info = OrderedDict( { - "family": sys.implementation.name, + "family": sys.implementation.name, # type: ignore "version": "", "build": "", "ver": "", @@ -529,9 +540,9 @@ def _info(): # type:() -> dict[str, str] info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( - sys.implementation._mpy + sys.implementation._mpy # type: ignore if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy + else sys.implementation.mpy # type: ignore if "mpy" in dir(sys.implementation) else "" ) @@ -687,10 +698,6 @@ def is_micropython() -> bool: # pylint: disable=unused-variable,eval-used try: # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented # Micropython: NotImplementedError @@ -704,102 +711,96 @@ def is_micropython() -> bool: return True -def main(): - import machine # type: ignore +SKIP_FILE = "modulelist.done" + + +def get_modules(skip=0): + # new + for p in LIBS: + fname = p + "/modulelist.txt" + if not file_exists(fname): + continue + try: + with open(fname) as f: + i = 0 + while True: + line = f.readline().strip() + if not line: + break + if len(line) > 0 and line[0] == "#": + continue + i += 1 + if i < skip: + continue + yield line + break + except OSError: + pass + + +def write_skip(done): + # write count of modules already processed to file + with open(SKIP_FILE, "w") as f: + f.write(str(done) + "\n") + +def read_skip(): + # read count of modules already processed from file + done = 0 try: - f = open("modulelist.done", "r+b") - was_running = True - print("Opened existing db") + with open(SKIP_FILE) as f: + done = int(f.readline().strip()) except OSError: - f = open("modulelist.done", "w+b") - print("created new db") - was_running = False + pass + return done + + +def main(): + import machine # type: ignore + + was_running = file_exists(SKIP_FILE) + if was_running: + log.info("Continue from last run") + else: + log.info("Starting new run") + # try: + # f = open("modulelist.done", "r+b") + # was_running = True + # print("Continue from last run") + # except OSError: + # f = open("modulelist.done", "w+b") + # was_running = False stubber = Stubber(path=read_path()) # f_name = "{}/{}".format(stubber.path, "modules.json") + skip = 0 if not was_running: # Only clean folder if this is a first run stubber.clean() - # get list of modules to process - modules_done = read_done() - # see if we can continue from where we left off - get_modulelist(stubber, modules_done) - - if not stubber.modules: - print("All modules have been processed, exiting") + stubber.report_start("modules.json") else: - del modules_done - gc.collect() - for modulename in stubber.modules: - # ------------------------------------ - # do epic shit - # but sometimes things fail / run out of memory and reboot - ok = False - try: - ok = stubber.create_one_stub(modulename) - except MemoryError: - # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER - machine.reset() - # ------------------------------------- - gc.collect() - # modules_done[modulename] = str(stubber._report[-1] if ok else "failed") - with open("modulelist.done", "a") as f: - f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) - - # Finished processing - load all the results , and remove the failed ones - modules_done = read_done() - if modules_done: - # stubber.write_json_end(mod_fp) - stubber._report = [] - for k, v in modules_done.items(): - if v != "failed": - stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(k)) - stubber.report() - - -def read_done(): - modules_done = {} # type: dict[str, str] - try: - with open("modulelist.done") as f: - while True: - line = f.readline().strip() - if not line: - break - if len(line) > 0 and line[0] != "#": - key, value = line.split("=", 1) - modules_done[key] = value - except (OSError, SyntaxError): - print("could not read modulelist.done") - finally: - gc.collect() - return modules_done + skip = read_skip() + stubber._json_name = "{}/{}".format(stubber.path, "modules.json") - -def get_modulelist(stubber, modules_done): - # new - gc.collect() - stubber.modules = [] # avoid duplicates - for p in LIBS: - fname = p + "/modulelist.txt" - if not file_exists(fname): - continue - with open(fname) as f: - # print("DEBUG: list of modules: " + p + "/modulelist.txt") - while True: - line = f.readline().strip() - if not line: - break - if line and line not in modules_done.keys(): - stubber.modules.append(line) - gc.collect() - print("BREAK") - break - - if not stubber.modules: - stubber.modules = ["micropython"] - # _log.warn("Could not find modulelist.txt, using default modules") - gc.collect() + for modulename in get_modules(skip): + # ------------------------------------ + # do epic shit + # but sometimes things fail / run out of memory and reboot + try: + stubber.create_one_stub(modulename) + except MemoryError: + # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER + machine.reset() + # ------------------------------------- + gc.collect() + # modules_done[modulename] = str(stubber._report[-1] if ok else "failed") + # with open("modulelist.done", "a") as f: + # f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) + skip += 1 + write_skip(skip) + + print("All modules have been processed, Finalizing report") + stubber.report_end() if __name__ == "__main__" or is_micropython(): diff --git a/src/stubber/board/createstubs_db_min.py b/src/stubber/board/createstubs_db_min.py index f61b4498f..2ee2f2410 100644 --- a/src/stubber/board/createstubs_db_min.py +++ b/src/stubber/board/createstubs_db_min.py @@ -1,324 +1,324 @@ -y='{}/{}' -x='method' -w='function' -v='bool' -u='str' -t='float' -s='int' -r='stubber' -q=TypeError -p=KeyError -o=sorted -n=MemoryError -m=NotImplementedError -g=',\n' -e='dict' -d='list' -c='tuple' -b='_' -a='micropython' -Z=repr -X='modulelist.done' +A3='No report file' +A2='Failed to create the report.' +A1='method' +A0='function' +z='bool' +y='str' +x='float' +w='int' +v='micropython' +u='stubber' +t=TypeError +s=Exception +r=KeyError +q=sorted +p=MemoryError +o=NotImplementedError +k=',\n' +j='modules.json' +i='{}/{}' +h='w' +g='dict' +f='list' +e='tuple' +d='_' +c=str +b=repr W='-preview' V='-' U='board' T=IndexError -S='family' -R=ImportError -Q=len -P=dir -O=True -N=open -L='port' -K='.' -J=print +S=print +R=True +Q='family' +P=len +O=ImportError +N=dir +M=open +K='port' +J='.' I=AttributeError H=False G='/' -F=None -E=OSError -D='version' -C='' -import gc as A,os,sys +E=None +D=OSError +C='version' +B='' +import gc as F,os,sys from time import sleep try:from ujson import dumps except:from json import dumps try:from machine import reset -except R:pass -try:from collections import OrderedDict as f -except R:from ucollections import OrderedDict as f +except O:pass +try:from collections import OrderedDict as l +except O:from ucollections import OrderedDict as l __version__='v1.16.3' -z=2 -A0=2 -A1=['lib','/lib','/sd/lib','/flash/lib',K] -class M: - INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=J +A4=2 +A5=2 +A6=['lib','/lib','/sd/lib','/flash/lib',J] +class L: + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=S @staticmethod - def getLogger(name):return M() + def getLogger(name):return L() @classmethod def basicConfig(A,level):A.level=level def info(A,msg): - if A.level<=M.INFO:A.prnt('INFO :',msg) + if A.level<=L.INFO:A.prnt('INFO :',msg) def warning(A,msg): - if A.level<=M.WARNING:A.prnt('WARN :',msg) + if A.level<=L.WARNING:A.prnt('WARN :',msg) def error(A,msg): - if A.level<=M.ERROR:A.prnt('ERROR :',msg) -B=M.getLogger(r) -M.basicConfig(level=M.INFO) + if A.level<=L.ERROR:A.prnt('ERROR :',msg) +A=L.getLogger(u) +L.basicConfig(level=L.INFO) class Stubber: - def __init__(C,path=F,firmware_id=F): - D=firmware_id + def __init__(B,path=E,firmware_id=E): + C=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise o('MicroPython 1.13.0 cannot be stubbed') except I:pass - C._report=[];C.info=_info();B.info('Port: {}'.format(C.info[L]));B.info('Board: {}'.format(C.info[U]));A.collect() - if D:C._fwid=D.lower() - elif C.info[S]==a:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info).rstrip(V) - else:C._fwid='{family}-v{version}-{port}'.format(**C.info) - C._start_free=A.mem_free() + B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[U]));F.collect() + if C:B._fwid=C.lower() + elif B.info[Q]==v:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(V) + else:B._fwid='{family}-v{version}-{port}'.format(**B.info) + B._start_free=F.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() - C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) - try:h(path+G) - except E:B.error('error creating stub folder {}'.format(path)) - C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] - def get_obj_attributes(M,item_instance): - H=item_instance;D=[];L=[] - for B in P(H): - if B.startswith(b)and not B in M.modules:continue + B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) + try:X(path+G) + except D:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[];B._json_name=E;B._json_first=H + def get_obj_attributes(L,item_instance): + H=item_instance;C=[];K=[] + for A in N(H): + if A.startswith(d)and not A in L.modules:continue try: - E=getattr(H,B) - try:F=Z(type(E)).split("'")[1] - except T:F=C - if F in{s,t,u,v,c,d,e}:G=1 - elif F in{w,x}:G=2 - elif F in'class':G=3 + D=getattr(H,A) + try:E=b(type(D)).split("'")[1] + except T:E=B + if E in{w,x,y,z,e,f,g}:G=1 + elif E in{A0,A1}:G=2 + elif E in'class':G=3 else:G=4 - D.append((B,Z(E),Z(type(E)),E,G)) - except I as K:L.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(B,H,K)) - except n as K:J('MemoryError: {}'.format(K));sleep(1);reset() - D=o([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);A.collect();return D,L - def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) - def create_all_stubs(C): - B.info('Start micropython-stubber v{} on {}'.format(__version__,C._fwid));A.collect() - for D in C.modules:C.create_one_stub(D) - B.info('Finally done') - def create_one_stub(D,module_name): - C=module_name - if C in D.problematic:B.warning('Skip module: {:<25} : Known problematic'.format(C));return H - if C in D.excluded:B.warning('Skip module: {:<25} : Excluded'.format(C));return H - I='{}/{}.py'.format(D.path,C.replace(K,G));A.collect();F=H - try:F=D.create_module_stub(C,I) - except E:return H - A.collect();return F - def create_module_stub(J,module_name,file_name=F): - I=file_name;D=module_name - if I is F:L=D.replace(K,b)+'.py';I=J.path+G+L + C.append((A,b(D),b(type(D)),D,G)) + except I as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,J)) + except p as J:S('MemoryError: {}'.format(J));sleep(1);reset() + C=q([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);F.collect();return C,K + def add_modules(A,modules):A.modules=q(set(A.modules)|set(modules)) + def create_all_stubs(B): + A.info('Start micropython-stubber {} on {}'.format(__version__,B._fwid));B.report_start();F.collect() + for C in B.modules:B.create_one_stub(C) + B.report_end();A.info('Finally done') + def create_one_stub(C,module_name): + B=module_name + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return H + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return H + I='{}/{}.py'.format(C.path,B.replace(J,G));F.collect();E=H + try:E=C.create_module_stub(B,I) + except D:return H + F.collect();return E + def create_module_stub(K,module_name,file_name=E): + I=file_name;C=module_name + if I is E:L=C.replace(J,d)+'.py';I=K.path+G+L else:L=I.split(G)[-1] - if G in D:D=D.replace(G,K) - M=F - try:M=__import__(D,F,F,'*');Q=A.mem_free();B.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(D,L,Q)) - except R:return H - h(I) - with N(I,'w')as P:S=str(J.info).replace('OrderedDict(',C).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(P,M,D,C) - J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,I.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: - try:del M - except(E,p):B.warning('could not del new_module') - A.collect();return O + if G in C:C=C.replace(G,J) + N=E + try:N=__import__(C,E,E,'*');Q=F.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,Q)) + except O:return H + X(I) + with M(I,h)as P:S=c(K.info).replace('OrderedDict(',B).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(P,N,C,B) + K.report_add(C,I) + if C not in{'os','sys','logging','gc'}: + try:del N + except(D,r):A.warning('could not del new_module') + F.collect();return R def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;E=indent;A.collect() - if L in K.problematic:B.warning('SKIPPING problematic module:{}'.format(L));return + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() + if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return X,O=K.get_obj_attributes(L) - if O:B.error(O) - for(F,J,G,Y,a)in X: - if F in['classmethod','staticmethod','BaseException',M]:continue - if F[0].isdigit():B.warning('NameError: invalid name {}'.format(F));continue - if G==""and Q(E)<=A0*4: - P=C;R=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] - if R:P=M - D='\n{}class {}({}):\n'.format(E,F,P) - if R:D+=E+' ...\n';I.write(D);continue - I.write(D);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',N+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';I.write(D) - elif any(A in G for A in[x,w,'closure']): - S=U;T=C + if O:A.error(O) + for(E,J,G,Y,a)in X: + if E in['classmethod','staticmethod','BaseException',M]:continue + if E[0].isdigit():A.warning('NameError: invalid name {}'.format(E));continue + if G==""and P(D)<=A5*4: + Q=B;R=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if R:Q=M + C='\n{}class {}({}):\n'.format(D,E,Q) + if R:C+=D+' ...\n';I.write(C);continue + I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) + elif any(A in G for A in[A1,A0,'closure']): + S=U;T=B if N>0:T='self, ' - if V in G or V in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) - else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,T,S) - D+=E+' ...\n\n';I.write(D) + if V in G or V in J:C='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,S) + else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,T,S) + C+=D+' ...\n\n';I.write(C) elif G=="":0 elif G.startswith("='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if E in A and A[E]: - G=int(A[E]);J=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] - if J:A[N]=J - A[E]='v{}.{}'.format(G&255,G>>8&3) - if A[B]and not A[D].endswith(W):A[D]=A[D]+W - A[K]=f"{A[D]}-{A[B]}"if A[B]else f"{A[D]}";return A -def A2(version): - A=version;B=K.join([str(A)for A in A[:3]]) - if Q(A)>3 and A[3]:B+=V+A[3] + if'uname'in N(os): + A[D]=Y(os.uname()[3]) + if not A[D]:A[D]=Y(os.uname()[2]) + elif C in N(sys):A[D]=Y(sys.version) + except(I,T,t):pass + if A[C]==B and sys.platform not in(S,R): + try:a=os.uname();A[C]=a.release + except(T,I,t):pass + for(b,c,d)in[(V,V,'const'),(X,X,'FAT'),(Z,'pybricks.hubs','EV3Brick')]: + try:e=__import__(c,E,E,d);A[Q]=b;del e;break + except(O,r):pass + if A[Q]==Z:A['release']='2.0.0' + if A[Q]==v: + A[C] + if A[C]and A[C].endswith('.0')and A[C]>='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if F in A and A[F]: + G=int(A[F]);J=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[P]=J + A[F]='v{}.{}'.format(G&255,G>>8&3) + if A[D]and not A[C].endswith(W):A[C]=A[C]+W + A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A +def A7(version): + A=version;B=J.join([c(A)for A in A[:3]]) + if P(A)>3 and A[3]:B+=V+A[3] return B -def A3(): - try:from boardname import BOARDNAME as A;B.info('Found BOARDNAME: {}'.format(A)) - except R:B.warning('BOARDNAME not found');A=C - return A +def A8(): + try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) + except O:A.warning('BOARDNAME not found');C=B + return C def get_root(): try:A=os.getcwd() - except(E,I):A=K + except(D,I):A=J B=A - for B in[A,'/sd','/flash',G,K]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break - except E:continue + except D:continue return B -def i(filename): +def Z(filename): try: - if os.stat(filename)[0]>>14:return O + if os.stat(filename)[0]>>14:return R return H - except E:return H -def j():J("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) + except D:return H +def m():S("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): - path=C - if Q(sys.argv)==3: + path=B + if P(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:j() - elif Q(sys.argv)==2:j() + else:m() + elif P(sys.argv)==2:m() return path -def k(): - try:A=bytes('abc',encoding='utf8');B=k.__module__;return H - except(m,I):return O -def main(): - I='failed';import machine as K - try:C=N(X,'r+b');D=O;J('Opened existing db') - except E:C=N(X,'w+b');J('created new db');D=H - stubber=Stubber(path=read_path()) - if not D:stubber.clean() - B=l();A4(stubber,B) - if not stubber.modules:J('All modules have been processed, exiting') - else: - del B;A.collect() - for F in stubber.modules: - G=H - try:G=stubber.create_one_stub(F) - except n:K.reset() - A.collect() - with N(X,'a')as C:C.write('{}={}\n'.format(F,'ok'if G else I)) - B=l() - if B: - stubber._report=[] - for(L,M)in B.items(): - if M!=I:stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(L)) - stubber.report() -def l(): - C={} +def n(): + try:A=bytes('abc',encoding='utf8');B=n.__module__;return H + except(o,I):return R +a='modulelist.done' +def A9(skip=0): + for E in A6: + B=E+'/modulelist.txt' + if not Z(B):continue + try: + with M(B)as F: + C=0 + while R: + A=F.readline().strip() + if not A:break + if P(A)>0 and A[0]=='#':continue + C+=1 + if C0 and B[0]!='#':F,G=B.split('=',1);C[F]=G - except(E,SyntaxError):J('could not read modulelist.done') - finally:A.collect();return C -def A4(stubber,modules_done): - A.collect();stubber.modules=[] - for D in A1: - C=D+'/modulelist.txt' - if not i(C):continue - with N(C)as E: - while O: - B=E.readline().strip() - if not B:break - if B and B not in modules_done.keys():stubber.modules.append(B) - A.collect();J('BREAK');break - if not stubber.modules:stubber.modules=[a] - A.collect() -if __name__=='__main__'or k(): - if not i('no_auto_stubber.txt'): - try:A.threshold(4*1024);A.enable() + with M(a)as B:A=int(B.readline().strip()) + except D:pass + return A +def main(): + import machine as D;C=Z(a) + if C:A.info('Continue from last run') + else:A.info('Starting new run') + stubber=Stubber(path=read_path());B=0 + if not C:stubber.clean();stubber.report_start(j) + else:B=AB();stubber._json_name=i.format(stubber.path,j) + for E in A9(B): + try:stubber.create_one_stub(E) + except p:D.reset() + F.collect();B+=1;AA(B) + S('All modules have been processed, Finalizing report');stubber.report_end() +if __name__=='__main__'or n(): + if not Z('no_auto_stubber.txt'): + try:F.threshold(4*1024);F.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_db_mpy.mpy b/src/stubber/board/createstubs_db_mpy.mpy index ce39a1007ab406f7c041cc8757aeec95d3f77135..0af4115e4b3407c93f6f23669b43dc6ab52207b5 100644 GIT binary patch delta 6209 zcmZWNSx{S9cK1Ct0YcpOBtHZKB=jT!LTo}jW8($Hvn@npTaAUSc4L-@Y-6)E;C+$q zwO#3DYT}8y(tk-lGN~k0Ng)<5ba%$!rS0j?q*9%#89K$dDoOvO)2R%VpG;MjbDv~S zcL!T~_nmX@+0VJ>>L0>uz1IGGWT*RgS88+d(S`W@!iBNzZ05sBn>cci}H4<_D1{1h_8 zFHbBW5qOUe&yFsfMTXJ2GZzsV=BH8q=$M9Zd|I0spO`*_3>Owocc8}H?p=r^cp2q( zcO%+cklP(ZL^J4{i?qr3=rpp<#b;;c7KY~+M&}lgW%%6u%=GZ|=u{k4XRH{WnT}Tg z`ob78X)}|PaSh0_o8r^ssTVoF*kPKQ8NV7p~00%P8XCM)^fUHxNDwM(%c8OF8mu6S>`O zV1*w(t?+3<{8hwXLHuRJUqDm*0^;Y<06&Ll4gU^`@v~@{pF#Y2#Gga_1me#k{tV(z zBOU~dBVI!^j~_$)al{WIK8hmzF+?u$1BibU@exFh^G8uXe*}?o{xBj_d_UU9_aQ!v zy7^wjhY)`V@dwZ-uOhw&@j=8NMEoQeKYTGhH$MRm90nZ&@M(vSg81 }5`VgCHY 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 diff --git a/src/stubber/board/createstubs_mem.py b/src/stubber/board/createstubs_mem.py index 124421fd3..9ea19f27b 100644 --- a/src/stubber/board/createstubs_mem.py +++ b/src/stubber/board/createstubs_mem.py @@ -87,7 +87,6 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self._report = [] # type: list[str] self.info = _info() log.info("Port: {}".format(self.info["port"])) log.info("Board: {}".format(self.info["board"])) @@ -131,6 +130,8 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore ] # there is no option to discover modules from micropython, list is read from an external file. self.modules = [] # type: list[str] + self._json_name = None + self._json_first = False def get_obj_attributes(self, item_instance: object): "extract information of the objects members and attributes" @@ -178,10 +179,12 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber {} on {}".format(__version__, self._fwid)) + self.report_start() gc.collect() for module_name in self.modules: self.create_one_stub(module_name) + self.report_end() log.info("Finally done") def create_one_stub(self, module_name: str): @@ -240,7 +243,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + self.report_add(module_name, file_name) if module_name not in {"os", "sys", "logging", "gc"}: # try to unload the module unless we use it @@ -248,11 +251,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] log.warning("could not del new_module") - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - # log.warning("could not del sys.modules[{}]".format(module_name)) + # do not try to delete from sys.modules - most times it does not work anyway gc.collect() return True @@ -412,41 +411,53 @@ def clean(self, path: str = None): # type: ignore except OSError: pass - def report(self, filename: str = "modules.json"): - "create json with list of exported modules" - log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) - f_name = "{}/{}".format(self.path, filename) - log.info("Report file: {}".format(f_name)) + def report_start(self, filename: str = "modules.json"): + """Start a report of the modules that have been stubbed + "create json with list of exported modules""" + self._json_name = "{}/{}".format(self.path, filename) + self._json_first = True + ensure_folder(self._json_name) + log.info("Report file: {}".format(self._json_name)) gc.collect() try: # write json by node to reduce memory requirements - with open(f_name, "w") as f: - self.write_json_header(f) - first = True - for n in self._report: - self.write_json_node(f, n, first) - first = False - self.write_json_end(f) - used = self._start_free - gc.mem_free() # type: ignore - # log.debug("Memory used: {0} Kb".format(used // 1024)) - except OSError: + with open(self._json_name, "w") as f: + f.write("{") + f.write(dumps({"firmware": self.info})[1:-1]) + f.write(",\n") + f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) + f.write(",\n") + f.write('"modules" :[\n') + + except OSError as e: log.error("Failed to create the report.") + self._json_name = None + raise e + + def report_add(self, module_name: str, stub_file: str): + "Add a module to the report" + # write json by node to reduce memory requirements + if not self._json_name: + raise Exception("No report file") + try: + with open(self._json_name, "a") as f: + if not self._json_first: + f.write(",\n") + else: + self._json_first = False + line = '{{"module": "{}", "file": "{}"}}'.format(module_name, stub_file.replace("\\", "/")) + f.write(line) - def write_json_header(self, f): - f.write("{") - f.write(dumps({"firmware": self.info})[1:-1]) - f.write(",\n") - f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) - f.write(",\n") - f.write('"modules" :[\n') - - def write_json_node(self, f, n, first): - if not first: - f.write(",\n") - f.write(n) + except OSError: + log.error("Failed to create the report.") - def write_json_end(self, f): - f.write("\n]}") + def report_end(self): + if not self._json_name: + raise Exception("No report file") + with open(self._json_name, "a") as f: + f.write("\n]}") + # is used as sucess indicator + log.info("Path: {}".format(self.path)) def ensure_folder(path: str): @@ -492,7 +503,7 @@ def _build(s): def _info(): # type:() -> dict[str, str] info = OrderedDict( { - "family": sys.implementation.name, + "family": sys.implementation.name, # type: ignore "version": "", "build": "", "ver": "", @@ -520,9 +531,9 @@ def _info(): # type:() -> dict[str, str] info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( - sys.implementation._mpy + sys.implementation._mpy # type: ignore if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy + else sys.implementation.mpy # type: ignore if "mpy" in dir(sys.implementation) else "" ) @@ -678,10 +689,6 @@ def is_micropython() -> bool: # pylint: disable=unused-variable,eval-used try: # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented # Micropython: NotImplementedError @@ -734,7 +741,6 @@ def get_modulelist(stubber): gc.collect() stubber.create_all_stubs() - stubber.report() if __name__ == "__main__" or is_micropython(): diff --git a/src/stubber/board/createstubs_mem_min.py b/src/stubber/board/createstubs_mem_min.py index 415b4e5bd..589d31bec 100644 --- a/src/stubber/board/createstubs_mem_min.py +++ b/src/stubber/board/createstubs_mem_min.py @@ -1,40 +1,43 @@ -v='{}/{}' -u='method' -t='function' -s='bool' -r='str' -q='float' -p='int' -o='stubber' -n=TypeError +y='No report file' +x='Failed to create the report.' +w='{}/{}' +v='method' +u='function' +t='bool' +s='str' +r='float' +q='int' +p='stubber' +o=TypeError +n=Exception m=KeyError l=sorted k=NotImplementedError -e=',\n' -d='dict' -c='list' -b='tuple' -a='_' -Z='micropython' -Y=open -X=repr -V='-preview' -U='-' -T='board' -S=IndexError -R=print -Q=True -P='family' -O=ImportError -N=len +f=',\n' +e='dict' +d='list' +c='tuple' +b='_' +a='micropython' +Z=repr +W='-preview' +V='-' +U='board' +T=IndexError +S=print +R=True +Q='family' +P=len +O=open +N=ImportError M=dir K='port' J='.' -I=False -H=AttributeError +I=AttributeError +H=False G='/' -F=None -E=OSError +F=OSError +E=None C='version' B='' import gc as D,os,sys @@ -42,15 +45,15 @@ try:from ujson import dumps except:from json import dumps try:from machine import reset -except O:pass -try:from collections import OrderedDict as f -except O:from ucollections import OrderedDict as f +except N:pass +try:from collections import OrderedDict as g +except N:from ucollections import OrderedDict as g __version__='v1.16.3' -w=2 -x=2 -y=['lib','/lib','/sd/lib','/flash/lib',J] +z=2 +A0=2 +A1=['lib','/lib','/sd/lib','/flash/lib',J] class L: - INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=R + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=S @staticmethod def getLogger(name):return L() @classmethod @@ -61,95 +64,95 @@ def warning(A,msg): if A.level<=L.WARNING:A.prnt('WARN :',msg) def error(A,msg): if A.level<=L.ERROR:A.prnt('ERROR :',msg) -A=L.getLogger(o) +A=L.getLogger(p) L.basicConfig(level=L.INFO) class Stubber: - def __init__(B,path=F,firmware_id=F): + def __init__(B,path=E,firmware_id=E): C=firmware_id try: if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') - except H:pass - B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[T]));D.collect() + except I:pass + B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[U]));D.collect() if C:B._fwid=C.lower() - elif B.info[P]==Z:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(U) + elif B.info[Q]==a:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(V) else:B._fwid='{family}-v{version}-{port}'.format(**B.info) B._start_free=D.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) - try:g(path+G) - except E:A.error('error creating stub folder {}'.format(path)) - B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[] + try:X(path+G) + except F:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[];B._json_name=E;B._json_first=H def get_obj_attributes(L,item_instance): - I=item_instance;C=[];K=[] - for A in M(I): - if A.startswith(a)and not A in L.modules:continue + H=item_instance;C=[];K=[] + for A in M(H): + if A.startswith(b)and not A in L.modules:continue try: - E=getattr(I,A) - try:F=X(type(E)).split("'")[1] - except S:F=B - if F in{p,q,r,s,b,c,d}:G=1 - elif F in{t,u}:G=2 + E=getattr(H,A) + try:F=Z(type(E)).split("'")[1] + except T:F=B + if F in{q,r,s,t,c,d,e}:G=1 + elif F in{u,v}:G=2 elif F in'class':G=3 else:G=4 - C.append((A,X(E),X(type(E)),E,G)) - except H as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,J)) - except MemoryError as J:R('MemoryError: {}'.format(J));sleep(1);reset() + C.append((A,Z(E),Z(type(E)),E,G)) + except I as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,J)) + except MemoryError as J:S('MemoryError: {}'.format(J));sleep(1);reset() C=l([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,K def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) def create_all_stubs(B): - A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));D.collect() + A.info('Start micropython-stubber {} on {}'.format(__version__,B._fwid));B.report_start();D.collect() for C in B.modules:B.create_one_stub(C) - A.info('Finally done') + B.report_end();A.info('Finally done') def create_one_stub(C,module_name): B=module_name - if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return I - if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return I - H='{}/{}.py'.format(C.path,B.replace(J,G));D.collect();F=I - try:F=C.create_module_stub(B,H) - except E:return I - D.collect();return F - def create_module_stub(K,module_name,file_name=F): - H=file_name;C=module_name - if H is F:L=C.replace(J,a)+'.py';H=K.path+G+L - else:L=H.split(G)[-1] + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return H + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return H + I='{}/{}.py'.format(C.path,B.replace(J,G));D.collect();E=H + try:E=C.create_module_stub(B,I) + except F:return H + D.collect();return E + def create_module_stub(K,module_name,file_name=E): + I=file_name;C=module_name + if I is E:L=C.replace(J,b)+'.py';I=K.path+G+L + else:L=I.split(G)[-1] if G in C:C=C.replace(G,J) - M=F - try:M=__import__(C,F,F,'*');P=D.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) - except O:return I - g(H) - with Y(H,'w')as N:R=str(K.info).replace('OrderedDict(',B).replace('})','}');S='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,R,__version__);N.write(S);N.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,M,C,B) - K._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + M=E + try:M=__import__(C,E,E,'*');Q=D.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,Q)) + except N:return H + X(I) + with O(I,'w')as P:S=str(K.info).replace('OrderedDict(',B).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(P,M,C,B) + K.report_add(C,I) if C not in{'os','sys','logging','gc'}: try:del M - except(E,m):A.warning('could not del new_module') - D.collect();return Q + except(F,m):A.warning('could not del new_module') + D.collect();return R def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';O=in_class;M='Exception';L=object_expr;I=fp;E=indent;D.collect() + W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;E=indent;D.collect() if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return - X,P=K.get_obj_attributes(L) - if P:A.error(P) + X,O=K.get_obj_attributes(L) + if O:A.error(O) for(F,J,G,Y,a)in X: if F in['classmethod','staticmethod','BaseException',M]:continue if F[0].isdigit():A.warning('NameError: invalid name {}'.format(F));continue - if G==""and N(E)<=x*4: + if G==""and P(E)<=A0*4: Q=B;R=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] if R:Q=M C='\n{}class {}({}):\n'.format(E,F,Q) if R:C+=E+' ...\n';I.write(C);continue - I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',O+1);C=E+' def __init__(self, *argv, **kwargs) -> None:\n';C+=E+' ...\n\n';I.write(C) - elif any(A in G for A in[u,t,'closure']): + I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',N+1);C=E+' def __init__(self, *argv, **kwargs) -> None:\n';C+=E+' ...\n\n';I.write(C) + elif any(A in G for A in[v,u,'closure']): S=U;T=B - if O>0:T='self, ' + if N>0:T='self, ' if V in G or V in J:C='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,T,S) C+=E+' ...\n\n';I.write(C) elif G=="":0 elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] - if E in A and A[E]: - G=int(A[E]);J=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] - if J:A[Q]=J - A[E]='v{}.{}'.format(G&255,G>>8&3) - if A[D]and not A[C].endswith(V):A[C]=A[C]+V + if F in A and A[F]: + G=int(A[F]);J=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[P]=J + A[F]='v{}.{}'.format(G&255,G>>8&3) + if A[D]and not A[C].endswith(W):A[C]=A[C]+W A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A -def z(version): +def A2(version): A=version;B=J.join([str(A)for A in A[:3]]) - if N(A)>3 and A[3]:B+=U+A[3] + if P(A)>3 and A[3]:B+=V+A[3] return B -def A0(): +def A3(): try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) - except O:A.warning('BOARDNAME not found');C=B + except N:A.warning('BOARDNAME not found');C=B return C def get_root(): try:A=os.getcwd() - except(E,H):A=J + except(F,I):A=J B=A for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break - except E:continue + except F:continue return B def h(filename): try: - if os.stat(filename)[0]>>14:return Q - return I - except E:return I -def i():R("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) + if os.stat(filename)[0]>>14:return R + return H + except F:return H +def i():S("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): path=B - if N(sys.argv)==3: + if P(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] else:i() - elif N(sys.argv)==2:i() + elif P(sys.argv)==2:i() return path def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return I - except(k,H):return Q + try:A=bytes('abc',encoding='utf8');B=j.__module__;return H + except(k,I):return R def main(): stubber=Stubber(path=read_path());stubber.clean() def A(stubber): D.collect();stubber.modules=[] - for C in y: + for C in A1: B=C+'/modulelist.txt' if not h(B):continue - with Y(B)as E: - while Q: + with O(B)as E: + while R: A=E.readline().strip() if not A:break - if N(A)>0 and A[0]!='#':stubber.modules.append(A) - D.collect();R('BREAK');break - if not stubber.modules:stubber.modules=[Z] + if P(A)>0 and A[0]!='#':stubber.modules.append(A) + D.collect();S('BREAK');break + if not stubber.modules:stubber.modules=[a] D.collect() - stubber.modules=[];A(stubber);D.collect();stubber.create_all_stubs();stubber.report() + stubber.modules=[];A(stubber);D.collect();stubber.create_all_stubs() if __name__=='__main__'or j(): if not h('no_auto_stubber.txt'): try:D.threshold(4*1024);D.enable() diff --git a/src/stubber/board/createstubs_mem_mpy.mpy b/src/stubber/board/createstubs_mem_mpy.mpy index 21f823ef6f1c9a86f0fffaa91f064d662be5b5a4..eb8daf6f83ad45482c138f2301d8e368bed13488 100644 GIT binary patch delta 5367 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 delta 5365 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 diff --git a/src/stubber/board/createstubs_min.py b/src/stubber/board/createstubs_min.py index 0fcb07093..39ae39e4b 100644 --- a/src/stubber/board/createstubs_min.py +++ b/src/stubber/board/createstubs_min.py @@ -1,43 +1,46 @@ -x='pyb' -w='{}/{}' -v='logging' -u='sys' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n='stubber' -m=TypeError -l=KeyError -k=sorted -j=NotImplementedError -e='pycom' -d=',\n' -c='dict' -b='list' -a='tuple' -Z='_' -Y='micropython' -X=repr -W=print -U='-preview' -T=True -S='-' -R='board' -Q=IndexError -P='family' -O=len +A0='No report file' +z='Failed to create the report.' +y='{}/{}' +x='logging' +w='sys' +v='method' +u='function' +t='bool' +s='str' +r='float' +q='int' +p='stubber' +o=TypeError +n=Exception +m=KeyError +l=sorted +k=NotImplementedError +g='pycom' +f=',\n' +e='dict' +d='list' +c='tuple' +b='_' +a='micropython' +Z=repr +Y=print +V='-preview' +U=True +T='-' +S='board' +R=len +Q=open +P=IndexError +O='family' N=ImportError M=dir K='port' J='.' -I=False -H=AttributeError +I=AttributeError +H=False G='/' -E=None -D=OSError +E=OSError +D=None C='version' B='' import gc as F,os,sys @@ -46,14 +49,14 @@ except:from json import dumps try:from machine import reset except N:pass -try:from collections import OrderedDict as f -except N:from ucollections import OrderedDict as f +try:from collections import OrderedDict as h +except N:from ucollections import OrderedDict as h __version__='v1.16.3' -y=2 -z=2 -A3=['lib','/lib','/sd/lib','/flash/lib',J] +A1=2 +A2=2 +A6=['lib','/lib','/sd/lib','/flash/lib',J] class L: - INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=W + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=Y @staticmethod def getLogger(name):return L() @classmethod @@ -64,85 +67,85 @@ def warning(A,msg): if A.level<=L.WARNING:A.prnt('WARN :',msg) def error(A,msg): if A.level<=L.ERROR:A.prnt('ERROR :',msg) -A=L.getLogger(n) +A=L.getLogger(p) L.basicConfig(level=L.INFO) class Stubber: - def __init__(B,path=E,firmware_id=E): + def __init__(B,path=D,firmware_id=D): C=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') - except H:pass - B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[R]));F.collect() + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + except I:pass + B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[S]));F.collect() if C:B._fwid=C.lower() - elif B.info[P]==Y:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(S) + elif B.info[O]==a:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(T) else:B._fwid='{family}-v{version}-{port}'.format(**B.info) B._start_free=F.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) - try:g(path+G) - except D:A.error('error creating stub folder {}'.format(path)) - B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[] + try:W(path+G) + except E:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[];B._json_name=D;B._json_first=H def get_obj_attributes(L,item_instance): - I=item_instance;C=[];K=[] - for A in M(I): - if A.startswith(Z)and not A in L.modules:continue + H=item_instance;C=[];K=[] + for A in M(H): + if A.startswith(b)and not A in L.modules:continue try: - D=getattr(I,A) - try:E=X(type(D)).split("'")[1] - except Q:E=B - if E in{o,p,q,r,a,b,c}:G=1 - elif E in{s,t}:G=2 + D=getattr(H,A) + try:E=Z(type(D)).split("'")[1] + except P:E=B + if E in{q,r,s,t,c,d,e}:G=1 + elif E in{u,v}:G=2 elif E in'class':G=3 else:G=4 - C.append((A,X(D),X(type(D)),D,G)) - except H as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,J)) - except MemoryError as J:W('MemoryError: {}'.format(J));sleep(1);reset() - C=k([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);F.collect();return C,K - def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) + C.append((A,Z(D),Z(type(D)),D,G)) + except I as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,J)) + except MemoryError as J:Y('MemoryError: {}'.format(J));sleep(1);reset() + C=l([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);F.collect();return C,K + def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) def create_all_stubs(B): - A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));F.collect() + A.info('Start micropython-stubber {} on {}'.format(__version__,B._fwid));B.report_start();F.collect() for C in B.modules:B.create_one_stub(C) - A.info('Finally done') + B.report_end();A.info('Finally done') def create_one_stub(C,module_name): B=module_name - if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return I - if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return I - H='{}/{}.py'.format(C.path,B.replace(J,G));F.collect();E=I - try:E=C.create_module_stub(B,H) - except D:return I - F.collect();return E - def create_module_stub(K,module_name,file_name=E): - H=file_name;C=module_name - if H is E:L=C.replace(J,Z)+'.py';H=K.path+G+L - else:L=H.split(G)[-1] + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return H + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return H + I='{}/{}.py'.format(C.path,B.replace(J,G));F.collect();D=H + try:D=C.create_module_stub(B,I) + except E:return H + F.collect();return D + def create_module_stub(K,module_name,file_name=D): + I=file_name;C=module_name + if I is D:L=C.replace(J,b)+'.py';I=K.path+G+L + else:L=I.split(G)[-1] if G in C:C=C.replace(G,J) - M=E - try:M=__import__(C,E,E,'*');P=F.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) - except N:return I - g(H) - with open(H,'w')as O:Q=str(K.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,Q,__version__);O.write(R);O.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(O,M,C,B) - K._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) - if C not in{'os',u,v,'gc'}: + M=D + try:M=__import__(C,D,D,'*');P=F.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) + except N:return H + W(I) + with Q(I,'w')as O:R=str(K.info).replace('OrderedDict(',B).replace('})','}');S='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,R,__version__);O.write(S);O.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(O,M,C,B) + K.report_add(C,I) + if C not in{'os',w,x,'gc'}: try:del M - except(D,l):A.warning('could not del new_module') - F.collect();return T + except(E,m):A.warning('could not del new_module') + F.collect();return U def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return - X,P=K.get_obj_attributes(L) - if P:A.error(P) - for(E,J,G,Y,d)in X: + X,O=K.get_obj_attributes(L) + if O:A.error(O) + for(E,J,G,Y,a)in X: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():A.warning('NameError: invalid name {}'.format(E));continue - if G==""and O(D)<=z*4: - Q=B;R=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if R:Q=M - C='\n{}class {}({}):\n'.format(D,E,Q) - if R:C+=D+' ...\n';I.write(C);continue + if G==""and R(D)<=A2*4: + P=B;Q=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if Q:P=M + C='\n{}class {}({}):\n'.format(D,E,P) + if Q:C+=D+' ...\n';I.write(C);continue I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) - elif any(A in G for A in[t,s,'closure']): + elif any(A in G for A in[v,u,'closure']): S=U;T=B if N>0:T='self, ' if V in G or V in J:C='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,S) @@ -151,8 +154,8 @@ def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): elif G=="":0 elif G.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] if F in A and A[F]: - G=int(A[F]);J=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] - if J:A[S]=J + G=int(A[F]);J=[D,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[R]=J A[F]='v{}.{}'.format(G&255,G>>8&3) - if A[D]and not A[C].endswith(U):A[C]=A[C]+U - A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A -def A0(version): + if A[E]and not A[C].endswith(V):A[C]=A[C]+V + A[L]=f"{A[C]}-{A[E]}"if A[E]else f"{A[C]}";return A +def A3(version): A=version;B=J.join([str(A)for A in A[:3]]) - if O(A)>3 and A[3]:B+=S+A[3] + if R(A)>3 and A[3]:B+=T+A[3] return B -def A1(): +def A4(): try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) except N:A.warning('BOARDNAME not found');C=B return C def get_root(): try:A=os.getcwd() - except(D,H):A=J + except(E,I):A=J B=A for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break - except D:continue + except E:continue return B -def A2(filename): +def A5(filename): try: - if os.stat(filename)[0]>>14:return T - return I - except D:return I -def h():W("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) + if os.stat(filename)[0]>>14:return U + return H + except E:return H +def i():Y("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): path=B - if O(sys.argv)==3: + if R(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:h() - elif O(sys.argv)==2:h() + else:i() + elif R(sys.argv)==2:i() return path -def i(): - try:A=bytes('abc',encoding='utf8');B=i.__module__;return I - except(j,H):return T -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',x,e,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];F.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or i(): - if not A2('no_auto_stubber.txt'): +def j(): + try:A=bytes('abc',encoding='utf8');B=j.__module__;return H + except(k,I):return U +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',x,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',a,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform','pyb',g,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',w,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];F.collect();stubber.create_all_stubs() +if __name__=='__main__'or j(): + if not A5('no_auto_stubber.txt'): try:F.threshold(4*1024);F.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mpy.mpy b/src/stubber/board/createstubs_mpy.mpy index a8ce4b59ba897a868e520ab5a69db41bbefec2e2..b8595e61d3c6007a02a4f8fb667a3b16f61f82f4 100644 GIT binary patch delta 6183 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 d1hyVn7O-q!8+`PfxM9D&&|u{ccvTI@{uiYXzf{ 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 Khm5aq?0*3=OsEe4 diff --git a/src/stubber/board/logging.py b/src/stubber/board/logging.py deleted file mode 100644 index c0657df2d..000000000 --- a/src/stubber/board/logging.py +++ /dev/null @@ -1,99 +0,0 @@ -import sys - -CRITICAL = 50 -ERROR = 40 -WARNING = 30 -INFO = 20 -DEBUG = 10 -NOTSET = 0 - -_level_dict = { - CRITICAL: "CRIT", - ERROR: "ERROR", - WARNING: "WARN", - INFO: "INFO", - DEBUG: "DEBUG", -} - -_stream = sys.stderr - - -class Logger: - - level = NOTSET - - def __init__(self, name): - self.name = name - - def _level_str(self, level): - l = _level_dict.get(level) - if l is not None: - return l - return "LVL%s" % level - - def setLevel(self, level): - self.level = level - - def isEnabledFor(self, level): - return level >= (self.level or _level) - - def log(self, level, msg, *args): - if level >= (self.level or _level): - _stream.write("%-6s:%-8s:" % (self._level_str(level), self.name)) - if not args: - print(msg, file=_stream) - else: - print(msg % args, file=_stream) - - def debug(self, msg, *args): - self.log(DEBUG, msg, *args) - - def info(self, msg, *args): - self.log(INFO, msg, *args) - - def warning(self, msg, *args): - self.log(WARNING, msg, *args) - - def error(self, msg, *args): - self.log(ERROR, msg, *args) - - def critical(self, msg, *args): - self.log(CRITICAL, msg, *args) - - # def exc(self, e, msg, *args): - # self.log(ERROR, msg, *args) - # sys.print_exception(e, _stream) # type : disable - - def exception(self, msg, *args): - self.critical(sys.exc_info()[1], msg, *args) - - -_level = INFO -_loggers = {} - - -def getLogger(name): - if name in _loggers: - return _loggers[name] - l = Logger(name) - _loggers[name] = l - return l - - -def info(msg, *args): - getLogger(None).info(msg, *args) - - -def debug(msg, *args): - getLogger(None).debug(msg, *args) - - -def basicConfig(level=INFO, filename=None, stream=None, format=None): - global _level, _stream - _level = level - if stream: - _stream = stream - if filename is not None: - print("logging.basicConfig: filename arg is not supported") - if format is not None: - print("logging.basicConfig: format arg is not supported") diff --git a/src/stubber/board/modulelist.txt b/src/stubber/board/modulelist.txt index d722c404c..32dacba0f 100644 --- a/src/stubber/board/modulelist.txt +++ b/src/stubber/board/modulelist.txt @@ -1,5 +1,4 @@ -# list of modules to stub. -# used by the memory optimised createstubs_mem.py +# list of modules to stub used by the memory optimised createstubs_mem.py WM8960 _OTA _asyncio diff --git a/src/stubber/codemod/_partials/db_main.py b/src/stubber/codemod/_partials/db_main.py index 53bee4476..4e38012ee 100644 --- a/src/stubber/codemod/_partials/db_main.py +++ b/src/stubber/codemod/_partials/db_main.py @@ -13,10 +13,20 @@ import logging import sys + class logging: + def getLogger(self, name: str) -> "logging": + ... + + def info(self, msg: str) -> None: + ... + + log = logging() + class Stubber: path: str _report: List[str] modules = [] + _json_name: str def __init__(self, path: str = "", firmware_id: str = "") -> None: ... @@ -27,16 +37,10 @@ def clean(self) -> None: def create_one_stub(self, modulename: str) -> bool: ... - def report(self, filename: str = "modules.json"): - ... - - def write_json_header(self, f: TextIOWrapper): - ... - - def write_json_node(self, f: TextIOWrapper, n, first=False): + def report_start(self, filename: str = "modules.json"): ... - def write_json_end(self, f): + def report_end(self): ... def create_all_stubs(self): @@ -50,7 +54,7 @@ def collect(self) -> None: ... gc: _gc - _log = logging.getLogger("stubber") + log = logging.getLogger("stubber") def file_exists(filename: str) -> bool: ... @@ -59,6 +63,9 @@ def file_exists(filename: str) -> bool: ###PARTIAL### +SKIP_FILE = "modulelist.done" + + def get_modules(skip=0): # new for p in LIBS: @@ -67,15 +74,17 @@ def get_modules(skip=0): continue try: with open(fname) as f: - # print("DEBUG: list of modules: " + p + "/modulelist.txt") - for _ in range(skip): - f.readline() + i = 0 while True: line = f.readline().strip() if not line: break - if len(line) > 0 and line[0] != "#": - yield line + if len(line) > 0 and line[0] == "#": + continue + i += 1 + if i < skip: + continue + yield line break except OSError: pass @@ -83,7 +92,7 @@ def get_modules(skip=0): def write_skip(done): # write count of modules already processed to file - with open("modulelist.skip", "w") as f: + with open(SKIP_FILE, "w") as f: f.write(str(done) + "\n") @@ -91,42 +100,28 @@ def read_skip(): # read count of modules already processed from file done = 0 try: - with open("modulelist.skip") as f: + with open(SKIP_FILE) as f: done = int(f.readline().strip()) except OSError: pass return done -def read_done(): - modules_done = {} # type: dict[str, str] - try: - with open("modulelist.done") as f: - while True: - line = f.readline().strip() - if not line: - break - if len(line) > 0 and line[0] != "#": - key, value = line.split("=", 1) - modules_done[key] = value - except (OSError, SyntaxError): - print("could not read modulelist.done") - finally: - gc.collect() - return modules_done - - def main(): import machine # type: ignore - try: - f = open("modulelist.done", "r+b") - was_running = True - print("Opened existing db") - except OSError: - f = open("modulelist.done", "w+b") - print("created new db") - was_running = False + was_running = file_exists(SKIP_FILE) + if was_running: + log.info("Continue from last run") + else: + log.info("Starting new run") + # try: + # f = open("modulelist.done", "r+b") + # was_running = True + # print("Continue from last run") + # except OSError: + # f = open("modulelist.done", "w+b") + # was_running = False stubber = Stubber(path=read_path()) # f_name = "{}/{}".format(stubber.path, "modules.json") @@ -134,38 +129,30 @@ def main(): if not was_running: # Only clean folder if this is a first run stubber.clean() + stubber.report_start("modules.json") else: skip = read_skip() + stubber._json_name = "{}/{}".format(stubber.path, "modules.json") for modulename in get_modules(skip): # ------------------------------------ # do epic shit # but sometimes things fail / run out of memory and reboot - ok = False try: - ok = stubber.create_one_stub(modulename) - stubber._report = [] + stubber.create_one_stub(modulename) except MemoryError: # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER machine.reset() # ------------------------------------- gc.collect() # modules_done[modulename] = str(stubber._report[-1] if ok else "failed") - with open("modulelist.done", "a") as f: - f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) + # with open("modulelist.done", "a") as f: + # f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) skip += 1 write_skip(skip) - print("All modules have been processed, Building Report") - # Finished processing - load all the results , and remove the failed ones - modules_done = read_done() - if modules_done: - # stubber.write_json_end(mod_fp) - stubber._report = [] - stubber._report.extend( - '{{"module": "{0}", "file": "{0}.py"}}'.format(k) for k, v in modules_done.items() if v != "failed" - ) - stubber.report() + print("All modules have been processed, Finalizing report") + stubber.report_end() ###PARTIALEND### From 64632a1630e05b104169c688ed399c66508a561b Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Fri, 2 Feb 2024 14:50:23 +0100 Subject: [PATCH 61/68] Refactor board_stubber.py: Add conditional stubgen and remove modulelist.done file Signed-off-by: Jos Verlinde --- scripts/board_stubber.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/board_stubber.py b/scripts/board_stubber.py index 020a24678..dfd6d30ad 100644 --- a/scripts/board_stubber.py +++ b/scripts/board_stubber.py @@ -454,7 +454,8 @@ def generate_board_stubs( log.warning("Error generating stubs, too few (<10)stubs were generated") return ERROR, None - utils.do_post_processing([stubs_path], stubgen=True, black=True, autoflake=True) + stubgen_needed = any(stubs_path.glob("*.py")) + utils.do_post_processing([stubs_path], stubgen=stubgen_needed, black=True, autoflake=True) return OK, stubs_path @@ -517,7 +518,7 @@ def scan_boards(optimistic: bool = False) -> List[MPRemoteBoard]: boards = [] for mpr_port in MPRemoteBoard.connected_boards(): board = MPRemoteBoard(mpr_port) - log.info(f"Attempt to connect to: {board.serialport}") + log.debug(f"Attempt to connect to: {board.serialport}") try: board.get_mcu_info() log.success(f"Detected board {board.description} {board.version}") @@ -633,7 +634,7 @@ def run_stubber_connected_boards(variant: str, format: str, debug: bool): tempdir = mkdtemp(prefix="board_stubber") - dest = Path(tempdir) + temp_path = Path(tempdir) # scan boards and just work with the ones that reponded with understandable data connected_boards = scan_boards(True) @@ -657,8 +658,10 @@ def run_stubber_connected_boards(variant: str, format: str, debug: bool): log.info( f"Connecting using {board.serialport} to {board.port} {board.board} {board.version}: {board.description}" ) + # remove the modulelist.done file before starting createstubs on each board + (temp_path / "modulelist.done").unlink(missing_ok=True) - rc, my_stubs = generate_board_stubs(dest, board, variant, form) + rc, my_stubs = generate_board_stubs(temp_path, board, variant, form) if rc == OK and my_stubs: log.success(f'Stubs generated for {board.firmware["port"]}-{board.firmware["board"]}') if destination := copy_to_repo(my_stubs, board.firmware): From 8368c466899149ca349f531d9b17ed340cfef3c6 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Fri, 2 Feb 2024 14:51:25 +0100 Subject: [PATCH 62/68] createsubs: Add additional typing for known classes Signed-off-by: Jos Verlinde --- src/stubber/board/createstubs.py | 32 ++-- src/stubber/board/createstubs_db.py | 30 ++-- src/stubber/board/createstubs_db_min.py | 187 +++++++++++----------- src/stubber/board/createstubs_db_mpy.mpy | Bin 9402 -> 9427 bytes src/stubber/board/createstubs_mem.py | 30 ++-- src/stubber/board/createstubs_mem_min.py | 161 ++++++++++--------- src/stubber/board/createstubs_mem_mpy.mpy | Bin 8985 -> 9009 bytes src/stubber/board/createstubs_min.py | 167 +++++++++---------- src/stubber/board/createstubs_mpy.mpy | Bin 12087 -> 12111 bytes 9 files changed, 312 insertions(+), 295 deletions(-) diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index c8b593b85..8eeb2a615 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -130,7 +130,7 @@ def get_obj_attributes(self, item_instance: object): _errors = [] # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: + if name.startswith("__") and not name in self.modules: continue # log.debug("get attribute {}".format(name)) try: @@ -185,7 +185,7 @@ def create_one_stub(self, module_name: str): log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + file_name = "{}/{}.pyi".format(self.path, module_name.replace(".", "/")) gc.collect() result = False try: @@ -200,10 +200,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: Args: - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + - file_name (Optional[str]): the 'path/filename.pyi' to write to. If omitted will be created based on the module name. """ if file_name is None: - fname = module_name.replace(".", "_") + ".py" + fname = module_name.replace(".", "_") + ".pyi" file_name = self.path + "/" + fname else: fname = file_name.split("/")[-1] @@ -232,7 +232,9 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: module_name, self._fwid, info_, __version__ ) fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write( + "from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n" + ) self.write_object_stub(fp, new_module, module_name, "") self.report_add(module_name, file_name) @@ -340,23 +342,27 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = item_type_txt[8:-2] s = "" - if t in ["str", "int", "float", "bool", "bytearray", "bytes"]: + if t in ("str", "int", "float", "bool", "bytearray", "bytes"): # known type: use actual value - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) - elif t in ["dict", "list", "tuple"]: + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, item_repr, t) + elif t in ("dict", "list", "tuple"): # dict, list , tuple: use empty value ev = {"dict": "{}", "list": "[]", "tuple": "()"} - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, ev[t], t) else: # something else - if t in ["object", "set", "frozenset", "Pin", "FileIO"]: + if t in ("object", "set", "frozenset", "Pin", "generator"): # "FileIO" # https://docs.python.org/3/tutorial/classes.html#item_instance-objects - # use these types for the attribute - s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + # use these types for the attribute + if t == "generator": + t = "Generator" + s = "{0}{1}: {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) else: # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1}: {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # log.debug("\n" + s) else: diff --git a/src/stubber/board/createstubs_db.py b/src/stubber/board/createstubs_db.py index f5d17d802..83fa7c622 100644 --- a/src/stubber/board/createstubs_db.py +++ b/src/stubber/board/createstubs_db.py @@ -149,7 +149,7 @@ def get_obj_attributes(self, item_instance: object): _errors = [] # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: + if name.startswith("__") and not name in self.modules: continue # log.debug("get attribute {}".format(name)) try: @@ -204,7 +204,7 @@ def create_one_stub(self, module_name: str): log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + file_name = "{}/{}.pyi".format(self.path, module_name.replace(".", "/")) gc.collect() result = False try: @@ -219,10 +219,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: Args: - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + - file_name (Optional[str]): the 'path/filename.pyi' to write to. If omitted will be created based on the module name. """ if file_name is None: - fname = module_name.replace(".", "_") + ".py" + fname = module_name.replace(".", "_") + ".pyi" file_name = self.path + "/" + fname else: fname = file_name.split("/")[-1] @@ -249,7 +249,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self.report_add(module_name, file_name) @@ -355,23 +355,27 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = item_type_txt[8:-2] s = "" - if t in ["str", "int", "float", "bool", "bytearray", "bytes"]: + if t in ("str", "int", "float", "bool", "bytearray", "bytes"): # known type: use actual value - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) - elif t in ["dict", "list", "tuple"]: + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, item_repr, t) + elif t in ("dict", "list", "tuple"): # dict, list , tuple: use empty value ev = {"dict": "{}", "list": "[]", "tuple": "()"} - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, ev[t], t) else: # something else - if t in ["object", "set", "frozenset", "Pin", "FileIO"]: + if t in ("object", "set", "frozenset", "Pin", "generator"): # "FileIO" # https://docs.python.org/3/tutorial/classes.html#item_instance-objects - # use these types for the attribute - s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + # use these types for the attribute + if t == "generator": + t = "Generator" + s = "{0}{1}: {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) else: # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1}: {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # log.debug("\n" + s) else: diff --git a/src/stubber/board/createstubs_db_min.py b/src/stubber/board/createstubs_db_min.py index 2ee2f2410..84fabc1db 100644 --- a/src/stubber/board/createstubs_db_min.py +++ b/src/stubber/board/createstubs_db_min.py @@ -1,27 +1,26 @@ -A3='No report file' -A2='Failed to create the report.' -A1='method' -A0='function' -z='bool' -y='str' -x='float' -w='int' -v='micropython' -u='stubber' -t=TypeError -s=Exception -r=KeyError -q=sorted -p=MemoryError -o=NotImplementedError -k=',\n' -j='modules.json' -i='{}/{}' -h='w' -g='dict' -f='list' -e='tuple' -d='_' +A2='No report file' +A1='Failed to create the report.' +A0='method' +z='function' +y='bool' +x='str' +w='float' +v='int' +u='micropython' +t='stubber' +s=TypeError +r=Exception +q=KeyError +p=sorted +o=MemoryError +n=NotImplementedError +j=',\n' +i='modules.json' +h='{}/{}' +g='w' +f='dict' +e='list' +d='tuple' c=str b=repr W='-preview' @@ -50,12 +49,12 @@ except:from json import dumps try:from machine import reset except O:pass -try:from collections import OrderedDict as l -except O:from ucollections import OrderedDict as l +try:from collections import OrderedDict as k +except O:from ucollections import OrderedDict as k __version__='v1.16.3' +A3=2 A4=2 -A5=2 -A6=['lib','/lib','/sd/lib','/flash/lib',J] +A5=['lib','/lib','/sd/lib','/flash/lib',J] class L: INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=S @staticmethod @@ -68,17 +67,17 @@ def warning(A,msg): if A.level<=L.WARNING:A.prnt('WARN :',msg) def error(A,msg): if A.level<=L.ERROR:A.prnt('ERROR :',msg) -A=L.getLogger(u) +A=L.getLogger(t) L.basicConfig(level=L.INFO) class Stubber: def __init__(B,path=E,firmware_id=E): C=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise o('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise n('MicroPython 1.13.0 cannot be stubbed') except I:pass B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[U]));F.collect() if C:B._fwid=C.lower() - elif B.info[Q]==v:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(V) + elif B.info[Q]==u:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(V) else:B._fwid='{family}-v{version}-{port}'.format(**B.info) B._start_free=F.mem_free() if path: @@ -91,20 +90,20 @@ def __init__(B,path=E,firmware_id=E): def get_obj_attributes(L,item_instance): H=item_instance;C=[];K=[] for A in N(H): - if A.startswith(d)and not A in L.modules:continue + if A.startswith('__')and not A in L.modules:continue try: D=getattr(H,A) try:E=b(type(D)).split("'")[1] except T:E=B - if E in{w,x,y,z,e,f,g}:G=1 - elif E in{A0,A1}:G=2 + if E in{v,w,x,y,d,e,f}:G=1 + elif E in{z,A0}:G=2 elif E in'class':G=3 else:G=4 C.append((A,b(D),b(type(D)),D,G)) except I as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,J)) - except p as J:S('MemoryError: {}'.format(J));sleep(1);reset() - C=q([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);F.collect();return C,K - def add_modules(A,modules):A.modules=q(set(A.modules)|set(modules)) + except o as J:S('MemoryError: {}'.format(J));sleep(1);reset() + C=p([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);F.collect();return C,K + def add_modules(A,modules):A.modules=p(set(A.modules)|set(modules)) def create_all_stubs(B): A.info('Start micropython-stubber {} on {}'.format(__version__,B._fwid));B.report_start();F.collect() for C in B.modules:B.create_one_stub(C) @@ -113,58 +112,60 @@ def create_one_stub(C,module_name): B=module_name if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return H if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return H - I='{}/{}.py'.format(C.path,B.replace(J,G));F.collect();E=H + I='{}/{}.pyi'.format(C.path,B.replace(J,G));F.collect();E=H try:E=C.create_module_stub(B,I) except D:return H F.collect();return E def create_module_stub(K,module_name,file_name=E): I=file_name;C=module_name - if I is E:L=C.replace(J,d)+'.py';I=K.path+G+L + if I is E:L=C.replace(J,'_')+'.pyi';I=K.path+G+L else:L=I.split(G)[-1] if G in C:C=C.replace(G,J) N=E try:N=__import__(C,E,E,'*');Q=F.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,Q)) except O:return H X(I) - with M(I,h)as P:S=c(K.info).replace('OrderedDict(',B).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(P,N,C,B) + with M(I,g)as P:S=c(K.info).replace('OrderedDict(',B).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(P,N,C,B) K.report_add(C,I) if C not in{'os','sys','logging','gc'}: try:del N - except(D,r):A.warning('could not del new_module') + except(D,q):A.warning('could not del new_module') F.collect();return R def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() + X='generator';W='{0}{1}: {3} = {2}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return - X,O=K.get_obj_attributes(L) + Y,O=K.get_obj_attributes(L) if O:A.error(O) - for(E,J,G,Y,a)in X: + for(E,J,H,Z,b)in Y: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():A.warning('NameError: invalid name {}'.format(E));continue - if G==""and P(D)<=A5*4: + if H==""and P(D)<=A4*4: Q=B;R=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if R:Q=M C='\n{}class {}({}):\n'.format(D,E,Q) if R:C+=D+' ...\n';I.write(C);continue - I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) - elif any(A in G for A in[A1,A0,'closure']): + I.write(C);K.write_object_stub(I,Z,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) + elif any(A in H for A in[A0,z,'closure']): S=U;T=B if N>0:T='self, ' - if V in G or V in J:C='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,S) + if V in H or V in J:C='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,S) else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,T,S) C+=D+' ...\n\n';I.write(C) - elif G=="":0 - elif G.startswith("":0 + elif H.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] if F in A and A[F]: @@ -247,11 +248,11 @@ def _info(): A[F]='v{}.{}'.format(G&255,G>>8&3) if A[D]and not A[C].endswith(W):A[C]=A[C]+W A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A -def A7(version): +def A6(version): A=version;B=J.join([c(A)for A in A[:3]]) if P(A)>3 and A[3]:B+=V+A[3] return B -def A8(): +def A7(): try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) except O:A.warning('BOARDNAME not found');C=B return C @@ -268,21 +269,21 @@ def Z(filename): if os.stat(filename)[0]>>14:return R return H except D:return H -def m():S("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) +def l():S("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): path=B if P(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:m() - elif P(sys.argv)==2:m() + else:l() + elif P(sys.argv)==2:l() return path -def n(): - try:A=bytes('abc',encoding='utf8');B=n.__module__;return H - except(o,I):return R +def m(): + try:A=bytes('abc',encoding='utf8');B=m.__module__;return H + except(n,I):return R a='modulelist.done' -def A9(skip=0): - for E in A6: +def A8(skip=0): + for E in A5: B=E+'/modulelist.txt' if not Z(B):continue try: @@ -297,9 +298,9 @@ def A9(skip=0): yield A break except D:pass -def AA(done): - with M(a,h)as A:A.write(c(done)+'\n') -def AB(): +def A9(done): + with M(a,g)as A:A.write(c(done)+'\n') +def AA(): A=0 try: with M(a)as B:A=int(B.readline().strip()) @@ -310,14 +311,14 @@ def main(): if C:A.info('Continue from last run') else:A.info('Starting new run') stubber=Stubber(path=read_path());B=0 - if not C:stubber.clean();stubber.report_start(j) - else:B=AB();stubber._json_name=i.format(stubber.path,j) - for E in A9(B): + if not C:stubber.clean();stubber.report_start(i) + else:B=AA();stubber._json_name=h.format(stubber.path,i) + for E in A8(B): try:stubber.create_one_stub(E) - except p:D.reset() - F.collect();B+=1;AA(B) + except o:D.reset() + F.collect();B+=1;A9(B) S('All modules have been processed, Finalizing report');stubber.report_end() -if __name__=='__main__'or n(): +if __name__=='__main__'or m(): if not Z('no_auto_stubber.txt'): try:F.threshold(4*1024);F.enable() except BaseException:pass diff --git a/src/stubber/board/createstubs_db_mpy.mpy b/src/stubber/board/createstubs_db_mpy.mpy index 0af4115e4b3407c93f6f23669b43dc6ab52207b5..707854048b2080a412273f58118cd92eef5d47ca 100644 GIT binary patch delta 5435 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 F{{w-d;xYgL delta 5429 zcmZWNYfu~4db^8w3w(C990U>;(no&)C?;j$e3n zj^nvbJkw!DnaQ6{r~T1RZ)e&;fMc5^_Zq*F+@!hF$&Z$FsAt;VU$=MeT&6$n&5yR< z*;SlJHAs8*JKy=lk31_&nBhy(9&78@eJ$mBIF|Oj`+?%~zyKQhgM+`yXY=eUw9WJ*G zCYIkQ*~905Zi`f+YxB`-^BuES^3QE`wlcQ(*4CBRO7E20UpjGmX84u-7p3VE+tgIv zQ|45=fk+I#UGVMXgsYrzg%d7w!bR>aVU80naO1*xj(UZ2Tt=AXri8Pca4LVS>}2C< z4o^*8nmK>r#Mv`bQ*c^^Zx4L6<=>Y5xs884f4h2n{>$nCXT!D5`DkoLFL$vD)0cR#N@00-&0_3ivYE0&l9g`cV1``9-V#=W{nDPi=Du|_+ zmWVW9!?YBMn3f?4({kj%v_hnnm{y6j8dLjzOly#w7q_^LI!x;k#?&d&222~rFm<7N zOx-C=n?$-5Qx9@t+Kgb+n@hPGG4;X2gmds}kI4|@T(A5$eW;$)l8^)aBqz`-Jz zpF}N~`YEOX_y$ocYC|Cu7O67~nztN?aVVk+I3h;mc9ERbcuZSi-GQQF#L=lyE^{Ep zqb@+{iV3(UR$}13m<-m zQmt~CRMtT69H>B%JMo_3VO~Q6K#L2p5_}xx4^>vQzntrrA}W`iZM1jL)@W{5VbK{)Whob`y+B)OXKrxO z5tYCk-{_-@hD;oY$OTORVQ59DcFsf@vQS7J!!c3t_b59|l-)&?`WGlp3*~lSMQ7KY z;Xe~^p}!0-$aFcPKKP zGF5@ZL?nPnP^nX}Qm;6bhHyC?Z$YFLkv2p^N~7WmmjWmpW*S8#+60d+5_Q3&J(bO0 zUzK8{BSK@j*IL7>((3WG?CcEtJRy(b2^1a~VeWC5dm>SJN#&p) zrDCwVvTQ5-V$1u(Ekt@)8W8&u#Ggc+X8dWw_ZEUcd6NInI!_%l*Gl&N!ykwm(P%yG zp<3>8-ibYibxzO(M7C`{WyFBW=H1Q52}q=!j3RHOpTcuxL*Kh%@^J$zO@OFsdX|Kc zjI6*4{t)R^ZO^{Tolh;3`Q-S@-Fv3{M`|F5pzG`gi@CCsQV%#aV@MP)OXP+s?AiC3 zL`xt)A@GQzfLz{UUTsHYhbDZk_<S+vyG(&;88f-5!qQ&(+r(Ay1ztq=sEe%QHlFeu~Jh&+dMX$iT0b zz9@XT@{cb_eFUO|i&GY(RyqEW>Ecut#O#1|r|{LUf2j|%?H#`aF@7;M`fFQfX%Gd) z7FSRTI{XNcK|~UW46TN38+szK)sJ#US|+;2>H96ZZF1a?Ou`91;8H^C`rik>SnX1o6i*F)I8Rq)mK%1755(C=~zLFCj7_$Cp7G0nkS`ACOJ0H1mlP z*#s*16Q#XKpm_e@sYLtyu4WGM5YqA#A}@za-e6@&|0Z`o2zALDbUw)ai@qC?y+P-_ zfNNvurF(wS*w7Cu9U!5`D^W|(daVR_BwkTEt#_xtUbC4@5!v@+uD>H-q^@;+DDfY# zVrAnMsEw8y%(8j&$XQsFXi<%dAu0LzH}2F4)q#~j0ikmjH! zf(i9gkrD(Y(wIgB{KLTmGMt|dHnNj&u+iU;E}otDHz0BVku)L`h#W-ZP`DJbUWr+l z4FQ*5)JlQLf&0M*rTYccu)r^jpO|DzMU~?Lml+4_6?knbJ)6u=|8Omp<;mek1Be_W zy-+saA1{oLk5)cf3UC|8GKn4-RC+Ur_-KFbuiIiQ-_{VxJX)F>t$kd8%v@&uLs(06 z7P9YNe$NqaCN;E~*mFORM73xjl z4@GHdTIC6A{+dyQlWX5&2oXpxX#dUA5;;4)gvitj^q*oYy>JYQ(@4Pf3@5=v1jd%N?uf{*lp);)A*?tu~YMPn_V5EFT5SR&^oavUb8BvcMl z4MYw@G2QkU_S=VEHdQc1P3$R-4a#<~IO`aQ94U5;Ck%~QnF)q1!SItt^#*joGByUWcIae_M@!k|%m0NA4CcOp0Q73HSX_ZcN3_icNzfnL zrpEgFyP~0>r#IpWwe@&>O4&n{SVKdPkp39$eu7?liuOE1$xqSnXK3Vei7Jsw$?X_* zye!e$X^_wiCF*^^*7keTu(uZ`;AylkPqw;^U5HhwVKlZ1z=_0B_DHX+10-cZ_L~s2 ze_c;5TabaID4j7`I8`1%%@aQwxs%5cR3@1rsQd=ZrWz4FaNhY}$9bhOf#%o6Ev$)($gJcgT zRv)B?Uil72Em-1Jkk};3PV9wUw}a{NU?MRv;s6;MVLX+{xll>*3IS}IAxgaK`guUz zy9|@!#@E~RH^B;~MqhsHIK*%!%+pnjzz*WAI+N!hbG{tb*Y#)8D-30eb#(HJB8YzXU!Kh^{=|Miw@`isyS>NLDMLUj-na#COU?W zqZ8<4xY{qi_lI;)@=N+|zqERH0-b^`F8YY^d%t-54>y0W39I*+UG&$B9L#_m+GoDO zdXp_ogfVnlj+mQ^SAj0 zFWx_!`yWqBR}%j9a1Q=6aNd3HVX=5tK>C`wJJJ9KhdC}~Zp@(PgMLz%X1oHR@h7i~Y8I$mgoPLfaRrd|i=b9UyPZ zkNf<_)rDGiGpJ&P+bv%stc+xDIi1q=1>|oJM_W{I?L!!Az_;@%e{)?w!d8%>aPwO$ zDAgMWoq;k2w~rR zBwfkxQW{E2HBO$$Pb&3%S^lD;j+N8s0?f@=B8RP><1p(bn||3fr;_z)D8#Ak&BONv ziBv6gz|Fc<$vsSZtWzq#M_iN2p~zaK|D?E$>IJnu8j5PYA+=3|{~jq1r7OTd<<|;2 zR29~SYk+QI#9G%fr*$Ei_OGj)O1Ve5$AzJB=n6G(Q-DXUM6NURL%?6<9-IAjiCqo= zEG)4*D6zr(J~gU7Nmc>=E@U=t(Yo6W!`;XSgnl?mFO%N@nQ}OkNkGEc71o#Gqy%`W G?Ee96ZQtDh diff --git a/src/stubber/board/createstubs_mem.py b/src/stubber/board/createstubs_mem.py index 9ea19f27b..cc1021ac7 100644 --- a/src/stubber/board/createstubs_mem.py +++ b/src/stubber/board/createstubs_mem.py @@ -140,7 +140,7 @@ def get_obj_attributes(self, item_instance: object): _errors = [] # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: + if name.startswith("__") and not name in self.modules: continue # log.debug("get attribute {}".format(name)) try: @@ -195,7 +195,7 @@ def create_one_stub(self, module_name: str): log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + file_name = "{}/{}.pyi".format(self.path, module_name.replace(".", "/")) gc.collect() result = False try: @@ -210,10 +210,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: Args: - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + - file_name (Optional[str]): the 'path/filename.pyi' to write to. If omitted will be created based on the module name. """ if file_name is None: - fname = module_name.replace(".", "_") + ".py" + fname = module_name.replace(".", "_") + ".pyi" file_name = self.path + "/" + fname else: fname = file_name.split("/")[-1] @@ -240,7 +240,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") self.report_add(module_name, file_name) @@ -346,23 +346,27 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = item_type_txt[8:-2] s = "" - if t in ["str", "int", "float", "bool", "bytearray", "bytes"]: + if t in ("str", "int", "float", "bool", "bytearray", "bytes"): # known type: use actual value - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) - elif t in ["dict", "list", "tuple"]: + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, item_repr, t) + elif t in ("dict", "list", "tuple"): # dict, list , tuple: use empty value ev = {"dict": "{}", "list": "[]", "tuple": "()"} - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, ev[t], t) else: # something else - if t in ["object", "set", "frozenset", "Pin", "FileIO"]: + if t in ("object", "set", "frozenset", "Pin", "generator"): # "FileIO" # https://docs.python.org/3/tutorial/classes.html#item_instance-objects - # use these types for the attribute - s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + # use these types for the attribute + if t == "generator": + t = "Generator" + s = "{0}{1}: {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) else: # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1}: {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # log.debug("\n" + s) else: diff --git a/src/stubber/board/createstubs_mem_min.py b/src/stubber/board/createstubs_mem_min.py index 589d31bec..fd4b408f6 100644 --- a/src/stubber/board/createstubs_mem_min.py +++ b/src/stubber/board/createstubs_mem_min.py @@ -1,23 +1,22 @@ -y='No report file' -x='Failed to create the report.' -w='{}/{}' -v='method' -u='function' -t='bool' -s='str' -r='float' -q='int' -p='stubber' -o=TypeError -n=Exception -m=KeyError -l=sorted -k=NotImplementedError -f=',\n' -e='dict' -d='list' -c='tuple' -b='_' +x='No report file' +w='Failed to create the report.' +v='{}/{}' +u='method' +t='function' +s='bool' +r='str' +q='float' +p='int' +o='stubber' +n=TypeError +m=Exception +l=KeyError +k=sorted +j=NotImplementedError +e=',\n' +d='dict' +c='list' +b='tuple' a='micropython' Z=repr W='-preview' @@ -46,12 +45,12 @@ except:from json import dumps try:from machine import reset except N:pass -try:from collections import OrderedDict as g -except N:from ucollections import OrderedDict as g +try:from collections import OrderedDict as f +except N:from ucollections import OrderedDict as f __version__='v1.16.3' +y=2 z=2 -A0=2 -A1=['lib','/lib','/sd/lib','/flash/lib',J] +A0=['lib','/lib','/sd/lib','/flash/lib',J] class L: INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=S @staticmethod @@ -64,13 +63,13 @@ def warning(A,msg): if A.level<=L.WARNING:A.prnt('WARN :',msg) def error(A,msg): if A.level<=L.ERROR:A.prnt('ERROR :',msg) -A=L.getLogger(p) +A=L.getLogger(o) L.basicConfig(level=L.INFO) class Stubber: def __init__(B,path=E,firmware_id=E): C=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') except I:pass B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[U]));D.collect() if C:B._fwid=C.lower() @@ -87,20 +86,20 @@ def __init__(B,path=E,firmware_id=E): def get_obj_attributes(L,item_instance): H=item_instance;C=[];K=[] for A in M(H): - if A.startswith(b)and not A in L.modules:continue + if A.startswith('__')and not A in L.modules:continue try: E=getattr(H,A) try:F=Z(type(E)).split("'")[1] except T:F=B - if F in{q,r,s,t,c,d,e}:G=1 - elif F in{u,v}:G=2 + if F in{p,q,r,s,b,c,d}:G=1 + elif F in{t,u}:G=2 elif F in'class':G=3 else:G=4 C.append((A,Z(E),Z(type(E)),E,G)) except I as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,J)) except MemoryError as J:S('MemoryError: {}'.format(J));sleep(1);reset() - C=l([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,K - def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) + C=k([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,K + def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) def create_all_stubs(B): A.info('Start micropython-stubber {} on {}'.format(__version__,B._fwid));B.report_start();D.collect() for C in B.modules:B.create_one_stub(C) @@ -109,58 +108,60 @@ def create_one_stub(C,module_name): B=module_name if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return H if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return H - I='{}/{}.py'.format(C.path,B.replace(J,G));D.collect();E=H + I='{}/{}.pyi'.format(C.path,B.replace(J,G));D.collect();E=H try:E=C.create_module_stub(B,I) except F:return H D.collect();return E def create_module_stub(K,module_name,file_name=E): I=file_name;C=module_name - if I is E:L=C.replace(J,b)+'.py';I=K.path+G+L + if I is E:L=C.replace(J,'_')+'.pyi';I=K.path+G+L else:L=I.split(G)[-1] if G in C:C=C.replace(G,J) M=E try:M=__import__(C,E,E,'*');Q=D.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,Q)) except N:return H X(I) - with O(I,'w')as P:S=str(K.info).replace('OrderedDict(',B).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(P,M,C,B) + with O(I,'w')as P:S=str(K.info).replace('OrderedDict(',B).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(P,M,C,B) K.report_add(C,I) if C not in{'os','sys','logging','gc'}: try:del M - except(F,m):A.warning('could not del new_module') + except(F,l):A.warning('could not del new_module') D.collect();return R def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;E=indent;D.collect() + X='generator';W='{0}{1}: {3} = {2}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;E=indent;D.collect() if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return - X,O=K.get_obj_attributes(L) + Y,O=K.get_obj_attributes(L) if O:A.error(O) - for(F,J,G,Y,a)in X: + for(F,J,H,Z,e)in Y: if F in['classmethod','staticmethod','BaseException',M]:continue if F[0].isdigit():A.warning('NameError: invalid name {}'.format(F));continue - if G==""and P(E)<=A0*4: + if H==""and P(E)<=z*4: Q=B;R=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] if R:Q=M C='\n{}class {}({}):\n'.format(E,F,Q) if R:C+=E+' ...\n';I.write(C);continue - I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',N+1);C=E+' def __init__(self, *argv, **kwargs) -> None:\n';C+=E+' ...\n\n';I.write(C) - elif any(A in G for A in[v,u,'closure']): + I.write(C);K.write_object_stub(I,Z,'{0}.{1}'.format(obj_name,F),E+' ',N+1);C=E+' def __init__(self, *argv, **kwargs) -> None:\n';C+=E+' ...\n\n';I.write(C) + elif any(A in H for A in[u,t,'closure']): S=U;T=B if N>0:T='self, ' - if V in G or V in J:C='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) + if V in H or V in J:C='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,T,S) C+=E+' ...\n\n';I.write(C) - elif G=="":0 - elif G.startswith("":0 + elif H.startswith(">8&3) if A[D]and not A[C].endswith(W):A[C]=A[C]+W A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A -def A2(version): +def A1(version): A=version;B=J.join([str(A)for A in A[:3]]) if P(A)>3 and A[3]:B+=V+A[3] return B -def A3(): +def A2(): try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) except N:A.warning('BOARDNAME not found');C=B return C @@ -259,30 +260,30 @@ def get_root(): try:C=os.stat(B);break except F:continue return B -def h(filename): +def g(filename): try: if os.stat(filename)[0]>>14:return R return H except F:return H -def i():S("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) +def h():S("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): path=B if P(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:i() - elif P(sys.argv)==2:i() + else:h() + elif P(sys.argv)==2:h() return path -def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return H - except(k,I):return R +def i(): + try:A=bytes('abc',encoding='utf8');B=i.__module__;return H + except(j,I):return R def main(): stubber=Stubber(path=read_path());stubber.clean() def A(stubber): D.collect();stubber.modules=[] - for C in A1: + for C in A0: B=C+'/modulelist.txt' - if not h(B):continue + if not g(B):continue with O(B)as E: while R: A=E.readline().strip() @@ -292,8 +293,8 @@ def A(stubber): if not stubber.modules:stubber.modules=[a] D.collect() stubber.modules=[];A(stubber);D.collect();stubber.create_all_stubs() -if __name__=='__main__'or j(): - if not h('no_auto_stubber.txt'): +if __name__=='__main__'or i(): + if not g('no_auto_stubber.txt'): try:D.threshold(4*1024);D.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mem_mpy.mpy b/src/stubber/board/createstubs_mem_mpy.mpy index eb8daf6f83ad45482c138f2301d8e368bed13488..945f69346e36576e847d613426c63f93116273da 100644 GIT binary patch delta 5280 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 V(eNipPRSd{$$<4T+9Hf5{s-bbyI24K delta 5209 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'.format(C,L,P)) except N:return H W(I) - with Q(I,'w')as O:R=str(K.info).replace('OrderedDict(',B).replace('})','}');S='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,R,__version__);O.write(S);O.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(O,M,C,B) + with Q(I,'w')as O:R=str(K.info).replace('OrderedDict(',B).replace('})','}');S='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,R,__version__);O.write(S);O.write('from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(O,M,C,B) K.report_add(C,I) - if C not in{'os',w,x,'gc'}: + if C not in{'os',v,w,'gc'}: try:del M - except(E,m):A.warning('could not del new_module') + except(E,l):A.warning('could not del new_module') F.collect();return U def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() + X='generator';W='{0}{1}: {3} = {2}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return - X,O=K.get_obj_attributes(L) + Y,O=K.get_obj_attributes(L) if O:A.error(O) - for(E,J,G,Y,a)in X: + for(E,J,H,Z,e)in Y: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():A.warning('NameError: invalid name {}'.format(E));continue - if G==""and R(D)<=A2*4: + if H==""and R(D)<=A1*4: P=B;Q=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] if Q:P=M C='\n{}class {}({}):\n'.format(D,E,P) if Q:C+=D+' ...\n';I.write(C);continue - I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) - elif any(A in G for A in[v,u,'closure']): + I.write(C);K.write_object_stub(I,Z,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) + elif any(A in H for A in[u,t,'closure']): S=U;T=B if N>0:T='self, ' - if V in G or V in J:C='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,S) + if V in H or V in J:C='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,S) else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,T,S) C+=D+' ...\n\n';I.write(C) - elif G=="":0 - elif G.startswith("":0 + elif H.startswith(">8&3) if A[E]and not A[C].endswith(V):A[C]=A[C]+V A[L]=f"{A[C]}-{A[E]}"if A[E]else f"{A[C]}";return A -def A3(version): +def A2(version): A=version;B=J.join([str(A)for A in A[:3]]) if R(A)>3 and A[3]:B+=T+A[3] return B -def A4(): +def A3(): try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) except N:A.warning('BOARDNAME not found');C=B return C @@ -262,26 +263,26 @@ def get_root(): try:C=os.stat(B);break except E:continue return B -def A5(filename): +def A4(filename): try: if os.stat(filename)[0]>>14:return U return H except E:return H -def i():Y("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) +def h():Y("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): path=B if R(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:i() - elif R(sys.argv)==2:i() + else:h() + elif R(sys.argv)==2:h() return path -def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return H - except(k,I):return U -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',x,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',a,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform','pyb',g,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',w,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];F.collect();stubber.create_all_stubs() -if __name__=='__main__'or j(): - if not A5('no_auto_stubber.txt'): +def i(): + try:A=bytes('abc',encoding='utf8');B=i.__module__;return H + except(j,I):return U +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',w,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',a,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform','pyb',f,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',v,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];F.collect();stubber.create_all_stubs() +if __name__=='__main__'or i(): + if not A4('no_auto_stubber.txt'): try:F.threshold(4*1024);F.enable() except BaseException:pass main() \ No newline at end of file diff --git a/src/stubber/board/createstubs_mpy.mpy b/src/stubber/board/createstubs_mpy.mpy index b8595e61d3c6007a02a4f8fb667a3b16f61f82f4..759ffb75675f95be3edf0bc4a26ca6dae350a12f 100644 GIT binary patch delta 5653 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 aKCl8{g?@TLTus-n3s^yKG$jW*_x}OefFYm& delta 5413 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 X5cno9J1<`0UX9=4Jq<7c!m Date: Fri, 2 Feb 2024 14:52:52 +0100 Subject: [PATCH 63/68] Update launch.json and tasks.json Signed-off-by: Jos Verlinde --- .vscode/launch.json | 14 +++++++++----- .vscode/tasks.json | 26 ++++++-------------------- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 383cbd072..ce1a09a37 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "name": "dgb pytest --collect-only", + "name": "Pytest --collect-only (debug)", "type": "python", "request": "launch", "module": "pytest", @@ -86,13 +86,17 @@ ] }, { - "name": "Python: stubber get-docstubs", + "name": "Python: board_stubber", "type": "python", "request": "launch", - "module": "stubber.stubber", + "program": "scripts/board_stubber.py", + "cwd": "${workspaceFolder}", "args": [ - "get-docstubs" - ] + "--format", + "mpy", + "--debug" + ], + "console": "integratedTerminal" }, { "name": "Python: Current File", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index c04afd0b3..2bc92caa5 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -8,36 +8,22 @@ "detail": "run createstubs in linux port", "type": "shell", "windows": { - "command": "ubuntu run MICROPYPATH=./board ./tools/micropython board/createstubs.py" + "command": "ubuntu run MICROPYPATH=./src/stubber/board ./tests/tools/ubuntu_20_04/micropython_v1_21_0 src/stubber/board/createstubs.py" }, "linux": { - "command": "MICROPYPATH=./board ./tools/micropython board/createstubs.py" + "command": "MICROPYPATH=./src/stubber/board ./tests/tools/ubuntu_20_04/micropython_v1_21_0 src/stubber/board/createstubs.py" }, "problemMatcher": [] }, { - "label": "minify", - "detail": "minify for esp8622", - "type": "shell", - "command": "poetry run stubber minify --all --compile", - "problemMatcher": [], - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "label": "run minified", - "detail": "run minified createstubs in linux port", - "dependsOn": [ - "minify" - ], + "label": "run createstubs_db", + "detail": "run createstubs_db in linux port", "type": "shell", "windows": { - "command": "ubuntu run ./tools/micropython minified/createstubs.py" + "command": "ubuntu run MICROPYPATH=./src/stubber/board ./tests/tools/ubuntu_20_04/micropython_v1_21_0 src/stubber/board/createstubs_db.py" }, "linux": { - "command": "./tools/micropython minified/createstubs.py" + "command": "MICROPYPATH=./src/stubber/board ./tests/tools/ubuntu_20_04/micropython_v1_21_0 src/stubber/board/createstubs_db.py" }, "problemMatcher": [] }, From d3a35e0e3fcecb46a7763da803529f392e7865ef Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Fri, 2 Feb 2024 21:20:55 +0100 Subject: [PATCH 64/68] chore: use 'preview' naming in version Signed-off-by: Jos Verlinde --- src/stubber/publish/merge_docstubs.py | 12 +++--- src/stubber/utils/versions.py | 26 +++++++++++-- tests/createstubs/createstubs_all_test.py | 44 +++++++--------------- tests/createstubs/literal_test.py | 2 +- tests/minify/test_minify_script.py | 5 +-- tests/native/native_createstubs_test.py | 10 ++--- tests/publish/test_merge.py | 17 ++++++--- tests/publish/test_pathnames.py | 42 +++++++++++++++++++++ tests/util_test.py | 46 +++++++++-------------- 9 files changed, 119 insertions(+), 85 deletions(-) create mode 100644 tests/publish/test_pathnames.py diff --git a/src/stubber/publish/merge_docstubs.py b/src/stubber/publish/merge_docstubs.py index 74ae2cc1c..f1934a7d6 100644 --- a/src/stubber/publish/merge_docstubs.py +++ b/src/stubber/publish/merge_docstubs.py @@ -49,9 +49,7 @@ def merge_all_docstubs( for candidate in candidates: # use the default board for the port if candidate["board"] in GENERIC: - candidate["board"] = default_board( - port=candidate["port"], version=candidate["version"] - ) + candidate["board"] = default_board(port=candidate["port"], version=candidate["version"]) # check if we have board stubs of this version and port doc_path = CONFIG.stub_path / f"{get_base(candidate)}-docstubs" # src and dest paths @@ -120,13 +118,13 @@ def copy_and_merge_docstubs(fw_path: Path, dest_path: Path, docstub_path: Path): "pycopy_imphook", # is not intended to be used directly, and has an unresolved subclass ]: for suffix in [".py", ".pyi"]: - if (dest_path / name).with_suffix(suffix).exists(): # type: ignore - (dest_path / name).with_suffix(suffix).unlink() # type: ignore + if (dest_path / name).with_suffix(suffix).exists(): # type: ignore + (dest_path / name).with_suffix(suffix).unlink() # type: ignore # 2 - Enrich the firmware stubs with the document stubs result = enrich_folder(dest_path, docstub_path=docstub_path, write_back=True) # copy the docstubs manifest.json file to the package folder - # if (docstub_path / "modules.json").exists(): - shutil.copy(docstub_path / "modules.json", dest_path / "doc_stubs.json") + if (docstub_path / "modules.json").exists(): + shutil.copy(docstub_path / "modules.json", dest_path / "doc_stubs.json") return result diff --git a/src/stubber/utils/versions.py b/src/stubber/utils/versions.py index d1494670c..61fe0cfbe 100644 --- a/src/stubber/utils/versions.py +++ b/src/stubber/utils/versions.py @@ -15,9 +15,9 @@ def clean_version( ): "Clean up and transform the many flavours of versions" # 'v1.13.0-103-gb137d064e' --> 'v1.13-103' - if version in {"", "-"}: return version + is_preview = "-preview" in version nibbles = version.split("-") ver_ = nibbles[0].lower().lstrip("v") if not patch and ver_ >= "1.10.0" and ver_ < "1.20.0" and ver_.endswith(".0"): @@ -25,12 +25,15 @@ def clean_version( nibbles[0] = nibbles[0][:-2] if len(nibbles) == 1: version = nibbles[0] - elif build: + elif build and not is_preview: version = "-".join(nibbles) if commit else "-".join(nibbles[:-1]) else: # version = "-".join((nibbles[0], LATEST)) # HACK: this is not always right, but good enough most of the time - version = "latest" + if is_preview: + version = "-".join((nibbles[0], "preview")) + else: + version = "latest" if flat: version = version.strip().replace(".", "_") else: @@ -40,6 +43,7 @@ def clean_version( version = version.lstrip("v") elif not version.startswith("v") and version.lower() != "latest": version = "v" + version + return version @@ -50,4 +54,18 @@ def micropython_versions(start: str = "v1.9.2"): repo = g.get_repo("micropython/micropython") return [tag.name for tag in repo.get_tags() if parse(tag.name) >= parse(start)] except Exception: - return ["v1.19.1", "v1.19", "v1.18", "v1.17", "v1.16", "v1.15", "v1.14", "v1.13", "v1.12", "v1.11", "v1.10", "v1.9.4", "v1.9.3"] + return [ + "v1.19.1", + "v1.19", + "v1.18", + "v1.17", + "v1.16", + "v1.15", + "v1.14", + "v1.13", + "v1.12", + "v1.11", + "v1.10", + "v1.9.4", + "v1.9.3", + ] diff --git a/tests/createstubs/createstubs_all_test.py b/tests/createstubs/createstubs_all_test.py index 85fa99237..b48c91a84 100644 --- a/tests/createstubs/createstubs_all_test.py +++ b/tests/createstubs/createstubs_all_test.py @@ -42,24 +42,6 @@ def test_firmwarestubber_all_versions_same( assert FIRST_VERSION == parse(createstubs.__version__) -@pytest.mark.parametrize("variant", VARIANTS) -@pytest.mark.parametrize("location", LOCATIONS) -@pytest.mark.skip(reason="not sure if this is needed") -def test_firmwarestubber_base_version_match_package( - location: Any, - variant: str, - mock_micropython_path: Generator[str, None, None], -): - # Q&D Location - path = Path(__file__).resolve().parents[2] / "pyproject.toml" - pyproject = tomllib.loads(open(str(path)).read()) - pyproject_version = pyproject["tool"]["poetry"]["version"] - - createstubs = import_variant(location, variant) - # base version should match the package - assert parse(createstubs.__version__).base_version == parse(pyproject_version).base_version - - @pytest.mark.parametrize("variant", VARIANTS) @pytest.mark.parametrize("location", LOCATIONS) def test_stubber_Class_available( @@ -223,9 +205,8 @@ def test_create_all_stubs( stubber.add_modules(["http_client", "webrepl", "_internal"]) stubber.create_all_stubs() - stublist = list(tmp_path.glob("**/*.py")) + stublist = list(tmp_path.glob("**/*.pyi")) assert len(stublist) == 3 - stubber.report() stublist = list(tmp_path.glob("**/modules.json")) assert len(stublist) == 1 @@ -261,11 +242,12 @@ def test_create_module_stub( myid = "MyCustomID" stubber = createstubs.Stubber(path=str(tmp_path), firmware_id=myid) # type: ignore assert stubber is not None, "Can't create Stubber instance" + stubber.report_start() # just in the test folder , no structure - stubber.create_module_stub("json", str(tmp_path / "json.py")) - stubber.create_module_stub("_thread", str(tmp_path / "_thread.py")) + stubber.create_module_stub("json", str(tmp_path / "json.pyi")) + stubber.create_module_stub("_thread", str(tmp_path / "_thread.pyi")) - stublist = list(tmp_path.glob("**/*.py")) + stublist = list(tmp_path.glob("**/*.pyi")) assert len(stublist) == 2 @@ -282,9 +264,9 @@ def test_create_module_stub_folder( myid = "MyCustomID" stubber = createstubs.Stubber(path=str(tmp_path), firmware_id=myid) # type: ignore assert stubber is not None, "Can't create Stubber instance" - + stubber.report_start() stubber.create_module_stub("json") - stublist = list((tmp_path / "stubs" / myid.lower()).glob("**/*.py")) + stublist = list((tmp_path / "stubs" / myid.lower()).glob("**/*.pyi")) assert len(stublist) == 1, "should create stub in stub folder if no folder specified" @@ -323,9 +305,10 @@ def test_nested_modules( myid = "MyCustomID" stubber = createstubs.Stubber(path=str(tmp_path), firmware_id=myid) # type: ignore assert stubber is not None, "Can't create Stubber instance" + stubber.report_start() # just in the test folder , no structure - stubber.create_module_stub("urllib/request", str(tmp_path / "request.py")) - stublist = list(tmp_path.glob("**/*.py")) + stubber.create_module_stub("urllib/request", str(tmp_path / "request.pyi")) + stublist = list(tmp_path.glob("**/*.pyi")) assert len(stublist) == 1 @@ -342,10 +325,11 @@ def test_unavailable_modules( myid = "MyCustomID" stubber = createstubs.Stubber(path=str(tmp_path), firmware_id=myid) # type: ignore assert stubber is not None, "Can't create Stubber instance" + stubber.report_start() # this should not generate a module , but also should not th - stubber.create_module_stub("notamodule1", str(tmp_path / "notamodule1.py")) - stubber.create_module_stub("not/amodule2", str(tmp_path / "notamodule2.py")) - stublist = list(tmp_path.glob("**/*.py")) + stubber.create_module_stub("notamodule1", str(tmp_path / "notamodule1.pyi")) + stubber.create_module_stub("not/amodule2", str(tmp_path / "notamodule2.pyi")) + stublist = list(tmp_path.glob("**/*.pyi")) assert len(stublist) == 0 diff --git a/tests/createstubs/literal_test.py b/tests/createstubs/literal_test.py index 89ac033ba..3558d1323 100644 --- a/tests/createstubs/literal_test.py +++ b/tests/createstubs/literal_test.py @@ -94,7 +94,7 @@ def test_literal_init_order( # check literals defined before first method class_line = lines.index("class SoftSPI():") - LSB_line = lines.index(" LSB = 1 # type: int", class_line + 1) + LSB_line = lines.index(" LSB: int = 1", class_line + 1) init_line = lines.index(" def __init__(self, *argv, **kwargs) -> None:", class_line + 1) assert class_line < LSB_line < init_line, "Literals MUST be listed before class methods" diff --git a/tests/minify/test_minify_script.py b/tests/minify/test_minify_script.py index 3ebcc7886..30b971bde 100644 --- a/tests/minify/test_minify_script.py +++ b/tests/minify/test_minify_script.py @@ -64,9 +64,7 @@ def test_get_whitespace_context(content, index, expected): # Happy path tests ( ["#0", "__version__ = 1", "print('Hello, World!')", ""], - # ["#0", "__version__ = 1", "# print('Hello, World!')", ""], - ["__version__=1"], - # "\n".join(["__version__=1"]), + ["__version__=1", "print('Hello, World!')"], True, ), ( @@ -100,5 +98,6 @@ def test_minify_script(source_script, expected, keep_report): result = minify_script(source, keep_report, diff=True) result = result.split("\n") + assert len(result) == len(expected), "Lengths do not match" for i, line in enumerate(result): assert expected[i] == line diff --git a/tests/native/native_createstubs_test.py b/tests/native/native_createstubs_test.py index c9c851f04..640783454 100644 --- a/tests/native/native_createstubs_test.py +++ b/tests/native/native_createstubs_test.py @@ -65,9 +65,7 @@ "firmware", fw_list, ) -def test_createstubs( - firmware: str, variant: str, suffix: str, tmp_path: Path, pytestconfig: Config -): +def test_createstubs(firmware: str, variant: str, suffix: str, tmp_path: Path, pytestconfig: Config): "run createstubs in the native (linux/windows) version of micropython" # all createstub variants are in the same folder script_path = (pytestconfig.rootpath / "src" / "stubber" / "board").absolute() @@ -106,7 +104,7 @@ def test_createstubs( # did it run without error ? stub_path = tmp_path / "stubs" - stubfiles = list(stub_path.rglob("*.py")) + stubfiles = list(stub_path.rglob("*.pyi")) # manifest exists jsons = list(stub_path.rglob("modules.json")) @@ -121,9 +119,7 @@ def test_createstubs( for x in ["firmware", "stubber", "modules"]: assert x in manifest.keys(), "module manifest should contain firmware, stubber , modules" - assert ( - len(manifest["modules"]) - len(stubfiles) == 0 - ), "number of modules must match count of stubfiles." + assert len(manifest["modules"]) - len(stubfiles) == 0, "number of modules must match count of stubfiles." # Delete databaseafter the test if variant == "createstubs_db": (script_path / "modulelist.done").unlink(missing_ok=False) # MUST exist diff --git a/tests/publish/test_merge.py b/tests/publish/test_merge.py index eec6c1856..32a75708d 100644 --- a/tests/publish/test_merge.py +++ b/tests/publish/test_merge.py @@ -1,7 +1,9 @@ from pathlib import Path + import pytest from mock import MagicMock -from stubber.publish.merge_docstubs import merge_all_docstubs, copy_and_merge_docstubs + +from stubber.publish.merge_docstubs import copy_and_merge_docstubs, merge_all_docstubs from .fakeconfig import FakeConfig @@ -25,8 +27,12 @@ def test_merge_all_docstubs_mocked(mocker, tmp_path, pytestconfig): {"family": "micropython", "version": "1.19.1", "port": "esp32", "board": "generic"}, ], ) - m_copy_and_merge_docstubs: MagicMock = mocker.patch("stubber.publish.merge_docstubs.copy_and_merge_docstubs", autospec=True) - m_add_machine_pin_call: MagicMock = mocker.patch("stubber.publish.merge_docstubs.add_machine_pin_call", autospec=True) + m_copy_and_merge_docstubs: MagicMock = mocker.patch( + "stubber.publish.merge_docstubs.copy_and_merge_docstubs", autospec=True + ) + m_add_machine_pin_call: MagicMock = mocker.patch( + "stubber.publish.merge_docstubs.add_machine_pin_call", autospec=True + ) # mock pathlib.Path.exists to return True so there is no dependency of folders existing on the test system mocker.patch("stubber.publish.merge_docstubs.Path.exists", autospec=True, return_value=True) @@ -44,7 +50,9 @@ def test_copydocstubs_mocked(mocker, tmp_path, pytestconfig): config = FakeConfig(tmp_path=tmp_path, rootpath=pytestconfig.rootpath) mocker.patch("stubber.publish.merge_docstubs.CONFIG", config) - m_enrich_folder: MagicMock = mocker.patch("stubber.publish.merge_docstubs.enrich_folder", autospec=True, return_value=42) + m_enrich_folder: MagicMock = mocker.patch( + "stubber.publish.merge_docstubs.enrich_folder", autospec=True, return_value=42 + ) m_copytree: MagicMock = mocker.patch("stubber.publish.merge_docstubs.shutil.copytree", autospec=True) m_copy: MagicMock = mocker.patch("stubber.publish.merge_docstubs.shutil.copy", autospec=True) @@ -57,4 +65,3 @@ def test_copydocstubs_mocked(mocker, tmp_path, pytestconfig): assert result == 42 assert m_enrich_folder.call_count == 1 assert m_copytree.call_count == 1 - assert m_copy.call_count == 1 diff --git a/tests/publish/test_pathnames.py b/tests/publish/test_pathnames.py new file mode 100644 index 000000000..157f9ad0b --- /dev/null +++ b/tests/publish/test_pathnames.py @@ -0,0 +1,42 @@ +import pytest + +from stubber.publish.pathnames import board_folder_name, get_base + + +@pytest.mark.parametrize( + "expected_base, candidate, version", + [ + ("micropython-v1_22", {"family": "MicroPython", "version": "1.22"}, None), + ("micropython-v1_22_1", {"family": "MicroPython", "version": "1.22"}, "1.22.1"), + ("micropython-v1_22_2", {"family": "MicroPython"}, "1.22.2"), + ("micropython-v1_23_0-preview", {"family": "MicroPython", "version": "1.23.0-preview"}, None), + ], +) +def test_get_base_with_version(expected_base, candidate, version): + base = get_base(candidate, version) + assert base == expected_base + + +@pytest.mark.parametrize( + "expected_folder_name, fw, version ", + [ + ( + "micropython-v1_22_1-esp8266-ESP8266_GENERIC", + {"family": "MicroPython", "port": "esp8266", "board": "ESP8266_GENERIC", "version": "1.22.1"}, + None, + ), + ( + "micropython-v1_23_4-esp8266-ESP8266_GENERIC", + {"family": "MicroPython", "port": "esp8266", "board": "ESP8266_GENERIC", "version": "1.23.4"}, + "1.23.4", + ), + ( + "micropython-v1_23_5-preview-esp8266-ESP8266_GENERIC", + {"family": "MicroPython", "port": "esp8266", "board": "ESP8266_GENERIC", "version": "1.23.5-preview"}, + "1.23.5-preview", + ), + ], +) +def test_board_folder_name(expected_folder_name: str, fw: dict, version: str): + folder_name = board_folder_name(fw, version=version) + assert folder_name == expected_folder_name diff --git a/tests/util_test.py b/tests/util_test.py index 090f4e25c..79924b9b9 100644 --- a/tests/util_test.py +++ b/tests/util_test.py @@ -12,49 +12,45 @@ @pytest.mark.parametrize( - "commit, build, clean", + "commit, build, expected", [ ("v1.13-103-gb137d064e", True, "v1.13-103"), + ("v1.13-103-gb137d064e", False, "latest"), ("v1.13", True, "v1.13"), - ("v1.13-dirty", True, "v1.13"), - ("v1.13-103-gb137d064e", False, "latest"), # "v1.13-Latest"), ("v1.13", False, "v1.13"), - ("v1.13-dirty", False, "latest"), # "v1.13-Latest"), + ("v1.13-dirty", True, "v1.13"), + ("v1.13-dirty", False, "latest"), + # lets keep all the preview tags simple based on the provided version + ("v1.23.0-preview", False, "v1.23.0-preview"), + ("v1.23.0-preview", True, "v1.23.0-preview"), + ("1.20.0-preview-487", False, "v1.20.0-preview"), + ("1.20.0-preview-487", True, "v1.20.0-preview"), ], ) -def test_clean_version_build(commit, build, clean): - assert utils.clean_version(commit, build=build) == clean +def test_clean_version_build(commit, build, expected): + assert utils.clean_version(commit, build=build) == expected def test_clean_version_special(): assert utils.clean_version("v1.13.0-103-gb137d064e") == "latest" assert utils.clean_version("v1.13.0-103-gb137d064e", build=True) == "v1.13-103" - assert ( - utils.clean_version("v1.13.0-103-gb137d064e", build=True, commit=True) - == "v1.13-103-gb137d064e" - ) + assert utils.clean_version("v1.13.0-103-gb137d064e", build=True, commit=True) == "v1.13-103-gb137d064e" # with path # assert utils.clean_version("v1.13.0-103-gb137d064e", patch=True) == "v1.13.0-Latest" assert utils.clean_version("v1.13.0-103-gb137d064e", patch=True) == "latest" assert utils.clean_version("v1.13.0-103-gb137d064e", patch=True, build=True) == "v1.13.0-103" # with commit assert ( - utils.clean_version("v1.13.0-103-gb137d064e", patch=True, build=True, commit=True) - == "v1.13.0-103-gb137d064e" + utils.clean_version("v1.13.0-103-gb137d064e", patch=True, build=True, commit=True) == "v1.13.0-103-gb137d064e" ) # FLats # assert utils.clean_version("v1.13.0-103-gb137d064e", flat=True) == "v1_13-Latest" assert utils.clean_version("v1.13.0-103-gb137d064e", flat=True) == "latest" - assert ( - utils.clean_version("v1.13.0-103-gb137d064e", build=True, commit=True, flat=True) - == "v1_13-103-gb137d064e" - ) + assert utils.clean_version("v1.13.0-103-gb137d064e", build=True, commit=True, flat=True) == "v1_13-103-gb137d064e" # all options , no V for version assert ( - utils.clean_version( - "v1.13.0-103-gb137d064e", patch=True, build=True, commit=True, flat=True, drop_v=True - ) + utils.clean_version("v1.13.0-103-gb137d064e", patch=True, build=True, commit=True, flat=True, drop_v=True) == "1_13_0-103-gb137d064e" ) @@ -109,14 +105,10 @@ def test_post_processing(tmp_path, pytestconfig, mocker: MockerFixture): dest = tmp_path / "stubs" # shutil.copytree(source, dest) - m_generate_pyi_files: MagicMock = mocker.patch( - "stubber.utils.post.generate_pyi_files", autospec=True - ) + m_generate_pyi_files: MagicMock = mocker.patch("stubber.utils.post.generate_pyi_files", autospec=True) return_val = SimpleNamespace() return_val.returncode = 0 - m_spr: MagicMock = mocker.patch( - "stubber.utils.post.subprocess.run", autospec=True, return_value=return_val - ) + m_spr: MagicMock = mocker.patch("stubber.utils.post.subprocess.run", autospec=True, return_value=return_val) utils.do_post_processing([dest], stubgen=True, black=True, autoflake=False) @@ -168,6 +160,4 @@ def test_make_stub_files_issues(tmp_path, pytestconfig): except ValueError: pass - assert ( - len(py_files) == PROBLEMATIC - ), "py and pyi files should match 1:1 and stored in the same folder" + assert len(py_files) == PROBLEMATIC, "py and pyi files should match 1:1 and stored in the same folder" From 912943f1d6dbaacf03e34cea19c69ff0fe469ba8 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Mon, 5 Feb 2024 12:40:14 +0100 Subject: [PATCH 65/68] Update launch.json to use debugpy Signed-off-by: Jos Verlinde --- .vscode/launch.json | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index ce1a09a37..e1799599d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,7 +6,7 @@ "configurations": [ { "name": "Pytest --collect-only (debug)", - "type": "python", + "type": "debugpy", "request": "launch", "module": "pytest", "args": [ @@ -19,14 +19,14 @@ }, { "name": "Python: file as Module", - "type": "python", + "type": "debugpy", "request": "launch", "module": "stubber.${fileBasenameNoExtension}", "justMyCode": false }, { "name": "mpremote", - "type": "python", + "type": "debugpy", "request": "launch", "module": "mpremote", "justMyCode": false, @@ -39,19 +39,18 @@ }, { "name": "Python: stubber - cmdline", - "type": "python", + "type": "debugpy", "request": "launch", "module": "stubber.stubber", "cwd": "${workspaceFolder}", "args": [ - "-v", - "-v", - "make-variants", + // "-v", + "get-frozen", + "--version", + "preview", // "switch", // "v1.20.0", // "build", - // "--version", - // "latest", // "--port", // "esp32", // "--board", @@ -87,7 +86,7 @@ }, { "name": "Python: board_stubber", - "type": "python", + "type": "debugpy", "request": "launch", "program": "scripts/board_stubber.py", "cwd": "${workspaceFolder}", @@ -100,7 +99,7 @@ }, { "name": "Python: Current File", - "type": "python", + "type": "debugpy", "request": "launch", "program": "${file}", "cwd": "${workspaceFolder}", @@ -108,7 +107,7 @@ }, { "name": "Python: this File - Args ", - "type": "python", + "type": "debugpy", "request": "launch", "program": "${file}", "console": "integratedTerminal", @@ -118,7 +117,7 @@ }, { "name": "Micro-CPython: Current File", - "type": "python", + "type": "debugpy", "subProcess": false, "justMyCode": true, "request": "launch", @@ -134,7 +133,7 @@ }, { "name": "Python: Debug process --path", - "type": "python", + "type": "debugpy", "request": "launch", "console": "integratedTerminal", "program": "${file}", @@ -148,7 +147,7 @@ "purpose": [ "debug-test" ], - "type": "python", + "type": "debugpy", "request": "launch", "console": "integratedTerminal", "justMyCode": false, From 4e2a35f71321e2a7aedfab9ab482d3d42dec3e2c Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Mon, 5 Feb 2024 14:43:14 +0100 Subject: [PATCH 66/68] Update code and tests to use 'preview' Signed-off-by: Jos Verlinde --- src/stubber/basicgit.py | 19 +- src/stubber/commands/build_cmd.py | 10 +- src/stubber/commands/get_docstubs_cmd.py | 17 +- src/stubber/commands/get_frozen_cmd.py | 17 +- src/stubber/commands/switch_cmd.py | 10 +- src/stubber/freeze/freeze_manifest_2.py | 3 +- src/stubber/freeze/get_frozen.py | 41 ++-- src/stubber/minify.py | 6 +- src/stubber/publish/candidates.py | 38 ++-- src/stubber/publish/defaults.py | 4 +- src/stubber/publish/pathnames.py | 4 +- src/stubber/publish/publish.py | 3 +- src/stubber/publish/stubpackage.py | 61 ++---- src/stubber/rst/reader.py | 3 +- src/stubber/stubber.py | 11 +- src/stubber/update_fallback.py | 4 +- src/stubber/utils/__init__.py | 2 +- src/stubber/utils/config.py | 16 +- src/stubber/utils/repos.py | 11 +- src/stubber/utils/versions.py | 33 +++- tests/commandline/stubber_cli_test.py | 236 +++++++++-------------- tests/common/upd_fallback_test.py | 3 + tests/freeze/freezer_mpy_test.py | 29 +-- tests/publish/test_candidates.py | 17 +- tests/publish/test_multi_build.py | 67 +++---- tests/publish/test_multi_publish.py | 104 +++++----- tests/publish/test_pathnames.py | 4 +- tests/util_test.py | 32 ++- 28 files changed, 373 insertions(+), 432 deletions(-) diff --git a/src/stubber/basicgit.py b/src/stubber/basicgit.py index c2dd8d2cf..fa7644df5 100644 --- a/src/stubber/basicgit.py +++ b/src/stubber/basicgit.py @@ -13,6 +13,8 @@ from loguru import logger as log from packaging.version import parse +# from stubber.utils.versions import SET_PREVIEW + # Token with no permissions to avoid throttling # https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#getting-a-higher-rate-limit PAT_NO_ACCESS = ( @@ -68,7 +70,7 @@ def clone(remote_repo: str, path: Path, shallow: bool = False, tag: Optional[str cmd = ["git", "clone"] if shallow: cmd += ["--depth", "1"] - if tag in ("latest", "master"): + if tag in {"preview", "latest", "master"}: tag = None cmd += [remote_repo, "--branch", tag, str(path)] if tag else [remote_repo, str(path)] if result := _run_local_git(cmd, expect_stderr=True, capture_output=False): @@ -99,21 +101,16 @@ def get_local_tag(repo: Optional[Union[str, Path]] = None, abbreviate: bool = Tr return None tag: str = result.stdout tag = tag.replace("\r", "").replace("\n", "") - if abbreviate and "-" in tag: - if result := _run_local_git( - ["git", "status", "--branch"], - repo=repo.as_posix(), - expect_stderr=True, - ): - lines = result.stdout.replace("\r", "").split("\n") - if lines[0].startswith("On branch") and lines[0].endswith("master"): - tag = "latest" + if not abbreviate or "-" not in tag: + return tag + if "-preview" in tag: + tag = tag.split("-preview")[0] + "-preview" return tag def get_local_tags(repo: Optional[Path] = None, minver: Optional[str] = None) -> List[str]: """ - get list of tag of a local repo + get list of all tags of a local repo """ if not repo: repo = Path(".") diff --git a/src/stubber/commands/build_cmd.py b/src/stubber/commands/build_cmd.py index 01dc4e472..5e1b3ce80 100644 --- a/src/stubber/commands/build_cmd.py +++ b/src/stubber/commands/build_cmd.py @@ -22,7 +22,7 @@ multiple=True, default=[CONFIG.stable_version], show_default=True, - help="multiple: ", + help="MicroPython version to build, or 'preview' for the latest preview version", ) @click.option( "--port", @@ -72,9 +72,11 @@ def cli_build( ports = list(ports) boards = list(boards) - if len(versions) > 1 : - raise NotImplementedError("Multiple versions are not supported yet\n See https://github.com/Josverl/micropython-stubber/issues/487") - + if len(versions) > 1: + raise NotImplementedError( + "Multiple versions are not supported yet\n See https://github.com/Josverl/micropython-stubber/issues/487" + ) + # db = get_database(publish_path=CONFIG.publish_path, production=production) log.info(f"Build {family} {versions} {ports} {boards}") diff --git a/src/stubber/commands/get_docstubs_cmd.py b/src/stubber/commands/get_docstubs_cmd.py index da8050012..a28e5c9dd 100644 --- a/src/stubber/commands/get_docstubs_cmd.py +++ b/src/stubber/commands/get_docstubs_cmd.py @@ -39,9 +39,7 @@ show_default=True, ) # @click.option("--family", "-f", "basename", default="micropython", help="Micropython family.", show_default=True) -@click.option( - "--version", "--tag", default="", type=str, help="Version number to use. [default: Git tag]" -) +@click.option("--version", "--tag", default="", type=str, help="Version number to use. [default: Git tag]") @click.option("--black/--no-black", "-b/-nb", default=True, help="Run black", show_default=True) @click.pass_context def cli_docstubs( @@ -72,16 +70,13 @@ def cli_docstubs( result = fetch_repos(version, CONFIG.mpy_path, CONFIG.mpy_lib_path) if not result: return -1 + # get the current checked out version + version = utils.checkedout_version(CONFIG.mpy_path) - v_tag = git.get_local_tag(rst_path.as_posix()) - if not v_tag: - # if we can't find a tag , bail - raise ValueError("No valid Tag found") - v_tag = utils.clean_version(v_tag, flat=True, drop_v=False) release = git.get_local_tag(rst_path.as_posix(), abbreviate=False) or "" - dst_path = Path(target) / f"{basename}-{v_tag}-docstubs" + dst_path = Path(target) / f"{basename}-{version}-docstubs" - log.info(f"Get docstubs for MicroPython {utils.clean_version(v_tag, drop_v=False)}") - generate_from_rst(rst_path, dst_path, v_tag, release=release, suffix=".pyi",black=black) + log.info(f"Get docstubs for MicroPython {utils.clean_version(version, drop_v=False)}") + generate_from_rst(rst_path, dst_path, version, release=release, suffix=".pyi", black=black) log.info("::group:: Done") diff --git a/src/stubber/commands/get_frozen_cmd.py b/src/stubber/commands/get_frozen_cmd.py index 5528ac339..a4237a214 100644 --- a/src/stubber/commands/get_frozen_cmd.py +++ b/src/stubber/commands/get_frozen_cmd.py @@ -36,6 +36,7 @@ default="", # default=[CONFIG.stable_version], show_default=True, + help="The version of MicroPython to get the frozen modules for. Use 'preview' to get the latest version from the micropython repo", ) @click.option( "--stubgen/--no-stubgen", @@ -78,27 +79,21 @@ def cli_get_frozen( else: version = utils.clean_version(git.get_local_tag(CONFIG.mpy_path.as_posix()) or "0.0") if not version: - log.warning( - "Unable to find the micropython repo in folder : {}".format(CONFIG.mpy_path.as_posix()) - ) + log.warning("Unable to find the micropython repo in folder : {}".format(CONFIG.mpy_path.as_posix())) log.info("MicroPython version : {}".format(version)) # folder/{family}-{version}-frozen family = "micropython" - stub_path = Path(stub_folder) / f"{family}-{utils.clean_version(version, flat=True)}-frozen" + + stub_path = freeze_any(version=version, mpy_path=CONFIG.mpy_path, mpy_lib_path=CONFIG.mpy_lib_path) stub_paths.append(stub_path) - freeze_any( - stub_path, version=version, mpy_path=CONFIG.mpy_path, mpy_lib_path=CONFIG.mpy_lib_path - ) # Also enrich the frozen modules from the doc stubs if available # first create .pyi files so they can be enriched utils.do_post_processing(stub_paths, stubgen=stubgen, black=False, autoflake=False) family = "micropython" - docstubs_path = ( - Path(CONFIG.stub_path) - / f"{family}-{utils.clean_version(version, drop_v=False, flat=True)}-docstubs" - ) + _version = utils.clean_version(version, drop_v=False, flat=True) + docstubs_path = Path(CONFIG.stub_path) / f"{family}-{_version}-docstubs" if docstubs_path.exists(): log.info(f"Enriching {str(stub_path)} with {docstubs_path}") if merged := enrich_folder( diff --git a/src/stubber/commands/switch_cmd.py b/src/stubber/commands/switch_cmd.py index 52c888840..0f8e31992 100644 --- a/src/stubber/commands/switch_cmd.py +++ b/src/stubber/commands/switch_cmd.py @@ -11,6 +11,7 @@ import stubber.basicgit as git from stubber.utils.config import CONFIG from stubber.utils.repos import fetch_repos, repo_paths +from stubber.utils.versions import SET_PREVIEW, V_PREVIEW from .cli import stubber_cli @@ -22,10 +23,10 @@ # get version list from Git tags in the repo that is provided on the command line try: - VERSION_LIST = git.get_tags("micropython/micropython", minver="v1.9.3") + ["latest"] + VERSION_LIST = git.get_tags("micropython/micropython", minver="v1.9.3") + [V_PREVIEW, "latest"] except Exception: # offline fallback - VERSION_LIST = ["v1.91.1", "v1.20.0", "latest"] + VERSION_LIST = ["v1.91.1", "v1.20.1", "v1.21.0", "v1.22.1", "preview"] @stubber_cli.command(name="switch") @@ -46,7 +47,8 @@ def cli_switch(path: Union[str, Path], tag: Optional[str] = None): mpy_path, mpy_lib_path = repo_paths(Path(path)) except Exception: return -1 - if not tag: - tag = "latest" + if not tag or tag in SET_PREVIEW: + tag = V_PREVIEW + result = fetch_repos(tag, mpy_path, mpy_lib_path) return -1 if result else 0 diff --git a/src/stubber/freeze/freeze_manifest_2.py b/src/stubber/freeze/freeze_manifest_2.py index 125f3f5b5..157cdab14 100644 --- a/src/stubber/freeze/freeze_manifest_2.py +++ b/src/stubber/freeze/freeze_manifest_2.py @@ -57,7 +57,8 @@ def freeze_one_manifest_2(manifest: Path, frozen_stub_path: Path, mpy_path: Path # so we need to get the port and board from the path log.info(f"input_manifest: {manifest}") port, board = get_portboard(manifest) - log.info(f"port-board: '{port}-{board}'") + + log.info("port-board: {}".format((port + "-" +board).rstrip("-"))) path_vars = make_path_vars(port=port, board=board, mpy_path=mpy_path, mpy_lib_path=mpy_lib_path) upy_manifest = ManifestFile(MODE_FREEZE, path_vars) diff --git a/src/stubber/freeze/get_frozen.py b/src/stubber/freeze/get_frozen.py index 3120aa89c..bf43c1333 100644 --- a/src/stubber/freeze/get_frozen.py +++ b/src/stubber/freeze/get_frozen.py @@ -24,14 +24,15 @@ from loguru import logger as log from packaging.version import Version + +import stubber.basicgit as git from stubber import utils +from stubber.codemod.add_comment import AddComment from stubber.freeze.freeze_folder import freeze_folders # Micropython < v1.12 from stubber.freeze.freeze_manifest_2 import freeze_one_manifest_2 from stubber.utils.config import CONFIG -from stubber.codemod.add_comment import AddComment - +from stubber.utils.versions import SET_PREVIEW, V_PREVIEW -# globals FAMILY = "micropython" @@ -54,13 +55,18 @@ def add_comment_to_path(path: Path, comment: str) -> None: Add a comment to the top of each file in the path using a codemod """ - #TODO: #305 add comment line to each file with the micropython version it was generated from + # TODO: #305 add comment line to each file with the micropython version it was generated from # frozen_stub_path # python -m libcst.tool codemod --include-stubs --no-format add_comment.AddComment .\repos\micropython-stubs\stubs\micropython-v1_19_1-frozen\ --comment "# Micropython 1.19.1 frozen stubs" pass -def freeze_any(stub_folder: Path, version: str, mpy_path: Optional[Path] = None, mpy_lib_path: Optional[Path] = None) -> int: +def freeze_any( + stub_folder: Optional[Path] = None, + version: str = V_PREVIEW, + mpy_path: Optional[Path] = None, + mpy_lib_path: Optional[Path] = None, +) -> Path: """ Get and parse the to-be-frozen .py modules for micropython to extract the static type information - requires that the MicroPython and Micropython-lib repos are checked out and available on a local path @@ -73,24 +79,24 @@ def freeze_any(stub_folder: Path, version: str, mpy_path: Optional[Path] = None, current_dir = os.getcwd() mpy_path = Path(mpy_path).absolute() if mpy_path else CONFIG.mpy_path.absolute() mpy_lib_path = Path(mpy_lib_path).absolute() if mpy_lib_path else CONFIG.mpy_path.absolute() - if not stub_folder: - frozen_stub_path = Path("{}/{}_{}_frozen".format(CONFIG.stub_path, FAMILY, utils.clean_version(version, flat=True))).absolute() - else: - frozen_stub_path: Path = Path(stub_folder).absolute() # if old version of micropython, use the old freeze method - if version not in ["master", "latest"] and Version(version) <= Version("1.11"): + if version not in SET_PREVIEW and Version(version) <= Version("1.11"): + frozen_stub_path = get_fsp(version, stub_folder) log.debug("MicroPython v1.11, older or other") # others modules = freeze_folders(frozen_stub_path.as_posix(), mpy_path.as_posix(), mpy_lib_path.as_posix(), version) count = len(modules) else: + # get the current checked out version + version = utils.checkedout_version(CONFIG.mpy_path) + + frozen_stub_path = get_fsp(version, stub_folder) # get the manifests of the different ports and boards all_manifests = get_manifests(mpy_path) # process all_manifests under the ports folder and update the frozen files in the stubs folder - # we are goning to jump around, avoid relative paths - frozen_stub_path = frozen_stub_path.absolute() + # we are going to jump around, avoid relative paths mpy_path = mpy_path.absolute() mpy_lib_path = mpy_lib_path.absolute() @@ -111,4 +117,13 @@ def freeze_any(stub_folder: Path, version: str, mpy_path: Optional[Path] = None, # restore cwd os.chdir(current_dir) - return count + return frozen_stub_path + + +def get_fsp(version: str, stub_folder: Optional[Path] = None) -> Path: + if not stub_folder: + frozen_stub_path = CONFIG.stub_path / f"{FAMILY}-{utils.clean_version(version, flat=True)}-frozen" + frozen_stub_path = frozen_stub_path.absolute() + else: + frozen_stub_path: Path = Path(stub_folder).absolute() + return frozen_stub_path diff --git a/src/stubber/minify.py b/src/stubber/minify.py index a70472987..c3f77c3c2 100644 --- a/src/stubber/minify.py +++ b/src/stubber/minify.py @@ -13,6 +13,8 @@ import python_minifier from loguru import logger as log +from stubber.utils.versions import SET_PREVIEW, V_PREVIEW + # Type Aliases for minify StubSource = Union[Path, str, StringIO, TextIOWrapper] XCompileDest = Union[Path, BytesIO] @@ -360,7 +362,7 @@ def cross_compile( result = pipx_mpy_cross(version, source_file, _target) if result.stderr and "No matching distribution found for mpy-cross==" in result.stderr: log.warning(f"mpy-cross=={version} not found, using latest") - result = pipx_mpy_cross("latest", source_file, _target) + result = pipx_mpy_cross(V_PREVIEW, source_file, _target) if result.returncode == 0: log.debug(f"mpy-cross compiled to : {_target.name}") @@ -380,7 +382,7 @@ def pipx_mpy_cross(version: str, source_file, _target): """Run mpy-cross using pipx""" log.info(f"Compiling with mpy-cross version: {version}") - if version == "latest": + if version in SET_PREVIEW: version = "" if version: version = "==" + version diff --git a/src/stubber/publish/candidates.py b/src/stubber/publish/candidates.py index 1baf5b49b..75274277d 100644 --- a/src/stubber/publish/candidates.py +++ b/src/stubber/publish/candidates.py @@ -10,7 +10,6 @@ - get a list of the firmware/board stubs (firmware candidates) """ - import re from pathlib import Path from typing import Any, Dict, Generator, List, Optional, Union @@ -18,15 +17,11 @@ from packaging.version import parse import stubber.basicgit as git -from stubber.publish.enums import COMBO_STUBS, DOC_STUBS, FIRMWARE_STUBS +from stubber import utils from stubber.publish.defaults import GENERIC, GENERIC_L, GENERIC_U +from stubber.publish.enums import COMBO_STUBS, DOC_STUBS, FIRMWARE_STUBS from stubber.utils.config import CONFIG -from stubber.utils.versions import clean_version, micropython_versions - -OLDEST_VERSION = "1.16" -"This is the oldest MicroPython version to build the stubs on" - -V_LATEST = "latest" +from stubber.utils.versions import OLDEST_VERSION, SET_PREVIEW, V_PREVIEW, clean_version, micropython_versions def subfolder_names(path: Path): @@ -50,13 +45,13 @@ def version_candidates( for name in subfolder_names(path): if match := re.match(folder_re, name): folder_ver = clean_version(match[1]) - if folder_ver == V_LATEST or parse(folder_ver) >= parse(oldest): + if folder_ver == V_PREVIEW or parse(folder_ver) >= parse(oldest): yield folder_ver def list_frozen_ports( family: str = "micropython", - version: str = V_LATEST, + version: str = V_PREVIEW, path: Path = CONFIG.stub_path, ): "get list of ports with frozen stubs for a given family and version" @@ -94,7 +89,7 @@ def list_micropython_port_boards( def frozen_candidates( family: str = "micropython", - versions: Union[str, List[str]] = V_LATEST, + versions: Union[str, List[str]] = V_PREVIEW, ports: Union[str, List[str]] = "all", boards: Union[str, List[str]] = "all", *, @@ -111,7 +106,7 @@ def frozen_candidates( auto_port = is_auto(ports) auto_board = is_auto(boards) if is_auto(versions): - versions = list(version_candidates(suffix="frozen", prefix=family, path=path)) + [V_LATEST] + versions = list(version_candidates(suffix="frozen", prefix=family, path=path)) + [V_PREVIEW] else: versions = [versions] if isinstance(versions, str) else versions @@ -129,9 +124,7 @@ def frozen_candidates( # lookup the (frozen) micropython ports ports = list_frozen_ports(family, version, path=path) else: - raise NotImplementedError( - f"auto ports not implemented for family {family}" - ) # pragma: no cover + raise NotImplementedError(f"auto ports not implemented for family {family}") # pragma: no cover # elif family == "pycom": # ports = ["esp32"] # elif family == "lobo": @@ -164,9 +157,7 @@ def frozen_candidates( else: # raise NotImplementedError(f"auto boards not implemented for family {family}") # pragma: no cover - raise NotImplementedError( - f"auto boards not implemented for family {family}" - ) # pragma: no cover + raise NotImplementedError(f"auto boards not implemented for family {family}") # pragma: no cover # elif family == "pycom": # boards = ["wipy", "lopy", "gpy", "fipy"] # --------------------------------------------------------------------------- @@ -199,7 +190,7 @@ def is_auto(thing: Union[None, str, List[str]]): def docstub_candidates( family: str = "micropython", - versions: Union[str, List[str]] = V_LATEST, + versions: Union[str, List[str]] = V_PREVIEW, path: Path = CONFIG.stub_path, ): """ @@ -220,7 +211,7 @@ def docstub_candidates( def board_candidates( family: str = "micropython", - versions: Union[str, List[str]] = V_LATEST, + versions: Union[str, List[str]] = V_PREVIEW, *, mpy_path: Path = CONFIG.mpy_path, pt: str = FIRMWARE_STUBS, @@ -237,8 +228,10 @@ def board_candidates( for version in versions: # check out the micropython repo for this version - if version in ["latest", "master"]: + if version in SET_PREVIEW: r = git.switch_branch(repo=mpy_path, branch="master") + # get the current checked out version + version = utils.checkedout_version(mpy_path) else: r = git.checkout_tag(repo=mpy_path, tag=version) if not r: @@ -283,7 +276,6 @@ def filter_list( worklist = [ i for i in worklist - if i["board"].lower() in boards_ - or i["board"].lower().replace("generic_", "") in boards_ + if i["board"].lower() in boards_ or i["board"].lower().replace("generic_", "") in boards_ ] return worklist diff --git a/src/stubber/publish/defaults.py b/src/stubber/publish/defaults.py index d507e7dd4..b74a31042 100644 --- a/src/stubber/publish/defaults.py +++ b/src/stubber/publish/defaults.py @@ -2,7 +2,7 @@ from typing import Dict, List from stubber.utils.config import CONFIG -from stubber.utils.versions import clean_version +from stubber.utils.versions import V_PREVIEW, clean_version # The default board for the ports modules documented with base name only # as the MicroPython BOARD naming convention has changed over time there are different options to try @@ -24,7 +24,7 @@ "GENERIC eithercase" -def default_board(port: str, version="latest") -> str: # sourcery skip: assign-if-exp +def default_board(port: str, version=V_PREVIEW) -> str: # sourcery skip: assign-if-exp """Return the default board for the given version and port""" ver_flat = clean_version(version, flat=True) if port in DEFAULT_BOARDS: diff --git a/src/stubber/publish/pathnames.py b/src/stubber/publish/pathnames.py index d3960976f..f0061e4bc 100644 --- a/src/stubber/publish/pathnames.py +++ b/src/stubber/publish/pathnames.py @@ -11,7 +11,7 @@ from stubber.publish.defaults import default_board from stubber.publish.package import GENERIC from stubber.utils.config import CONFIG -from stubber.utils.versions import clean_version +from stubber.utils.versions import V_PREVIEW, clean_version ## Helper functions @@ -40,7 +40,7 @@ def board_folder_name(fw: Dict, *, version: Optional[str] = None) -> str: def get_board_path(candidate: Dict) -> Path: board_path = CONFIG.stub_path / board_folder_name(candidate) - if candidate["version"] == "latest" and not board_path.exists(): + if V_PREVIEW in candidate["version"] and not board_path.exists(): log.debug(f"no board stubs found for {candidate['version']}, trying stable") board_path = CONFIG.stub_path / board_folder_name(candidate, version=CONFIG.stable_version) diff --git a/src/stubber/publish/publish.py b/src/stubber/publish/publish.py index 66749a5a3..0529d9ab4 100644 --- a/src/stubber/publish/publish.py +++ b/src/stubber/publish/publish.py @@ -13,11 +13,12 @@ from stubber.publish.enums import COMBO_STUBS from stubber.publish.package import get_package from stubber.utils.config import CONFIG +from stubber.utils.versions import V_PREVIEW def build_multiple( family: str = "micropython", - versions: List[str] = ["v1.19.1"], + versions: List[str] = [V_PREVIEW], ports: List[str] = ["all"], boards: List[str] = [GENERIC_U], production: bool = False, diff --git a/src/stubber/publish/stubpackage.py b/src/stubber/publish/stubpackage.py index 07f2f2687..ceabdfd7c 100644 --- a/src/stubber/publish/stubpackage.py +++ b/src/stubber/publish/stubpackage.py @@ -29,7 +29,7 @@ from stubber.publish.enums import StubSource from stubber.publish.pypi import Version, get_pypi_versions from stubber.utils.config import CONFIG -from stubber.utils.versions import clean_version +from stubber.utils.versions import SET_PREVIEW, V_PREVIEW, clean_version Status = NewType("Status", Dict[str, Union[str, None]]) StubSources = List[Tuple[StubSource, Path]] @@ -108,7 +108,7 @@ def next_package_version(self, production: bool) -> str: return self._get_next_package_version(production) def is_preview(self): - return self.mpy_version == "latest" or "preview" in self.mpy_version + return self.mpy_version in SET_PREVIEW or V_PREVIEW in self.mpy_version def _get_next_preview_package_version(self, production: bool = False) -> str: """ @@ -125,17 +125,9 @@ def _get_next_preview_package_version(self, production: bool = False) -> str: parts = describe.split("-", 3) ver = parts[0] if len(parts) > 1: - rc = ( - parts[1] - if parts[1].isdigit() - else parts[2] - if len(parts) > 2 and parts[2].isdigit() - else 1 - ) + rc = parts[1] if parts[1].isdigit() else parts[2] if len(parts) > 2 and parts[2].isdigit() else 1 rc = int(rc) - base = ( - bump_version(Version(ver), minor_bump=True) if parts[1] != "preview" else Version(ver) - ) + base = bump_version(Version(ver), minor_bump=True) if parts[1] != V_PREVIEW else Version(ver) return str(bump_version(base, rc=rc)) # raise ValueError("cannot determine next version number micropython") @@ -312,9 +304,7 @@ def copy_stubs(self) -> None: # Check if all stub source folders exist for stub_type, src_path in self.stub_sources: if not (CONFIG.stub_path / src_path).exists(): - raise FileNotFoundError( - f"Could not find stub source folder {CONFIG.stub_path / src_path}" - ) + raise FileNotFoundError(f"Could not find stub source folder {CONFIG.stub_path / src_path}") # 1 - Copy the stubs to the package, directly in the package folder (no folders) # for stub_type, fw_path in [s for s in self.stub_sources]: @@ -325,9 +315,7 @@ def copy_stubs(self) -> None: self.copy_folder(stub_type, src_path) except OSError as e: if stub_type != StubSource.FROZEN: - raise FileNotFoundError( - f"Could not find stub source folder {src_path}" - ) from e + raise FileNotFoundError(f"Could not find stub source folder {src_path}") from e else: log.debug(f"Error copying stubs from : {CONFIG.stub_path / src_path}, {e}") finally: @@ -594,7 +582,7 @@ def pkg_version(self) -> str: with open(_toml, "rb") as f: pyproject = tomllib.load(f) ver = pyproject["tool"]["poetry"]["version"] - return str(parse(ver)) if ver != "latest" else ver + return str(parse(ver)) if ver not in SET_PREVIEW else ver @pkg_version.setter def pkg_version(self, version: str) -> None: @@ -654,7 +642,7 @@ def run_poetry(self, parameters: List[str]) -> bool: # stdout=subprocess.PIPE, stdout=subprocess.PIPE, # interestingly: errors on stdout , output on stderr ..... universal_newlines=True, - encoding="utf-8" + encoding="utf-8", ) log.trace(f"poetry {parameters} completed") except (NotADirectoryError, FileNotFoundError) as e: # pragma: no cover # InvalidVersion @@ -719,8 +707,7 @@ def update_pyproject_stubs(self) -> int: _pyproject = self.pyproject assert _pyproject is not None, "No pyproject.toml file found" _pyproject["tool"]["poetry"]["packages"] = [ - {"include": p.relative_to(self.package_path).as_posix()} - for p in sorted((self.package_path).rglob("*.pyi")) + {"include": p.relative_to(self.package_path).as_posix()} for p in sorted((self.package_path).rglob("*.pyi")) ] # write out the pyproject.toml file self.pyproject = _pyproject @@ -863,9 +850,7 @@ def update_distribution(self, production: bool) -> bool: # check if the sources exist ok = self.are_package_sources_available() if not ok: - log.debug( - f"{self.package_name}: skipping as one or more source stub folders are missing" - ) + log.debug(f"{self.package_name}: skipping as one or more source stub folders are missing") self.status["error"] = "Skipped, stub folder(s) missing" shutil.rmtree(self.package_path.as_posix()) self._publish = False # type: ignore @@ -887,9 +872,7 @@ def build_distribution( self, production: bool, # PyPI or Test-PyPi - USED TO FIND THE NEXT VERSION NUMBER force=False, # BUILD even if no changes - ) -> ( - bool - ): # sourcery skip: default-mutable-arg, extract-duplicate-method, require-parameter-annotation + ) -> bool: # sourcery skip: default-mutable-arg, extract-duplicate-method, require-parameter-annotation """ Build a package look up the previous package version in the dabase @@ -909,14 +892,14 @@ def build_distribution( if not self.status["error"]: self.status["error"] = "Could not build/update package" return False - # If there are changes to the package, then publish it - if self.is_changed(): - log.info(f"Found changes to package sources: {self.package_name} {self.pkg_version} ") - log.trace(f"Old hash {self.hash} != New hash {self.calculate_hash()}") - elif force: - log.info(f"Force build: {self.package_name} {self.pkg_version} ") + # If there are changes to the package, then publish it if self.is_changed() or force: + if force: + log.info(f"Force build: {self.package_name} {self.pkg_version} ") + else: + log.info(f"Found changes to package sources: {self.package_name} {self.pkg_version} ") + log.trace(f"Old hash {self.hash} != New hash {self.calculate_hash()}") # Build the distribution files old_ver = self.pkg_version self.pkg_version = self.next_package_version(production) @@ -976,10 +959,8 @@ def publish_distribution_ifchanged( self.next_package_version(production=production) # Publish the package to PyPi, Test-PyPi or Github if self.is_changed(): - if self.mpy_version == "latest" and production and not force: - log.warning( - "version: `latest` package will only be available on Github, and not published to PyPi." - ) + if self.mpy_version in SET_PREVIEW and production and not force: + log.warning("version: `latest` package will only be available on Github, and not published to PyPi.") self.status["result"] = "Published to GitHub" else: return self.publish_distribution(dry_run, production, db) @@ -1008,9 +989,7 @@ def publish_distribution(self, dry_run, production, db): if not dry_run: pub_ok = self.poetry_publish(production=production) else: - log.warning( - f"{self.package_name}: Dry run, not publishing to {'' if production else 'Test-'}PyPi" - ) + log.warning(f"{self.package_name}: Dry run, not publishing to {'' if production else 'Test-'}PyPi") pub_ok = True if not pub_ok: log.warning(f"{self.package_name}: Publish failed for {self.pkg_version}") diff --git a/src/stubber/rst/reader.py b/src/stubber/rst/reader.py index 2304e2662..d6876725f 100644 --- a/src/stubber/rst/reader.py +++ b/src/stubber/rst/reader.py @@ -83,6 +83,7 @@ ) from stubber.rst.lookup import Fix from stubber.utils.config import CONFIG +from stubber.utils.versions import V_PREVIEW SEPERATOR = "::" @@ -506,7 +507,7 @@ def parse_module(self): # Add link to online documentation # https://docs.micropython.org/en/v1.17/library/array.html if "nightly" in self.source_tag: - version = "latest" + version = V_PREVIEW else: version = self.source_tag.replace( "_", "." diff --git a/src/stubber/stubber.py b/src/stubber/stubber.py index 706706c97..db831b0db 100644 --- a/src/stubber/stubber.py +++ b/src/stubber/stubber.py @@ -4,8 +4,8 @@ """Create, Process, and Maintain stubs ✏️ for MicroPython""" -from stubber.commands.cli import stubber_cli from stubber.commands.build_cmd import cli_build +from stubber.commands.cli import stubber_cli from stubber.commands.clone_cmd import cli_clone from stubber.commands.config_cmd import cli_config from stubber.commands.enrich_folder_cmd import cli_enrich_folder @@ -22,7 +22,6 @@ from stubber.commands.upd_module_list_cmd import cli_update_module_list from stubber.commands.variants_cmd import cli_variants - ########################################################################################## if __name__ == "__main__": # add all commands to the CLI @@ -33,13 +32,13 @@ stubber_cli.add_command(cli_docstubs) stubber_cli.add_command(cli_get_core) stubber_cli.add_command(cli_get_frozen) - stubber_cli.add_command(cli_get_lobo) + # stubber_cli.add_command(cli_get_lobo) stubber_cli.add_command(cli_stub) stubber_cli.add_command(cli_enrich_folder) - stubber_cli.add_command(cli_minify) + # stubber_cli.add_command(cli_minify) stubber_cli.add_command(cli_publish) stubber_cli.add_command(cli_merge_docstubs) - stubber_cli.add_command(cli_update_module_list) - stubber_cli.add_command(cli_update_fallback) + # stubber_cli.add_command(cli_update_module_list) + # stubber_cli.add_command(cli_update_fallback) stubber_cli.add_command(cli_variants) stubber_cli() diff --git a/src/stubber/update_fallback.py b/src/stubber/update_fallback.py index f61302b6f..d55768101 100644 --- a/src/stubber/update_fallback.py +++ b/src/stubber/update_fallback.py @@ -9,6 +9,8 @@ from loguru import logger as log +from stubber.utils.versions import V_PREVIEW + # log = logging.getLogger() RELEASED = "v1_18" @@ -24,7 +26,7 @@ def fallback_sources(version: str, fw_version: Optional[str] = None) -> List[Tup """ if not fw_version: fw_version = version - if fw_version == "latest": + if fw_version == V_PREVIEW: fw_version = RELEASED SOURCES = [ ("uasyncio", f"micropython-{fw_version}-esp32"), diff --git a/src/stubber/utils/__init__.py b/src/stubber/utils/__init__.py index a1af5e04c..7188d95d7 100644 --- a/src/stubber/utils/__init__.py +++ b/src/stubber/utils/__init__.py @@ -2,4 +2,4 @@ from .manifest import make_manifest, manifest from .post import do_post_processing from .stubmaker import generate_pyi_files, generate_pyi_from_file -from .versions import clean_version +from .versions import checkedout_version, clean_version diff --git a/src/stubber/utils/config.py b/src/stubber/utils/config.py index d4b31f818..d5232a47b 100644 --- a/src/stubber/utils/config.py +++ b/src/stubber/utils/config.py @@ -2,12 +2,14 @@ from pathlib import Path +from loguru import logger as log from typedconfig.config import Config, key, section from typedconfig.source import EnvironmentConfigSource -from .typed_config_toml import TomlConfigSource -from loguru import logger as log import stubber.basicgit as git +from stubber.utils.versions import V_PREVIEW + +from .typed_config_toml import TomlConfigSource @section("micropython-stubber") @@ -16,9 +18,7 @@ class StubberConfig(Config): stub_path = key(key_name="stub-path", cast=Path, required=False, default=Path("./stubs")) "a Path to the stubs directory" # relative to stubs folder - fallback_path = key( - key_name="fallback-path", cast=Path, required=False, default=Path("typings/fallback") - ) + fallback_path = key(key_name="fallback-path", cast=Path, required=False, default=Path("typings/fallback")) "a Path to the fallback stubs directory" # ------------------------------------------------------------------------------------------ @@ -29,9 +29,7 @@ class StubberConfig(Config): mpy_path = key(key_name="mpy-path", cast=Path, required=False, default=Path("micropython")) "a Path to the micropython folder in the repos directory" - mpy_lib_path = key( - key_name="mpy-lib-path", cast=Path, required=False, default=Path("micropython-lib") - ) + mpy_lib_path = key(key_name="mpy-lib-path", cast=Path, required=False, default=Path("micropython-lib")) "a Path to the micropython-lib folder in the repos directory" # mpy_stubs_repo_path = key(key_name="mpy-stubs-repo-path", cast=Path, required=False, default=Path("./micropython-stubs")) @@ -96,7 +94,7 @@ def post_read_hook(self) -> dict: all_versions = ["1.19", "1.19.1", "1.20.0", "1.21.0"] config_updates.update(all_versions=all_versions) config_updates.update( - stable_version=[v for v in all_versions if not v.endswith("preview")][-1] + stable_version=[v for v in all_versions if not v.endswith(V_PREVIEW)][-1] ) # second last version - last version is the preview version return config_updates diff --git a/src/stubber/utils/repos.py b/src/stubber/utils/repos.py index cec444831..2e39544af 100644 --- a/src/stubber/utils/repos.py +++ b/src/stubber/utils/repos.py @@ -13,6 +13,7 @@ import stubber.basicgit as git from stubber.utils.config import CONFIG +from stubber.utils.versions import SET_PREVIEW, V_PREVIEW # # log = logging.getLogger(__name__) @@ -34,8 +35,8 @@ def switch(tag: str, *, mpy_path: Path, mpy_lib_path: Path): git.fetch(mpy_lib_path) if not tag or tag in {"master", ""}: - tag = "latest" - if tag == "latest": + tag = V_PREVIEW + if tag in SET_PREVIEW: git.switch_branch(repo=mpy_path, branch="master") else: git.checkout_tag(repo=mpy_path, tag=tag) @@ -76,7 +77,7 @@ def match_lib_with_mpy(version_tag: str, mpy_path: Path, lib_path: Path) -> bool micropython_lib_commits = read_micropython_lib_commits() # Make sure that the correct micropython-lib release is checked out # check if micropython-lib has matching tags - if version_tag == "latest": + if version_tag in SET_PREVIEW: # micropython-lib is now a submodule result = git.checkout_commit("master", lib_path) if not result: @@ -111,10 +112,10 @@ def fetch_repos(tag: str, mpy_path: Path, mpy_lib_path: Path): log.trace("no stubs repo found : {CONFIG.stub_path.parent}") if not tag: - tag = "latest" + tag = V_PREVIEW log.info(f"Switching to {tag}") - if tag == "latest": + if tag == V_PREVIEW: git.switch_branch(repo=mpy_path, branch="master") else: git.checkout_tag(repo=mpy_path, tag=tag) diff --git a/src/stubber/utils/versions.py b/src/stubber/utils/versions.py index 61fe0cfbe..37b5267f8 100644 --- a/src/stubber/utils/versions.py +++ b/src/stubber/utils/versions.py @@ -1,8 +1,21 @@ """Handle versions of micropython based on the git tags in the repo """ +from pathlib import Path + from github import Github from packaging.version import parse +import stubber.basicgit as git +import stubber.utils as utils + +OLDEST_VERSION = "1.16" +"This is the oldest MicroPython version to build the stubs on" + +V_PREVIEW = "preview" +"Latest preview version" + +SET_PREVIEW = {"preview", "latest", "master"} + def clean_version( version: str, @@ -31,19 +44,29 @@ def clean_version( # version = "-".join((nibbles[0], LATEST)) # HACK: this is not always right, but good enough most of the time if is_preview: - version = "-".join((nibbles[0], "preview")) + version = "-".join((nibbles[0], V_PREVIEW)) else: - version = "latest" + version = V_PREVIEW if flat: - version = version.strip().replace(".", "_") + version = version.strip().replace(".", "_").replace("-", "_") else: - version = version.strip().replace("_", ".") + version = version.strip().replace("_preview", "-preview").replace("_", ".") if drop_v: version = version.lstrip("v") - elif not version.startswith("v") and version.lower() != "latest": + elif not version.startswith("v") and version.lower() not in SET_PREVIEW: version = "v" + version + if version == "latest": + version = V_PREVIEW + return version + +def checkedout_version(path: Path, flat: bool = False) -> str: + """Get the checked-out version of the repo""" + version = git.get_local_tag(path.as_posix()) + if not version: + raise ValueError("No valid Tag found") + version = utils.clean_version(version, flat=flat, drop_v=False) return version diff --git a/tests/commandline/stubber_cli_test.py b/tests/commandline/stubber_cli_test.py index bba9814ca..9fdecdbd3 100644 --- a/tests/commandline/stubber_cli_test.py +++ b/tests/commandline/stubber_cli_test.py @@ -42,12 +42,8 @@ def test_cmd_get_config(): def test_cmd_clone(mocker: MockerFixture, tmp_path: Path): runner = CliRunner() # from stubber.commands.clone import git - m_clone: MagicMock = mocker.patch( - "stubber.commands.clone_cmd.git.clone", autospec=True, return_value=0 - ) - m_fetch: MagicMock = mocker.patch( - "stubber.commands.clone_cmd.git.fetch", autospec=True, return_value=0 - ) + m_clone = mocker.patch("stubber.commands.clone_cmd.git.clone", autospec=True, return_value=0) + m_fetch = mocker.patch("stubber.commands.clone_cmd.git.fetch", autospec=True, return_value=0) result = runner.invoke(stubber.stubber_cli, ["clone"]) assert result.exit_code == 0 @@ -70,9 +66,7 @@ def test_cmd_clone(mocker: MockerFixture, tmp_path: Path): @pytest.mark.mocked def test_cmd_clone_path(mocker: MockerFixture, tmp_path: Path): runner = CliRunner() - m_clone: MagicMock = mocker.patch( - "stubber.commands.clone_cmd.git.clone", autospec=True, return_value=0 - ) + m_clone = mocker.patch("stubber.commands.clone_cmd.git.clone", autospec=True, return_value=0) m_tag = mocker.patch("stubber.commands.clone_cmd.git.get_local_tag", autospec=True) m_dir = mocker.patch("stubber.commands.clone_cmd.os.mkdir", autospec=True) # type: ignore @@ -101,6 +95,7 @@ def test_cmd_clone_path(mocker: MockerFixture, tmp_path: Path): @pytest.mark.parametrize( "params", [ + pytest.param(["switch", "preview"], id="preview"), pytest.param(["switch", "latest"], id="latest"), pytest.param(["switch", "v1.17"], id="v1.17"), pytest.param(["switch", "v1.9.4"], id="v1.9.4"), @@ -111,23 +106,13 @@ def test_cmd_switch(mocker: MockerFixture, params: List[str]): runner = CliRunner() # Mock Path.exists mocker.patch("stubber.commands.clone_cmd.git.clone", autospec=True, return_value=0) - m_fetch: MagicMock = mocker.patch( - "stubber.commands.clone_cmd.git.fetch", autospec=True, return_value=0 - ) + m_fetch = mocker.patch("stubber.commands.clone_cmd.git.fetch", autospec=True, return_value=0) - m_switch: MagicMock = mocker.patch( - "stubber.commands.clone_cmd.git.switch_branch", autospec=True, return_value=0 - ) - m_checkout: MagicMock = mocker.patch( - "stubber.commands.clone_cmd.git.checkout_tag", autospec=True, return_value=0 - ) - mocker.patch( - "stubber.commands.clone_cmd.git.get_local_tag", autospec=True, return_value="v1.42" - ) + m_switch = mocker.patch("stubber.commands.clone_cmd.git.switch_branch", autospec=True, return_value=0) + m_checkout = mocker.patch("stubber.commands.clone_cmd.git.checkout_tag", autospec=True, return_value=0) + mocker.patch("stubber.commands.clone_cmd.git.get_local_tag", autospec=True, return_value="v1.42") - m_match = mocker.patch( - "stubber.utils.repos.match_lib_with_mpy", autospec=True - ) # Moved to other module + m_match = mocker.patch("stubber.utils.repos.match_lib_with_mpy", autospec=True) # Moved to other module mocker.patch("stubber.commands.clone_cmd.Path.exists", return_value=True) result = runner.invoke(stubber.stubber_cli, params) @@ -142,7 +127,7 @@ def test_cmd_switch(mocker: MockerFixture, params: List[str]): # core m_match.assert_called_once() - if "latest" in params: + if "latest" in params or "preview" in params: m_switch.assert_called_once() m_checkout.assert_not_called() else: @@ -155,22 +140,12 @@ def test_cmd_switch(mocker: MockerFixture, params: List[str]): def test_cmd_switch_version(mocker: MockerFixture, version: str): runner = CliRunner() # Mock Path.exists - m_clone: MagicMock = mocker.patch( - "stubber.commands.clone_cmd.git.clone", autospec=True, return_value=0 - ) - m_fetch: MagicMock = mocker.patch( - "stubber.commands.clone_cmd.git.fetch", autospec=True, return_value=0 - ) + m_clone = mocker.patch("stubber.commands.clone_cmd.git.clone", autospec=True, return_value=0) + m_fetch = mocker.patch("stubber.commands.clone_cmd.git.fetch", autospec=True, return_value=0) - m_switch: MagicMock = mocker.patch( - "stubber.commands.clone_cmd.git.switch_branch", autospec=True, return_value=0 - ) - m_checkout: MagicMock = mocker.patch( - "stubber.commands.clone_cmd.git.checkout_tag", autospec=True, return_value=0 - ) - m_get_l_tag: MagicMock = mocker.patch( - "stubber.commands.clone_cmd.git.get_local_tag", autospec=True, return_value="v1.42" - ) + m_switch = mocker.patch("stubber.commands.clone_cmd.git.switch_branch", autospec=True, return_value=0) + m_checkout = mocker.patch("stubber.commands.clone_cmd.git.checkout_tag", autospec=True, return_value=0) + m_get_l_tag = mocker.patch("stubber.commands.clone_cmd.git.get_local_tag", autospec=True, return_value="v1.42") m_match = mocker.patch("stubber.utils.repos.match_lib_with_mpy", autospec=True) @@ -197,28 +172,28 @@ def test_cmd_switch_version(mocker: MockerFixture, version: str): ########################################################################################## # minify ########################################################################################## -@pytest.mark.mocked -def test_cmd_minify(mocker: MockerFixture): - # check basic command line sanity check - runner = CliRunner() - mock_minify: MagicMock = mocker.MagicMock(return_value=0) - mocker.patch("stubber.commands.minify_cmd.minify", mock_minify) +# @pytest.mark.mocked +# def test_cmd_minify(mocker: MockerFixture): +# # check basic command line sanity check +# runner = CliRunner() +# mock_minify = mocker.MagicMock(return_value=0) +# mocker.patch("stubber.commands.minify_cmd.minify", mock_minify) - result = runner.invoke(stubber.stubber_cli, ["minify"]) - assert result.exit_code == 0 - mock_minify.assert_called_once() +# result = runner.invoke(stubber.stubber_cli, ["minify"]) +# assert result.exit_code == 0 +# mock_minify.assert_called_once() -@pytest.mark.mocked -def test_cmd_minify_all(mocker: MockerFixture): - # check basic command line sanity check - runner = CliRunner() - mock_minify: MagicMock = mocker.MagicMock(return_value=0) - mocker.patch("stubber.commands.minify_cmd.minify", mock_minify) +# @pytest.mark.mocked +# def test_cmd_minify_all(mocker: MockerFixture): +# # check basic command line sanity check +# runner = CliRunner() +# mock_minify = mocker.MagicMock(return_value=0) +# mocker.patch("stubber.commands.minify_cmd.minify", mock_minify) - result = runner.invoke(stubber.stubber_cli, ["minify", "--all"]) - assert result.exit_code == 0 - assert mock_minify.call_count == 3 +# result = runner.invoke(stubber.stubber_cli, ["minify", "--all"]) +# assert result.exit_code == 0 +# assert mock_minify.call_count == 3 ########################################################################################## @@ -228,9 +203,9 @@ def test_cmd_minify_all(mocker: MockerFixture): def test_cmd_stub(mocker: MockerFixture): # check basic command line sanity check runner = CliRunner() - # m_generate: MagicMock = mocker.patch("stubber.commands.stub_cmd.generate_pyi_files", autospec=True, return_value=True) - m_generate: MagicMock = mocker.MagicMock(return_value=True) - m_postprocessing: MagicMock = mocker.MagicMock() + # m_generate = mocker.patch("stubber.commands.stub_cmd.generate_pyi_files", autospec=True, return_value=True) + m_generate = mocker.MagicMock(return_value=True) + m_postprocessing = mocker.MagicMock() mocker.patch("stubber.commands.stub_cmd.generate_pyi_files", m_generate) mocker.patch("stubber.commands.stub_cmd.do_post_processing", m_postprocessing) # fake run on current folder @@ -238,9 +213,7 @@ def test_cmd_stub(mocker: MockerFixture): m_generate.assert_called_once_with(Path(".")) m_postprocessing.assert_called_once() - m_postprocessing.assert_called_once_with( - [Path(".")], stubgen=False, black=True, autoflake=False - ) + m_postprocessing.assert_called_once_with([Path(".")], stubgen=False, black=True, autoflake=False) assert result.exit_code == 0 @@ -252,58 +225,51 @@ def test_cmd_get_frozen(mocker: MockerFixture, tmp_path: Path): # check basic command line sanity check runner = CliRunner() - m_get_local_tag: MagicMock = mocker.patch( - "stubber.basicgit.get_local_tag", autospec=True, return_value="v1.42" - ) + m_get_local_tag = mocker.patch("stubber.basicgit.get_local_tag", autospec=True, return_value="v1.42") - m_freeze_any: MagicMock = mocker.patch( - "stubber.commands.get_frozen_cmd.freeze_any", autospec=True - ) - m_post: MagicMock = mocker.patch("stubber.utils.do_post_processing", autospec=True) + m_freeze_any = mocker.patch("stubber.commands.get_frozen_cmd.freeze_any", autospec=True) + m_post = mocker.patch("stubber.utils.do_post_processing", autospec=True) # fake run - need to ensure that there is a destination folder - result = runner.invoke( - stubber.stubber_cli, ["get-frozen", "--stub-folder", tmp_path.as_posix()] - ) + result = runner.invoke(stubber.stubber_cli, ["get-frozen", "--stub-folder", tmp_path.as_posix()]) assert result.exit_code == 0 # FIXME : test fails in CI m_freeze_any.assert_called_once() m_get_local_tag.assert_called_once() - m_post.assert_any_call( - [tmp_path / "micropython-v1_42-frozen"], - stubgen=True, - black=False, - autoflake=False, - ) - m_post.assert_any_call( - [tmp_path / "micropython-v1_42-frozen"], - stubgen=False, - black=True, - autoflake=True, - ) - - -########################################################################################## -# get-lobo -########################################################################################## -@pytest.mark.mocked -def test_cmd_get_lobo(mocker: MockerFixture, tmp_path: Path): - # check basic command line sanity check - runner = CliRunner() - - mock_get_frozen: MagicMock = mocker.patch("stubber.get_lobo.get_frozen", autospec=True) - mock_post: MagicMock = mocker.patch("stubber.utils.do_post_processing", autospec=True) - - # fake run - result = runner.invoke(stubber.stubber_cli, ["get-lobo", "--stub-folder", tmp_path.as_posix()]) - assert result.exit_code == 0 - mock_get_frozen.assert_called_once() - mock_post.assert_called_once() - mock_post.assert_called_once_with( - [tmp_path / "loboris-v3_2_24-frozen"], stubgen=True, black=True, autoflake=True - ) - assert result.exit_code == 0 + assert m_post.call_count == 2 + # m_post.assert_any_call( + # [tmp_path / "micropython-v1_42-frozen"], + # stubgen=True, + # black=False, + # autoflake=False, + # ) + # m_post.assert_any_call( + # [tmp_path / "micropython-v1_42-frozen"], + # stubgen=False, + # black=True, + # autoflake=True, + # ) + + +# ########################################################################################## +# # get-lobo +# ########################################################################################## +# @pytest.mark.mocked +# def test_cmd_get_lobo(mocker: MockerFixture, tmp_path: Path): +# # check basic command line sanity check +# runner = CliRunner() + +# mock_get_frozen = mocker.patch("stubber.get_lobo.get_frozen", autospec=True) +# mock_post = mocker.patch("stubber.utils.do_post_processing", autospec=True) + +# # fake run +# result = runner.invoke(stubber.stubber_cli, ["get-lobo", "--stub-folder", tmp_path.as_posix()]) +# assert result.exit_code == 0 +# mock_get_frozen.assert_called_once() +# mock_post.assert_called_once() +# mock_post.assert_called_once_with([tmp_path / "loboris-v3_2_24-frozen"], stubgen=True, black=True, autoflake=True) +# assert result.exit_code == 0 ########################################################################################## @@ -313,8 +279,8 @@ def test_cmd_get_lobo(mocker: MockerFixture, tmp_path: Path): def test_cmd_get_core(mocker: MockerFixture, tmp_path: Path): # check basic command line sanity check runner = CliRunner() - mock: MagicMock = mocker.patch("stubber.get_cpython.get_core", autospec=True) - mock_post: MagicMock = mocker.patch("stubber.utils.do_post_processing", autospec=True) + mock = mocker.patch("stubber.get_cpython.get_core", autospec=True) + mock_post = mocker.patch("stubber.utils.do_post_processing", autospec=True) # fake run result = runner.invoke(stubber.stubber_cli, ["get-core", "--stub-folder", tmp_path.as_posix()]) @@ -339,21 +305,15 @@ def test_cmd_get_docstubs(mocker: MockerFixture, tmp_path: Path): # check basic command line sanity check runner = CliRunner() - m_get_l_tag: MagicMock = mocker.patch( - "stubber.basicgit.get_local_tag", autospec=True, return_value="v1.42" - ) + m_get_l_tag = mocker.patch("stubber.basicgit.get_local_tag", autospec=True, return_value="v1.42") # from stubber.commands.get_docstubs import generate_from_rst - mock: MagicMock = mocker.patch( - "stubber.commands.get_docstubs_cmd.generate_from_rst", autospec=True - ) + mock = mocker.patch("stubber.commands.get_docstubs_cmd.generate_from_rst", autospec=True) - mock_post: MagicMock = mocker.patch("stubber.utils.do_post_processing", autospec=True) + mock_post = mocker.patch("stubber.utils.do_post_processing", autospec=True) # fake run - result = runner.invoke( - stubber.stubber_cli, ["get-docstubs", "--stub-folder", tmp_path.as_posix()] - ) + result = runner.invoke(stubber.stubber_cli, ["get-docstubs", "--stub-folder", tmp_path.as_posix()]) assert result.exit_code == 0 # process is called twice assert mock.call_count == 1 @@ -362,24 +322,20 @@ def test_cmd_get_docstubs(mocker: MockerFixture, tmp_path: Path): ########################################################################################## -# get-lobo +# fallback ########################################################################################## -@pytest.mark.mocked -def test_cmd_fallback(mocker: MockerFixture, tmp_path: Path): - # check basic command line sanity check - runner = CliRunner() +# @pytest.mark.mocked +# def test_cmd_fallback(mocker: MockerFixture, tmp_path: Path): +# # check basic command line sanity check +# runner = CliRunner() - mock: MagicMock = mocker.patch( - "stubber.commands.upd_fallback_cmd.update_fallback", autospec=True - ) - # mock2: MagicMock = mocker.patch("stubber.update_fallback.update_fallback", autospec=True) - # from .update_fallback import update_fallback, - # fake run - result = runner.invoke( - stubber.stubber_cli, ["update-fallback", "--stub-folder", tmp_path.as_posix()] - ) - mock.assert_called_once() - assert result.exit_code == 0 +# mock = mocker.patch("stubber.commands.upd_fallback_cmd.update_fallback", autospec=True) +# # mock2 = mocker.patch("stubber.update_fallback.update_fallback", autospec=True) +# # from .update_fallback import update_fallback, +# # fake run +# result = runner.invoke(stubber.stubber_cli, ["update-fallback", "--stub-folder", tmp_path.as_posix()]) +# mock.assert_called_once() +# assert result.exit_code == 0 ########################################################################################## @@ -396,9 +352,7 @@ def test_cmd_fallback(mocker: MockerFixture, tmp_path: Path): def test_cmd_merge(mocker: MockerFixture, cmdline: List[str]): runner = CliRunner() # from stubber.commands.clone import git - m_merge_docstubs: MagicMock = mocker.patch( - "stubber.commands.merge_cmd.merge_all_docstubs", autospec=True, return_value={} - ) + m_merge_docstubs = mocker.patch("stubber.commands.merge_cmd.merge_all_docstubs", autospec=True, return_value={}) result = runner.invoke(stubber.stubber_cli, cmdline) assert result.exit_code == 0 m_merge_docstubs.assert_called_once() @@ -418,9 +372,7 @@ def test_cmd_merge(mocker: MockerFixture, cmdline: List[str]): def test_cmd_publish(mocker: MockerFixture, cmdline: List[str]): runner = CliRunner() # from stubber.commands.clone import git - m_publish_multiple: MagicMock = mocker.patch( - "stubber.commands.publish_cmd.publish_multiple", autospec=True, return_value={} - ) + m_publish_multiple = mocker.patch("stubber.commands.publish_cmd.publish_multiple", autospec=True, return_value={}) result = runner.invoke(stubber.stubber_cli, cmdline) assert result.exit_code == 0 m_publish_multiple.assert_called_once() diff --git a/tests/common/upd_fallback_test.py b/tests/common/upd_fallback_test.py index 78e642c09..b8bd595f6 100644 --- a/tests/common/upd_fallback_test.py +++ b/tests/common/upd_fallback_test.py @@ -1,6 +1,7 @@ import os from pathlib import Path +import pytest # pylint: disable=wrong-import-position,import-error # Module Under Test @@ -8,6 +9,7 @@ from stubber.utils.config import CONFIG +@pytest.mark.skip("deprecated") def test_update_fallback(tmp_path): # test requires an actuall filled source # from actual source @@ -21,6 +23,7 @@ def test_update_fallback(tmp_path): assert count >= 0 +@pytest.mark.skip("deprecated") def test_update_fallback_2(tmp_path: Path): # test requires an actuall filled source # from actual source diff --git a/tests/freeze/freezer_mpy_test.py b/tests/freeze/freezer_mpy_test.py index 26f22fb7d..78f4a2c72 100644 --- a/tests/freeze/freezer_mpy_test.py +++ b/tests/freeze/freezer_mpy_test.py @@ -66,9 +66,7 @@ def test_get_portboard(path: str, port: str, board: str): assert _port == port -def test_manifest_uasync( - tmp_path: Path, testrepo_micropython: Path, testrepo_micropython_lib: Path -): +def test_manifest_uasync(tmp_path: Path, testrepo_micropython: Path, testrepo_micropython_lib: Path): "test if task.py is included with the uasyncio frozen module" mpy_version = "v1.18" mpy_folder = testrepo_micropython.absolute() @@ -80,9 +78,7 @@ def test_manifest_uasync( manifest = mpy_folder / "ports/esp32/boards/manifest.py" freeze_one_manifest_2(manifest, stub_folder, mpy_folder, lib_folder, mpy_version) - assert ( - tmp_path / "esp32" / GENERIC_U / "uasyncio/task.py" - ).exists(), "task.py must be included in uasyncio" + assert (tmp_path / "esp32" / GENERIC_U / "uasyncio/task.py").exists(), "task.py must be included in uasyncio" ####################################################################################################################### @@ -264,11 +260,9 @@ def test_freeze_any_mocked( ): "mocked test if we can freeze source using manifest.py files" - m_freeze_folders: MagicMock = mocker.patch( - "stubber.freeze.get_frozen.freeze_folders", autospec=True, return_value=[1] - ) - # m_freeze_one_manifest_1: MagicMock = mocker.patch("stubber.freeze.get_frozen.freeze_one_manifest_1", autospec=True, return_value=1) - m_freeze_one_manifest_2: MagicMock = mocker.patch( + m_freeze_folders = mocker.patch("stubber.freeze.get_frozen.freeze_folders", autospec=True, return_value=[1]) + # m_freeze_one_manifest_1= mocker.patch("stubber.freeze.get_frozen.freeze_one_manifest_1", autospec=True, return_value=1) + m_freeze_one_manifest_2 = mocker.patch( "stubber.freeze.get_frozen.freeze_one_manifest_2", autospec=True, return_value=1 ) x = freeze_any( @@ -297,25 +291,22 @@ def test_freeze_manifest2_error_mocked( ): "mocked test if we can freeze source using manifest.py files" - m_freeze_folders: MagicMock = mocker.patch( - "stubber.freeze.get_frozen.freeze_folders", autospec=True, return_value=[1] - ) - # m_freeze_one_manifest_1: MagicMock = mocker.patch("stubber.freeze.get_frozen.freeze_one_manifest_1", autospec=True, return_value=1) - m_freeze_one_manifest_2: MagicMock = mocker.patch( + m_freeze_folders = mocker.patch("stubber.freeze.get_frozen.freeze_folders", autospec=True, return_value=[1]) + m_freeze_one_manifest_2 = mocker.patch( "stubber.freeze.get_frozen.freeze_one_manifest_2", autospec=True, return_value=1 ) # get the correct version to test switch(mpy_version, mpy_path=testrepo_micropython, mpy_lib_path=testrepo_micropython_lib) - x = freeze_any( + test_path = freeze_any( tmp_path, version=mpy_version, mpy_path=testrepo_micropython, mpy_lib_path=testrepo_micropython_lib, ) - assert x >= 1, "expect >= 1 stubs" + assert test_path is not None, "expect a path" + # no further asserts of path as this is mocked assert m_freeze_folders.call_count == 0, "expect no calls to freeze_folders" assert m_freeze_one_manifest_2.call_count == 34, "34 calls to freeze_one_manifest_2" - # assert m_freeze_one_manifest_1.call_count == 0 ########################################################################## diff --git a/tests/publish/test_candidates.py b/tests/publish/test_candidates.py index 21e94926d..b052ef183 100644 --- a/tests/publish/test_candidates.py +++ b/tests/publish/test_candidates.py @@ -1,4 +1,5 @@ """Test candidates.py""" + from pathlib import Path from typing import Generator, List, Union @@ -74,7 +75,7 @@ def test_docstub_candidates(pytestconfig, family, versions, count): # list GENERIC boards for any version (case sensitive on linux/mac) ("micropython", "auto", "auto", "GENERIC", 11), ("micropython", "auto", "auto", "generic", 11), - ("micropython", "latest", "auto", "auto", 7), + ("micropython", "preview", "auto", "auto", 7), ("micropython", "v1.16", "foo", "GENERIC", 0), # port folder does not exist ("micropython", "v1.16", "foo", "generic", 0), # port folder does not exist # list GENERIC boards for specific version (case sensitive on linux/mac) @@ -90,12 +91,12 @@ def test_docstub_candidates(pytestconfig, family, versions, count): ("micropython", "v1.18", "stm32", "pybd_sf2", 2), # Self + Generic ], ) +@pytest.mark.xfail() +# "test is overdepedent on the data in the stubber-repo" def test_frozen_candidates(pytestconfig, family, versions, ports, boards, count): # test data path = pytestconfig.rootpath / "tests/publish/data/stub-version" - frozen = frozen_candidates( - path=path, family=family, versions=versions, ports=ports, boards=boards - ) + frozen = frozen_candidates(path=path, family=family, versions=versions, ports=ports, boards=boards) assert isinstance(frozen, Generator) l = list(frozen) print() @@ -119,9 +120,7 @@ def test_frozen_candidates_err(pytestconfig, family, versions, ports, boards, co # test data path = pytestconfig.rootpath / "tests/publish/data/stub-version" with pytest.raises(Exception) as exc_info: - _ = frozen_candidates( - path=path, family=family, versions=versions, ports=ports, boards=boards - ) + _ = frozen_candidates(path=path, family=family, versions=versions, ports=ports, boards=boards) assert exc_info.type == NotImplementedError @@ -156,9 +155,7 @@ def test_frozen_candidates_err(pytestconfig, family, versions, ports, boards, co ), # find v1.18 NUCLEO_F091RC boards ], ) -def test_worklist( - family: str, versions: Union[List[str], str], ports: str, boards: str, count: int -): +def test_worklist(family: str, versions: Union[List[str], str], ports: str, boards: str, count: int): wl = build_worklist(family=family, versions=versions, ports=ports, boards=boards) assert isinstance(wl, list) msg = ", ".join(sorted([f"{l['version']}-{l['port']}-{l['board']}" for l in wl])) diff --git a/tests/publish/test_multi_build.py b/tests/publish/test_multi_build.py index 0d44c5ea8..1c31ca83a 100644 --- a/tests/publish/test_multi_build.py +++ b/tests/publish/test_multi_build.py @@ -1,5 +1,7 @@ """Test publish module""" + from pathlib import Path + import pytest from mock import MagicMock from pytest_mock import MockerFixture @@ -23,15 +25,11 @@ def test_build_no_change(mocker: MockerFixture, tmp_path: Path, pytestconfig: py config = FakeConfig(tmp_path=tmp_path, rootpath=pytestconfig.rootpath) mocker.patch("stubber.publish.publish.CONFIG", config) mocker.patch("stubber.publish.stubpackage.CONFIG", config) - m_is_changed: MagicMock = mocker.patch("stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False) # type: ignore + m_is_changed = mocker.patch("stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False) # type: ignore - m_check: MagicMock = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) # type: ignore - m_p_build: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True - ) - m_p_publish: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True - ) + m_check = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) # type: ignore + m_p_build = mocker.patch("stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True) + m_p_publish = mocker.patch("stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True) # ----------------------------------------------------------------------------------------------- # Test build: not changed :--> should not build or publish @@ -54,23 +52,23 @@ def test_build_changed(mocker: MockerFixture, tmp_path: Path, pytestconfig: pyte config = FakeConfig(tmp_path=tmp_path, rootpath=pytestconfig.rootpath) mocker.patch("stubber.publish.publish.CONFIG", config) mocker.patch("stubber.publish.stubpackage.CONFIG", config) - m_is_changed: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False - ) - - m_check: MagicMock = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) # type: ignore - m_p_build: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True - ) - m_p_publish: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True - ) + m_is_changed = mocker.patch("stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False) + m_check = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) # type: ignore + m_p_build = mocker.patch("stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True) + m_p_publish = mocker.patch("stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True) + # mock the package on disk + mocker.patch("stubber.publish.package.StubPackage.are_package_sources_available", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.update_package_files", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.update_pyproject_stubs", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.calculate_hash", autospec=True, return_value="hash") + + m_is_changed.return_value = True # ----------------------------------------------------------------------------------------------- # Test publish - changed :--> should build and publish # ----------------------------------------------------------------------------------------------- - m_is_changed.return_value = True - result = build_multiple(production=False, ports=["stm32"], versions=["latest"]) + result = build_multiple(production=False, ports=["stm32"], versions=["preview"]) + # ----------------------------------------------------------------------------------------------- assert len(result) > 0 assert m_p_build.call_count >= 1 assert m_p_publish.call_count == 0 @@ -88,20 +86,16 @@ def test_build_force(mocker: MockerFixture, tmp_path: Path, pytestconfig: pytest config = FakeConfig(tmp_path=tmp_path, rootpath=pytestconfig.rootpath) mocker.patch("stubber.publish.publish.CONFIG", config) mocker.patch("stubber.publish.stubpackage.CONFIG", config) - m_is_changed: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False - ) - - m_check: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.check", autospec=True, return_value=True - ) - m_p_build: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True - ) - m_p_publish: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True - ) - + m_is_changed = mocker.patch("stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False) + + m_check = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) + m_p_build = mocker.patch("stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True) + m_p_publish = mocker.patch("stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True) + # mock the package on disk + mocker.patch("stubber.publish.package.StubPackage.are_package_sources_available", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.update_package_files", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.update_pyproject_stubs", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.calculate_hash", autospec=True, return_value="hash") # ----------------------------------------------------------------------------------------------- # Test publish - not changed + Force :--> should build and publish m_p_build.reset_mock() @@ -110,7 +104,8 @@ def test_build_force(mocker: MockerFixture, tmp_path: Path, pytestconfig: pytest m_is_changed.reset_mock() # ----------------------------------------------------------------------------------------------- m_is_changed.return_value = False - result = build_multiple(production=False, force=True, ports=["stm32"], versions=["latest"]) + result = build_multiple(production=False, force=True, ports=["stm32"], versions=["preview"]) + # ----------------------------------------------------------------------------------------------- assert len(result) > 0 assert m_p_build.call_count >= 1 assert m_p_publish.call_count == 0 diff --git a/tests/publish/test_multi_publish.py b/tests/publish/test_multi_publish.py index 959d67b3b..d0250ec59 100644 --- a/tests/publish/test_multi_publish.py +++ b/tests/publish/test_multi_publish.py @@ -1,4 +1,5 @@ """Test publish module""" + from pathlib import Path import pytest @@ -22,15 +23,11 @@ def test_publish_no_change(mocker: MockerFixture, tmp_path: Path, pytestconfig: config = FakeConfig(tmp_path=tmp_path, rootpath=pytestconfig.rootpath) mocker.patch("stubber.publish.publish.CONFIG", config) mocker.patch("stubber.publish.stubpackage.CONFIG", config) - m_is_changed: MagicMock = mocker.patch("stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False) # type: ignore + m_is_changed = mocker.patch("stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False) # type: ignore - m_check: MagicMock = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) # type: ignore - m_p_build: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True - ) - m_p_publish: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True - ) + m_check = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) # type: ignore + m_p_build = mocker.patch("stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True) + m_p_publish = mocker.patch("stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True) # ----------------------------------------------------------------------------------------------- # Test publish: not changed :--> should not build or publish @@ -53,23 +50,23 @@ def test_publish_changed(mocker: MockerFixture, tmp_path: Path, pytestconfig: py config = FakeConfig(tmp_path=tmp_path, rootpath=pytestconfig.rootpath) mocker.patch("stubber.publish.publish.CONFIG", config) mocker.patch("stubber.publish.stubpackage.CONFIG", config) - m_is_changed: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False - ) - - m_check: MagicMock = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) # type: ignore - m_p_build: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True - ) - m_p_publish: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True - ) + m_is_changed = mocker.patch("stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False) + + m_check = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) # type: ignore + m_p_build = mocker.patch("stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True) + m_p_publish = mocker.patch("stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True) + # mock the package on disk + mocker.patch("stubber.publish.package.StubPackage.are_package_sources_available", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.update_package_files", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.update_pyproject_stubs", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.calculate_hash", autospec=True, return_value="hash") # ----------------------------------------------------------------------------------------------- # Test publish - changed :--> should build and publish # ----------------------------------------------------------------------------------------------- m_is_changed.return_value = True - result = publish_multiple(production=False, ports=["stm32"], versions=["latest"]) + result = publish_multiple(production=False, ports=["stm32"], versions=["preview"]) + # ----------------------------------------------------------------------------------------------- assert len(result) > 0 assert m_p_build.call_count >= 1, "Build should be called" assert m_p_publish.call_count >= 1, "Publish should be called" @@ -87,17 +84,11 @@ def test_publish_build(mocker: MockerFixture, tmp_path: Path, pytestconfig: pyte config = FakeConfig(tmp_path=tmp_path, rootpath=pytestconfig.rootpath) mocker.patch("stubber.publish.publish.CONFIG", config) mocker.patch("stubber.publish.stubpackage.CONFIG", config) - m_is_changed: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False - ) - - m_check: MagicMock = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) # type: ignore - m_p_build: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True - ) - m_p_publish: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True - ) + m_is_changed = mocker.patch("stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False) + + m_check = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) # type: ignore + m_p_build = mocker.patch("stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True) + m_p_publish = mocker.patch("stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True) # ----------------------------------------------------------------------------------------------- # Test publish - unchanged + explicit build :--> should not build and not publish @@ -121,25 +112,22 @@ def test_publish_build_force(mocker: MockerFixture, tmp_path: Path, pytestconfig config = FakeConfig(tmp_path=tmp_path, rootpath=pytestconfig.rootpath) mocker.patch("stubber.publish.publish.CONFIG", config) mocker.patch("stubber.publish.stubpackage.CONFIG", config) - m_is_changed: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False - ) - - m_check: MagicMock = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) # type: ignore - m_p_build: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True - ) - m_p_publish: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True - ) + m_is_changed = mocker.patch("stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False) + + m_check = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) # type: ignore + m_p_build = mocker.patch("stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True) + m_p_publish = mocker.patch("stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True) + # mock the package on disk + mocker.patch("stubber.publish.package.StubPackage.are_package_sources_available", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.update_package_files", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.update_pyproject_stubs", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.calculate_hash", autospec=True, return_value="hash") # ----------------------------------------------------------------------------------------------- # Test publish - unchanged + explicit build :--> should build but not publish # ----------------------------------------------------------------------------------------------- m_is_changed.return_value = False - result = publish_multiple( - production=False, build=True, force=True, ports=["stm32"], versions=["latest"] - ) + result = publish_multiple(production=False, build=True, force=True, ports=["stm32"], versions=["preview"]) assert len(result) > 0 assert m_p_build.call_count >= 1, "Build should be called" assert m_p_publish.call_count >= 1, "Publish should be called" @@ -157,20 +145,16 @@ def test_publish_force(mocker: MockerFixture, tmp_path: Path, pytestconfig: pyte config = FakeConfig(tmp_path=tmp_path, rootpath=pytestconfig.rootpath) mocker.patch("stubber.publish.publish.CONFIG", config) mocker.patch("stubber.publish.stubpackage.CONFIG", config) - m_is_changed: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False - ) - - m_check: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.check", autospec=True, return_value=True - ) - m_p_build: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True - ) - m_p_publish: MagicMock = mocker.patch( - "stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True - ) - + m_is_changed = mocker.patch("stubber.publish.package.StubPackage.is_changed", autospec=True, return_value=False) + + m_check = mocker.patch("stubber.publish.package.StubPackage.check", autospec=True, return_value=True) + m_p_build = mocker.patch("stubber.publish.package.StubPackage.poetry_build", autospec=True, return_value=True) + m_p_publish = mocker.patch("stubber.publish.package.StubPackage.poetry_publish", autospec=True, return_value=True) + # mock the package on disk + mocker.patch("stubber.publish.package.StubPackage.are_package_sources_available", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.update_package_files", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.update_pyproject_stubs", autospec=True, return_value=True) + mocker.patch("stubber.publish.package.StubPackage.calculate_hash", autospec=True, return_value="hash") # ----------------------------------------------------------------------------------------------- # Test publish - not changed + Force :--> should build and publish m_p_build.reset_mock() @@ -179,7 +163,7 @@ def test_publish_force(mocker: MockerFixture, tmp_path: Path, pytestconfig: pyte m_is_changed.reset_mock() # ----------------------------------------------------------------------------------------------- m_is_changed.return_value = False - result = publish_multiple(production=False, force=True, ports=["stm32"], versions=["latest"]) + result = publish_multiple(production=False, force=True, ports=["stm32"], versions=["preview"]) assert len(result) > 0 assert m_p_build.call_count >= 1, "Build should be called" assert m_p_publish.call_count >= 1, "Publish should be called" diff --git a/tests/publish/test_pathnames.py b/tests/publish/test_pathnames.py index 157f9ad0b..09df7fd1a 100644 --- a/tests/publish/test_pathnames.py +++ b/tests/publish/test_pathnames.py @@ -9,7 +9,7 @@ ("micropython-v1_22", {"family": "MicroPython", "version": "1.22"}, None), ("micropython-v1_22_1", {"family": "MicroPython", "version": "1.22"}, "1.22.1"), ("micropython-v1_22_2", {"family": "MicroPython"}, "1.22.2"), - ("micropython-v1_23_0-preview", {"family": "MicroPython", "version": "1.23.0-preview"}, None), + ("micropython-v1_23_0_preview", {"family": "MicroPython", "version": "1.23.0-preview"}, None), ], ) def test_get_base_with_version(expected_base, candidate, version): @@ -31,7 +31,7 @@ def test_get_base_with_version(expected_base, candidate, version): "1.23.4", ), ( - "micropython-v1_23_5-preview-esp8266-ESP8266_GENERIC", + "micropython-v1_23_5_preview-esp8266-ESP8266_GENERIC", {"family": "MicroPython", "port": "esp8266", "board": "ESP8266_GENERIC", "version": "1.23.5-preview"}, "1.23.5-preview", ), diff --git a/tests/util_test.py b/tests/util_test.py index 79924b9b9..609960cb4 100644 --- a/tests/util_test.py +++ b/tests/util_test.py @@ -15,29 +15,43 @@ "commit, build, expected", [ ("v1.13-103-gb137d064e", True, "v1.13-103"), - ("v1.13-103-gb137d064e", False, "latest"), + ("v1.13-103-gb137d064e", False, "preview"), # used to be 'latest' ("v1.13", True, "v1.13"), ("v1.13", False, "v1.13"), ("v1.13-dirty", True, "v1.13"), - ("v1.13-dirty", False, "latest"), + ("v1.13-dirty", False, "preview"), # used to be 'latest' # lets keep all the preview tags simple based on the provided version ("v1.23.0-preview", False, "v1.23.0-preview"), ("v1.23.0-preview", True, "v1.23.0-preview"), ("1.20.0-preview-487", False, "v1.20.0-preview"), ("1.20.0-preview-487", True, "v1.20.0-preview"), + ("v1.23.0-preview-87-g0285cb2bf", False, "v1.23.0-preview"), ], ) def test_clean_version_build(commit, build, expected): assert utils.clean_version(commit, build=build) == expected +@pytest.mark.parametrize( + "input, expected", + [ + ("", ""), + ("latest", "preview"), + ("preview", "preview"), + ("v1.23.0-preview-87-g0285cb2bf", "v1_23_0_preview"), + ], +) +def test_clean_version_flat_preview(input: str, expected: str): + assert utils.clean_version(input, drop_v=False, flat=True) == expected + + def test_clean_version_special(): - assert utils.clean_version("v1.13.0-103-gb137d064e") == "latest" + assert utils.clean_version("v1.13.0-103-gb137d064e") == "preview" assert utils.clean_version("v1.13.0-103-gb137d064e", build=True) == "v1.13-103" assert utils.clean_version("v1.13.0-103-gb137d064e", build=True, commit=True) == "v1.13-103-gb137d064e" # with path # assert utils.clean_version("v1.13.0-103-gb137d064e", patch=True) == "v1.13.0-Latest" - assert utils.clean_version("v1.13.0-103-gb137d064e", patch=True) == "latest" + assert utils.clean_version("v1.13.0-103-gb137d064e", patch=True) == "preview" assert utils.clean_version("v1.13.0-103-gb137d064e", patch=True, build=True) == "v1.13.0-103" # with commit assert ( @@ -45,13 +59,13 @@ def test_clean_version_special(): ) # FLats # assert utils.clean_version("v1.13.0-103-gb137d064e", flat=True) == "v1_13-Latest" - assert utils.clean_version("v1.13.0-103-gb137d064e", flat=True) == "latest" - assert utils.clean_version("v1.13.0-103-gb137d064e", build=True, commit=True, flat=True) == "v1_13-103-gb137d064e" + assert utils.clean_version("v1.13.0-103-gb137d064e", flat=True) == "preview" + assert utils.clean_version("v1.13.0-103-gb137d064e", build=True, commit=True, flat=True) == "v1_13_103_gb137d064e" # all options , no V for version assert ( utils.clean_version("v1.13.0-103-gb137d064e", patch=True, build=True, commit=True, flat=True, drop_v=True) - == "1_13_0-103-gb137d064e" + == "1_13_0_103_gb137d064e" ) @@ -105,10 +119,10 @@ def test_post_processing(tmp_path, pytestconfig, mocker: MockerFixture): dest = tmp_path / "stubs" # shutil.copytree(source, dest) - m_generate_pyi_files: MagicMock = mocker.patch("stubber.utils.post.generate_pyi_files", autospec=True) + m_generate_pyi_files = mocker.patch("stubber.utils.post.generate_pyi_files", autospec=True) return_val = SimpleNamespace() return_val.returncode = 0 - m_spr: MagicMock = mocker.patch("stubber.utils.post.subprocess.run", autospec=True, return_value=return_val) + m_spr = mocker.patch("stubber.utils.post.subprocess.run", autospec=True, return_value=return_val) utils.do_post_processing([dest], stubgen=True, black=True, autoflake=False) From 9114e189164ec9e8a552061663fce0f95c9a7921 Mon Sep 17 00:00:00 2001 From: Jos Verlinde Date: Mon, 5 Feb 2024 16:47:55 +0100 Subject: [PATCH 67/68] Bump version and publish Signed-off-by: Jos Verlinde --- mip/full.json | 2 +- mip/minified.json | 2 +- mip/mpy_v5.json | 48 +++++++++++----------- mip/mpy_v6.json | 48 +++++++++++----------- package.json | 2 +- pyproject.toml | 2 +- src/stubber/__init__.py | 2 +- src/stubber/board/createstubs.py | 2 +- src/stubber/board/createstubs_db.py | 4 +- src/stubber/board/createstubs_db_min.py | 2 +- src/stubber/board/createstubs_db_mpy.mpy | Bin 9427 -> 9427 bytes src/stubber/board/createstubs_mem.py | 4 +- src/stubber/board/createstubs_mem_min.py | 2 +- src/stubber/board/createstubs_mem_mpy.mpy | Bin 9009 -> 9009 bytes src/stubber/board/createstubs_min.py | 2 +- src/stubber/board/createstubs_mpy.mpy | Bin 12111 -> 12111 bytes 16 files changed, 61 insertions(+), 61 deletions(-) diff --git a/mip/full.json b/mip/full.json index 2865d81f5..b7501ed23 100644 --- a/mip/full.json +++ b/mip/full.json @@ -26,5 +26,5 @@ ] ], "deps": [], - "version": "1.16.2" + "version": "1.17.0" } diff --git a/mip/minified.json b/mip/minified.json index 5ed419d72..2adbb29f0 100644 --- a/mip/minified.json +++ b/mip/minified.json @@ -22,5 +22,5 @@ ] ], "deps": [], - "version": "1.16.2" + "version": "1.17.0" } diff --git a/mip/mpy_v5.json b/mip/mpy_v5.json index b6722c750..a38d05284 100644 --- a/mip/mpy_v5.json +++ b/mip/mpy_v5.json @@ -1,26 +1,26 @@ { - "urls": [ - [ - "createstubs.mpy", - "github:josverl/micropython-stubber/mip/v5/createstubs_mpy.mpy" - ], - [ - "createstubs_db.mpy", - "github:Josverl/micropython-stubber/mip/v5/createstubs_db_mpy.mpy" - ], - [ - "createstubs_mem.mpy", - "github:Josverl/micropython-stubber/mip/v5/createstubs_mem_mpy.mpy" - ], - [ - "modulelist.txt", - "github:Josverl/micropython-stubber/mip/v5/modulelist.txt" - ], - [ - "board_info.csv", - "github:Josverl/micropython-stubber/src/stubber/board/board_info.csv" - ] + "urls": [ + [ + "createstubs.mpy", + "github:josverl/micropython-stubber/mip/v5/createstubs_mpy.mpy" ], - "deps": [], - "version": "1.16.2" -} \ No newline at end of file + [ + "createstubs_db.mpy", + "github:Josverl/micropython-stubber/mip/v5/createstubs_db_mpy.mpy" + ], + [ + "createstubs_mem.mpy", + "github:Josverl/micropython-stubber/mip/v5/createstubs_mem_mpy.mpy" + ], + [ + "modulelist.txt", + "github:Josverl/micropython-stubber/mip/v5/modulelist.txt" + ], + [ + "board_info.csv", + "github:Josverl/micropython-stubber/src/stubber/board/board_info.csv" + ] + ], + "deps": [], + "version": "1.17.0" +} diff --git a/mip/mpy_v6.json b/mip/mpy_v6.json index 85311c517..f174662c8 100644 --- a/mip/mpy_v6.json +++ b/mip/mpy_v6.json @@ -1,26 +1,26 @@ { - "urls": [ - [ - "createstubs.mpy", - "github:josverl/micropython-stubber/mip/v6/createstubs_mpy.mpy" - ], - [ - "createstubs_mem.mpy", - "github:Josverl/micropython-stubber/mip/v6/createstubs_mem_mpy.mpy" - ], - [ - "createstubs_db.mpy", - "github:Josverl/micropython-stubber/mip/v6/createstubs_db_mpy.mpy" - ], - [ - "modulelist.txt", - "github:Josverl/micropython-stubber/mip/v6/modulelist.txt" - ], - [ - "board_info.csv", - "github:Josverl/micropython-stubber/src/stubber/board/board_info.csv" - ] + "urls": [ + [ + "createstubs.mpy", + "github:josverl/micropython-stubber/mip/v6/createstubs_mpy.mpy" ], - "deps": [], - "version": "1.16.2" -} \ No newline at end of file + [ + "createstubs_mem.mpy", + "github:Josverl/micropython-stubber/mip/v6/createstubs_mem_mpy.mpy" + ], + [ + "createstubs_db.mpy", + "github:Josverl/micropython-stubber/mip/v6/createstubs_db_mpy.mpy" + ], + [ + "modulelist.txt", + "github:Josverl/micropython-stubber/mip/v6/modulelist.txt" + ], + [ + "board_info.csv", + "github:Josverl/micropython-stubber/src/stubber/board/board_info.csv" + ] + ], + "deps": [], + "version": "1.17.0" +} diff --git a/package.json b/package.json index b3f30d5e3..0559c3106 100644 --- a/package.json +++ b/package.json @@ -18,5 +18,5 @@ ] ], "deps": [], - "version": "1.16.2" + "version": "1.17.0" } diff --git a/pyproject.toml b/pyproject.toml index 2684138e7..b6b27d80b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ repo-path = "./repos" [tool.poetry] name = "micropython-stubber" -version = "1.16.3" +version = "1.17.0" description = "Tooling to create and maintain stubs for MicroPython" authors = ["Jos Verlinde "] license = "MIT" diff --git a/src/stubber/__init__.py b/src/stubber/__init__.py index c99e52374..7bbc1a306 100644 --- a/src/stubber/__init__.py +++ b/src/stubber/__init__.py @@ -1,4 +1,4 @@ """get the version""" -__version__ = "1.16.3" +__version__ = "1.17.0" diff --git a/src/stubber/board/createstubs.py b/src/stubber/board/createstubs.py index 8eeb2a615..2ab22f8ed 100644 --- a/src/stubber/board/createstubs.py +++ b/src/stubber/board/createstubs.py @@ -23,7 +23,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.3" +__version__ = "v1.17.0" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] diff --git a/src/stubber/board/createstubs_db.py b/src/stubber/board/createstubs_db.py index 83fa7c622..38f14d899 100644 --- a/src/stubber/board/createstubs_db.py +++ b/src/stubber/board/createstubs_db.py @@ -18,7 +18,7 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.3 +This variant was generated from createstubs.py by micropython-stubber v1.17.0 """ # Copyright (c) 2019-2023 Jos Verlinde @@ -42,7 +42,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.3" +__version__ = "v1.17.0" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] diff --git a/src/stubber/board/createstubs_db_min.py b/src/stubber/board/createstubs_db_min.py index 84fabc1db..f3bc2d297 100644 --- a/src/stubber/board/createstubs_db_min.py +++ b/src/stubber/board/createstubs_db_min.py @@ -51,7 +51,7 @@ except O:pass try:from collections import OrderedDict as k except O:from ucollections import OrderedDict as k -__version__='v1.16.3' +__version__='v1.17.0' A3=2 A4=2 A5=['lib','/lib','/sd/lib','/flash/lib',J] diff --git a/src/stubber/board/createstubs_db_mpy.mpy b/src/stubber/board/createstubs_db_mpy.mpy index 707854048b2080a412273f58118cd92eef5d47ca..9a5325230836e055b07cb18c08d985e5f631f741 100644 GIT binary patch delta 14 WcmccYdD(Nq2WE3UgN>gbC<6dBfd=>h delta 14 WcmccYdD(Nq2WB%pjhe1_%HE delta 14 Vcmdn!w$W|ETV^vojhm1_}TG diff --git a/src/stubber/board/createstubs_min.py b/src/stubber/board/createstubs_min.py index fcb6f4f2f..63ab05685 100644 --- a/src/stubber/board/createstubs_min.py +++ b/src/stubber/board/createstubs_min.py @@ -50,7 +50,7 @@ except N:pass try:from collections import OrderedDict as g except N:from ucollections import OrderedDict as g -__version__='v1.16.3' +__version__='v1.17.0' A0=2 A1=2 A5=['lib','/lib','/sd/lib','/flash/lib',J] diff --git a/src/stubber/board/createstubs_mpy.mpy b/src/stubber/board/createstubs_mpy.mpy index 759ffb75675f95be3edf0bc4a26ca6dae350a12f..49ccf4652255b808f5ae39b197157c1744a74c6c 100644 GIT binary patch delta 15 WcmX>fcRp^yKW1}1gUyVLetG~n;03Y( delta 15 WcmX>fcRp^yKV~yMIJj_ From fe5fccd66865ec6e6e006e771a2fa032729b03c1 Mon Sep 17 00:00:00 2001 From: Josverl Date: Mon, 5 Feb 2024 15:49:11 +0000 Subject: [PATCH 68/68] Update mip packages --- mip/v5/createstubs.py | 130 ++++---- mip/v5/createstubs_db.py | 293 +++++++++--------- mip/v5/createstubs_db_min.py | 535 +++++++++++++++++---------------- mip/v5/createstubs_db_mpy.mpy | Bin 9744 -> 9669 bytes mip/v5/createstubs_mem.py | 130 ++++---- mip/v5/createstubs_mem_min.py | 329 ++++++++++---------- mip/v5/createstubs_mem_mpy.mpy | Bin 9099 -> 9190 bytes mip/v5/createstubs_min.py | 347 ++++++++++----------- mip/v5/createstubs_mpy.mpy | Bin 11732 -> 11837 bytes mip/v5/modulelist.txt | 3 +- mip/v6/createstubs.py | 130 ++++---- mip/v6/createstubs_db.py | 293 +++++++++--------- mip/v6/createstubs_db_min.py | 535 +++++++++++++++++---------------- mip/v6/createstubs_db_mpy.mpy | Bin 9581 -> 9450 bytes mip/v6/createstubs_mem.py | 130 ++++---- mip/v6/createstubs_mem_min.py | 329 ++++++++++---------- mip/v6/createstubs_mem_mpy.mpy | Bin 8928 -> 9032 bytes mip/v6/createstubs_min.py | 347 ++++++++++----------- mip/v6/createstubs_mpy.mpy | Bin 12030 -> 12133 bytes mip/v6/modulelist.txt | 3 +- 20 files changed, 1808 insertions(+), 1726 deletions(-) diff --git a/mip/v5/createstubs.py b/mip/v5/createstubs.py index 1f7ca21d3..2ab22f8ed 100644 --- a/mip/v5/createstubs.py +++ b/mip/v5/createstubs.py @@ -23,7 +23,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.3" +__version__ = "v1.17.0" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] @@ -77,7 +77,6 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self._report = [] # type: list[str] self.info = _info() log.info("Port: {}".format(self.info["port"])) log.info("Board: {}".format(self.info["board"])) @@ -121,6 +120,8 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore ] # there is no option to discover modules from micropython, list is read from an external file. self.modules = [] # type: list[str] + self._json_name = None + self._json_first = False def get_obj_attributes(self, item_instance: object): "extract information of the objects members and attributes" @@ -129,7 +130,7 @@ def get_obj_attributes(self, item_instance: object): _errors = [] # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: + if name.startswith("__") and not name in self.modules: continue # log.debug("get attribute {}".format(name)) try: @@ -168,10 +169,12 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber {} on {}".format(__version__, self._fwid)) + self.report_start() gc.collect() for module_name in self.modules: self.create_one_stub(module_name) + self.report_end() log.info("Finally done") def create_one_stub(self, module_name: str): @@ -182,7 +185,7 @@ def create_one_stub(self, module_name: str): log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + file_name = "{}/{}.pyi".format(self.path, module_name.replace(".", "/")) gc.collect() result = False try: @@ -197,10 +200,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: Args: - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + - file_name (Optional[str]): the 'path/filename.pyi' to write to. If omitted will be created based on the module name. """ if file_name is None: - fname = module_name.replace(".", "_") + ".py" + fname = module_name.replace(".", "_") + ".pyi" file_name = self.path + "/" + fname else: fname = file_name.split("/")[-1] @@ -229,10 +232,12 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: module_name, self._fwid, info_, __version__ ) fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write( + "from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n" + ) self.write_object_stub(fp, new_module, module_name, "") - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + self.report_add(module_name, file_name) if module_name not in {"os", "sys", "logging", "gc"}: # try to unload the module unless we use it @@ -240,11 +245,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] log.warning("could not del new_module") - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - # log.warning("could not del sys.modules[{}]".format(module_name)) + # do not try to delete from sys.modules - most times it does not work anyway gc.collect() return True @@ -341,23 +342,27 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = item_type_txt[8:-2] s = "" - if t in ["str", "int", "float", "bool", "bytearray", "bytes"]: + if t in ("str", "int", "float", "bool", "bytearray", "bytes"): # known type: use actual value - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) - elif t in ["dict", "list", "tuple"]: + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, item_repr, t) + elif t in ("dict", "list", "tuple"): # dict, list , tuple: use empty value ev = {"dict": "{}", "list": "[]", "tuple": "()"} - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, ev[t], t) else: # something else - if t in ["object", "set", "frozenset", "Pin", "FileIO"]: + if t in ("object", "set", "frozenset", "Pin", "generator"): # "FileIO" # https://docs.python.org/3/tutorial/classes.html#item_instance-objects - # use these types for the attribute - s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + # use these types for the attribute + if t == "generator": + t = "Generator" + s = "{0}{1}: {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) else: # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1}: {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # log.debug("\n" + s) else: @@ -406,41 +411,53 @@ def clean(self, path: str = None): # type: ignore except OSError: pass - def report(self, filename: str = "modules.json"): - "create json with list of exported modules" - log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) - f_name = "{}/{}".format(self.path, filename) - log.info("Report file: {}".format(f_name)) + def report_start(self, filename: str = "modules.json"): + """Start a report of the modules that have been stubbed + "create json with list of exported modules""" + self._json_name = "{}/{}".format(self.path, filename) + self._json_first = True + ensure_folder(self._json_name) + log.info("Report file: {}".format(self._json_name)) gc.collect() try: # write json by node to reduce memory requirements - with open(f_name, "w") as f: - self.write_json_header(f) - first = True - for n in self._report: - self.write_json_node(f, n, first) - first = False - self.write_json_end(f) - used = self._start_free - gc.mem_free() # type: ignore - # log.debug("Memory used: {0} Kb".format(used // 1024)) - except OSError: + with open(self._json_name, "w") as f: + f.write("{") + f.write(dumps({"firmware": self.info})[1:-1]) + f.write(",\n") + f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) + f.write(",\n") + f.write('"modules" :[\n') + + except OSError as e: log.error("Failed to create the report.") + self._json_name = None + raise e + + def report_add(self, module_name: str, stub_file: str): + "Add a module to the report" + # write json by node to reduce memory requirements + if not self._json_name: + raise Exception("No report file") + try: + with open(self._json_name, "a") as f: + if not self._json_first: + f.write(",\n") + else: + self._json_first = False + line = '{{"module": "{}", "file": "{}"}}'.format(module_name, stub_file.replace("\\", "/")) + f.write(line) - def write_json_header(self, f): - f.write("{") - f.write(dumps({"firmware": self.info})[1:-1]) - f.write(",\n") - f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) - f.write(",\n") - f.write('"modules" :[\n') - - def write_json_node(self, f, n, first): - if not first: - f.write(",\n") - f.write(n) + except OSError: + log.error("Failed to create the report.") - def write_json_end(self, f): - f.write("\n]}") + def report_end(self): + if not self._json_name: + raise Exception("No report file") + with open(self._json_name, "a") as f: + f.write("\n]}") + # is used as sucess indicator + log.info("Path: {}".format(self.path)) def ensure_folder(path: str): @@ -486,7 +503,7 @@ def _build(s): def _info(): # type:() -> dict[str, str] info = OrderedDict( { - "family": sys.implementation.name, + "family": sys.implementation.name, # type: ignore "version": "", "build": "", "ver": "", @@ -516,9 +533,9 @@ def _info(): # type:() -> dict[str, str] info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( - sys.implementation._mpy + sys.implementation._mpy # type: ignore if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy + else sys.implementation.mpy # type: ignore if "mpy" in dir(sys.implementation) else "" ) @@ -674,10 +691,6 @@ def is_micropython() -> bool: # pylint: disable=unused-variable,eval-used try: # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented # Micropython: NotImplementedError @@ -942,7 +955,6 @@ def main(): gc.collect() stubber.create_all_stubs() - stubber.report() if __name__ == "__main__" or is_micropython(): diff --git a/mip/v5/createstubs_db.py b/mip/v5/createstubs_db.py index 2743ac849..38f14d899 100644 --- a/mip/v5/createstubs_db.py +++ b/mip/v5/createstubs_db.py @@ -18,7 +18,7 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.3 +This variant was generated from createstubs.py by micropython-stubber v1.17.0 """ # Copyright (c) 2019-2023 Jos Verlinde @@ -42,7 +42,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.3" +__version__ = "v1.17.0" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] @@ -96,7 +96,6 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self._report = [] # type: list[str] self.info = _info() log.info("Port: {}".format(self.info["port"])) log.info("Board: {}".format(self.info["board"])) @@ -140,6 +139,8 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore ] # there is no option to discover modules from micropython, list is read from an external file. self.modules = [] # type: list[str] + self._json_name = None + self._json_first = False def get_obj_attributes(self, item_instance: object): "extract information of the objects members and attributes" @@ -148,7 +149,7 @@ def get_obj_attributes(self, item_instance: object): _errors = [] # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: + if name.startswith("__") and not name in self.modules: continue # log.debug("get attribute {}".format(name)) try: @@ -187,10 +188,12 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber {} on {}".format(__version__, self._fwid)) + self.report_start() gc.collect() for module_name in self.modules: self.create_one_stub(module_name) + self.report_end() log.info("Finally done") def create_one_stub(self, module_name: str): @@ -201,7 +204,7 @@ def create_one_stub(self, module_name: str): log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + file_name = "{}/{}.pyi".format(self.path, module_name.replace(".", "/")) gc.collect() result = False try: @@ -216,10 +219,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: Args: - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + - file_name (Optional[str]): the 'path/filename.pyi' to write to. If omitted will be created based on the module name. """ if file_name is None: - fname = module_name.replace(".", "_") + ".py" + fname = module_name.replace(".", "_") + ".pyi" file_name = self.path + "/" + fname else: fname = file_name.split("/")[-1] @@ -246,10 +249,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + self.report_add(module_name, file_name) if module_name not in {"os", "sys", "logging", "gc"}: # try to unload the module unless we use it @@ -257,11 +260,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] log.warning("could not del new_module") - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - # log.warning("could not del sys.modules[{}]".format(module_name)) + # do not try to delete from sys.modules - most times it does not work anyway gc.collect() return True @@ -356,23 +355,27 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = item_type_txt[8:-2] s = "" - if t in ["str", "int", "float", "bool", "bytearray", "bytes"]: + if t in ("str", "int", "float", "bool", "bytearray", "bytes"): # known type: use actual value - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) - elif t in ["dict", "list", "tuple"]: + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, item_repr, t) + elif t in ("dict", "list", "tuple"): # dict, list , tuple: use empty value ev = {"dict": "{}", "list": "[]", "tuple": "()"} - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, ev[t], t) else: # something else - if t in ["object", "set", "frozenset", "Pin", "FileIO"]: + if t in ("object", "set", "frozenset", "Pin", "generator"): # "FileIO" # https://docs.python.org/3/tutorial/classes.html#item_instance-objects - # use these types for the attribute - s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + # use these types for the attribute + if t == "generator": + t = "Generator" + s = "{0}{1}: {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) else: # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1}: {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # log.debug("\n" + s) else: @@ -421,41 +424,53 @@ def clean(self, path: str = None): # type: ignore except OSError: pass - def report(self, filename: str = "modules.json"): - "create json with list of exported modules" - log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) - f_name = "{}/{}".format(self.path, filename) - log.info("Report file: {}".format(f_name)) + def report_start(self, filename: str = "modules.json"): + """Start a report of the modules that have been stubbed + "create json with list of exported modules""" + self._json_name = "{}/{}".format(self.path, filename) + self._json_first = True + ensure_folder(self._json_name) + log.info("Report file: {}".format(self._json_name)) gc.collect() try: # write json by node to reduce memory requirements - with open(f_name, "w") as f: - self.write_json_header(f) - first = True - for n in self._report: - self.write_json_node(f, n, first) - first = False - self.write_json_end(f) - used = self._start_free - gc.mem_free() # type: ignore - # log.debug("Memory used: {0} Kb".format(used // 1024)) - except OSError: + with open(self._json_name, "w") as f: + f.write("{") + f.write(dumps({"firmware": self.info})[1:-1]) + f.write(",\n") + f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) + f.write(",\n") + f.write('"modules" :[\n') + + except OSError as e: log.error("Failed to create the report.") + self._json_name = None + raise e + + def report_add(self, module_name: str, stub_file: str): + "Add a module to the report" + # write json by node to reduce memory requirements + if not self._json_name: + raise Exception("No report file") + try: + with open(self._json_name, "a") as f: + if not self._json_first: + f.write(",\n") + else: + self._json_first = False + line = '{{"module": "{}", "file": "{}"}}'.format(module_name, stub_file.replace("\\", "/")) + f.write(line) - def write_json_header(self, f): - f.write("{") - f.write(dumps({"firmware": self.info})[1:-1]) - f.write(",\n") - f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) - f.write(",\n") - f.write('"modules" :[\n') - - def write_json_node(self, f, n, first): - if not first: - f.write(",\n") - f.write(n) + except OSError: + log.error("Failed to create the report.") - def write_json_end(self, f): - f.write("\n]}") + def report_end(self): + if not self._json_name: + raise Exception("No report file") + with open(self._json_name, "a") as f: + f.write("\n]}") + # is used as sucess indicator + log.info("Path: {}".format(self.path)) def ensure_folder(path: str): @@ -501,7 +516,7 @@ def _build(s): def _info(): # type:() -> dict[str, str] info = OrderedDict( { - "family": sys.implementation.name, + "family": sys.implementation.name, # type: ignore "version": "", "build": "", "ver": "", @@ -529,9 +544,9 @@ def _info(): # type:() -> dict[str, str] info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( - sys.implementation._mpy + sys.implementation._mpy # type: ignore if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy + else sys.implementation.mpy # type: ignore if "mpy" in dir(sys.implementation) else "" ) @@ -687,10 +702,6 @@ def is_micropython() -> bool: # pylint: disable=unused-variable,eval-used try: # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented # Micropython: NotImplementedError @@ -704,102 +715,96 @@ def is_micropython() -> bool: return True -def main(): - import machine # type: ignore +SKIP_FILE = "modulelist.done" + + +def get_modules(skip=0): + # new + for p in LIBS: + fname = p + "/modulelist.txt" + if not file_exists(fname): + continue + try: + with open(fname) as f: + i = 0 + while True: + line = f.readline().strip() + if not line: + break + if len(line) > 0 and line[0] == "#": + continue + i += 1 + if i < skip: + continue + yield line + break + except OSError: + pass + + +def write_skip(done): + # write count of modules already processed to file + with open(SKIP_FILE, "w") as f: + f.write(str(done) + "\n") + +def read_skip(): + # read count of modules already processed from file + done = 0 try: - f = open("modulelist.done", "r+b") - was_running = True - print("Opened existing db") + with open(SKIP_FILE) as f: + done = int(f.readline().strip()) except OSError: - f = open("modulelist.done", "w+b") - print("created new db") - was_running = False + pass + return done + + +def main(): + import machine # type: ignore + + was_running = file_exists(SKIP_FILE) + if was_running: + log.info("Continue from last run") + else: + log.info("Starting new run") + # try: + # f = open("modulelist.done", "r+b") + # was_running = True + # print("Continue from last run") + # except OSError: + # f = open("modulelist.done", "w+b") + # was_running = False stubber = Stubber(path=read_path()) # f_name = "{}/{}".format(stubber.path, "modules.json") + skip = 0 if not was_running: # Only clean folder if this is a first run stubber.clean() - # get list of modules to process - modules_done = read_done() - # see if we can continue from where we left off - get_modulelist(stubber, modules_done) - - if not stubber.modules: - print("All modules have been processed, exiting") + stubber.report_start("modules.json") else: - del modules_done - gc.collect() - for modulename in stubber.modules: - # ------------------------------------ - # do epic shit - # but sometimes things fail / run out of memory and reboot - ok = False - try: - ok = stubber.create_one_stub(modulename) - except MemoryError: - # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER - machine.reset() - # ------------------------------------- - gc.collect() - # modules_done[modulename] = str(stubber._report[-1] if ok else "failed") - with open("modulelist.done", "a") as f: - f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) - - # Finished processing - load all the results , and remove the failed ones - modules_done = read_done() - if modules_done: - # stubber.write_json_end(mod_fp) - stubber._report = [] - for k, v in modules_done.items(): - if v != "failed": - stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(k)) - stubber.report() - - -def read_done(): - modules_done = {} # type: dict[str, str] - try: - with open("modulelist.done") as f: - while True: - line = f.readline().strip() - if not line: - break - if len(line) > 0 and line[0] != "#": - key, value = line.split("=", 1) - modules_done[key] = value - except (OSError, SyntaxError): - print("could not read modulelist.done") - finally: - gc.collect() - return modules_done + skip = read_skip() + stubber._json_name = "{}/{}".format(stubber.path, "modules.json") - -def get_modulelist(stubber, modules_done): - # new - gc.collect() - stubber.modules = [] # avoid duplicates - for p in LIBS: - fname = p + "/modulelist.txt" - if not file_exists(fname): - continue - with open(fname) as f: - # print("DEBUG: list of modules: " + p + "/modulelist.txt") - while True: - line = f.readline().strip() - if not line: - break - if line and line not in modules_done.keys(): - stubber.modules.append(line) - gc.collect() - print("BREAK") - break - - if not stubber.modules: - stubber.modules = ["micropython"] - # _log.warn("Could not find modulelist.txt, using default modules") - gc.collect() + for modulename in get_modules(skip): + # ------------------------------------ + # do epic shit + # but sometimes things fail / run out of memory and reboot + try: + stubber.create_one_stub(modulename) + except MemoryError: + # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER + machine.reset() + # ------------------------------------- + gc.collect() + # modules_done[modulename] = str(stubber._report[-1] if ok else "failed") + # with open("modulelist.done", "a") as f: + # f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) + skip += 1 + write_skip(skip) + + print("All modules have been processed, Finalizing report") + stubber.report_end() if __name__ == "__main__" or is_micropython(): diff --git a/mip/v5/createstubs_db_min.py b/mip/v5/createstubs_db_min.py index f61b4498f..f3bc2d297 100644 --- a/mip/v5/createstubs_db_min.py +++ b/mip/v5/createstubs_db_min.py @@ -1,324 +1,325 @@ -y='{}/{}' -x='method' -w='function' -v='bool' -u='str' -t='float' -s='int' -r='stubber' -q=TypeError -p=KeyError -o=sorted -n=MemoryError -m=NotImplementedError -g=',\n' -e='dict' -d='list' -c='tuple' -b='_' -a='micropython' -Z=repr -X='modulelist.done' +A2='No report file' +A1='Failed to create the report.' +A0='method' +z='function' +y='bool' +x='str' +w='float' +v='int' +u='micropython' +t='stubber' +s=TypeError +r=Exception +q=KeyError +p=sorted +o=MemoryError +n=NotImplementedError +j=',\n' +i='modules.json' +h='{}/{}' +g='w' +f='dict' +e='list' +d='tuple' +c=str +b=repr W='-preview' V='-' U='board' T=IndexError -S='family' -R=ImportError -Q=len -P=dir -O=True -N=open -L='port' -K='.' -J=print +S=print +R=True +Q='family' +P=len +O=ImportError +N=dir +M=open +K='port' +J='.' I=AttributeError H=False G='/' -F=None -E=OSError -D='version' -C='' -import gc as A,os,sys +E=None +D=OSError +C='version' +B='' +import gc as F,os,sys from time import sleep try:from ujson import dumps except:from json import dumps try:from machine import reset -except R:pass -try:from collections import OrderedDict as f -except R:from ucollections import OrderedDict as f -__version__='v1.16.3' -z=2 -A0=2 -A1=['lib','/lib','/sd/lib','/flash/lib',K] -class M: - INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=J +except O:pass +try:from collections import OrderedDict as k +except O:from ucollections import OrderedDict as k +__version__='v1.17.0' +A3=2 +A4=2 +A5=['lib','/lib','/sd/lib','/flash/lib',J] +class L: + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=S @staticmethod - def getLogger(name):return M() + def getLogger(name):return L() @classmethod def basicConfig(A,level):A.level=level def info(A,msg): - if A.level<=M.INFO:A.prnt('INFO :',msg) + if A.level<=L.INFO:A.prnt('INFO :',msg) def warning(A,msg): - if A.level<=M.WARNING:A.prnt('WARN :',msg) + if A.level<=L.WARNING:A.prnt('WARN :',msg) def error(A,msg): - if A.level<=M.ERROR:A.prnt('ERROR :',msg) -B=M.getLogger(r) -M.basicConfig(level=M.INFO) + if A.level<=L.ERROR:A.prnt('ERROR :',msg) +A=L.getLogger(t) +L.basicConfig(level=L.INFO) class Stubber: - def __init__(C,path=F,firmware_id=F): - D=firmware_id + def __init__(B,path=E,firmware_id=E): + C=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise n('MicroPython 1.13.0 cannot be stubbed') except I:pass - C._report=[];C.info=_info();B.info('Port: {}'.format(C.info[L]));B.info('Board: {}'.format(C.info[U]));A.collect() - if D:C._fwid=D.lower() - elif C.info[S]==a:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info).rstrip(V) - else:C._fwid='{family}-v{version}-{port}'.format(**C.info) - C._start_free=A.mem_free() + B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[U]));F.collect() + if C:B._fwid=C.lower() + elif B.info[Q]==u:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(V) + else:B._fwid='{family}-v{version}-{port}'.format(**B.info) + B._start_free=F.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() - C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) - try:h(path+G) - except E:B.error('error creating stub folder {}'.format(path)) - C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] - def get_obj_attributes(M,item_instance): - H=item_instance;D=[];L=[] - for B in P(H): - if B.startswith(b)and not B in M.modules:continue + B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) + try:X(path+G) + except D:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[];B._json_name=E;B._json_first=H + def get_obj_attributes(L,item_instance): + H=item_instance;C=[];K=[] + for A in N(H): + if A.startswith('__')and not A in L.modules:continue try: - E=getattr(H,B) - try:F=Z(type(E)).split("'")[1] - except T:F=C - if F in{s,t,u,v,c,d,e}:G=1 - elif F in{w,x}:G=2 - elif F in'class':G=3 + D=getattr(H,A) + try:E=b(type(D)).split("'")[1] + except T:E=B + if E in{v,w,x,y,d,e,f}:G=1 + elif E in{z,A0}:G=2 + elif E in'class':G=3 else:G=4 - D.append((B,Z(E),Z(type(E)),E,G)) - except I as K:L.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(B,H,K)) - except n as K:J('MemoryError: {}'.format(K));sleep(1);reset() - D=o([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);A.collect();return D,L - def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) - def create_all_stubs(C): - B.info('Start micropython-stubber v{} on {}'.format(__version__,C._fwid));A.collect() - for D in C.modules:C.create_one_stub(D) - B.info('Finally done') - def create_one_stub(D,module_name): - C=module_name - if C in D.problematic:B.warning('Skip module: {:<25} : Known problematic'.format(C));return H - if C in D.excluded:B.warning('Skip module: {:<25} : Excluded'.format(C));return H - I='{}/{}.py'.format(D.path,C.replace(K,G));A.collect();F=H - try:F=D.create_module_stub(C,I) - except E:return H - A.collect();return F - def create_module_stub(J,module_name,file_name=F): - I=file_name;D=module_name - if I is F:L=D.replace(K,b)+'.py';I=J.path+G+L + C.append((A,b(D),b(type(D)),D,G)) + except I as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,J)) + except o as J:S('MemoryError: {}'.format(J));sleep(1);reset() + C=p([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);F.collect();return C,K + def add_modules(A,modules):A.modules=p(set(A.modules)|set(modules)) + def create_all_stubs(B): + A.info('Start micropython-stubber {} on {}'.format(__version__,B._fwid));B.report_start();F.collect() + for C in B.modules:B.create_one_stub(C) + B.report_end();A.info('Finally done') + def create_one_stub(C,module_name): + B=module_name + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return H + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return H + I='{}/{}.pyi'.format(C.path,B.replace(J,G));F.collect();E=H + try:E=C.create_module_stub(B,I) + except D:return H + F.collect();return E + def create_module_stub(K,module_name,file_name=E): + I=file_name;C=module_name + if I is E:L=C.replace(J,'_')+'.pyi';I=K.path+G+L else:L=I.split(G)[-1] - if G in D:D=D.replace(G,K) - M=F - try:M=__import__(D,F,F,'*');Q=A.mem_free();B.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(D,L,Q)) - except R:return H - h(I) - with N(I,'w')as P:S=str(J.info).replace('OrderedDict(',C).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(P,M,D,C) - J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,I.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: - try:del M - except(E,p):B.warning('could not del new_module') - A.collect();return O + if G in C:C=C.replace(G,J) + N=E + try:N=__import__(C,E,E,'*');Q=F.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,Q)) + except O:return H + X(I) + with M(I,g)as P:S=c(K.info).replace('OrderedDict(',B).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(P,N,C,B) + K.report_add(C,I) + if C not in{'os','sys','logging','gc'}: + try:del N + except(D,q):A.warning('could not del new_module') + F.collect();return R def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;E=indent;A.collect() - if L in K.problematic:B.warning('SKIPPING problematic module:{}'.format(L));return - X,O=K.get_obj_attributes(L) - if O:B.error(O) - for(F,J,G,Y,a)in X: - if F in['classmethod','staticmethod','BaseException',M]:continue - if F[0].isdigit():B.warning('NameError: invalid name {}'.format(F));continue - if G==""and Q(E)<=A0*4: - P=C;R=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] - if R:P=M - D='\n{}class {}({}):\n'.format(E,F,P) - if R:D+=E+' ...\n';I.write(D);continue - I.write(D);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',N+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';I.write(D) - elif any(A in G for A in[x,w,'closure']): - S=U;T=C + X='generator';W='{0}{1}: {3} = {2}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() + if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return + Y,O=K.get_obj_attributes(L) + if O:A.error(O) + for(E,J,H,Z,b)in Y: + if E in['classmethod','staticmethod','BaseException',M]:continue + if E[0].isdigit():A.warning('NameError: invalid name {}'.format(E));continue + if H==""and P(D)<=A4*4: + Q=B;R=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if R:Q=M + C='\n{}class {}({}):\n'.format(D,E,Q) + if R:C+=D+' ...\n';I.write(C);continue + I.write(C);K.write_object_stub(I,Z,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) + elif any(A in H for A in[A0,z,'closure']): + S=U;T=B if N>0:T='self, ' - if V in G or V in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) - else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,T,S) - D+=E+' ...\n\n';I.write(D) - elif G=="":0 - elif G.startswith(" {}:\n'.format(D,E,S) + else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,T,S) + C+=D+' ...\n\n';I.write(C) + elif H=="":0 + elif H.startswith("='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if E in A and A[E]: - G=int(A[E]);J=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] - if J:A[N]=J - A[E]='v{}.{}'.format(G&255,G>>8&3) - if A[B]and not A[D].endswith(W):A[D]=A[D]+W - A[K]=f"{A[D]}-{A[B]}"if A[B]else f"{A[D]}";return A -def A2(version): - A=version;B=K.join([str(A)for A in A[:3]]) - if Q(A)>3 and A[3]:B+=V+A[3] + if'uname'in N(os): + A[D]=Y(os.uname()[3]) + if not A[D]:A[D]=Y(os.uname()[2]) + elif C in N(sys):A[D]=Y(sys.version) + except(I,T,s):pass + if A[C]==B and sys.platform not in(S,R): + try:a=os.uname();A[C]=a.release + except(T,I,s):pass + for(b,c,d)in[(V,V,'const'),(X,X,'FAT'),(Z,'pybricks.hubs','EV3Brick')]: + try:e=__import__(c,E,E,d);A[Q]=b;del e;break + except(O,q):pass + if A[Q]==Z:A['release']='2.0.0' + if A[Q]==u: + A[C] + if A[C]and A[C].endswith('.0')and A[C]>='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if F in A and A[F]: + G=int(A[F]);J=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[P]=J + A[F]='v{}.{}'.format(G&255,G>>8&3) + if A[D]and not A[C].endswith(W):A[C]=A[C]+W + A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A +def A6(version): + A=version;B=J.join([c(A)for A in A[:3]]) + if P(A)>3 and A[3]:B+=V+A[3] return B -def A3(): - try:from boardname import BOARDNAME as A;B.info('Found BOARDNAME: {}'.format(A)) - except R:B.warning('BOARDNAME not found');A=C - return A +def A7(): + try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) + except O:A.warning('BOARDNAME not found');C=B + return C def get_root(): try:A=os.getcwd() - except(E,I):A=K + except(D,I):A=J B=A - for B in[A,'/sd','/flash',G,K]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break - except E:continue + except D:continue return B -def i(filename): +def Z(filename): try: - if os.stat(filename)[0]>>14:return O + if os.stat(filename)[0]>>14:return R return H - except E:return H -def j():J("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) + except D:return H +def l():S("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): - path=C - if Q(sys.argv)==3: + path=B + if P(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:j() - elif Q(sys.argv)==2:j() + else:l() + elif P(sys.argv)==2:l() return path -def k(): - try:A=bytes('abc',encoding='utf8');B=k.__module__;return H - except(m,I):return O -def main(): - I='failed';import machine as K - try:C=N(X,'r+b');D=O;J('Opened existing db') - except E:C=N(X,'w+b');J('created new db');D=H - stubber=Stubber(path=read_path()) - if not D:stubber.clean() - B=l();A4(stubber,B) - if not stubber.modules:J('All modules have been processed, exiting') - else: - del B;A.collect() - for F in stubber.modules: - G=H - try:G=stubber.create_one_stub(F) - except n:K.reset() - A.collect() - with N(X,'a')as C:C.write('{}={}\n'.format(F,'ok'if G else I)) - B=l() - if B: - stubber._report=[] - for(L,M)in B.items(): - if M!=I:stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(L)) - stubber.report() -def l(): - C={} +def m(): + try:A=bytes('abc',encoding='utf8');B=m.__module__;return H + except(n,I):return R +a='modulelist.done' +def A8(skip=0): + for E in A5: + B=E+'/modulelist.txt' + if not Z(B):continue + try: + with M(B)as F: + C=0 + while R: + A=F.readline().strip() + if not A:break + if P(A)>0 and A[0]=='#':continue + C+=1 + if C0 and B[0]!='#':F,G=B.split('=',1);C[F]=G - except(E,SyntaxError):J('could not read modulelist.done') - finally:A.collect();return C -def A4(stubber,modules_done): - A.collect();stubber.modules=[] - for D in A1: - C=D+'/modulelist.txt' - if not i(C):continue - with N(C)as E: - while O: - B=E.readline().strip() - if not B:break - if B and B not in modules_done.keys():stubber.modules.append(B) - A.collect();J('BREAK');break - if not stubber.modules:stubber.modules=[a] - A.collect() -if __name__=='__main__'or k(): - if not i('no_auto_stubber.txt'): - try:A.threshold(4*1024);A.enable() + with M(a)as B:A=int(B.readline().strip()) + except D:pass + return A +def main(): + import machine as D;C=Z(a) + if C:A.info('Continue from last run') + else:A.info('Starting new run') + stubber=Stubber(path=read_path());B=0 + if not C:stubber.clean();stubber.report_start(i) + else:B=AA();stubber._json_name=h.format(stubber.path,i) + for E in A8(B): + try:stubber.create_one_stub(E) + except o:D.reset() + F.collect();B+=1;A9(B) + S('All modules have been processed, Finalizing report');stubber.report_end() +if __name__=='__main__'or m(): + if not Z('no_auto_stubber.txt'): + try:F.threshold(4*1024);F.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_db_mpy.mpy b/mip/v5/createstubs_db_mpy.mpy index d7910db3d017ffcc5cce9ca96e3921ec6a2ad299..48bd4732701f446e4207d1e947c9425279473905 100644 GIT binary patch delta 4766 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 bool: Args: - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + - file_name (Optional[str]): the 'path/filename.pyi' to write to. If omitted will be created based on the module name. """ if file_name is None: - fname = module_name.replace(".", "_") + ".py" + fname = module_name.replace(".", "_") + ".pyi" file_name = self.path + "/" + fname else: fname = file_name.split("/")[-1] @@ -237,10 +240,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + self.report_add(module_name, file_name) if module_name not in {"os", "sys", "logging", "gc"}: # try to unload the module unless we use it @@ -248,11 +251,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] log.warning("could not del new_module") - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - # log.warning("could not del sys.modules[{}]".format(module_name)) + # do not try to delete from sys.modules - most times it does not work anyway gc.collect() return True @@ -347,23 +346,27 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = item_type_txt[8:-2] s = "" - if t in ["str", "int", "float", "bool", "bytearray", "bytes"]: + if t in ("str", "int", "float", "bool", "bytearray", "bytes"): # known type: use actual value - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) - elif t in ["dict", "list", "tuple"]: + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, item_repr, t) + elif t in ("dict", "list", "tuple"): # dict, list , tuple: use empty value ev = {"dict": "{}", "list": "[]", "tuple": "()"} - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, ev[t], t) else: # something else - if t in ["object", "set", "frozenset", "Pin", "FileIO"]: + if t in ("object", "set", "frozenset", "Pin", "generator"): # "FileIO" # https://docs.python.org/3/tutorial/classes.html#item_instance-objects - # use these types for the attribute - s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + # use these types for the attribute + if t == "generator": + t = "Generator" + s = "{0}{1}: {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) else: # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1}: {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # log.debug("\n" + s) else: @@ -412,41 +415,53 @@ def clean(self, path: str = None): # type: ignore except OSError: pass - def report(self, filename: str = "modules.json"): - "create json with list of exported modules" - log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) - f_name = "{}/{}".format(self.path, filename) - log.info("Report file: {}".format(f_name)) + def report_start(self, filename: str = "modules.json"): + """Start a report of the modules that have been stubbed + "create json with list of exported modules""" + self._json_name = "{}/{}".format(self.path, filename) + self._json_first = True + ensure_folder(self._json_name) + log.info("Report file: {}".format(self._json_name)) gc.collect() try: # write json by node to reduce memory requirements - with open(f_name, "w") as f: - self.write_json_header(f) - first = True - for n in self._report: - self.write_json_node(f, n, first) - first = False - self.write_json_end(f) - used = self._start_free - gc.mem_free() # type: ignore - # log.debug("Memory used: {0} Kb".format(used // 1024)) - except OSError: + with open(self._json_name, "w") as f: + f.write("{") + f.write(dumps({"firmware": self.info})[1:-1]) + f.write(",\n") + f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) + f.write(",\n") + f.write('"modules" :[\n') + + except OSError as e: log.error("Failed to create the report.") + self._json_name = None + raise e + + def report_add(self, module_name: str, stub_file: str): + "Add a module to the report" + # write json by node to reduce memory requirements + if not self._json_name: + raise Exception("No report file") + try: + with open(self._json_name, "a") as f: + if not self._json_first: + f.write(",\n") + else: + self._json_first = False + line = '{{"module": "{}", "file": "{}"}}'.format(module_name, stub_file.replace("\\", "/")) + f.write(line) - def write_json_header(self, f): - f.write("{") - f.write(dumps({"firmware": self.info})[1:-1]) - f.write(",\n") - f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) - f.write(",\n") - f.write('"modules" :[\n') - - def write_json_node(self, f, n, first): - if not first: - f.write(",\n") - f.write(n) + except OSError: + log.error("Failed to create the report.") - def write_json_end(self, f): - f.write("\n]}") + def report_end(self): + if not self._json_name: + raise Exception("No report file") + with open(self._json_name, "a") as f: + f.write("\n]}") + # is used as sucess indicator + log.info("Path: {}".format(self.path)) def ensure_folder(path: str): @@ -492,7 +507,7 @@ def _build(s): def _info(): # type:() -> dict[str, str] info = OrderedDict( { - "family": sys.implementation.name, + "family": sys.implementation.name, # type: ignore "version": "", "build": "", "ver": "", @@ -520,9 +535,9 @@ def _info(): # type:() -> dict[str, str] info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( - sys.implementation._mpy + sys.implementation._mpy # type: ignore if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy + else sys.implementation.mpy # type: ignore if "mpy" in dir(sys.implementation) else "" ) @@ -678,10 +693,6 @@ def is_micropython() -> bool: # pylint: disable=unused-variable,eval-used try: # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented # Micropython: NotImplementedError @@ -734,7 +745,6 @@ def get_modulelist(stubber): gc.collect() stubber.create_all_stubs() - stubber.report() if __name__ == "__main__" or is_micropython(): diff --git a/mip/v5/createstubs_mem_min.py b/mip/v5/createstubs_mem_min.py index 415b4e5bd..9c2cfd272 100644 --- a/mip/v5/createstubs_mem_min.py +++ b/mip/v5/createstubs_mem_min.py @@ -1,3 +1,5 @@ +x='No report file' +w='Failed to create the report.' v='{}/{}' u='method' t='function' @@ -7,34 +9,34 @@ p='int' o='stubber' n=TypeError -m=KeyError -l=sorted -k=NotImplementedError +m=Exception +l=KeyError +k=sorted +j=NotImplementedError e=',\n' d='dict' c='list' b='tuple' -a='_' -Z='micropython' -Y=open -X=repr -V='-preview' -U='-' -T='board' -S=IndexError -R=print -Q=True -P='family' -O=ImportError -N=len +a='micropython' +Z=repr +W='-preview' +V='-' +U='board' +T=IndexError +S=print +R=True +Q='family' +P=len +O=open +N=ImportError M=dir K='port' J='.' -I=False -H=AttributeError +I=AttributeError +H=False G='/' -F=None -E=OSError +F=OSError +E=None C='version' B='' import gc as D,os,sys @@ -42,15 +44,15 @@ try:from ujson import dumps except:from json import dumps try:from machine import reset -except O:pass +except N:pass try:from collections import OrderedDict as f -except O:from ucollections import OrderedDict as f -__version__='v1.16.3' -w=2 -x=2 -y=['lib','/lib','/sd/lib','/flash/lib',J] +except N:from ucollections import OrderedDict as f +__version__='v1.17.0' +y=2 +z=2 +A0=['lib','/lib','/sd/lib','/flash/lib',J] class L: - INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=R + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=S @staticmethod def getLogger(name):return L() @classmethod @@ -64,230 +66,235 @@ def error(A,msg): A=L.getLogger(o) L.basicConfig(level=L.INFO) class Stubber: - def __init__(B,path=F,firmware_id=F): + def __init__(B,path=E,firmware_id=E): C=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') - except H:pass - B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[T]));D.collect() + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') + except I:pass + B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[U]));D.collect() if C:B._fwid=C.lower() - elif B.info[P]==Z:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(U) + elif B.info[Q]==a:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(V) else:B._fwid='{family}-v{version}-{port}'.format(**B.info) B._start_free=D.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) - try:g(path+G) - except E:A.error('error creating stub folder {}'.format(path)) - B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[] + try:X(path+G) + except F:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[];B._json_name=E;B._json_first=H def get_obj_attributes(L,item_instance): - I=item_instance;C=[];K=[] - for A in M(I): - if A.startswith(a)and not A in L.modules:continue + H=item_instance;C=[];K=[] + for A in M(H): + if A.startswith('__')and not A in L.modules:continue try: - E=getattr(I,A) - try:F=X(type(E)).split("'")[1] - except S:F=B + E=getattr(H,A) + try:F=Z(type(E)).split("'")[1] + except T:F=B if F in{p,q,r,s,b,c,d}:G=1 elif F in{t,u}:G=2 elif F in'class':G=3 else:G=4 - C.append((A,X(E),X(type(E)),E,G)) - except H as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,J)) - except MemoryError as J:R('MemoryError: {}'.format(J));sleep(1);reset() - C=l([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,K - def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) + C.append((A,Z(E),Z(type(E)),E,G)) + except I as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,J)) + except MemoryError as J:S('MemoryError: {}'.format(J));sleep(1);reset() + C=k([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,K + def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) def create_all_stubs(B): - A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));D.collect() + A.info('Start micropython-stubber {} on {}'.format(__version__,B._fwid));B.report_start();D.collect() for C in B.modules:B.create_one_stub(C) - A.info('Finally done') + B.report_end();A.info('Finally done') def create_one_stub(C,module_name): B=module_name - if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return I - if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return I - H='{}/{}.py'.format(C.path,B.replace(J,G));D.collect();F=I - try:F=C.create_module_stub(B,H) - except E:return I - D.collect();return F - def create_module_stub(K,module_name,file_name=F): - H=file_name;C=module_name - if H is F:L=C.replace(J,a)+'.py';H=K.path+G+L - else:L=H.split(G)[-1] + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return H + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return H + I='{}/{}.pyi'.format(C.path,B.replace(J,G));D.collect();E=H + try:E=C.create_module_stub(B,I) + except F:return H + D.collect();return E + def create_module_stub(K,module_name,file_name=E): + I=file_name;C=module_name + if I is E:L=C.replace(J,'_')+'.pyi';I=K.path+G+L + else:L=I.split(G)[-1] if G in C:C=C.replace(G,J) - M=F - try:M=__import__(C,F,F,'*');P=D.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) - except O:return I - g(H) - with Y(H,'w')as N:R=str(K.info).replace('OrderedDict(',B).replace('})','}');S='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,R,__version__);N.write(S);N.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,M,C,B) - K._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + M=E + try:M=__import__(C,E,E,'*');Q=D.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,Q)) + except N:return H + X(I) + with O(I,'w')as P:S=str(K.info).replace('OrderedDict(',B).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(P,M,C,B) + K.report_add(C,I) if C not in{'os','sys','logging','gc'}: try:del M - except(E,m):A.warning('could not del new_module') - D.collect();return Q + except(F,l):A.warning('could not del new_module') + D.collect();return R def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';O=in_class;M='Exception';L=object_expr;I=fp;E=indent;D.collect() + X='generator';W='{0}{1}: {3} = {2}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;E=indent;D.collect() if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return - X,P=K.get_obj_attributes(L) - if P:A.error(P) - for(F,J,G,Y,a)in X: + Y,O=K.get_obj_attributes(L) + if O:A.error(O) + for(F,J,H,Z,e)in Y: if F in['classmethod','staticmethod','BaseException',M]:continue if F[0].isdigit():A.warning('NameError: invalid name {}'.format(F));continue - if G==""and N(E)<=x*4: + if H==""and P(E)<=z*4: Q=B;R=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] if R:Q=M C='\n{}class {}({}):\n'.format(E,F,Q) if R:C+=E+' ...\n';I.write(C);continue - I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',O+1);C=E+' def __init__(self, *argv, **kwargs) -> None:\n';C+=E+' ...\n\n';I.write(C) - elif any(A in G for A in[u,t,'closure']): + I.write(C);K.write_object_stub(I,Z,'{0}.{1}'.format(obj_name,F),E+' ',N+1);C=E+' def __init__(self, *argv, **kwargs) -> None:\n';C+=E+' ...\n\n';I.write(C) + elif any(A in H for A in[u,t,'closure']): S=U;T=B - if O>0:T='self, ' - if V in G or V in J:C='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) + if N>0:T='self, ' + if V in H or V in J:C='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,T,S) C+=E+' ...\n\n';I.write(C) - elif G=="":0 - elif G.startswith("":0 + elif H.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] - if E in A and A[E]: - G=int(A[E]);J=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] - if J:A[Q]=J - A[E]='v{}.{}'.format(G&255,G>>8&3) - if A[D]and not A[C].endswith(V):A[C]=A[C]+V + if F in A and A[F]: + G=int(A[F]);J=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[P]=J + A[F]='v{}.{}'.format(G&255,G>>8&3) + if A[D]and not A[C].endswith(W):A[C]=A[C]+W A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A -def z(version): +def A1(version): A=version;B=J.join([str(A)for A in A[:3]]) - if N(A)>3 and A[3]:B+=U+A[3] + if P(A)>3 and A[3]:B+=V+A[3] return B -def A0(): +def A2(): try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) - except O:A.warning('BOARDNAME not found');C=B + except N:A.warning('BOARDNAME not found');C=B return C def get_root(): try:A=os.getcwd() - except(E,H):A=J + except(F,I):A=J B=A for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break - except E:continue + except F:continue return B -def h(filename): +def g(filename): try: - if os.stat(filename)[0]>>14:return Q - return I - except E:return I -def i():R("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) + if os.stat(filename)[0]>>14:return R + return H + except F:return H +def h():S("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): path=B - if N(sys.argv)==3: + if P(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:i() - elif N(sys.argv)==2:i() + else:h() + elif P(sys.argv)==2:h() return path -def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return I - except(k,H):return Q +def i(): + try:A=bytes('abc',encoding='utf8');B=i.__module__;return H + except(j,I):return R def main(): stubber=Stubber(path=read_path());stubber.clean() def A(stubber): D.collect();stubber.modules=[] - for C in y: + for C in A0: B=C+'/modulelist.txt' - if not h(B):continue - with Y(B)as E: - while Q: + if not g(B):continue + with O(B)as E: + while R: A=E.readline().strip() if not A:break - if N(A)>0 and A[0]!='#':stubber.modules.append(A) - D.collect();R('BREAK');break - if not stubber.modules:stubber.modules=[Z] + if P(A)>0 and A[0]!='#':stubber.modules.append(A) + D.collect();S('BREAK');break + if not stubber.modules:stubber.modules=[a] D.collect() - stubber.modules=[];A(stubber);D.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or j(): - if not h('no_auto_stubber.txt'): + stubber.modules=[];A(stubber);D.collect();stubber.create_all_stubs() +if __name__=='__main__'or i(): + if not g('no_auto_stubber.txt'): try:D.threshold(4*1024);D.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_mem_mpy.mpy b/mip/v5/createstubs_mem_mpy.mpy index c3acec7c4c8d58fbfdef272abee6285c6f8eb261..f60d383c7968df80d7390b0f65e8f20136cf9c82 100644 GIT binary patch delta 3751 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 delta 3598 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 diff --git a/mip/v5/createstubs_min.py b/mip/v5/createstubs_min.py index 0fcb07093..63ab05685 100644 --- a/mip/v5/createstubs_min.py +++ b/mip/v5/createstubs_min.py @@ -1,43 +1,45 @@ -x='pyb' -w='{}/{}' -v='logging' -u='sys' -t='method' -s='function' -r='bool' -q='str' -p='float' -o='int' -n='stubber' -m=TypeError +z='No report file' +y='Failed to create the report.' +x='{}/{}' +w='logging' +v='sys' +u='method' +t='function' +s='bool' +r='str' +q='float' +p='int' +o='stubber' +n=TypeError +m=Exception l=KeyError k=sorted j=NotImplementedError -e='pycom' -d=',\n' -c='dict' -b='list' -a='tuple' -Z='_' -Y='micropython' -X=repr -W=print -U='-preview' -T=True -S='-' -R='board' -Q=IndexError -P='family' -O=len +f='pycom' +e=',\n' +d='dict' +c='list' +b='tuple' +a='micropython' +Z=repr +Y=print +V='-preview' +U=True +T='-' +S='board' +R=len +Q=open +P=IndexError +O='family' N=ImportError M=dir K='port' J='.' -I=False -H=AttributeError +I=AttributeError +H=False G='/' -E=None -D=OSError +E=OSError +D=None C='version' B='' import gc as F,os,sys @@ -46,14 +48,14 @@ except:from json import dumps try:from machine import reset except N:pass -try:from collections import OrderedDict as f -except N:from ucollections import OrderedDict as f -__version__='v1.16.3' -y=2 -z=2 -A3=['lib','/lib','/sd/lib','/flash/lib',J] +try:from collections import OrderedDict as g +except N:from ucollections import OrderedDict as g +__version__='v1.17.0' +A0=2 +A1=2 +A5=['lib','/lib','/sd/lib','/flash/lib',J] class L: - INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=W + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=Y @staticmethod def getLogger(name):return L() @classmethod @@ -64,218 +66,223 @@ def warning(A,msg): if A.level<=L.WARNING:A.prnt('WARN :',msg) def error(A,msg): if A.level<=L.ERROR:A.prnt('ERROR :',msg) -A=L.getLogger(n) +A=L.getLogger(o) L.basicConfig(level=L.INFO) class Stubber: - def __init__(B,path=E,firmware_id=E): + def __init__(B,path=D,firmware_id=D): C=firmware_id try: if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') - except H:pass - B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[R]));F.collect() + except I:pass + B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[S]));F.collect() if C:B._fwid=C.lower() - elif B.info[P]==Y:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(S) + elif B.info[O]==a:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(T) else:B._fwid='{family}-v{version}-{port}'.format(**B.info) B._start_free=F.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) - try:g(path+G) - except D:A.error('error creating stub folder {}'.format(path)) - B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[] + try:W(path+G) + except E:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[];B._json_name=D;B._json_first=H def get_obj_attributes(L,item_instance): - I=item_instance;C=[];K=[] - for A in M(I): - if A.startswith(Z)and not A in L.modules:continue + H=item_instance;C=[];K=[] + for A in M(H): + if A.startswith('__')and not A in L.modules:continue try: - D=getattr(I,A) - try:E=X(type(D)).split("'")[1] - except Q:E=B - if E in{o,p,q,r,a,b,c}:G=1 - elif E in{s,t}:G=2 + D=getattr(H,A) + try:E=Z(type(D)).split("'")[1] + except P:E=B + if E in{p,q,r,s,b,c,d}:G=1 + elif E in{t,u}:G=2 elif E in'class':G=3 else:G=4 - C.append((A,X(D),X(type(D)),D,G)) - except H as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,J)) - except MemoryError as J:W('MemoryError: {}'.format(J));sleep(1);reset() + C.append((A,Z(D),Z(type(D)),D,G)) + except I as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,J)) + except MemoryError as J:Y('MemoryError: {}'.format(J));sleep(1);reset() C=k([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);F.collect();return C,K def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) def create_all_stubs(B): - A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));F.collect() + A.info('Start micropython-stubber {} on {}'.format(__version__,B._fwid));B.report_start();F.collect() for C in B.modules:B.create_one_stub(C) - A.info('Finally done') + B.report_end();A.info('Finally done') def create_one_stub(C,module_name): B=module_name - if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return I - if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return I - H='{}/{}.py'.format(C.path,B.replace(J,G));F.collect();E=I - try:E=C.create_module_stub(B,H) - except D:return I - F.collect();return E - def create_module_stub(K,module_name,file_name=E): - H=file_name;C=module_name - if H is E:L=C.replace(J,Z)+'.py';H=K.path+G+L - else:L=H.split(G)[-1] + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return H + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return H + I='{}/{}.pyi'.format(C.path,B.replace(J,G));F.collect();D=H + try:D=C.create_module_stub(B,I) + except E:return H + F.collect();return D + def create_module_stub(K,module_name,file_name=D): + I=file_name;C=module_name + if I is D:L=C.replace(J,'_')+'.pyi';I=K.path+G+L + else:L=I.split(G)[-1] if G in C:C=C.replace(G,J) - M=E - try:M=__import__(C,E,E,'*');P=F.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) - except N:return I - g(H) - with open(H,'w')as O:Q=str(K.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,Q,__version__);O.write(R);O.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(O,M,C,B) - K._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) - if C not in{'os',u,v,'gc'}: + M=D + try:M=__import__(C,D,D,'*');P=F.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) + except N:return H + W(I) + with Q(I,'w')as O:R=str(K.info).replace('OrderedDict(',B).replace('})','}');S='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,R,__version__);O.write(S);O.write('from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(O,M,C,B) + K.report_add(C,I) + if C not in{'os',v,w,'gc'}: try:del M - except(D,l):A.warning('could not del new_module') - F.collect();return T + except(E,l):A.warning('could not del new_module') + F.collect();return U def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() + X='generator';W='{0}{1}: {3} = {2}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return - X,P=K.get_obj_attributes(L) - if P:A.error(P) - for(E,J,G,Y,d)in X: + Y,O=K.get_obj_attributes(L) + if O:A.error(O) + for(E,J,H,Z,e)in Y: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():A.warning('NameError: invalid name {}'.format(E));continue - if G==""and O(D)<=z*4: - Q=B;R=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if R:Q=M - C='\n{}class {}({}):\n'.format(D,E,Q) - if R:C+=D+' ...\n';I.write(C);continue - I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) - elif any(A in G for A in[t,s,'closure']): + if H==""and R(D)<=A1*4: + P=B;Q=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if Q:P=M + C='\n{}class {}({}):\n'.format(D,E,P) + if Q:C+=D+' ...\n';I.write(C);continue + I.write(C);K.write_object_stub(I,Z,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) + elif any(A in H for A in[u,t,'closure']): S=U;T=B if N>0:T='self, ' - if V in G or V in J:C='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,S) + if V in H or V in J:C='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,S) else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,T,S) C+=D+' ...\n\n';I.write(C) - elif G=="":0 - elif G.startswith("":0 + elif H.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] if F in A and A[F]: - G=int(A[F]);J=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] - if J:A[S]=J + G=int(A[F]);J=[D,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[R]=J A[F]='v{}.{}'.format(G&255,G>>8&3) - if A[D]and not A[C].endswith(U):A[C]=A[C]+U - A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A -def A0(version): + if A[E]and not A[C].endswith(V):A[C]=A[C]+V + A[L]=f"{A[C]}-{A[E]}"if A[E]else f"{A[C]}";return A +def A2(version): A=version;B=J.join([str(A)for A in A[:3]]) - if O(A)>3 and A[3]:B+=S+A[3] + if R(A)>3 and A[3]:B+=T+A[3] return B -def A1(): +def A3(): try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) except N:A.warning('BOARDNAME not found');C=B return C def get_root(): try:A=os.getcwd() - except(D,H):A=J + except(E,I):A=J B=A for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break - except D:continue + except E:continue return B -def A2(filename): +def A4(filename): try: - if os.stat(filename)[0]>>14:return T - return I - except D:return I -def h():W("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) + if os.stat(filename)[0]>>14:return U + return H + except E:return H +def h():Y("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): path=B - if O(sys.argv)==3: + if R(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] else:h() - elif O(sys.argv)==2:h() + elif R(sys.argv)==2:h() return path def i(): - try:A=bytes('abc',encoding='utf8');B=i.__module__;return I - except(j,H):return T -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',x,e,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];F.collect();stubber.create_all_stubs();stubber.report() + try:A=bytes('abc',encoding='utf8');B=i.__module__;return H + except(j,I):return U +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',w,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',a,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform','pyb',f,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',v,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];F.collect();stubber.create_all_stubs() if __name__=='__main__'or i(): - if not A2('no_auto_stubber.txt'): + if not A4('no_auto_stubber.txt'): try:F.threshold(4*1024);F.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v5/createstubs_mpy.mpy b/mip/v5/createstubs_mpy.mpy index 0fe1b26a0d424ffe4053f0b89a45761e5ad3769a..5f0dcebebc793662bc3affedef66c37b802723a8 100644 GIT binary patch delta 3691 zcmZ8jdu&_P89(>fjuXdmj*qXeW5~KKDE4eCPK)&hPs^JaGA7-M4hu8qS>qu5UIwT(x@ZMbl?j^WYz1@D?))2)MI{G42{S$oAnj z$Evn~AjD!vi9o@KCUt#Wgk#voXyks;SDEwrAW~c_fp~y9b6+GE3LgvrC$0ZZ-R> z#?SRJUVC5TT14$3ltidJ9UqoAI!x7iWj&fM)>wN$xLPwwnoSnHvVk4f`ngT)C)y@% zGy6a*2L0vtF56&!cFXhTDdJT#yRvy_nRgTQaCLn=m1mrN|DD&wqY_C}a z6wBq~S=AbT={?@x4^}O|$?5){BxlSShco@7DLL16B$r7)XS}6wA!M#ox*9~+YRTpD zvCguXv-?(5tMqN<&>_0$ybvnZl&fB(VfJoWklW4vSGLlzqnG0N&1kJ6YI(G0chRC- zg?RK7#d}znKHjt;f_XGav@2IqeFTF7)vaA7MDf09s#^$geOv3%K8icpAM}MrilfCE zKBmHosg9$#t5_o}z7Gs#bNQa65#bK+Y`lCO2d@5JMT?hcW3dPqH7aL|7Tf%0jneVw zLf08Y(Y~3pA$+6D4re{cKC7^YcixJYD}B`ZmTJ^_ibp7Zl;SMKIf@e$Cn@f4)z3$D z%H-P}9t9TUDIR5O4I8*_Hf{*Oc|S8;rh}*j6=U11=<2l6%Ogg@Y@)Ir68PoHTJA7= zwbErzZQ|XF91)ABQVYbT*GcP{O;kQWHvK01|*SgUAp$}@d*J;I# zu9b-LvDnbCdV6BAIjW%?LAsFk2DR~ISRRfIWMw&m-U5%biW*3$xwGdZ8nAGyS_<)ll()3^hFJC%sYzr;)BUlLlnp1bHsDXy>DF z?>;F=X7x%u96?d5LN&ZzEC=0^Il_U4j*A7aQ>?fd{e?pDt}7vq0 zDw+8L+Ho<$b=E2{Mmvb1Q#~C7CJ+$ROi(*P;TFxjPmlyS@1oBt8bJRQ$t+nT8lMfM zf+E?j5aNbUTU(o9;V(YhWgh)VvZ(;>FWep%dCz6ZLQLa&HoAt`85}l7a6tPOhAK^rk`U~!pY9bmqvV$mM^^$3J zkZDUO2wk@8F2l+u!L#J18iW5RUZ+Y*WL+{9&*j`JfEs@bvZo$z!@WKS)q^HSiS!oP z5Bi0T1a&l*%|~fLIlpu!l^p7s9nUE0;{FmhCYm+#(Kf}eA=>c?s!tH@fkU(cej1x- zWx`jxyth_z^e%1R2HOc5CFof~2eO&taylpHN!iY!^too;eAENe=WeR*p`|-SrF2u@Au|?4enE}B!v16lm?^{? z!o9{l-ag@8?;a1%w(vYxZ@n!JPPj!;oe51Ca`r_ri&>N03+$S;nfo#O+}hAm;<&3F zpBJW~mZPVq4nAXX8le@Mf+ETJM4)tLTx>mG=H&-bo%r1b^ zp@+55V(3b>W_m_#Rq#QIw?r@$EOpu3l0kMb$a^bFN|f)VUJ#d{JCYm{g++LaEsI)l zW2MIMUefT$iFIMRj1}51uW~i89#Fbel%NJMQm+co3;3Y)Ppi==GaQ;&JQnzQH6c5p zWm5f63S+5(DrLCZN!Cq0{PZc@fcM#zH`(KM8@Ga;vA0`VZbf%1Z+34%XDw*G(hE!* zV4v7Ujh$b~uwx}>V-bhPzTc{RAT@^l{x&}X-h=+&YH_m`iUJ#PNcKI&dG$q?Eb{0y zg}_eszA*zm(q8s+M}Yg7ed>4w<3YBy*2V2$M{1kvb|+}%*#zaz!*>pH=bZ~wUuuxb zM#d8Cm$lusL29+sSxigqeTch2Yxi!gQVV-Gvp8QSJJnmV+;l>V&R%!gxc%(+&TcNv zJazlI0d~ADY>ZOwN=WECFb8+^sx_@(f*+1%&G64du-M delta 3644 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 K_h#LXbpHb{DcRuw diff --git a/mip/v5/modulelist.txt b/mip/v5/modulelist.txt index d722c404c..32dacba0f 100644 --- a/mip/v5/modulelist.txt +++ b/mip/v5/modulelist.txt @@ -1,5 +1,4 @@ -# list of modules to stub. -# used by the memory optimised createstubs_mem.py +# list of modules to stub used by the memory optimised createstubs_mem.py WM8960 _OTA _asyncio diff --git a/mip/v6/createstubs.py b/mip/v6/createstubs.py index 1f7ca21d3..2ab22f8ed 100644 --- a/mip/v6/createstubs.py +++ b/mip/v6/createstubs.py @@ -23,7 +23,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.3" +__version__ = "v1.17.0" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] @@ -77,7 +77,6 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self._report = [] # type: list[str] self.info = _info() log.info("Port: {}".format(self.info["port"])) log.info("Board: {}".format(self.info["board"])) @@ -121,6 +120,8 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore ] # there is no option to discover modules from micropython, list is read from an external file. self.modules = [] # type: list[str] + self._json_name = None + self._json_first = False def get_obj_attributes(self, item_instance: object): "extract information of the objects members and attributes" @@ -129,7 +130,7 @@ def get_obj_attributes(self, item_instance: object): _errors = [] # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: + if name.startswith("__") and not name in self.modules: continue # log.debug("get attribute {}".format(name)) try: @@ -168,10 +169,12 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber {} on {}".format(__version__, self._fwid)) + self.report_start() gc.collect() for module_name in self.modules: self.create_one_stub(module_name) + self.report_end() log.info("Finally done") def create_one_stub(self, module_name: str): @@ -182,7 +185,7 @@ def create_one_stub(self, module_name: str): log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + file_name = "{}/{}.pyi".format(self.path, module_name.replace(".", "/")) gc.collect() result = False try: @@ -197,10 +200,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: Args: - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + - file_name (Optional[str]): the 'path/filename.pyi' to write to. If omitted will be created based on the module name. """ if file_name is None: - fname = module_name.replace(".", "_") + ".py" + fname = module_name.replace(".", "_") + ".pyi" file_name = self.path + "/" + fname else: fname = file_name.split("/")[-1] @@ -229,10 +232,12 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: module_name, self._fwid, info_, __version__ ) fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write( + "from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n" + ) self.write_object_stub(fp, new_module, module_name, "") - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + self.report_add(module_name, file_name) if module_name not in {"os", "sys", "logging", "gc"}: # try to unload the module unless we use it @@ -240,11 +245,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] log.warning("could not del new_module") - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - # log.warning("could not del sys.modules[{}]".format(module_name)) + # do not try to delete from sys.modules - most times it does not work anyway gc.collect() return True @@ -341,23 +342,27 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = item_type_txt[8:-2] s = "" - if t in ["str", "int", "float", "bool", "bytearray", "bytes"]: + if t in ("str", "int", "float", "bool", "bytearray", "bytes"): # known type: use actual value - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) - elif t in ["dict", "list", "tuple"]: + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, item_repr, t) + elif t in ("dict", "list", "tuple"): # dict, list , tuple: use empty value ev = {"dict": "{}", "list": "[]", "tuple": "()"} - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, ev[t], t) else: # something else - if t in ["object", "set", "frozenset", "Pin", "FileIO"]: + if t in ("object", "set", "frozenset", "Pin", "generator"): # "FileIO" # https://docs.python.org/3/tutorial/classes.html#item_instance-objects - # use these types for the attribute - s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + # use these types for the attribute + if t == "generator": + t = "Generator" + s = "{0}{1}: {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) else: # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1}: {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # log.debug("\n" + s) else: @@ -406,41 +411,53 @@ def clean(self, path: str = None): # type: ignore except OSError: pass - def report(self, filename: str = "modules.json"): - "create json with list of exported modules" - log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) - f_name = "{}/{}".format(self.path, filename) - log.info("Report file: {}".format(f_name)) + def report_start(self, filename: str = "modules.json"): + """Start a report of the modules that have been stubbed + "create json with list of exported modules""" + self._json_name = "{}/{}".format(self.path, filename) + self._json_first = True + ensure_folder(self._json_name) + log.info("Report file: {}".format(self._json_name)) gc.collect() try: # write json by node to reduce memory requirements - with open(f_name, "w") as f: - self.write_json_header(f) - first = True - for n in self._report: - self.write_json_node(f, n, first) - first = False - self.write_json_end(f) - used = self._start_free - gc.mem_free() # type: ignore - # log.debug("Memory used: {0} Kb".format(used // 1024)) - except OSError: + with open(self._json_name, "w") as f: + f.write("{") + f.write(dumps({"firmware": self.info})[1:-1]) + f.write(",\n") + f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) + f.write(",\n") + f.write('"modules" :[\n') + + except OSError as e: log.error("Failed to create the report.") + self._json_name = None + raise e + + def report_add(self, module_name: str, stub_file: str): + "Add a module to the report" + # write json by node to reduce memory requirements + if not self._json_name: + raise Exception("No report file") + try: + with open(self._json_name, "a") as f: + if not self._json_first: + f.write(",\n") + else: + self._json_first = False + line = '{{"module": "{}", "file": "{}"}}'.format(module_name, stub_file.replace("\\", "/")) + f.write(line) - def write_json_header(self, f): - f.write("{") - f.write(dumps({"firmware": self.info})[1:-1]) - f.write(",\n") - f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) - f.write(",\n") - f.write('"modules" :[\n') - - def write_json_node(self, f, n, first): - if not first: - f.write(",\n") - f.write(n) + except OSError: + log.error("Failed to create the report.") - def write_json_end(self, f): - f.write("\n]}") + def report_end(self): + if not self._json_name: + raise Exception("No report file") + with open(self._json_name, "a") as f: + f.write("\n]}") + # is used as sucess indicator + log.info("Path: {}".format(self.path)) def ensure_folder(path: str): @@ -486,7 +503,7 @@ def _build(s): def _info(): # type:() -> dict[str, str] info = OrderedDict( { - "family": sys.implementation.name, + "family": sys.implementation.name, # type: ignore "version": "", "build": "", "ver": "", @@ -516,9 +533,9 @@ def _info(): # type:() -> dict[str, str] info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( - sys.implementation._mpy + sys.implementation._mpy # type: ignore if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy + else sys.implementation.mpy # type: ignore if "mpy" in dir(sys.implementation) else "" ) @@ -674,10 +691,6 @@ def is_micropython() -> bool: # pylint: disable=unused-variable,eval-used try: # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented # Micropython: NotImplementedError @@ -942,7 +955,6 @@ def main(): gc.collect() stubber.create_all_stubs() - stubber.report() if __name__ == "__main__" or is_micropython(): diff --git a/mip/v6/createstubs_db.py b/mip/v6/createstubs_db.py index 2743ac849..38f14d899 100644 --- a/mip/v6/createstubs_db.py +++ b/mip/v6/createstubs_db.py @@ -18,7 +18,7 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.3 +This variant was generated from createstubs.py by micropython-stubber v1.17.0 """ # Copyright (c) 2019-2023 Jos Verlinde @@ -42,7 +42,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.3" +__version__ = "v1.17.0" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] @@ -96,7 +96,6 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self._report = [] # type: list[str] self.info = _info() log.info("Port: {}".format(self.info["port"])) log.info("Board: {}".format(self.info["board"])) @@ -140,6 +139,8 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore ] # there is no option to discover modules from micropython, list is read from an external file. self.modules = [] # type: list[str] + self._json_name = None + self._json_first = False def get_obj_attributes(self, item_instance: object): "extract information of the objects members and attributes" @@ -148,7 +149,7 @@ def get_obj_attributes(self, item_instance: object): _errors = [] # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: + if name.startswith("__") and not name in self.modules: continue # log.debug("get attribute {}".format(name)) try: @@ -187,10 +188,12 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber {} on {}".format(__version__, self._fwid)) + self.report_start() gc.collect() for module_name in self.modules: self.create_one_stub(module_name) + self.report_end() log.info("Finally done") def create_one_stub(self, module_name: str): @@ -201,7 +204,7 @@ def create_one_stub(self, module_name: str): log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + file_name = "{}/{}.pyi".format(self.path, module_name.replace(".", "/")) gc.collect() result = False try: @@ -216,10 +219,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: Args: - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + - file_name (Optional[str]): the 'path/filename.pyi' to write to. If omitted will be created based on the module name. """ if file_name is None: - fname = module_name.replace(".", "_") + ".py" + fname = module_name.replace(".", "_") + ".pyi" file_name = self.path + "/" + fname else: fname = file_name.split("/")[-1] @@ -246,10 +249,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + self.report_add(module_name, file_name) if module_name not in {"os", "sys", "logging", "gc"}: # try to unload the module unless we use it @@ -257,11 +260,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] log.warning("could not del new_module") - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - # log.warning("could not del sys.modules[{}]".format(module_name)) + # do not try to delete from sys.modules - most times it does not work anyway gc.collect() return True @@ -356,23 +355,27 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = item_type_txt[8:-2] s = "" - if t in ["str", "int", "float", "bool", "bytearray", "bytes"]: + if t in ("str", "int", "float", "bool", "bytearray", "bytes"): # known type: use actual value - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) - elif t in ["dict", "list", "tuple"]: + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, item_repr, t) + elif t in ("dict", "list", "tuple"): # dict, list , tuple: use empty value ev = {"dict": "{}", "list": "[]", "tuple": "()"} - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, ev[t], t) else: # something else - if t in ["object", "set", "frozenset", "Pin", "FileIO"]: + if t in ("object", "set", "frozenset", "Pin", "generator"): # "FileIO" # https://docs.python.org/3/tutorial/classes.html#item_instance-objects - # use these types for the attribute - s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + # use these types for the attribute + if t == "generator": + t = "Generator" + s = "{0}{1}: {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) else: # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1}: {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # log.debug("\n" + s) else: @@ -421,41 +424,53 @@ def clean(self, path: str = None): # type: ignore except OSError: pass - def report(self, filename: str = "modules.json"): - "create json with list of exported modules" - log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) - f_name = "{}/{}".format(self.path, filename) - log.info("Report file: {}".format(f_name)) + def report_start(self, filename: str = "modules.json"): + """Start a report of the modules that have been stubbed + "create json with list of exported modules""" + self._json_name = "{}/{}".format(self.path, filename) + self._json_first = True + ensure_folder(self._json_name) + log.info("Report file: {}".format(self._json_name)) gc.collect() try: # write json by node to reduce memory requirements - with open(f_name, "w") as f: - self.write_json_header(f) - first = True - for n in self._report: - self.write_json_node(f, n, first) - first = False - self.write_json_end(f) - used = self._start_free - gc.mem_free() # type: ignore - # log.debug("Memory used: {0} Kb".format(used // 1024)) - except OSError: + with open(self._json_name, "w") as f: + f.write("{") + f.write(dumps({"firmware": self.info})[1:-1]) + f.write(",\n") + f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) + f.write(",\n") + f.write('"modules" :[\n') + + except OSError as e: log.error("Failed to create the report.") + self._json_name = None + raise e + + def report_add(self, module_name: str, stub_file: str): + "Add a module to the report" + # write json by node to reduce memory requirements + if not self._json_name: + raise Exception("No report file") + try: + with open(self._json_name, "a") as f: + if not self._json_first: + f.write(",\n") + else: + self._json_first = False + line = '{{"module": "{}", "file": "{}"}}'.format(module_name, stub_file.replace("\\", "/")) + f.write(line) - def write_json_header(self, f): - f.write("{") - f.write(dumps({"firmware": self.info})[1:-1]) - f.write(",\n") - f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) - f.write(",\n") - f.write('"modules" :[\n') - - def write_json_node(self, f, n, first): - if not first: - f.write(",\n") - f.write(n) + except OSError: + log.error("Failed to create the report.") - def write_json_end(self, f): - f.write("\n]}") + def report_end(self): + if not self._json_name: + raise Exception("No report file") + with open(self._json_name, "a") as f: + f.write("\n]}") + # is used as sucess indicator + log.info("Path: {}".format(self.path)) def ensure_folder(path: str): @@ -501,7 +516,7 @@ def _build(s): def _info(): # type:() -> dict[str, str] info = OrderedDict( { - "family": sys.implementation.name, + "family": sys.implementation.name, # type: ignore "version": "", "build": "", "ver": "", @@ -529,9 +544,9 @@ def _info(): # type:() -> dict[str, str] info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( - sys.implementation._mpy + sys.implementation._mpy # type: ignore if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy + else sys.implementation.mpy # type: ignore if "mpy" in dir(sys.implementation) else "" ) @@ -687,10 +702,6 @@ def is_micropython() -> bool: # pylint: disable=unused-variable,eval-used try: # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented # Micropython: NotImplementedError @@ -704,102 +715,96 @@ def is_micropython() -> bool: return True -def main(): - import machine # type: ignore +SKIP_FILE = "modulelist.done" + + +def get_modules(skip=0): + # new + for p in LIBS: + fname = p + "/modulelist.txt" + if not file_exists(fname): + continue + try: + with open(fname) as f: + i = 0 + while True: + line = f.readline().strip() + if not line: + break + if len(line) > 0 and line[0] == "#": + continue + i += 1 + if i < skip: + continue + yield line + break + except OSError: + pass + + +def write_skip(done): + # write count of modules already processed to file + with open(SKIP_FILE, "w") as f: + f.write(str(done) + "\n") + +def read_skip(): + # read count of modules already processed from file + done = 0 try: - f = open("modulelist.done", "r+b") - was_running = True - print("Opened existing db") + with open(SKIP_FILE) as f: + done = int(f.readline().strip()) except OSError: - f = open("modulelist.done", "w+b") - print("created new db") - was_running = False + pass + return done + + +def main(): + import machine # type: ignore + + was_running = file_exists(SKIP_FILE) + if was_running: + log.info("Continue from last run") + else: + log.info("Starting new run") + # try: + # f = open("modulelist.done", "r+b") + # was_running = True + # print("Continue from last run") + # except OSError: + # f = open("modulelist.done", "w+b") + # was_running = False stubber = Stubber(path=read_path()) # f_name = "{}/{}".format(stubber.path, "modules.json") + skip = 0 if not was_running: # Only clean folder if this is a first run stubber.clean() - # get list of modules to process - modules_done = read_done() - # see if we can continue from where we left off - get_modulelist(stubber, modules_done) - - if not stubber.modules: - print("All modules have been processed, exiting") + stubber.report_start("modules.json") else: - del modules_done - gc.collect() - for modulename in stubber.modules: - # ------------------------------------ - # do epic shit - # but sometimes things fail / run out of memory and reboot - ok = False - try: - ok = stubber.create_one_stub(modulename) - except MemoryError: - # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER - machine.reset() - # ------------------------------------- - gc.collect() - # modules_done[modulename] = str(stubber._report[-1] if ok else "failed") - with open("modulelist.done", "a") as f: - f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) - - # Finished processing - load all the results , and remove the failed ones - modules_done = read_done() - if modules_done: - # stubber.write_json_end(mod_fp) - stubber._report = [] - for k, v in modules_done.items(): - if v != "failed": - stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(k)) - stubber.report() - - -def read_done(): - modules_done = {} # type: dict[str, str] - try: - with open("modulelist.done") as f: - while True: - line = f.readline().strip() - if not line: - break - if len(line) > 0 and line[0] != "#": - key, value = line.split("=", 1) - modules_done[key] = value - except (OSError, SyntaxError): - print("could not read modulelist.done") - finally: - gc.collect() - return modules_done + skip = read_skip() + stubber._json_name = "{}/{}".format(stubber.path, "modules.json") - -def get_modulelist(stubber, modules_done): - # new - gc.collect() - stubber.modules = [] # avoid duplicates - for p in LIBS: - fname = p + "/modulelist.txt" - if not file_exists(fname): - continue - with open(fname) as f: - # print("DEBUG: list of modules: " + p + "/modulelist.txt") - while True: - line = f.readline().strip() - if not line: - break - if line and line not in modules_done.keys(): - stubber.modules.append(line) - gc.collect() - print("BREAK") - break - - if not stubber.modules: - stubber.modules = ["micropython"] - # _log.warn("Could not find modulelist.txt, using default modules") - gc.collect() + for modulename in get_modules(skip): + # ------------------------------------ + # do epic shit + # but sometimes things fail / run out of memory and reboot + try: + stubber.create_one_stub(modulename) + except MemoryError: + # RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER + machine.reset() + # ------------------------------------- + gc.collect() + # modules_done[modulename] = str(stubber._report[-1] if ok else "failed") + # with open("modulelist.done", "a") as f: + # f.write("{}={}\n".format(modulename, "ok" if ok else "failed")) + skip += 1 + write_skip(skip) + + print("All modules have been processed, Finalizing report") + stubber.report_end() if __name__ == "__main__" or is_micropython(): diff --git a/mip/v6/createstubs_db_min.py b/mip/v6/createstubs_db_min.py index f61b4498f..f3bc2d297 100644 --- a/mip/v6/createstubs_db_min.py +++ b/mip/v6/createstubs_db_min.py @@ -1,324 +1,325 @@ -y='{}/{}' -x='method' -w='function' -v='bool' -u='str' -t='float' -s='int' -r='stubber' -q=TypeError -p=KeyError -o=sorted -n=MemoryError -m=NotImplementedError -g=',\n' -e='dict' -d='list' -c='tuple' -b='_' -a='micropython' -Z=repr -X='modulelist.done' +A2='No report file' +A1='Failed to create the report.' +A0='method' +z='function' +y='bool' +x='str' +w='float' +v='int' +u='micropython' +t='stubber' +s=TypeError +r=Exception +q=KeyError +p=sorted +o=MemoryError +n=NotImplementedError +j=',\n' +i='modules.json' +h='{}/{}' +g='w' +f='dict' +e='list' +d='tuple' +c=str +b=repr W='-preview' V='-' U='board' T=IndexError -S='family' -R=ImportError -Q=len -P=dir -O=True -N=open -L='port' -K='.' -J=print +S=print +R=True +Q='family' +P=len +O=ImportError +N=dir +M=open +K='port' +J='.' I=AttributeError H=False G='/' -F=None -E=OSError -D='version' -C='' -import gc as A,os,sys +E=None +D=OSError +C='version' +B='' +import gc as F,os,sys from time import sleep try:from ujson import dumps except:from json import dumps try:from machine import reset -except R:pass -try:from collections import OrderedDict as f -except R:from ucollections import OrderedDict as f -__version__='v1.16.3' -z=2 -A0=2 -A1=['lib','/lib','/sd/lib','/flash/lib',K] -class M: - INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=J +except O:pass +try:from collections import OrderedDict as k +except O:from ucollections import OrderedDict as k +__version__='v1.17.0' +A3=2 +A4=2 +A5=['lib','/lib','/sd/lib','/flash/lib',J] +class L: + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=S @staticmethod - def getLogger(name):return M() + def getLogger(name):return L() @classmethod def basicConfig(A,level):A.level=level def info(A,msg): - if A.level<=M.INFO:A.prnt('INFO :',msg) + if A.level<=L.INFO:A.prnt('INFO :',msg) def warning(A,msg): - if A.level<=M.WARNING:A.prnt('WARN :',msg) + if A.level<=L.WARNING:A.prnt('WARN :',msg) def error(A,msg): - if A.level<=M.ERROR:A.prnt('ERROR :',msg) -B=M.getLogger(r) -M.basicConfig(level=M.INFO) + if A.level<=L.ERROR:A.prnt('ERROR :',msg) +A=L.getLogger(t) +L.basicConfig(level=L.INFO) class Stubber: - def __init__(C,path=F,firmware_id=F): - D=firmware_id + def __init__(B,path=E,firmware_id=E): + C=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise m('MicroPython 1.13.0 cannot be stubbed') + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise n('MicroPython 1.13.0 cannot be stubbed') except I:pass - C._report=[];C.info=_info();B.info('Port: {}'.format(C.info[L]));B.info('Board: {}'.format(C.info[U]));A.collect() - if D:C._fwid=D.lower() - elif C.info[S]==a:C._fwid='{family}-v{version}-{port}-{board}'.format(**C.info).rstrip(V) - else:C._fwid='{family}-v{version}-{port}'.format(**C.info) - C._start_free=A.mem_free() + B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[U]));F.collect() + if C:B._fwid=C.lower() + elif B.info[Q]==u:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(V) + else:B._fwid='{family}-v{version}-{port}'.format(**B.info) + B._start_free=F.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() - C.path='{}/stubs/{}'.format(path,C.flat_fwid).replace('//',G) - try:h(path+G) - except E:B.error('error creating stub folder {}'.format(path)) - C.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];C.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];C.modules=[] - def get_obj_attributes(M,item_instance): - H=item_instance;D=[];L=[] - for B in P(H): - if B.startswith(b)and not B in M.modules:continue + B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) + try:X(path+G) + except D:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[];B._json_name=E;B._json_first=H + def get_obj_attributes(L,item_instance): + H=item_instance;C=[];K=[] + for A in N(H): + if A.startswith('__')and not A in L.modules:continue try: - E=getattr(H,B) - try:F=Z(type(E)).split("'")[1] - except T:F=C - if F in{s,t,u,v,c,d,e}:G=1 - elif F in{w,x}:G=2 - elif F in'class':G=3 + D=getattr(H,A) + try:E=b(type(D)).split("'")[1] + except T:E=B + if E in{v,w,x,y,d,e,f}:G=1 + elif E in{z,A0}:G=2 + elif E in'class':G=3 else:G=4 - D.append((B,Z(E),Z(type(E)),E,G)) - except I as K:L.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(B,H,K)) - except n as K:J('MemoryError: {}'.format(K));sleep(1);reset() - D=o([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);A.collect();return D,L - def add_modules(A,modules):A.modules=o(set(A.modules)|set(modules)) - def create_all_stubs(C): - B.info('Start micropython-stubber v{} on {}'.format(__version__,C._fwid));A.collect() - for D in C.modules:C.create_one_stub(D) - B.info('Finally done') - def create_one_stub(D,module_name): - C=module_name - if C in D.problematic:B.warning('Skip module: {:<25} : Known problematic'.format(C));return H - if C in D.excluded:B.warning('Skip module: {:<25} : Excluded'.format(C));return H - I='{}/{}.py'.format(D.path,C.replace(K,G));A.collect();F=H - try:F=D.create_module_stub(C,I) - except E:return H - A.collect();return F - def create_module_stub(J,module_name,file_name=F): - I=file_name;D=module_name - if I is F:L=D.replace(K,b)+'.py';I=J.path+G+L + C.append((A,b(D),b(type(D)),D,G)) + except I as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,J)) + except o as J:S('MemoryError: {}'.format(J));sleep(1);reset() + C=p([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);F.collect();return C,K + def add_modules(A,modules):A.modules=p(set(A.modules)|set(modules)) + def create_all_stubs(B): + A.info('Start micropython-stubber {} on {}'.format(__version__,B._fwid));B.report_start();F.collect() + for C in B.modules:B.create_one_stub(C) + B.report_end();A.info('Finally done') + def create_one_stub(C,module_name): + B=module_name + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return H + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return H + I='{}/{}.pyi'.format(C.path,B.replace(J,G));F.collect();E=H + try:E=C.create_module_stub(B,I) + except D:return H + F.collect();return E + def create_module_stub(K,module_name,file_name=E): + I=file_name;C=module_name + if I is E:L=C.replace(J,'_')+'.pyi';I=K.path+G+L else:L=I.split(G)[-1] - if G in D:D=D.replace(G,K) - M=F - try:M=__import__(D,F,F,'*');Q=A.mem_free();B.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(D,L,Q)) - except R:return H - h(I) - with N(I,'w')as P:S=str(J.info).replace('OrderedDict(',C).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(D,J._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');J.write_object_stub(P,M,D,C) - J._report.append('{{"module": "{}", "file": "{}"}}'.format(D,I.replace('\\',G))) - if D not in{'os','sys','logging','gc'}: - try:del M - except(E,p):B.warning('could not del new_module') - A.collect();return O + if G in C:C=C.replace(G,J) + N=E + try:N=__import__(C,E,E,'*');Q=F.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,Q)) + except O:return H + X(I) + with M(I,g)as P:S=c(K.info).replace('OrderedDict(',B).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(P,N,C,B) + K.report_add(C,I) + if C not in{'os','sys','logging','gc'}: + try:del N + except(D,q):A.warning('could not del new_module') + F.collect();return R def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;E=indent;A.collect() - if L in K.problematic:B.warning('SKIPPING problematic module:{}'.format(L));return - X,O=K.get_obj_attributes(L) - if O:B.error(O) - for(F,J,G,Y,a)in X: - if F in['classmethod','staticmethod','BaseException',M]:continue - if F[0].isdigit():B.warning('NameError: invalid name {}'.format(F));continue - if G==""and Q(E)<=A0*4: - P=C;R=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] - if R:P=M - D='\n{}class {}({}):\n'.format(E,F,P) - if R:D+=E+' ...\n';I.write(D);continue - I.write(D);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',N+1);D=E+' def __init__(self, *argv, **kwargs) -> None:\n';D+=E+' ...\n\n';I.write(D) - elif any(A in G for A in[x,w,'closure']): - S=U;T=C + X='generator';W='{0}{1}: {3} = {2}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() + if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return + Y,O=K.get_obj_attributes(L) + if O:A.error(O) + for(E,J,H,Z,b)in Y: + if E in['classmethod','staticmethod','BaseException',M]:continue + if E[0].isdigit():A.warning('NameError: invalid name {}'.format(E));continue + if H==""and P(D)<=A4*4: + Q=B;R=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if R:Q=M + C='\n{}class {}({}):\n'.format(D,E,Q) + if R:C+=D+' ...\n';I.write(C);continue + I.write(C);K.write_object_stub(I,Z,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) + elif any(A in H for A in[A0,z,'closure']): + S=U;T=B if N>0:T='self, ' - if V in G or V in J:D='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) - else:D='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,T,S) - D+=E+' ...\n\n';I.write(D) - elif G=="":0 - elif G.startswith(" {}:\n'.format(D,E,S) + else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,T,S) + C+=D+' ...\n\n';I.write(C) + elif H=="":0 + elif H.startswith("='1.10.0'and A[D]<='1.19.9':A[D]=A[D][:-2] - if E in A and A[E]: - G=int(A[E]);J=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] - if J:A[N]=J - A[E]='v{}.{}'.format(G&255,G>>8&3) - if A[B]and not A[D].endswith(W):A[D]=A[D]+W - A[K]=f"{A[D]}-{A[B]}"if A[B]else f"{A[D]}";return A -def A2(version): - A=version;B=K.join([str(A)for A in A[:3]]) - if Q(A)>3 and A[3]:B+=V+A[3] + if'uname'in N(os): + A[D]=Y(os.uname()[3]) + if not A[D]:A[D]=Y(os.uname()[2]) + elif C in N(sys):A[D]=Y(sys.version) + except(I,T,s):pass + if A[C]==B and sys.platform not in(S,R): + try:a=os.uname();A[C]=a.release + except(T,I,s):pass + for(b,c,d)in[(V,V,'const'),(X,X,'FAT'),(Z,'pybricks.hubs','EV3Brick')]: + try:e=__import__(c,E,E,d);A[Q]=b;del e;break + except(O,q):pass + if A[Q]==Z:A['release']='2.0.0' + if A[Q]==u: + A[C] + if A[C]and A[C].endswith('.0')and A[C]>='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] + if F in A and A[F]: + G=int(A[F]);J=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[P]=J + A[F]='v{}.{}'.format(G&255,G>>8&3) + if A[D]and not A[C].endswith(W):A[C]=A[C]+W + A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A +def A6(version): + A=version;B=J.join([c(A)for A in A[:3]]) + if P(A)>3 and A[3]:B+=V+A[3] return B -def A3(): - try:from boardname import BOARDNAME as A;B.info('Found BOARDNAME: {}'.format(A)) - except R:B.warning('BOARDNAME not found');A=C - return A +def A7(): + try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) + except O:A.warning('BOARDNAME not found');C=B + return C def get_root(): try:A=os.getcwd() - except(E,I):A=K + except(D,I):A=J B=A - for B in[A,'/sd','/flash',G,K]: + for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break - except E:continue + except D:continue return B -def i(filename): +def Z(filename): try: - if os.stat(filename)[0]>>14:return O + if os.stat(filename)[0]>>14:return R return H - except E:return H -def j():J("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) + except D:return H +def l():S("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): - path=C - if Q(sys.argv)==3: + path=B + if P(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:j() - elif Q(sys.argv)==2:j() + else:l() + elif P(sys.argv)==2:l() return path -def k(): - try:A=bytes('abc',encoding='utf8');B=k.__module__;return H - except(m,I):return O -def main(): - I='failed';import machine as K - try:C=N(X,'r+b');D=O;J('Opened existing db') - except E:C=N(X,'w+b');J('created new db');D=H - stubber=Stubber(path=read_path()) - if not D:stubber.clean() - B=l();A4(stubber,B) - if not stubber.modules:J('All modules have been processed, exiting') - else: - del B;A.collect() - for F in stubber.modules: - G=H - try:G=stubber.create_one_stub(F) - except n:K.reset() - A.collect() - with N(X,'a')as C:C.write('{}={}\n'.format(F,'ok'if G else I)) - B=l() - if B: - stubber._report=[] - for(L,M)in B.items(): - if M!=I:stubber._report.append('{{"module": "{0}", "file": "{0}.py"}}'.format(L)) - stubber.report() -def l(): - C={} +def m(): + try:A=bytes('abc',encoding='utf8');B=m.__module__;return H + except(n,I):return R +a='modulelist.done' +def A8(skip=0): + for E in A5: + B=E+'/modulelist.txt' + if not Z(B):continue + try: + with M(B)as F: + C=0 + while R: + A=F.readline().strip() + if not A:break + if P(A)>0 and A[0]=='#':continue + C+=1 + if C0 and B[0]!='#':F,G=B.split('=',1);C[F]=G - except(E,SyntaxError):J('could not read modulelist.done') - finally:A.collect();return C -def A4(stubber,modules_done): - A.collect();stubber.modules=[] - for D in A1: - C=D+'/modulelist.txt' - if not i(C):continue - with N(C)as E: - while O: - B=E.readline().strip() - if not B:break - if B and B not in modules_done.keys():stubber.modules.append(B) - A.collect();J('BREAK');break - if not stubber.modules:stubber.modules=[a] - A.collect() -if __name__=='__main__'or k(): - if not i('no_auto_stubber.txt'): - try:A.threshold(4*1024);A.enable() + with M(a)as B:A=int(B.readline().strip()) + except D:pass + return A +def main(): + import machine as D;C=Z(a) + if C:A.info('Continue from last run') + else:A.info('Starting new run') + stubber=Stubber(path=read_path());B=0 + if not C:stubber.clean();stubber.report_start(i) + else:B=AA();stubber._json_name=h.format(stubber.path,i) + for E in A8(B): + try:stubber.create_one_stub(E) + except o:D.reset() + F.collect();B+=1;A9(B) + S('All modules have been processed, Finalizing report');stubber.report_end() +if __name__=='__main__'or m(): + if not Z('no_auto_stubber.txt'): + try:F.threshold(4*1024);F.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_db_mpy.mpy b/mip/v6/createstubs_db_mpy.mpy index 45221f43d3581e06e61248282d2cedde5f6c9e67..a1746dc5403c2a9e0ef70aaad692458a71b118c3 100644 GIT binary patch delta 5421 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 V%5dnw5EQEqCj2s5`~(_}|1YAV3SIyJ diff --git a/mip/v6/createstubs_mem.py b/mip/v6/createstubs_mem.py index 124421fd3..9a4349297 100644 --- a/mip/v6/createstubs_mem.py +++ b/mip/v6/createstubs_mem.py @@ -9,7 +9,7 @@ - cross compilation, using mpy-cross, to avoid the compilation step on the micropython device -This variant was generated from createstubs.py by micropython-stubber v1.16.3 +This variant was generated from createstubs.py by micropython-stubber v1.17.0 """ # Copyright (c) 2019-2023 Jos Verlinde @@ -33,7 +33,7 @@ except ImportError: from ucollections import OrderedDict # type: ignore -__version__ = "v1.16.3" +__version__ = "v1.17.0" ENOENT = 2 _MAX_CLASS_LEVEL = 2 # Max class nesting LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."] @@ -87,7 +87,6 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed") except AttributeError: pass - self._report = [] # type: list[str] self.info = _info() log.info("Port: {}".format(self.info["port"])) log.info("Board: {}".format(self.info["board"])) @@ -131,6 +130,8 @@ def __init__(self, path: str = None, firmware_id: str = None): # type: ignore ] # there is no option to discover modules from micropython, list is read from an external file. self.modules = [] # type: list[str] + self._json_name = None + self._json_first = False def get_obj_attributes(self, item_instance: object): "extract information of the objects members and attributes" @@ -139,7 +140,7 @@ def get_obj_attributes(self, item_instance: object): _errors = [] # log.debug("get attributes {} {}".format(repr(item_instance), item_instance)) for name in dir(item_instance): - if name.startswith("_") and not name in self.modules: + if name.startswith("__") and not name in self.modules: continue # log.debug("get attribute {}".format(name)) try: @@ -178,10 +179,12 @@ def add_modules(self, modules): def create_all_stubs(self): "Create stubs for all configured modules" - log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid)) + log.info("Start micropython-stubber {} on {}".format(__version__, self._fwid)) + self.report_start() gc.collect() for module_name in self.modules: self.create_one_stub(module_name) + self.report_end() log.info("Finally done") def create_one_stub(self, module_name: str): @@ -192,7 +195,7 @@ def create_one_stub(self, module_name: str): log.warning("Skip module: {:<25} : Excluded".format(module_name)) return False - file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/")) + file_name = "{}/{}.pyi".format(self.path, module_name.replace(".", "/")) gc.collect() result = False try: @@ -207,10 +210,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: Args: - module_name (str): name of the module to document. This module will be imported. - - file_name (Optional[str]): the 'path/filename.py' to write to. If omitted will be created based on the module name. + - file_name (Optional[str]): the 'path/filename.pyi' to write to. If omitted will be created based on the module name. """ if file_name is None: - fname = module_name.replace(".", "_") + ".py" + fname = module_name.replace(".", "_") + ".pyi" file_name = self.path + "/" + fname else: fname = file_name.split("/")[-1] @@ -237,10 +240,10 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}") s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__) fp.write(s) - fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n") + fp.write("from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n") self.write_object_stub(fp, new_module, module_name, "") - self._report.append('{{"module": "{}", "file": "{}"}}'.format(module_name, file_name.replace("\\", "/"))) + self.report_add(module_name, file_name) if module_name not in {"os", "sys", "logging", "gc"}: # try to unload the module unless we use it @@ -248,11 +251,7 @@ def create_module_stub(self, module_name: str, file_name: str = None) -> bool: del new_module except (OSError, KeyError): # lgtm [py/unreachable-statement] log.warning("could not del new_module") - # lets not try - most times it does not work anyway - # try: - # del sys.modules[module_name] - # except KeyError: - # log.warning("could not del sys.modules[{}]".format(module_name)) + # do not try to delete from sys.modules - most times it does not work anyway gc.collect() return True @@ -347,23 +346,27 @@ def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, t = item_type_txt[8:-2] s = "" - if t in ["str", "int", "float", "bool", "bytearray", "bytes"]: + if t in ("str", "int", "float", "bool", "bytearray", "bytes"): # known type: use actual value - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) - elif t in ["dict", "list", "tuple"]: + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, item_repr, t) + elif t in ("dict", "list", "tuple"): # dict, list , tuple: use empty value ev = {"dict": "{}", "list": "[]", "tuple": "()"} - s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + # s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t) + s = "{0}{1}: {3} = {2}\n".format(indent, item_name, ev[t], t) else: # something else - if t in ["object", "set", "frozenset", "Pin", "FileIO"]: + if t in ("object", "set", "frozenset", "Pin", "generator"): # "FileIO" # https://docs.python.org/3/tutorial/classes.html#item_instance-objects - # use these types for the attribute - s = "{0}{1} : {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + # use these types for the attribute + if t == "generator": + t = "Generator" + s = "{0}{1}: {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) else: # Requires Python 3.6 syntax, which is OK for the stubs/pyi t = "Incomplete" - s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) + s = "{0}{1}: {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr) fp.write(s) # log.debug("\n" + s) else: @@ -412,41 +415,53 @@ def clean(self, path: str = None): # type: ignore except OSError: pass - def report(self, filename: str = "modules.json"): - "create json with list of exported modules" - log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)) - f_name = "{}/{}".format(self.path, filename) - log.info("Report file: {}".format(f_name)) + def report_start(self, filename: str = "modules.json"): + """Start a report of the modules that have been stubbed + "create json with list of exported modules""" + self._json_name = "{}/{}".format(self.path, filename) + self._json_first = True + ensure_folder(self._json_name) + log.info("Report file: {}".format(self._json_name)) gc.collect() try: # write json by node to reduce memory requirements - with open(f_name, "w") as f: - self.write_json_header(f) - first = True - for n in self._report: - self.write_json_node(f, n, first) - first = False - self.write_json_end(f) - used = self._start_free - gc.mem_free() # type: ignore - # log.debug("Memory used: {0} Kb".format(used // 1024)) - except OSError: + with open(self._json_name, "w") as f: + f.write("{") + f.write(dumps({"firmware": self.info})[1:-1]) + f.write(",\n") + f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) + f.write(",\n") + f.write('"modules" :[\n') + + except OSError as e: log.error("Failed to create the report.") + self._json_name = None + raise e + + def report_add(self, module_name: str, stub_file: str): + "Add a module to the report" + # write json by node to reduce memory requirements + if not self._json_name: + raise Exception("No report file") + try: + with open(self._json_name, "a") as f: + if not self._json_first: + f.write(",\n") + else: + self._json_first = False + line = '{{"module": "{}", "file": "{}"}}'.format(module_name, stub_file.replace("\\", "/")) + f.write(line) - def write_json_header(self, f): - f.write("{") - f.write(dumps({"firmware": self.info})[1:-1]) - f.write(",\n") - f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1]) - f.write(",\n") - f.write('"modules" :[\n') - - def write_json_node(self, f, n, first): - if not first: - f.write(",\n") - f.write(n) + except OSError: + log.error("Failed to create the report.") - def write_json_end(self, f): - f.write("\n]}") + def report_end(self): + if not self._json_name: + raise Exception("No report file") + with open(self._json_name, "a") as f: + f.write("\n]}") + # is used as sucess indicator + log.info("Path: {}".format(self.path)) def ensure_folder(path: str): @@ -492,7 +507,7 @@ def _build(s): def _info(): # type:() -> dict[str, str] info = OrderedDict( { - "family": sys.implementation.name, + "family": sys.implementation.name, # type: ignore "version": "", "build": "", "ver": "", @@ -520,9 +535,9 @@ def _info(): # type:() -> dict[str, str] info["board"] = _machine info["cpu"] = _machine.split("with")[-1].strip() info["mpy"] = ( - sys.implementation._mpy + sys.implementation._mpy # type: ignore if "_mpy" in dir(sys.implementation) - else sys.implementation.mpy + else sys.implementation.mpy # type: ignore if "mpy" in dir(sys.implementation) else "" ) @@ -678,10 +693,6 @@ def is_micropython() -> bool: # pylint: disable=unused-variable,eval-used try: # either test should fail on micropython - # a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces - # Micropython : SyntaxError - # a = eval("1and 0") # lgtm [py/unused-local-variable] - # Eval blocks some minification aspects # b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented # Micropython: NotImplementedError @@ -734,7 +745,6 @@ def get_modulelist(stubber): gc.collect() stubber.create_all_stubs() - stubber.report() if __name__ == "__main__" or is_micropython(): diff --git a/mip/v6/createstubs_mem_min.py b/mip/v6/createstubs_mem_min.py index 415b4e5bd..9c2cfd272 100644 --- a/mip/v6/createstubs_mem_min.py +++ b/mip/v6/createstubs_mem_min.py @@ -1,3 +1,5 @@ +x='No report file' +w='Failed to create the report.' v='{}/{}' u='method' t='function' @@ -7,34 +9,34 @@ p='int' o='stubber' n=TypeError -m=KeyError -l=sorted -k=NotImplementedError +m=Exception +l=KeyError +k=sorted +j=NotImplementedError e=',\n' d='dict' c='list' b='tuple' -a='_' -Z='micropython' -Y=open -X=repr -V='-preview' -U='-' -T='board' -S=IndexError -R=print -Q=True -P='family' -O=ImportError -N=len +a='micropython' +Z=repr +W='-preview' +V='-' +U='board' +T=IndexError +S=print +R=True +Q='family' +P=len +O=open +N=ImportError M=dir K='port' J='.' -I=False -H=AttributeError +I=AttributeError +H=False G='/' -F=None -E=OSError +F=OSError +E=None C='version' B='' import gc as D,os,sys @@ -42,15 +44,15 @@ try:from ujson import dumps except:from json import dumps try:from machine import reset -except O:pass +except N:pass try:from collections import OrderedDict as f -except O:from ucollections import OrderedDict as f -__version__='v1.16.3' -w=2 -x=2 -y=['lib','/lib','/sd/lib','/flash/lib',J] +except N:from ucollections import OrderedDict as f +__version__='v1.17.0' +y=2 +z=2 +A0=['lib','/lib','/sd/lib','/flash/lib',J] class L: - INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=R + INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=S @staticmethod def getLogger(name):return L() @classmethod @@ -64,230 +66,235 @@ def error(A,msg): A=L.getLogger(o) L.basicConfig(level=L.INFO) class Stubber: - def __init__(B,path=F,firmware_id=F): + def __init__(B,path=E,firmware_id=E): C=firmware_id try: - if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed') - except H:pass - B._report=[];B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[T]));D.collect() + if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise j('MicroPython 1.13.0 cannot be stubbed') + except I:pass + B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[U]));D.collect() if C:B._fwid=C.lower() - elif B.info[P]==Z:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(U) + elif B.info[Q]==a:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(V) else:B._fwid='{family}-v{version}-{port}'.format(**B.info) B._start_free=D.mem_free() if path: if path.endswith(G):path=path[:-1] else:path=get_root() B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G) - try:g(path+G) - except E:A.error('error creating stub folder {}'.format(path)) - B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[] + try:X(path+G) + except F:A.error('error creating stub folder {}'.format(path)) + B.problematic=['upip','upysh','webrepl_setup','http_client','http_client_ssl','http_server','http_server_ssl'];B.excluded=['webrepl','_webrepl','port_diag','example_sub_led.py','example_pub_button.py'];B.modules=[];B._json_name=E;B._json_first=H def get_obj_attributes(L,item_instance): - I=item_instance;C=[];K=[] - for A in M(I): - if A.startswith(a)and not A in L.modules:continue + H=item_instance;C=[];K=[] + for A in M(H): + if A.startswith('__')and not A in L.modules:continue try: - E=getattr(I,A) - try:F=X(type(E)).split("'")[1] - except S:F=B + E=getattr(H,A) + try:F=Z(type(E)).split("'")[1] + except T:F=B if F in{p,q,r,s,b,c,d}:G=1 elif F in{t,u}:G=2 elif F in'class':G=3 else:G=4 - C.append((A,X(E),X(type(E)),E,G)) - except H as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,J)) - except MemoryError as J:R('MemoryError: {}'.format(J));sleep(1);reset() - C=l([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,K - def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules)) + C.append((A,Z(E),Z(type(E)),E,G)) + except I as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,J)) + except MemoryError as J:S('MemoryError: {}'.format(J));sleep(1);reset() + C=k([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,K + def add_modules(A,modules):A.modules=k(set(A.modules)|set(modules)) def create_all_stubs(B): - A.info('Start micropython-stubber v{} on {}'.format(__version__,B._fwid));D.collect() + A.info('Start micropython-stubber {} on {}'.format(__version__,B._fwid));B.report_start();D.collect() for C in B.modules:B.create_one_stub(C) - A.info('Finally done') + B.report_end();A.info('Finally done') def create_one_stub(C,module_name): B=module_name - if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return I - if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return I - H='{}/{}.py'.format(C.path,B.replace(J,G));D.collect();F=I - try:F=C.create_module_stub(B,H) - except E:return I - D.collect();return F - def create_module_stub(K,module_name,file_name=F): - H=file_name;C=module_name - if H is F:L=C.replace(J,a)+'.py';H=K.path+G+L - else:L=H.split(G)[-1] + if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return H + if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return H + I='{}/{}.pyi'.format(C.path,B.replace(J,G));D.collect();E=H + try:E=C.create_module_stub(B,I) + except F:return H + D.collect();return E + def create_module_stub(K,module_name,file_name=E): + I=file_name;C=module_name + if I is E:L=C.replace(J,'_')+'.pyi';I=K.path+G+L + else:L=I.split(G)[-1] if G in C:C=C.replace(G,J) - M=F - try:M=__import__(C,F,F,'*');P=D.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) - except O:return I - g(H) - with Y(H,'w')as N:R=str(K.info).replace('OrderedDict(',B).replace('})','}');S='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,R,__version__);N.write(S);N.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(N,M,C,B) - K._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) + M=E + try:M=__import__(C,E,E,'*');Q=D.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,Q)) + except N:return H + X(I) + with O(I,'w')as P:S=str(K.info).replace('OrderedDict(',B).replace('})','}');T='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,S,__version__);P.write(T);P.write('from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(P,M,C,B) + K.report_add(C,I) if C not in{'os','sys','logging','gc'}: try:del M - except(E,m):A.warning('could not del new_module') - D.collect();return Q + except(F,l):A.warning('could not del new_module') + D.collect();return R def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';O=in_class;M='Exception';L=object_expr;I=fp;E=indent;D.collect() + X='generator';W='{0}{1}: {3} = {2}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;E=indent;D.collect() if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return - X,P=K.get_obj_attributes(L) - if P:A.error(P) - for(F,J,G,Y,a)in X: + Y,O=K.get_obj_attributes(L) + if O:A.error(O) + for(F,J,H,Z,e)in Y: if F in['classmethod','staticmethod','BaseException',M]:continue if F[0].isdigit():A.warning('NameError: invalid name {}'.format(F));continue - if G==""and N(E)<=x*4: + if H==""and P(E)<=z*4: Q=B;R=F.endswith(M)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit'] if R:Q=M C='\n{}class {}({}):\n'.format(E,F,Q) if R:C+=E+' ...\n';I.write(C);continue - I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,F),E+' ',O+1);C=E+' def __init__(self, *argv, **kwargs) -> None:\n';C+=E+' ...\n\n';I.write(C) - elif any(A in G for A in[u,t,'closure']): + I.write(C);K.write_object_stub(I,Z,'{0}.{1}'.format(obj_name,F),E+' ',N+1);C=E+' def __init__(self, *argv, **kwargs) -> None:\n';C+=E+' ...\n\n';I.write(C) + elif any(A in H for A in[u,t,'closure']): S=U;T=B - if O>0:T='self, ' - if V in G or V in J:C='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) + if N>0:T='self, ' + if V in H or V in J:C='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,S) else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,T,S) C+=E+' ...\n\n';I.write(C) - elif G=="":0 - elif G.startswith("":0 + elif H.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] - if E in A and A[E]: - G=int(A[E]);J=[F,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] - if J:A[Q]=J - A[E]='v{}.{}'.format(G&255,G>>8&3) - if A[D]and not A[C].endswith(V):A[C]=A[C]+V + if F in A and A[F]: + G=int(A[F]);J=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[P]=J + A[F]='v{}.{}'.format(G&255,G>>8&3) + if A[D]and not A[C].endswith(W):A[C]=A[C]+W A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A -def z(version): +def A1(version): A=version;B=J.join([str(A)for A in A[:3]]) - if N(A)>3 and A[3]:B+=U+A[3] + if P(A)>3 and A[3]:B+=V+A[3] return B -def A0(): +def A2(): try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) - except O:A.warning('BOARDNAME not found');C=B + except N:A.warning('BOARDNAME not found');C=B return C def get_root(): try:A=os.getcwd() - except(E,H):A=J + except(F,I):A=J B=A for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break - except E:continue + except F:continue return B -def h(filename): +def g(filename): try: - if os.stat(filename)[0]>>14:return Q - return I - except E:return I -def i():R("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) + if os.stat(filename)[0]>>14:return R + return H + except F:return H +def h():S("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): path=B - if N(sys.argv)==3: + if P(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] - else:i() - elif N(sys.argv)==2:i() + else:h() + elif P(sys.argv)==2:h() return path -def j(): - try:A=bytes('abc',encoding='utf8');B=j.__module__;return I - except(k,H):return Q +def i(): + try:A=bytes('abc',encoding='utf8');B=i.__module__;return H + except(j,I):return R def main(): stubber=Stubber(path=read_path());stubber.clean() def A(stubber): D.collect();stubber.modules=[] - for C in y: + for C in A0: B=C+'/modulelist.txt' - if not h(B):continue - with Y(B)as E: - while Q: + if not g(B):continue + with O(B)as E: + while R: A=E.readline().strip() if not A:break - if N(A)>0 and A[0]!='#':stubber.modules.append(A) - D.collect();R('BREAK');break - if not stubber.modules:stubber.modules=[Z] + if P(A)>0 and A[0]!='#':stubber.modules.append(A) + D.collect();S('BREAK');break + if not stubber.modules:stubber.modules=[a] D.collect() - stubber.modules=[];A(stubber);D.collect();stubber.create_all_stubs();stubber.report() -if __name__=='__main__'or j(): - if not h('no_auto_stubber.txt'): + stubber.modules=[];A(stubber);D.collect();stubber.create_all_stubs() +if __name__=='__main__'or i(): + if not g('no_auto_stubber.txt'): try:D.threshold(4*1024);D.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_mem_mpy.mpy b/mip/v6/createstubs_mem_mpy.mpy index 430edcd3681b41267ac4389a2508d35b6a3adf57..9584595431b93546b38cd9515e5ae1b34a6bf422 100644 GIT binary patch literal 9032 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 literal 8928 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'.format(C,L,P)) - except N:return I - g(H) - with open(H,'w')as O:Q=str(K.info).replace('OrderedDict(',B).replace('})','}');R='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,Q,__version__);O.write(R);O.write('from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(O,M,C,B) - K._report.append('{{"module": "{}", "file": "{}"}}'.format(C,H.replace('\\',G))) - if C not in{'os',u,v,'gc'}: + M=D + try:M=__import__(C,D,D,'*');P=F.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,P)) + except N:return H + W(I) + with Q(I,'w')as O:R=str(K.info).replace('OrderedDict(',B).replace('})','}');S='"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(C,K._fwid,R,__version__);O.write(S);O.write('from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n');K.write_object_stub(O,M,C,B) + K.report_add(C,I) + if C not in{'os',v,w,'gc'}: try:del M - except(D,l):A.warning('could not del new_module') - F.collect();return T + except(E,l):A.warning('could not del new_module') + F.collect();return U def write_object_stub(K,fp,object_expr,obj_name,indent,in_class=0): - W='{0}{1} = {2} # type: {3}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() + X='generator';W='{0}{1}: {3} = {2}\n';V='bound_method';U='Incomplete';N=in_class;M='Exception';L=object_expr;I=fp;D=indent;F.collect() if L in K.problematic:A.warning('SKIPPING problematic module:{}'.format(L));return - X,P=K.get_obj_attributes(L) - if P:A.error(P) - for(E,J,G,Y,d)in X: + Y,O=K.get_obj_attributes(L) + if O:A.error(O) + for(E,J,H,Z,e)in Y: if E in['classmethod','staticmethod','BaseException',M]:continue if E[0].isdigit():A.warning('NameError: invalid name {}'.format(E));continue - if G==""and O(D)<=z*4: - Q=B;R=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] - if R:Q=M - C='\n{}class {}({}):\n'.format(D,E,Q) - if R:C+=D+' ...\n';I.write(C);continue - I.write(C);K.write_object_stub(I,Y,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) - elif any(A in G for A in[t,s,'closure']): + if H==""and R(D)<=A1*4: + P=B;Q=E.endswith(M)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit'] + if Q:P=M + C='\n{}class {}({}):\n'.format(D,E,P) + if Q:C+=D+' ...\n';I.write(C);continue + I.write(C);K.write_object_stub(I,Z,'{0}.{1}'.format(obj_name,E),D+' ',N+1);C=D+' def __init__(self, *argv, **kwargs) -> None:\n';C+=D+' ...\n\n';I.write(C) + elif any(A in H for A in[u,t,'closure']): S=U;T=B if N>0:T='self, ' - if V in G or V in J:C='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,S) + if V in H or V in J:C='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,S) else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,T,S) C+=D+' ...\n\n';I.write(C) - elif G=="":0 - elif G.startswith("":0 + elif H.startswith("='1.10.0'and A[C]<='1.19.9':A[C]=A[C][:-2] if F in A and A[F]: - G=int(A[F]);J=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] - if J:A[S]=J + G=int(A[F]);J=[D,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10] + if J:A[R]=J A[F]='v{}.{}'.format(G&255,G>>8&3) - if A[D]and not A[C].endswith(U):A[C]=A[C]+U - A[L]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A -def A0(version): + if A[E]and not A[C].endswith(V):A[C]=A[C]+V + A[L]=f"{A[C]}-{A[E]}"if A[E]else f"{A[C]}";return A +def A2(version): A=version;B=J.join([str(A)for A in A[:3]]) - if O(A)>3 and A[3]:B+=S+A[3] + if R(A)>3 and A[3]:B+=T+A[3] return B -def A1(): +def A3(): try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C)) except N:A.warning('BOARDNAME not found');C=B return C def get_root(): try:A=os.getcwd() - except(D,H):A=J + except(E,I):A=J B=A for B in[A,'/sd','/flash',G,J]: try:C=os.stat(B);break - except D:continue + except E:continue return B -def A2(filename): +def A4(filename): try: - if os.stat(filename)[0]>>14:return T - return I - except D:return I -def h():W("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) + if os.stat(filename)[0]>>14:return U + return H + except E:return H +def h():Y("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1) def read_path(): path=B - if O(sys.argv)==3: + if R(sys.argv)==3: A=sys.argv[1].lower() if A in('--path','-p'):path=sys.argv[2] else:h() - elif O(sys.argv)==2:h() + elif R(sys.argv)==2:h() return path def i(): - try:A=bytes('abc',encoding='utf8');B=i.__module__;return I - except(j,H):return T -def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',Y,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform',x,e,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];F.collect();stubber.create_all_stubs();stubber.report() + try:A=bytes('abc',encoding='utf8');B=i.__module__;return H + except(j,I):return U +def main():stubber=Stubber(path=read_path());stubber.clean();stubber.modules=['WM8960','_OTA','_asyncio','_boot_fat','_coap','_espnow','_flash_control_OTA','_main_pybytes','_mqtt','_mqtt_core','_msg_handl','_onewire','_periodical_pin','_pybytes','_pybytes_ca','_pybytes_config','_pybytes_config_reader','_pybytes_connection','_pybytes_constants','_pybytes_debug','_pybytes_library','_pybytes_machine_learning','_pybytes_main','_pybytes_protocol','_pybytes_pyconfig','_pybytes_pymesh_config','_rp2','_terminal','_thread','_uasyncio','_urequest','adcfft','aioble/__init__','aioble/central','aioble/client','aioble/core','aioble/device','aioble/l2cap','aioble/peripheral','aioble/security','aioble/server','aioespnow','ak8963','apa102','apa106','argparse','array','asyncio/__init__','asyncio/core','asyncio/event','asyncio/funcs','asyncio/lock','asyncio/stream','binascii','bluetooth','breakout_as7262','breakout_bh1745','breakout_bme280','breakout_bme68x','breakout_bmp280','breakout_dotmatrix','breakout_encoder','breakout_icp10125','breakout_ioexpander','breakout_ltr559','breakout_matrix11x7','breakout_mics6814','breakout_msa301','breakout_paa5100','breakout_pmw3901','breakout_potentiometer','breakout_rgbmatrix5x5','breakout_rtc','breakout_scd41','breakout_sgp30','breakout_trackball','breakout_vl53l5cx','btree','cmath','collections','crypto','cryptolib','curl','deflate','dht','display','display_driver_utils','ds18x20','encoder','errno','esp','esp32','espidf','espnow','ffi','flashbdev','framebuf','freesans20','fs_driver','functools','galactic','gc','gfx_pack','gsm','hashlib','heapq','hub75','ili9341','ili9XXX','imagetools','inisetup','interstate75','io','jpegdec','json','lcd160cr','lodepng',w,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',a,'mip','mip/__init__','mip/__main__','motor','mpu6500','mpu9250','neopixel','network','ntptime','onewire','os','pcf85063a','picoexplorer','picographics','picokeypad','picoscroll','picounicorn','picowireless','pimoroni','pimoroni_bus','pimoroni_i2c','plasma','platform','pyb',f,'pye','qrcode','queue','random','requests','requests/__init__','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',v,'termios','time','tpcalib','uarray','uasyncio/__init__','uasyncio/core','uasyncio/event','uasyncio/funcs','uasyncio/lock','uasyncio/stream','uasyncio/tasks','ubinascii','ubluetooth','ucollections','ucrypto','ucryptolib','uctypes','uerrno','uftpd','uhashlib','uheapq','uio','ujson','ulab','ulab/approx','ulab/compare','ulab/fft','ulab/filter','ulab/linalg','ulab/numerical','ulab/poly','ulab/user','ulab/vector','umachine','umqtt/__init__','umqtt/robust','umqtt/simple','uos','uplatform','uqueue','urandom','ure','urequests','urllib/urequest','uselect','usocket','ussl','ustruct','usys','utelnetserver','utime','utimeq','uwebsocket','uzlib',C,'websocket','websocket_helper','wipy','writer','xpt2046','ymodem','zephyr','zlib'];F.collect();stubber.create_all_stubs() if __name__=='__main__'or i(): - if not A2('no_auto_stubber.txt'): + if not A4('no_auto_stubber.txt'): try:F.threshold(4*1024);F.enable() except BaseException:pass main() \ No newline at end of file diff --git a/mip/v6/createstubs_mpy.mpy b/mip/v6/createstubs_mpy.mpy index 268efa46913e0933112083cfc1f65512085abb7a..79c022b32a5f91d1704c715c1adde1a16d021df6 100644 GIT binary patch delta 6594 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 BF)RQ8 delta 6500 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