micropython-stubber 1.20.5__py3-none-any.whl → 1.20.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {micropython_stubber-1.20.5.dist-info → micropython_stubber-1.20.6.dist-info}/LICENSE +30 -30
- {micropython_stubber-1.20.5.dist-info → micropython_stubber-1.20.6.dist-info}/METADATA +1 -1
- micropython_stubber-1.20.6.dist-info/RECORD +159 -0
- mpflash/README.md +184 -184
- mpflash/libusb_flash.ipynb +203 -203
- mpflash/mpflash/add_firmware.py +98 -98
- mpflash/mpflash/ask_input.py +236 -236
- mpflash/mpflash/bootloader/__init__.py +37 -36
- mpflash/mpflash/bootloader/manual.py +102 -102
- mpflash/mpflash/bootloader/micropython.py +10 -10
- mpflash/mpflash/bootloader/touch1200.py +45 -45
- mpflash/mpflash/cli_download.py +129 -129
- mpflash/mpflash/cli_flash.py +219 -219
- mpflash/mpflash/cli_group.py +98 -98
- mpflash/mpflash/cli_list.py +81 -81
- mpflash/mpflash/cli_main.py +41 -41
- mpflash/mpflash/common.py +164 -164
- mpflash/mpflash/config.py +47 -47
- mpflash/mpflash/connected.py +74 -74
- mpflash/mpflash/download.py +360 -360
- mpflash/mpflash/downloaded.py +129 -129
- mpflash/mpflash/errors.py +9 -9
- mpflash/mpflash/flash.py +52 -52
- mpflash/mpflash/flash_esp.py +59 -59
- mpflash/mpflash/flash_stm32.py +24 -24
- mpflash/mpflash/flash_stm32_cube.py +111 -111
- mpflash/mpflash/flash_stm32_dfu.py +101 -101
- mpflash/mpflash/flash_uf2.py +67 -67
- mpflash/mpflash/flash_uf2_boardid.py +15 -15
- mpflash/mpflash/flash_uf2_linux.py +123 -123
- mpflash/mpflash/flash_uf2_macos.py +34 -34
- mpflash/mpflash/flash_uf2_windows.py +34 -34
- mpflash/mpflash/list.py +89 -89
- mpflash/mpflash/logger.py +41 -41
- mpflash/mpflash/mpboard_id/__init__.py +93 -93
- mpflash/mpflash/mpboard_id/add_boards.py +255 -255
- mpflash/mpflash/mpboard_id/board.py +37 -37
- mpflash/mpflash/mpboard_id/board_id.py +86 -86
- mpflash/mpflash/mpboard_id/store.py +43 -43
- mpflash/mpflash/mpremoteboard/__init__.py +221 -221
- mpflash/mpflash/mpremoteboard/mpy_fw_info.py +141 -141
- mpflash/mpflash/mpremoteboard/runner.py +140 -140
- mpflash/mpflash/uf2disk.py +12 -12
- mpflash/mpflash/vendor/basicgit.py +288 -288
- mpflash/mpflash/vendor/click_aliases.py +91 -91
- mpflash/mpflash/vendor/dfu.py +165 -165
- mpflash/mpflash/vendor/pydfu.py +605 -605
- mpflash/mpflash/vendor/readme.md +2 -2
- mpflash/mpflash/vendor/versions.py +119 -117
- mpflash/mpflash/worklist.py +170 -170
- mpflash/poetry.lock +1588 -1588
- mpflash/pyproject.toml +60 -60
- mpflash/stm32_udev_rules.md +62 -62
- stubber/__init__.py +3 -3
- stubber/basicgit.py +294 -288
- stubber/board/board_info.csv +193 -193
- stubber/board/boot.py +34 -34
- stubber/board/createstubs.py +986 -986
- stubber/board/createstubs_db.py +825 -825
- stubber/board/createstubs_db_min.py +331 -331
- stubber/board/createstubs_db_mpy.mpy +0 -0
- stubber/board/createstubs_lvgl.py +741 -741
- stubber/board/createstubs_lvgl_min.py +741 -741
- stubber/board/createstubs_mem.py +766 -766
- stubber/board/createstubs_mem_min.py +306 -306
- stubber/board/createstubs_mem_mpy.mpy +0 -0
- stubber/board/createstubs_min.py +294 -294
- stubber/board/createstubs_mpy.mpy +0 -0
- stubber/board/fw_info.py +141 -141
- stubber/board/info.py +183 -183
- stubber/board/main.py +19 -19
- stubber/board/modulelist.txt +247 -247
- stubber/board/pyrightconfig.json +34 -34
- stubber/bulk/mcu_stubber.py +454 -454
- stubber/codemod/_partials/__init__.py +48 -48
- stubber/codemod/_partials/db_main.py +147 -147
- stubber/codemod/_partials/lvgl_main.py +77 -77
- stubber/codemod/_partials/modules_reader.py +80 -80
- stubber/codemod/add_comment.py +53 -53
- stubber/codemod/add_method.py +65 -65
- stubber/codemod/board.py +317 -317
- stubber/codemod/enrich.py +145 -145
- stubber/codemod/merge_docstub.py +284 -284
- stubber/codemod/modify_list.py +54 -54
- stubber/codemod/utils.py +57 -57
- stubber/commands/build_cmd.py +94 -94
- stubber/commands/cli.py +51 -51
- stubber/commands/clone_cmd.py +66 -66
- stubber/commands/config_cmd.py +29 -29
- stubber/commands/enrich_folder_cmd.py +70 -70
- stubber/commands/get_core_cmd.py +69 -69
- stubber/commands/get_docstubs_cmd.py +87 -87
- stubber/commands/get_frozen_cmd.py +112 -112
- stubber/commands/get_mcu_cmd.py +56 -56
- stubber/commands/merge_cmd.py +66 -66
- stubber/commands/publish_cmd.py +119 -119
- stubber/commands/stub_cmd.py +30 -30
- stubber/commands/switch_cmd.py +54 -54
- stubber/commands/variants_cmd.py +48 -48
- stubber/cst_transformer.py +178 -178
- stubber/data/board_info.csv +193 -193
- stubber/data/board_info.json +1729 -1729
- stubber/data/micropython_tags.csv +15 -15
- stubber/data/requirements-core-micropython.txt +38 -38
- stubber/data/requirements-core-pycopy.txt +39 -39
- stubber/downloader.py +36 -36
- stubber/freeze/common.py +68 -68
- stubber/freeze/freeze_folder.py +69 -69
- stubber/freeze/freeze_manifest_2.py +113 -113
- stubber/freeze/get_frozen.py +127 -127
- stubber/get_cpython.py +101 -101
- stubber/get_lobo.py +59 -59
- stubber/minify.py +418 -418
- stubber/publish/bump.py +86 -86
- stubber/publish/candidates.py +262 -262
- stubber/publish/database.py +18 -18
- stubber/publish/defaults.py +45 -45
- stubber/publish/enums.py +24 -24
- stubber/publish/helpers.py +29 -29
- stubber/publish/merge_docstubs.py +130 -130
- stubber/publish/missing_class_methods.py +49 -49
- stubber/publish/package.py +146 -146
- stubber/publish/pathnames.py +51 -51
- stubber/publish/publish.py +120 -120
- stubber/publish/pypi.py +38 -38
- stubber/publish/stubpackage.py +1029 -1029
- stubber/rst/__init__.py +9 -9
- stubber/rst/classsort.py +77 -77
- stubber/rst/lookup.py +530 -530
- stubber/rst/output_dict.py +401 -401
- stubber/rst/reader.py +822 -822
- stubber/rst/report_return.py +69 -69
- stubber/rst/rst_utils.py +540 -540
- stubber/stubber.py +38 -38
- stubber/stubs_from_docs.py +90 -90
- stubber/tools/manifestfile.py +610 -610
- stubber/tools/readme.md +5 -5
- stubber/update_fallback.py +117 -117
- stubber/update_module_list.py +123 -123
- stubber/utils/__init__.py +5 -5
- stubber/utils/config.py +127 -127
- stubber/utils/makeversionhdr.py +54 -54
- stubber/utils/manifest.py +92 -92
- stubber/utils/post.py +79 -79
- stubber/utils/repos.py +157 -154
- stubber/utils/stubmaker.py +139 -139
- stubber/utils/typed_config_toml.py +77 -77
- stubber/utils/versions.py +128 -120
- stubber/variants.py +106 -106
- micropython_stubber-1.20.5.dist-info/RECORD +0 -159
- {micropython_stubber-1.20.5.dist-info → micropython_stubber-1.20.6.dist-info}/WHEEL +0 -0
- {micropython_stubber-1.20.5.dist-info → micropython_stubber-1.20.6.dist-info}/entry_points.txt +0 -0
@@ -1,307 +1,307 @@
|
|
1
|
-
x='No report file'
|
2
|
-
w='Failed to create the report.'
|
3
|
-
v='{}/{}'
|
4
|
-
u='method'
|
5
|
-
t='function'
|
6
|
-
s='bool'
|
7
|
-
r='str'
|
8
|
-
q='float'
|
9
|
-
p='int'
|
10
|
-
o='stubber'
|
11
|
-
n=Exception
|
12
|
-
m=KeyError
|
13
|
-
l=sorted
|
14
|
-
k=NotImplementedError
|
15
|
-
f=',\n'
|
16
|
-
e='dict'
|
17
|
-
d='list'
|
18
|
-
c='tuple'
|
19
|
-
b='micropython'
|
20
|
-
a=TypeError
|
21
|
-
Z=repr
|
22
|
-
W='-preview'
|
23
|
-
V='-'
|
24
|
-
U='board'
|
25
|
-
T=IndexError
|
26
|
-
S=print
|
27
|
-
R=True
|
28
|
-
Q='family'
|
29
|
-
P=len
|
30
|
-
O=open
|
31
|
-
N=ImportError
|
32
|
-
M=dir
|
33
|
-
K='port'
|
34
|
-
J='.'
|
35
|
-
I=AttributeError
|
36
|
-
H=False
|
37
|
-
G='/'
|
38
|
-
F=OSError
|
39
|
-
E=None
|
40
|
-
C='version'
|
41
|
-
B=''
|
42
|
-
import gc as D,os,sys
|
43
|
-
from time import sleep
|
44
|
-
try:from ujson import dumps
|
45
|
-
except:from json import dumps
|
46
|
-
try:from machine import reset
|
47
|
-
except N:pass
|
48
|
-
try:from collections import OrderedDict as g
|
49
|
-
except N:from ucollections import OrderedDict as g
|
50
|
-
__version__='v1.20.
|
51
|
-
y=2
|
52
|
-
z=2
|
53
|
-
A0=['lib','/lib','/sd/lib','/flash/lib',J]
|
54
|
-
class L:
|
55
|
-
INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=S
|
56
|
-
@staticmethod
|
57
|
-
def getLogger(name):return L()
|
58
|
-
@classmethod
|
59
|
-
def basicConfig(A,level):A.level=level
|
60
|
-
def info(A,msg):
|
61
|
-
if A.level<=L.INFO:A.prnt('INFO :',msg)
|
62
|
-
def warning(A,msg):
|
63
|
-
if A.level<=L.WARNING:A.prnt('WARN :',msg)
|
64
|
-
def error(A,msg):
|
65
|
-
if A.level<=L.ERROR:A.prnt('ERROR :',msg)
|
66
|
-
A=L.getLogger(o)
|
67
|
-
L.basicConfig(level=L.INFO)
|
68
|
-
class Stubber:
|
69
|
-
def __init__(B,path=E,firmware_id=E):
|
70
|
-
C=firmware_id
|
71
|
-
try:
|
72
|
-
if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed')
|
73
|
-
except I:pass
|
74
|
-
B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[U]));D.collect()
|
75
|
-
if C:B._fwid=C.lower()
|
76
|
-
elif B.info[Q]==b:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(V)
|
77
|
-
else:B._fwid='{family}-v{version}-{port}'.format(**B.info)
|
78
|
-
B._start_free=D.mem_free()
|
79
|
-
if path:
|
80
|
-
if path.endswith(G):path=path[:-1]
|
81
|
-
else:path=get_root()
|
82
|
-
B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G)
|
83
|
-
try:X(path+G)
|
84
|
-
except F:A.error('error creating stub folder {}'.format(path))
|
85
|
-
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
|
86
|
-
def get_obj_attributes(L,item_instance):
|
87
|
-
H=item_instance;C=[];K=[]
|
88
|
-
for A in M(H):
|
89
|
-
if A.startswith('__')and not A in L.modules:continue
|
90
|
-
try:
|
91
|
-
E=getattr(H,A)
|
92
|
-
try:F=Z(type(E)).split("'")[1]
|
93
|
-
except T:F=B
|
94
|
-
if F in{p,q,r,s,c,d,e}:G=1
|
95
|
-
elif F in{t,u}:G=2
|
96
|
-
elif F in'class':G=3
|
97
|
-
else:G=4
|
98
|
-
C.append((A,Z(E),Z(type(E)),E,G))
|
99
|
-
except I as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,J))
|
100
|
-
except MemoryError as J:S('MemoryError: {}'.format(J));sleep(1);reset()
|
101
|
-
C=l([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,K
|
102
|
-
def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules))
|
103
|
-
def create_all_stubs(B):
|
104
|
-
A.info('Start micropython-stubber {} on {}'.format(__version__,B._fwid));B.report_start();D.collect()
|
105
|
-
for C in B.modules:B.create_one_stub(C)
|
106
|
-
B.report_end();A.info('Finally done')
|
107
|
-
def create_one_stub(C,module_name):
|
108
|
-
B=module_name
|
109
|
-
if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return H
|
110
|
-
if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return H
|
111
|
-
I='{}/{}.pyi'.format(C.path,B.replace(J,G));D.collect();E=H
|
112
|
-
try:E=C.create_module_stub(B,I)
|
113
|
-
except F:return H
|
114
|
-
D.collect();return E
|
115
|
-
def create_module_stub(K,module_name,file_name=E):
|
116
|
-
I=file_name;C=module_name
|
117
|
-
if I is E:L=C.replace(J,'_')+'.pyi';I=K.path+G+L
|
118
|
-
else:L=I.split(G)[-1]
|
119
|
-
if G in C:C=C.replace(G,J)
|
120
|
-
M=E
|
121
|
-
try:M=__import__(C,E,E,'*');Q=D.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,Q))
|
122
|
-
except N:return H
|
123
|
-
X(I)
|
124
|
-
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)
|
125
|
-
K.report_add(C,I)
|
126
|
-
if C not in{'os','sys','logging','gc'}:
|
127
|
-
try:del M
|
128
|
-
except(F,m):A.warning('could not del new_module')
|
129
|
-
D.collect();return R
|
130
|
-
def write_object_stub(L,fp,object_expr,obj_name,indent,in_class=0):
|
131
|
-
Z=' at ...>';Y='generator';X='{0}{1}: {3} = {2}\n';W='bound_method';V='Incomplete';O=in_class;N='Exception';M=object_expr;K=' at ';J=fp;E=indent;D.collect()
|
132
|
-
if M in L.problematic:A.warning('SKIPPING problematic module:{}'.format(M));return
|
133
|
-
a,Q=L.get_obj_attributes(M)
|
134
|
-
if Q:A.error(Q)
|
135
|
-
for(F,H,I,b,g)in a:
|
136
|
-
if F in['classmethod','staticmethod','BaseException',N]:continue
|
137
|
-
if F[0].isdigit():A.warning('NameError: invalid name {}'.format(F));continue
|
138
|
-
if I=="<class 'type'>"and P(E)<=z*4:
|
139
|
-
R=B;S=F.endswith(N)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit']
|
140
|
-
if S:R=N
|
141
|
-
C='\n{}class {}({}):\n'.format(E,F,R)
|
142
|
-
if S:C+=E+' ...\n';J.write(C);continue
|
143
|
-
J.write(C);L.write_object_stub(J,b,'{0}.{1}'.format(obj_name,F),E+' ',O+1);C=E+' def __init__(self, *argv, **kwargs) -> None:\n';C+=E+' ...\n\n';J.write(C)
|
144
|
-
elif any(A in I for A in[u,t,'closure']):
|
145
|
-
T=V;U=B
|
146
|
-
if O>0:U='self, '
|
147
|
-
if W in I or W in H:C='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,T)
|
148
|
-
else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,U,T)
|
149
|
-
C+=E+' ...\n\n';J.write(C)
|
150
|
-
elif I=="<class 'module'>":0
|
151
|
-
elif I.startswith("<class '"):
|
152
|
-
G=I[8:-2];C=B
|
153
|
-
if G in(r,p,q,s,'bytearray','bytes'):C=X.format(E,F,H,G)
|
154
|
-
elif G in(e,d,c):f={e:'{}',d:'[]',c:'()'};C=X.format(E,F,f[G],G)
|
155
|
-
elif G in('object','set','frozenset','Pin',Y):
|
156
|
-
if G==Y:G='Generator'
|
157
|
-
C='{0}{1}: {2} ## = {4}\n'.format(E,F,G,I,H)
|
158
|
-
else:
|
159
|
-
G=V
|
160
|
-
if K in H:H=H.split(K)[0]+Z
|
161
|
-
if K in H:H=H.split(K)[0]+Z
|
162
|
-
C='{0}{1}: {2} ## {3} = {4}\n'.format(E,F,G,I,H)
|
163
|
-
J.write(C)
|
164
|
-
else:J.write("# all other, type = '{0}'\n".format(I));J.write(E+F+' # type: Incomplete\n')
|
165
|
-
@property
|
166
|
-
def flat_fwid(self):
|
167
|
-
A=self._fwid;B=' .()/\\:$'
|
168
|
-
for C in B:A=A.replace(C,'_')
|
169
|
-
return A
|
170
|
-
def clean(C,path=E):
|
171
|
-
if path is E:path=C.path
|
172
|
-
A.info('Clean/remove files in folder: {}'.format(path))
|
173
|
-
try:os.stat(path);D=os.listdir(path)
|
174
|
-
except(F,I):return
|
175
|
-
for G in D:
|
176
|
-
B=v.format(path,G)
|
177
|
-
try:os.remove(B)
|
178
|
-
except F:
|
179
|
-
try:C.clean(B);os.rmdir(B)
|
180
|
-
except F:pass
|
181
|
-
def report_start(B,filename='modules.json'):
|
182
|
-
H='firmware';B._json_name=v.format(B.path,filename);B._json_first=R;X(B._json_name);A.info('Report file: {}'.format(B._json_name));D.collect()
|
183
|
-
try:
|
184
|
-
with O(B._json_name,'w')as G:G.write('{');G.write(dumps({H:B.info})[1:-1]);G.write(f);G.write(dumps({o:{C:__version__},'stubtype':H})[1:-1]);G.write(f);G.write('"modules" :[\n')
|
185
|
-
except F as I:A.error(w);B._json_name=E;raise I
|
186
|
-
def report_add(B,module_name,stub_file):
|
187
|
-
if not B._json_name:raise n(x)
|
188
|
-
try:
|
189
|
-
with O(B._json_name,'a')as C:
|
190
|
-
if not B._json_first:C.write(f)
|
191
|
-
else:B._json_first=H
|
192
|
-
D='{{"module": "{}", "file": "{}"}}'.format(module_name,stub_file.replace('\\',G));C.write(D)
|
193
|
-
except F:A.error(w)
|
194
|
-
def report_end(B):
|
195
|
-
if not B._json_name:raise n(x)
|
196
|
-
with O(B._json_name,'a')as C:C.write('\n]}')
|
197
|
-
A.info('Path: {}'.format(B.path))
|
198
|
-
def X(path):
|
199
|
-
B=D=0
|
200
|
-
while B!=-1:
|
201
|
-
B=path.find(G,D)
|
202
|
-
if B!=-1:
|
203
|
-
C=path[0]if B==0 else path[:B]
|
204
|
-
try:I=os.stat(C)
|
205
|
-
except F as E:
|
206
|
-
if E.args[0]==y:
|
207
|
-
try:os.mkdir(C)
|
208
|
-
except F as H:A.error('failed to create folder {}'.format(C));raise H
|
209
|
-
D=B+1
|
210
|
-
def Y(s):
|
211
|
-
C=' on '
|
212
|
-
if not s:return B
|
213
|
-
s=s.split(C,1)[0]if C in s else s
|
214
|
-
if s.startswith('v'):
|
215
|
-
if not V in s:return B
|
216
|
-
A=s.split(V)[1];return A
|
217
|
-
if not W in s:return B
|
218
|
-
A=s.split(W)[1].split(J)[1];return A
|
219
|
-
def _info():
|
220
|
-
c='ev3-pybricks';Z='pycom';X='pycopy';V='unix';S='win32';R='arch';P='cpu';O='ver';F='mpy';D='build'
|
221
|
-
try:H=sys.implementation[0]
|
222
|
-
except a:H=sys.implementation.name
|
223
|
-
A=g({Q:H,C:B,D:B,O:B,K:sys.platform,U:'UNKNOWN',P:B,F:B,R:B})
|
224
|
-
if A[K].startswith('pyb'):A[K]='stm32'
|
225
|
-
elif A[K]==S:A[K]='windows'
|
226
|
-
elif A[K]=='linux':A[K]=V
|
227
|
-
try:A[C]=A1(sys.implementation.version)
|
228
|
-
except I:pass
|
229
|
-
try:J=sys.implementation._machine if'_machine'in M(sys.implementation)else os.uname().machine;A[U]=J;A[P]=J.split('with')[-1].strip();A[F]=sys.implementation._mpy if'_mpy'in M(sys.implementation)else sys.implementation.mpy if F in M(sys.implementation)else B
|
230
|
-
except(I,T):pass
|
231
|
-
A[U]=A2()
|
232
|
-
try:
|
233
|
-
if'uname'in M(os):
|
234
|
-
A[D]=Y(os.uname()[3])
|
235
|
-
if not A[D]:A[D]=Y(os.uname()[2])
|
236
|
-
elif C in M(sys):A[D]=Y(sys.version)
|
237
|
-
except(I,T,a):pass
|
238
|
-
if A[C]==B and sys.platform not in(V,S):
|
239
|
-
try:d=os.uname();A[C]=d.release
|
240
|
-
except(T,I,a):pass
|
241
|
-
for(e,f,h)in[(X,X,'const'),(Z,Z,'FAT'),(c,'pybricks.hubs','EV3Brick')]:
|
242
|
-
try:i=__import__(f,E,E,h);A[Q]=e;del i;break
|
243
|
-
except(N,m):pass
|
244
|
-
if A[Q]==c:A['release']='2.0.0'
|
245
|
-
if A[Q]==b:
|
246
|
-
A[C]
|
247
|
-
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]
|
248
|
-
if F in A and A[F]:
|
249
|
-
G=int(A[F]);L=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10]
|
250
|
-
if L:A[R]=L
|
251
|
-
A[F]='v{}.{}'.format(G&255,G>>8&3)
|
252
|
-
if A[D]and not A[C].endswith(W):A[C]=A[C]+W
|
253
|
-
A[O]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A
|
254
|
-
def A1(version):
|
255
|
-
A=version;B=J.join([str(A)for A in A[:3]])
|
256
|
-
if P(A)>3 and A[3]:B+=V+A[3]
|
257
|
-
return B
|
258
|
-
def A2():
|
259
|
-
try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C))
|
260
|
-
except N:A.warning('BOARDNAME not found');C=B
|
261
|
-
return C
|
262
|
-
def get_root():
|
263
|
-
try:A=os.getcwd()
|
264
|
-
except(F,I):A=J
|
265
|
-
B=A
|
266
|
-
for B in[A,'/sd','/flash',G,J]:
|
267
|
-
try:C=os.stat(B);break
|
268
|
-
except F:continue
|
269
|
-
return B
|
270
|
-
def h(filename):
|
271
|
-
try:
|
272
|
-
if os.stat(filename)[0]>>14:return R
|
273
|
-
return H
|
274
|
-
except F:return H
|
275
|
-
def i():S("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1)
|
276
|
-
def read_path():
|
277
|
-
path=B
|
278
|
-
if P(sys.argv)==3:
|
279
|
-
A=sys.argv[1].lower()
|
280
|
-
if A in('--path','-p'):path=sys.argv[2]
|
281
|
-
else:i()
|
282
|
-
elif P(sys.argv)==2:i()
|
283
|
-
return path
|
284
|
-
def j():
|
285
|
-
try:A=bytes('abc',encoding='utf8');B=j.__module__;return H
|
286
|
-
except(k,I):return R
|
287
|
-
def main():
|
288
|
-
stubber=Stubber(path=read_path());stubber.clean()
|
289
|
-
def A(stubber):
|
290
|
-
D.collect();stubber.modules=[]
|
291
|
-
for C in A0:
|
292
|
-
B=C+'/modulelist.txt'
|
293
|
-
if not h(B):continue
|
294
|
-
with O(B)as E:
|
295
|
-
while R:
|
296
|
-
A=E.readline().strip()
|
297
|
-
if not A:break
|
298
|
-
if P(A)>0 and A[0]!='#':stubber.modules.append(A)
|
299
|
-
D.collect();S('BREAK');break
|
300
|
-
if not stubber.modules:stubber.modules=[b]
|
301
|
-
D.collect()
|
302
|
-
stubber.modules=[];A(stubber);D.collect();stubber.create_all_stubs()
|
303
|
-
if __name__=='__main__'or j():
|
304
|
-
if not h('no_auto_stubber.txt'):
|
305
|
-
try:D.threshold(4*1024);D.enable()
|
306
|
-
except BaseException:pass
|
1
|
+
x='No report file'
|
2
|
+
w='Failed to create the report.'
|
3
|
+
v='{}/{}'
|
4
|
+
u='method'
|
5
|
+
t='function'
|
6
|
+
s='bool'
|
7
|
+
r='str'
|
8
|
+
q='float'
|
9
|
+
p='int'
|
10
|
+
o='stubber'
|
11
|
+
n=Exception
|
12
|
+
m=KeyError
|
13
|
+
l=sorted
|
14
|
+
k=NotImplementedError
|
15
|
+
f=',\n'
|
16
|
+
e='dict'
|
17
|
+
d='list'
|
18
|
+
c='tuple'
|
19
|
+
b='micropython'
|
20
|
+
a=TypeError
|
21
|
+
Z=repr
|
22
|
+
W='-preview'
|
23
|
+
V='-'
|
24
|
+
U='board'
|
25
|
+
T=IndexError
|
26
|
+
S=print
|
27
|
+
R=True
|
28
|
+
Q='family'
|
29
|
+
P=len
|
30
|
+
O=open
|
31
|
+
N=ImportError
|
32
|
+
M=dir
|
33
|
+
K='port'
|
34
|
+
J='.'
|
35
|
+
I=AttributeError
|
36
|
+
H=False
|
37
|
+
G='/'
|
38
|
+
F=OSError
|
39
|
+
E=None
|
40
|
+
C='version'
|
41
|
+
B=''
|
42
|
+
import gc as D,os,sys
|
43
|
+
from time import sleep
|
44
|
+
try:from ujson import dumps
|
45
|
+
except:from json import dumps
|
46
|
+
try:from machine import reset
|
47
|
+
except N:pass
|
48
|
+
try:from collections import OrderedDict as g
|
49
|
+
except N:from ucollections import OrderedDict as g
|
50
|
+
__version__='v1.20.6'
|
51
|
+
y=2
|
52
|
+
z=2
|
53
|
+
A0=['lib','/lib','/sd/lib','/flash/lib',J]
|
54
|
+
class L:
|
55
|
+
INFO=20;WARNING=30;ERROR=40;level=INFO;prnt=S
|
56
|
+
@staticmethod
|
57
|
+
def getLogger(name):return L()
|
58
|
+
@classmethod
|
59
|
+
def basicConfig(A,level):A.level=level
|
60
|
+
def info(A,msg):
|
61
|
+
if A.level<=L.INFO:A.prnt('INFO :',msg)
|
62
|
+
def warning(A,msg):
|
63
|
+
if A.level<=L.WARNING:A.prnt('WARN :',msg)
|
64
|
+
def error(A,msg):
|
65
|
+
if A.level<=L.ERROR:A.prnt('ERROR :',msg)
|
66
|
+
A=L.getLogger(o)
|
67
|
+
L.basicConfig(level=L.INFO)
|
68
|
+
class Stubber:
|
69
|
+
def __init__(B,path=E,firmware_id=E):
|
70
|
+
C=firmware_id
|
71
|
+
try:
|
72
|
+
if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed')
|
73
|
+
except I:pass
|
74
|
+
B.info=_info();A.info('Port: {}'.format(B.info[K]));A.info('Board: {}'.format(B.info[U]));D.collect()
|
75
|
+
if C:B._fwid=C.lower()
|
76
|
+
elif B.info[Q]==b:B._fwid='{family}-v{version}-{port}-{board}'.format(**B.info).rstrip(V)
|
77
|
+
else:B._fwid='{family}-v{version}-{port}'.format(**B.info)
|
78
|
+
B._start_free=D.mem_free()
|
79
|
+
if path:
|
80
|
+
if path.endswith(G):path=path[:-1]
|
81
|
+
else:path=get_root()
|
82
|
+
B.path='{}/stubs/{}'.format(path,B.flat_fwid).replace('//',G)
|
83
|
+
try:X(path+G)
|
84
|
+
except F:A.error('error creating stub folder {}'.format(path))
|
85
|
+
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
|
86
|
+
def get_obj_attributes(L,item_instance):
|
87
|
+
H=item_instance;C=[];K=[]
|
88
|
+
for A in M(H):
|
89
|
+
if A.startswith('__')and not A in L.modules:continue
|
90
|
+
try:
|
91
|
+
E=getattr(H,A)
|
92
|
+
try:F=Z(type(E)).split("'")[1]
|
93
|
+
except T:F=B
|
94
|
+
if F in{p,q,r,s,c,d,e}:G=1
|
95
|
+
elif F in{t,u}:G=2
|
96
|
+
elif F in'class':G=3
|
97
|
+
else:G=4
|
98
|
+
C.append((A,Z(E),Z(type(E)),E,G))
|
99
|
+
except I as J:K.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,H,J))
|
100
|
+
except MemoryError as J:S('MemoryError: {}'.format(J));sleep(1);reset()
|
101
|
+
C=l([A for A in C if not A[0].startswith('__')],key=lambda x:x[4]);D.collect();return C,K
|
102
|
+
def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules))
|
103
|
+
def create_all_stubs(B):
|
104
|
+
A.info('Start micropython-stubber {} on {}'.format(__version__,B._fwid));B.report_start();D.collect()
|
105
|
+
for C in B.modules:B.create_one_stub(C)
|
106
|
+
B.report_end();A.info('Finally done')
|
107
|
+
def create_one_stub(C,module_name):
|
108
|
+
B=module_name
|
109
|
+
if B in C.problematic:A.warning('Skip module: {:<25} : Known problematic'.format(B));return H
|
110
|
+
if B in C.excluded:A.warning('Skip module: {:<25} : Excluded'.format(B));return H
|
111
|
+
I='{}/{}.pyi'.format(C.path,B.replace(J,G));D.collect();E=H
|
112
|
+
try:E=C.create_module_stub(B,I)
|
113
|
+
except F:return H
|
114
|
+
D.collect();return E
|
115
|
+
def create_module_stub(K,module_name,file_name=E):
|
116
|
+
I=file_name;C=module_name
|
117
|
+
if I is E:L=C.replace(J,'_')+'.pyi';I=K.path+G+L
|
118
|
+
else:L=I.split(G)[-1]
|
119
|
+
if G in C:C=C.replace(G,J)
|
120
|
+
M=E
|
121
|
+
try:M=__import__(C,E,E,'*');Q=D.mem_free();A.info('Stub module: {:<25} to file: {:<70} mem:{:>5}'.format(C,L,Q))
|
122
|
+
except N:return H
|
123
|
+
X(I)
|
124
|
+
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)
|
125
|
+
K.report_add(C,I)
|
126
|
+
if C not in{'os','sys','logging','gc'}:
|
127
|
+
try:del M
|
128
|
+
except(F,m):A.warning('could not del new_module')
|
129
|
+
D.collect();return R
|
130
|
+
def write_object_stub(L,fp,object_expr,obj_name,indent,in_class=0):
|
131
|
+
Z=' at ...>';Y='generator';X='{0}{1}: {3} = {2}\n';W='bound_method';V='Incomplete';O=in_class;N='Exception';M=object_expr;K=' at ';J=fp;E=indent;D.collect()
|
132
|
+
if M in L.problematic:A.warning('SKIPPING problematic module:{}'.format(M));return
|
133
|
+
a,Q=L.get_obj_attributes(M)
|
134
|
+
if Q:A.error(Q)
|
135
|
+
for(F,H,I,b,g)in a:
|
136
|
+
if F in['classmethod','staticmethod','BaseException',N]:continue
|
137
|
+
if F[0].isdigit():A.warning('NameError: invalid name {}'.format(F));continue
|
138
|
+
if I=="<class 'type'>"and P(E)<=z*4:
|
139
|
+
R=B;S=F.endswith(N)or F.endswith('Error')or F in['KeyboardInterrupt','StopIteration','SystemExit']
|
140
|
+
if S:R=N
|
141
|
+
C='\n{}class {}({}):\n'.format(E,F,R)
|
142
|
+
if S:C+=E+' ...\n';J.write(C);continue
|
143
|
+
J.write(C);L.write_object_stub(J,b,'{0}.{1}'.format(obj_name,F),E+' ',O+1);C=E+' def __init__(self, *argv, **kwargs) -> None:\n';C+=E+' ...\n\n';J.write(C)
|
144
|
+
elif any(A in I for A in[u,t,'closure']):
|
145
|
+
T=V;U=B
|
146
|
+
if O>0:U='self, '
|
147
|
+
if W in I or W in H:C='{}@classmethod\n'.format(E)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(E,F,T)
|
148
|
+
else:C='{}def {}({}*args, **kwargs) -> {}:\n'.format(E,F,U,T)
|
149
|
+
C+=E+' ...\n\n';J.write(C)
|
150
|
+
elif I=="<class 'module'>":0
|
151
|
+
elif I.startswith("<class '"):
|
152
|
+
G=I[8:-2];C=B
|
153
|
+
if G in(r,p,q,s,'bytearray','bytes'):C=X.format(E,F,H,G)
|
154
|
+
elif G in(e,d,c):f={e:'{}',d:'[]',c:'()'};C=X.format(E,F,f[G],G)
|
155
|
+
elif G in('object','set','frozenset','Pin',Y):
|
156
|
+
if G==Y:G='Generator'
|
157
|
+
C='{0}{1}: {2} ## = {4}\n'.format(E,F,G,I,H)
|
158
|
+
else:
|
159
|
+
G=V
|
160
|
+
if K in H:H=H.split(K)[0]+Z
|
161
|
+
if K in H:H=H.split(K)[0]+Z
|
162
|
+
C='{0}{1}: {2} ## {3} = {4}\n'.format(E,F,G,I,H)
|
163
|
+
J.write(C)
|
164
|
+
else:J.write("# all other, type = '{0}'\n".format(I));J.write(E+F+' # type: Incomplete\n')
|
165
|
+
@property
|
166
|
+
def flat_fwid(self):
|
167
|
+
A=self._fwid;B=' .()/\\:$'
|
168
|
+
for C in B:A=A.replace(C,'_')
|
169
|
+
return A
|
170
|
+
def clean(C,path=E):
|
171
|
+
if path is E:path=C.path
|
172
|
+
A.info('Clean/remove files in folder: {}'.format(path))
|
173
|
+
try:os.stat(path);D=os.listdir(path)
|
174
|
+
except(F,I):return
|
175
|
+
for G in D:
|
176
|
+
B=v.format(path,G)
|
177
|
+
try:os.remove(B)
|
178
|
+
except F:
|
179
|
+
try:C.clean(B);os.rmdir(B)
|
180
|
+
except F:pass
|
181
|
+
def report_start(B,filename='modules.json'):
|
182
|
+
H='firmware';B._json_name=v.format(B.path,filename);B._json_first=R;X(B._json_name);A.info('Report file: {}'.format(B._json_name));D.collect()
|
183
|
+
try:
|
184
|
+
with O(B._json_name,'w')as G:G.write('{');G.write(dumps({H:B.info})[1:-1]);G.write(f);G.write(dumps({o:{C:__version__},'stubtype':H})[1:-1]);G.write(f);G.write('"modules" :[\n')
|
185
|
+
except F as I:A.error(w);B._json_name=E;raise I
|
186
|
+
def report_add(B,module_name,stub_file):
|
187
|
+
if not B._json_name:raise n(x)
|
188
|
+
try:
|
189
|
+
with O(B._json_name,'a')as C:
|
190
|
+
if not B._json_first:C.write(f)
|
191
|
+
else:B._json_first=H
|
192
|
+
D='{{"module": "{}", "file": "{}"}}'.format(module_name,stub_file.replace('\\',G));C.write(D)
|
193
|
+
except F:A.error(w)
|
194
|
+
def report_end(B):
|
195
|
+
if not B._json_name:raise n(x)
|
196
|
+
with O(B._json_name,'a')as C:C.write('\n]}')
|
197
|
+
A.info('Path: {}'.format(B.path))
|
198
|
+
def X(path):
|
199
|
+
B=D=0
|
200
|
+
while B!=-1:
|
201
|
+
B=path.find(G,D)
|
202
|
+
if B!=-1:
|
203
|
+
C=path[0]if B==0 else path[:B]
|
204
|
+
try:I=os.stat(C)
|
205
|
+
except F as E:
|
206
|
+
if E.args[0]==y:
|
207
|
+
try:os.mkdir(C)
|
208
|
+
except F as H:A.error('failed to create folder {}'.format(C));raise H
|
209
|
+
D=B+1
|
210
|
+
def Y(s):
|
211
|
+
C=' on '
|
212
|
+
if not s:return B
|
213
|
+
s=s.split(C,1)[0]if C in s else s
|
214
|
+
if s.startswith('v'):
|
215
|
+
if not V in s:return B
|
216
|
+
A=s.split(V)[1];return A
|
217
|
+
if not W in s:return B
|
218
|
+
A=s.split(W)[1].split(J)[1];return A
|
219
|
+
def _info():
|
220
|
+
c='ev3-pybricks';Z='pycom';X='pycopy';V='unix';S='win32';R='arch';P='cpu';O='ver';F='mpy';D='build'
|
221
|
+
try:H=sys.implementation[0]
|
222
|
+
except a:H=sys.implementation.name
|
223
|
+
A=g({Q:H,C:B,D:B,O:B,K:sys.platform,U:'UNKNOWN',P:B,F:B,R:B})
|
224
|
+
if A[K].startswith('pyb'):A[K]='stm32'
|
225
|
+
elif A[K]==S:A[K]='windows'
|
226
|
+
elif A[K]=='linux':A[K]=V
|
227
|
+
try:A[C]=A1(sys.implementation.version)
|
228
|
+
except I:pass
|
229
|
+
try:J=sys.implementation._machine if'_machine'in M(sys.implementation)else os.uname().machine;A[U]=J;A[P]=J.split('with')[-1].strip();A[F]=sys.implementation._mpy if'_mpy'in M(sys.implementation)else sys.implementation.mpy if F in M(sys.implementation)else B
|
230
|
+
except(I,T):pass
|
231
|
+
A[U]=A2()
|
232
|
+
try:
|
233
|
+
if'uname'in M(os):
|
234
|
+
A[D]=Y(os.uname()[3])
|
235
|
+
if not A[D]:A[D]=Y(os.uname()[2])
|
236
|
+
elif C in M(sys):A[D]=Y(sys.version)
|
237
|
+
except(I,T,a):pass
|
238
|
+
if A[C]==B and sys.platform not in(V,S):
|
239
|
+
try:d=os.uname();A[C]=d.release
|
240
|
+
except(T,I,a):pass
|
241
|
+
for(e,f,h)in[(X,X,'const'),(Z,Z,'FAT'),(c,'pybricks.hubs','EV3Brick')]:
|
242
|
+
try:i=__import__(f,E,E,h);A[Q]=e;del i;break
|
243
|
+
except(N,m):pass
|
244
|
+
if A[Q]==c:A['release']='2.0.0'
|
245
|
+
if A[Q]==b:
|
246
|
+
A[C]
|
247
|
+
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]
|
248
|
+
if F in A and A[F]:
|
249
|
+
G=int(A[F]);L=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][G>>10]
|
250
|
+
if L:A[R]=L
|
251
|
+
A[F]='v{}.{}'.format(G&255,G>>8&3)
|
252
|
+
if A[D]and not A[C].endswith(W):A[C]=A[C]+W
|
253
|
+
A[O]=f"{A[C]}-{A[D]}"if A[D]else f"{A[C]}";return A
|
254
|
+
def A1(version):
|
255
|
+
A=version;B=J.join([str(A)for A in A[:3]])
|
256
|
+
if P(A)>3 and A[3]:B+=V+A[3]
|
257
|
+
return B
|
258
|
+
def A2():
|
259
|
+
try:from boardname import BOARDNAME as C;A.info('Found BOARDNAME: {}'.format(C))
|
260
|
+
except N:A.warning('BOARDNAME not found');C=B
|
261
|
+
return C
|
262
|
+
def get_root():
|
263
|
+
try:A=os.getcwd()
|
264
|
+
except(F,I):A=J
|
265
|
+
B=A
|
266
|
+
for B in[A,'/sd','/flash',G,J]:
|
267
|
+
try:C=os.stat(B);break
|
268
|
+
except F:continue
|
269
|
+
return B
|
270
|
+
def h(filename):
|
271
|
+
try:
|
272
|
+
if os.stat(filename)[0]>>14:return R
|
273
|
+
return H
|
274
|
+
except F:return H
|
275
|
+
def i():S("-p, --path path to store the stubs in, defaults to '.'");sys.exit(1)
|
276
|
+
def read_path():
|
277
|
+
path=B
|
278
|
+
if P(sys.argv)==3:
|
279
|
+
A=sys.argv[1].lower()
|
280
|
+
if A in('--path','-p'):path=sys.argv[2]
|
281
|
+
else:i()
|
282
|
+
elif P(sys.argv)==2:i()
|
283
|
+
return path
|
284
|
+
def j():
|
285
|
+
try:A=bytes('abc',encoding='utf8');B=j.__module__;return H
|
286
|
+
except(k,I):return R
|
287
|
+
def main():
|
288
|
+
stubber=Stubber(path=read_path());stubber.clean()
|
289
|
+
def A(stubber):
|
290
|
+
D.collect();stubber.modules=[]
|
291
|
+
for C in A0:
|
292
|
+
B=C+'/modulelist.txt'
|
293
|
+
if not h(B):continue
|
294
|
+
with O(B)as E:
|
295
|
+
while R:
|
296
|
+
A=E.readline().strip()
|
297
|
+
if not A:break
|
298
|
+
if P(A)>0 and A[0]!='#':stubber.modules.append(A)
|
299
|
+
D.collect();S('BREAK');break
|
300
|
+
if not stubber.modules:stubber.modules=[b]
|
301
|
+
D.collect()
|
302
|
+
stubber.modules=[];A(stubber);D.collect();stubber.create_all_stubs()
|
303
|
+
if __name__=='__main__'or j():
|
304
|
+
if not h('no_auto_stubber.txt'):
|
305
|
+
try:D.threshold(4*1024);D.enable()
|
306
|
+
except BaseException:pass
|
307
307
|
main()
|
Binary file
|