micropython-stubber 1.14.1__py3-none-any.whl → 1.15.1__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.15.1.dist-info/METADATA +244 -0
- {micropython_stubber-1.14.1.dist-info → micropython_stubber-1.15.1.dist-info}/RECORD +49 -46
- stubber/__init__.py +1 -1
- stubber/basicgit.py +27 -14
- stubber/board/createstubs.py +34 -36
- stubber/board/createstubs_db.py +35 -35
- stubber/board/createstubs_db_min.py +195 -193
- stubber/board/createstubs_db_mpy.mpy +0 -0
- stubber/board/createstubs_info.py +73 -42
- stubber/board/createstubs_lvgl.py +35 -35
- stubber/board/createstubs_lvgl_min.py +88 -87
- stubber/board/createstubs_lvgl_mpy.mpy +0 -0
- stubber/board/createstubs_mem.py +44 -40
- stubber/board/createstubs_mem_min.py +179 -174
- stubber/board/createstubs_mem_mpy.mpy +0 -0
- stubber/board/createstubs_min.py +75 -74
- stubber/board/createstubs_mpy.mpy +0 -0
- stubber/board/info.py +183 -0
- stubber/codemod/enrich.py +28 -16
- stubber/commands/build_cmd.py +3 -3
- stubber/commands/get_core_cmd.py +17 -5
- stubber/commands/get_docstubs_cmd.py +23 -8
- stubber/commands/get_frozen_cmd.py +62 -9
- stubber/commands/get_lobo_cmd.py +13 -3
- stubber/commands/merge_cmd.py +7 -4
- stubber/commands/publish_cmd.py +5 -4
- stubber/commands/stub_cmd.py +2 -1
- stubber/commands/variants_cmd.py +0 -1
- stubber/freeze/common.py +2 -2
- stubber/freeze/freeze_folder.py +1 -1
- stubber/freeze/get_frozen.py +1 -1
- stubber/minify.py +43 -28
- stubber/publish/bump.py +1 -1
- stubber/publish/candidates.py +61 -17
- stubber/publish/defaults.py +44 -0
- stubber/publish/merge_docstubs.py +19 -56
- stubber/publish/package.py +44 -37
- stubber/publish/pathnames.py +51 -0
- stubber/publish/publish.py +5 -4
- stubber/publish/stubpacker.py +55 -33
- stubber/rst/lookup.py +7 -16
- stubber/rst/reader.py +39 -8
- stubber/stubs_from_docs.py +5 -8
- stubber/utils/post.py +34 -40
- stubber/utils/repos.py +32 -17
- stubber/utils/stubmaker.py +22 -14
- micropython_stubber-1.14.1.dist-info/METADATA +0 -217
- {micropython_stubber-1.14.1.dist-info → micropython_stubber-1.15.1.dist-info}/LICENSE +0 -0
- {micropython_stubber-1.14.1.dist-info → micropython_stubber-1.15.1.dist-info}/WHEEL +0 -0
- {micropython_stubber-1.14.1.dist-info → micropython_stubber-1.15.1.dist-info}/entry_points.txt +0 -0
stubber/board/createstubs_min.py
CHANGED
@@ -1,23 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
1
|
+
x='pyb'
|
2
|
+
w='{}/{}'
|
3
|
+
v='logging'
|
4
|
+
u='sys'
|
5
|
+
t='method'
|
6
|
+
s='function'
|
7
|
+
r='bool'
|
8
|
+
q='str'
|
9
|
+
p='float'
|
10
|
+
o='int'
|
11
|
+
n='port'
|
12
|
+
m=NameError
|
13
|
+
l=sorted
|
14
|
+
k=NotImplementedError
|
15
|
+
c='pycom'
|
16
|
+
b=',\n'
|
17
|
+
a='dict'
|
18
|
+
Z='list'
|
19
|
+
Y='tuple'
|
20
|
+
X='micropython'
|
21
|
+
W='stubber'
|
21
22
|
V=open
|
22
23
|
U=repr
|
23
24
|
S='_'
|
@@ -39,32 +40,32 @@ F=OSError
|
|
39
40
|
D='version'
|
40
41
|
B=''
|
41
42
|
import gc as C,os,sys
|
42
|
-
from ujson import dumps as
|
43
|
+
from ujson import dumps as d
|
43
44
|
try:from machine import reset
|
44
45
|
except N:pass
|
45
|
-
try:from collections import OrderedDict as
|
46
|
-
except N:from ucollections import OrderedDict as
|
47
|
-
__version__='v1.
|
48
|
-
x=2
|
46
|
+
try:from collections import OrderedDict as e
|
47
|
+
except N:from ucollections import OrderedDict as e
|
48
|
+
__version__='v1.15.1'
|
49
49
|
y=2
|
50
|
-
z=
|
50
|
+
z=2
|
51
|
+
A0=[K,'/lib','/sd/lib','/flash/lib','lib']
|
51
52
|
from time import sleep
|
52
53
|
class Stubber:
|
53
54
|
def __init__(A,path=E,firmware_id=E):
|
54
55
|
B=firmware_id
|
55
56
|
try:
|
56
|
-
if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise
|
57
|
+
if os.uname().release=='1.13.0'and os.uname().version<'v1.13-103':raise k('MicroPython 1.13.0 cannot be stubbed')
|
57
58
|
except H:pass
|
58
|
-
A._report=[];A.info=_info();J('Port: {}'.format(A.info[
|
59
|
+
A.log=E;A.log=logging.getLogger(W);A._report=[];A.info=_info();J('Port: {}'.format(A.info[n]));J('Board: {}'.format(A.info[I]));C.collect()
|
59
60
|
if B:A._fwid=B.lower()
|
60
|
-
elif A.info[L]==
|
61
|
+
elif A.info[L]==X:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info)
|
61
62
|
else:A._fwid='{family}-{ver}-{port}'.format(**A.info)
|
62
63
|
A._start_free=C.mem_free()
|
63
64
|
if path:
|
64
65
|
if path.endswith(G):path=path[:-1]
|
65
66
|
else:path=get_root()
|
66
67
|
A.path='{}/stubs/{}'.format(path,A.flat_fwid).replace('//',G)
|
67
|
-
try:
|
68
|
+
try:f(path+G)
|
68
69
|
except F:J('error creating stub folder {}'.format(path))
|
69
70
|
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=[]
|
70
71
|
def get_obj_attributes(L,item_instance):
|
@@ -75,15 +76,15 @@ class Stubber:
|
|
75
76
|
E=getattr(I,A)
|
76
77
|
try:F=U(type(E)).split("'")[1]
|
77
78
|
except P:F=B
|
78
|
-
if F in{
|
79
|
-
elif F in{
|
79
|
+
if F in{o,p,q,r,Y,Z,a}:G=1
|
80
|
+
elif F in{s,t}:G=2
|
80
81
|
elif F in'class':G=3
|
81
82
|
else:G=4
|
82
83
|
D.append((A,U(E),U(type(E)),E,G))
|
83
84
|
except H as K:J.append("Couldn't get attribute '{}' from object '{}', Err: {}".format(A,I,K))
|
84
85
|
except MemoryError as K:sleep(1);reset()
|
85
|
-
D=
|
86
|
-
def add_modules(A,modules):A.modules=
|
86
|
+
D=l([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J
|
87
|
+
def add_modules(A,modules):A.modules=l(set(A.modules)|set(modules))
|
87
88
|
def create_all_stubs(A):
|
88
89
|
C.collect()
|
89
90
|
for B in A.modules:A.create_one_stub(B)
|
@@ -103,10 +104,10 @@ class Stubber:
|
|
103
104
|
J=E
|
104
105
|
try:J=__import__(D,E,E,'*');T=C.mem_free()
|
105
106
|
except N:return A
|
106
|
-
|
107
|
+
f(H)
|
107
108
|
with V(H,'w')as L: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__);L.write(R);L.write('from typing import Any\nfrom _typeshed import Incomplete\n\n');I.write_object_stub(L,J,D,B)
|
108
109
|
I._report.append('{{"module": "{}", "file": "{}"}}'.format(D,H.replace('\\',G)))
|
109
|
-
if D not in{'os',
|
110
|
+
if D not in{'os',u,v,'gc'}:
|
110
111
|
try:del J
|
111
112
|
except (F,Q):pass
|
112
113
|
try:del sys.modules[D]
|
@@ -120,23 +121,23 @@ class Stubber:
|
|
120
121
|
for (E,K,G,T,f) in S:
|
121
122
|
if E in['classmethod','staticmethod','BaseException',N]:continue
|
122
123
|
if E[0].isdigit():continue
|
123
|
-
if G=="<class 'type'>"and R(D)<=
|
124
|
+
if G=="<class 'type'>"and R(D)<=z*4:
|
124
125
|
U=B;V=E.endswith(N)or E.endswith('Error')or E in['KeyboardInterrupt','StopIteration','SystemExit']
|
125
126
|
if V:U=N
|
126
127
|
A='\n{}class {}({}):\n'.format(D,E,U)
|
127
128
|
if V:A+=D+' ...\n';H.write(A);return
|
128
129
|
H.write(A);L.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)
|
129
|
-
elif any((A in G for A in[s,
|
130
|
-
W=b;
|
131
|
-
if P>0:
|
130
|
+
elif any((A in G for A in[t,s,'closure'])):
|
131
|
+
W=b;X=B
|
132
|
+
if P>0:X='self, '
|
132
133
|
if c in G or c in K:A='{}@classmethod\n'.format(D)+'{}def {}(cls, *args, **kwargs) -> {}:\n'.format(D,E,W)
|
133
|
-
else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,
|
134
|
+
else:A='{}def {}({}*args, **kwargs) -> {}:\n'.format(D,E,X,W)
|
134
135
|
A+=D+' ...\n\n';H.write(A)
|
135
136
|
elif G=="<class 'module'>":0
|
136
137
|
elif G.startswith("<class '"):
|
137
138
|
I=G[8:-2];A=B
|
138
|
-
if I in[
|
139
|
-
elif I in[Z,Y
|
139
|
+
if I in[q,o,p,r,'bytearray','bytes']:A=d.format(D,E,K,I)
|
140
|
+
elif I in[a,Z,Y]:e={a:'{}',Z:'[]',Y:'()'};A=d.format(D,E,e[I],I)
|
140
141
|
else:
|
141
142
|
if I not in['object','set','frozenset']:I=b
|
142
143
|
A='{0}{1} : {2} ## {3} = {4}\n'.format(D,E,I,G,K)
|
@@ -144,7 +145,7 @@ class Stubber:
|
|
144
145
|
else:H.write("# all other, type = '{0}'\n".format(G));H.write(D+E+' # type: Incomplete\n')
|
145
146
|
del S;del M
|
146
147
|
try:del E,K,G,T
|
147
|
-
except (F,Q,
|
148
|
+
except (F,Q,m):pass
|
148
149
|
@property
|
149
150
|
def flat_fwid(self):
|
150
151
|
A=self._fwid;B=' .()/\\:$'
|
@@ -156,13 +157,13 @@ class Stubber:
|
|
156
157
|
try:os.stat(path);C=os.listdir(path)
|
157
158
|
except (F,H):return
|
158
159
|
for D in C:
|
159
|
-
A=
|
160
|
+
A=w.format(path,D)
|
160
161
|
try:os.remove(A)
|
161
162
|
except F:
|
162
163
|
try:B.clean(A);os.rmdir(A)
|
163
164
|
except F:pass
|
164
165
|
def report(B,filename='modules.json'):
|
165
|
-
G=
|
166
|
+
G=w.format(B.path,filename);C.collect()
|
166
167
|
try:
|
167
168
|
with V(G,'w')as D:
|
168
169
|
B.write_json_header(D);E=M
|
@@ -170,12 +171,12 @@ class Stubber:
|
|
170
171
|
B.write_json_end(D)
|
171
172
|
I=B._start_free-C.mem_free()
|
172
173
|
except F:J('Failed to create the report.')
|
173
|
-
def write_json_header(B,f):A='firmware';f.write('{');f.write(
|
174
|
+
def write_json_header(B,f):A='firmware';f.write('{');f.write(d({A:B.info})[1:-1]);f.write(b);f.write(d({W:{D:__version__},'stubtype':A})[1:-1]);f.write(b);f.write('"modules" :[\n')
|
174
175
|
def write_json_node(A,f,n,first):
|
175
|
-
if not first:f.write(
|
176
|
+
if not first:f.write(b)
|
176
177
|
f.write(n)
|
177
178
|
def write_json_end(A,f):f.write('\n]}')
|
178
|
-
def
|
179
|
+
def f(path):
|
179
180
|
A=C=0
|
180
181
|
while A!=-1:
|
181
182
|
A=path.find(G,C)
|
@@ -183,7 +184,7 @@ def e(path):
|
|
183
184
|
B=path[0]if A==0 else path[:A]
|
184
185
|
try:H=os.stat(B)
|
185
186
|
except F as D:
|
186
|
-
if D.args[0]==
|
187
|
+
if D.args[0]==y:
|
187
188
|
try:os.mkdir(B)
|
188
189
|
except F as E:J('failed to create folder {}'.format(B));raise E
|
189
190
|
C=A+1
|
@@ -193,20 +194,20 @@ def T(s):
|
|
193
194
|
if A in s:s=s.split(A,1)[0]
|
194
195
|
return s.split('-')[1]if'-'in s else B
|
195
196
|
def _info():
|
196
|
-
i='ev3-pybricks';
|
197
|
+
i='ev3-pybricks';f='pycopy';d='GENERIC';b='arch';a='cpu';Z='ver';V='with';G='mpy';F='build';A=e({L:sys.implementation.name,D:B,F:B,Z:B,n:'stm32'if sys.platform.startswith(x)else sys.platform,I:d,a:B,G:B,b:B})
|
197
198
|
try:A[D]=K.join([str(A)for A in sys.implementation.version])
|
198
199
|
except H:pass
|
199
|
-
try:
|
200
|
+
try:W=sys.implementation._machine if'_machine'in O(sys.implementation)else os.uname().machine;A[I]=W.strip();A[a]=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
|
200
201
|
except (H,P):pass
|
201
202
|
C.collect()
|
202
|
-
for M in [A+'/board_info.csv'for A in
|
203
|
-
if
|
203
|
+
for M in [A+'/board_info.csv'for A in A0]:
|
204
|
+
if h(M):
|
204
205
|
J=A[I].strip()
|
205
|
-
if
|
206
|
+
if g(A,J,M):break
|
206
207
|
if V in J:
|
207
208
|
J=J.split(V)[0].strip()
|
208
|
-
if
|
209
|
-
A[I]=
|
209
|
+
if g(A,J,M):break
|
210
|
+
A[I]=d
|
210
211
|
A[I]=A[I].replace(' ',S);C.collect()
|
211
212
|
try:
|
212
213
|
A[F]=T(os.uname()[3])
|
@@ -217,18 +218,18 @@ def _info():
|
|
217
218
|
if A[D]==B and sys.platform not in('unix','win32'):
|
218
219
|
try:j=os.uname();A[D]=j.release
|
219
220
|
except (P,H,TypeError):pass
|
220
|
-
for (k,l,
|
221
|
-
try:o=__import__(l,E,E,
|
221
|
+
for (k,l,m) in [(f,f,'const'),(c,c,'FAT'),(i,'pybricks.hubs','EV3Brick')]:
|
222
|
+
try:o=__import__(l,E,E,m);A[L]=k;del o;break
|
222
223
|
except (N,Q):pass
|
223
224
|
if A[L]==i:A['release']='2.0.0'
|
224
|
-
if A[L]==
|
225
|
+
if A[L]==X:
|
225
226
|
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]
|
226
227
|
if G in A and A[G]:
|
227
228
|
U=int(A[G]);Y=[E,'x86','x64','armv6','armv6m','armv7m','armv7em','armv7emsp','armv7emdp','xtensa','xtensawin'][U>>10]
|
228
|
-
if Y:A[
|
229
|
+
if Y:A[b]=Y
|
229
230
|
A[G]='v{}.{}'.format(U&255,U>>8&3)
|
230
231
|
A[Z]=f"v{A[D]}-{A[F]}"if A[F]else f"v{A[D]}";return A
|
231
|
-
def
|
232
|
+
def g(info,board_descr,filename):
|
232
233
|
with V(filename,'r')as C:
|
233
234
|
while 1:
|
234
235
|
B=C.readline()
|
@@ -244,28 +245,28 @@ def get_root():
|
|
244
245
|
try:C=os.stat(B);break
|
245
246
|
except F:continue
|
246
247
|
return B
|
247
|
-
def
|
248
|
+
def h(filename):
|
248
249
|
try:
|
249
250
|
if os.stat(filename)[0]>>14:return M
|
250
251
|
return A
|
251
252
|
except F:return A
|
252
|
-
def
|
253
|
+
def i():sys.exit(1)
|
253
254
|
def read_path():
|
254
255
|
path=B
|
255
256
|
if R(sys.argv)==3:
|
256
257
|
A=sys.argv[1].lower()
|
257
258
|
if A in('--path','-p'):path=sys.argv[2]
|
258
|
-
else:
|
259
|
-
elif R(sys.argv)==2:
|
259
|
+
else:i()
|
260
|
+
elif R(sys.argv)==2:i()
|
260
261
|
return path
|
261
|
-
def
|
262
|
-
try:B=bytes('abc',encoding='utf8');C=
|
263
|
-
except (
|
264
|
-
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',
|
265
|
-
if __name__=='__main__'or
|
266
|
-
try:logging.basicConfig(level=logging.INFO)
|
267
|
-
except
|
268
|
-
if not
|
262
|
+
def j():
|
263
|
+
try:B=bytes('abc',encoding='utf8');C=j.__module__;return A
|
264
|
+
except (k,H):return M
|
265
|
+
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',v,'lsm6dsox','lv_colors','lv_utils','lvgl','lwip','machine','math','microWebSocket','microWebSrv','microWebTemplate',X,'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',x,c,'pye','qrcode','queue','random','requests','rp2','rtch','samd','select','servo','socket','ssd1306','ssh','ssl','stm','struct',u,'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()
|
266
|
+
if __name__=='__main__'or j():
|
267
|
+
try:A1=logging.getLogger(W);logging.basicConfig(level=logging.INFO)
|
268
|
+
except m:pass
|
269
|
+
if not h('no_auto_stubber.txt'):
|
269
270
|
try:C.threshold(4*1024);C.enable()
|
270
271
|
except BaseException:pass
|
271
272
|
main()
|
Binary file
|
stubber/board/info.py
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
import gc
|
2
|
+
import logging
|
3
|
+
import os
|
4
|
+
import sys
|
5
|
+
|
6
|
+
LIBS = [".", "/lib", "/sd/lib", "/flash/lib", "lib"]
|
7
|
+
# from ujson import dumps
|
8
|
+
|
9
|
+
try:
|
10
|
+
from machine import reset # type: ignore
|
11
|
+
except ImportError:
|
12
|
+
pass
|
13
|
+
|
14
|
+
try:
|
15
|
+
from collections import OrderedDict
|
16
|
+
except ImportError:
|
17
|
+
from ucollections import OrderedDict # type: ignore
|
18
|
+
|
19
|
+
|
20
|
+
def _info(): # type:() -> dict[str, str]
|
21
|
+
info = OrderedDict(
|
22
|
+
{
|
23
|
+
"family": sys.implementation.name,
|
24
|
+
"version": "",
|
25
|
+
"build": "",
|
26
|
+
"ver": "",
|
27
|
+
"port": "stm32"
|
28
|
+
if sys.platform.startswith("pyb")
|
29
|
+
else sys.platform, # port: esp32 / win32 / linux / stm32
|
30
|
+
"board": "GENERIC",
|
31
|
+
"cpu": "",
|
32
|
+
"mpy": "",
|
33
|
+
"arch": "",
|
34
|
+
}
|
35
|
+
)
|
36
|
+
try:
|
37
|
+
info["version"] = ".".join([str(n) for n in sys.implementation.version])
|
38
|
+
except AttributeError:
|
39
|
+
pass
|
40
|
+
try:
|
41
|
+
machine = (
|
42
|
+
sys.implementation._machine
|
43
|
+
if "_machine" in dir(sys.implementation)
|
44
|
+
else os.uname().machine
|
45
|
+
)
|
46
|
+
info["board"] = machine.strip()
|
47
|
+
info["cpu"] = machine.split("with")[1].strip()
|
48
|
+
info["mpy"] = (
|
49
|
+
sys.implementation._mpy
|
50
|
+
if "_mpy" in dir(sys.implementation)
|
51
|
+
else sys.implementation.mpy
|
52
|
+
if "mpy" in dir(sys.implementation)
|
53
|
+
else ""
|
54
|
+
)
|
55
|
+
except (AttributeError, IndexError):
|
56
|
+
pass
|
57
|
+
gc.collect()
|
58
|
+
for filename in [d + "/board_info.csv" for d in LIBS]:
|
59
|
+
print("Check file:", filename)
|
60
|
+
if file_exists(filename):
|
61
|
+
print("Found board info file: {}".format(filename))
|
62
|
+
b = info["board"].strip()
|
63
|
+
if find_board(info, b, filename):
|
64
|
+
break
|
65
|
+
if "with" in b:
|
66
|
+
b = b.split("with")[0].strip()
|
67
|
+
if find_board(info, b, filename):
|
68
|
+
break
|
69
|
+
info["board"] = "GENERIC"
|
70
|
+
break
|
71
|
+
info["board"] = info["board"].replace(" ", "_")
|
72
|
+
gc.collect()
|
73
|
+
|
74
|
+
try:
|
75
|
+
# extract build from uname().version if available
|
76
|
+
info["build"] = _build(os.uname()[3])
|
77
|
+
if not info["build"]:
|
78
|
+
# extract build from uname().release if available
|
79
|
+
info["build"] = _build(os.uname()[2])
|
80
|
+
if not info["build"] and ";" in sys.version:
|
81
|
+
# extract build from uname().release if available
|
82
|
+
info["build"] = _build(sys.version.split(";")[1])
|
83
|
+
except (AttributeError, IndexError):
|
84
|
+
pass
|
85
|
+
# avoid build hashes
|
86
|
+
if info["build"] and len(info["build"]) > 5:
|
87
|
+
info["build"] = ""
|
88
|
+
|
89
|
+
if info["version"] == "" and sys.platform not in ("unix", "win32"):
|
90
|
+
try:
|
91
|
+
u = os.uname()
|
92
|
+
info["version"] = u.release
|
93
|
+
except (IndexError, AttributeError, TypeError):
|
94
|
+
pass
|
95
|
+
# detect families
|
96
|
+
for fam_name, mod_name, mod_thing in [
|
97
|
+
("pycopy", "pycopy", "const"),
|
98
|
+
("pycom", "pycom", "FAT"),
|
99
|
+
("ev3-pybricks", "pybricks.hubs", "EV3Brick"),
|
100
|
+
]:
|
101
|
+
try:
|
102
|
+
_t = __import__(mod_name, None, None, (mod_thing))
|
103
|
+
info["family"] = fam_name
|
104
|
+
del _t
|
105
|
+
break
|
106
|
+
except (ImportError, KeyError):
|
107
|
+
pass
|
108
|
+
|
109
|
+
if info["family"] == "ev3-pybricks":
|
110
|
+
info["release"] = "2.0.0"
|
111
|
+
|
112
|
+
if info["family"] == "micropython":
|
113
|
+
if (
|
114
|
+
info["version"]
|
115
|
+
and info["version"].endswith(".0")
|
116
|
+
and info["version"]
|
117
|
+
>= "1.10.0" # versions from 1.10.0 to 1.20.0 do not have a micro .0
|
118
|
+
and info["version"] <= "1.19.9"
|
119
|
+
):
|
120
|
+
# drop the .0 for newer releases
|
121
|
+
info["version"] = info["version"][:-2]
|
122
|
+
|
123
|
+
# spell-checker: disable
|
124
|
+
if "mpy" in info and info["mpy"]: # mpy on some v1.11+ builds
|
125
|
+
sys_mpy = int(info["mpy"])
|
126
|
+
# .mpy architecture
|
127
|
+
arch = [
|
128
|
+
None,
|
129
|
+
"x86",
|
130
|
+
"x64",
|
131
|
+
"armv6",
|
132
|
+
"armv6m",
|
133
|
+
"armv7m",
|
134
|
+
"armv7em",
|
135
|
+
"armv7emsp",
|
136
|
+
"armv7emdp",
|
137
|
+
"xtensa",
|
138
|
+
"xtensawin",
|
139
|
+
][sys_mpy >> 10]
|
140
|
+
if arch:
|
141
|
+
info["arch"] = arch
|
142
|
+
# .mpy version.minor
|
143
|
+
info["mpy"] = "v{}.{}".format(sys_mpy & 0xFF, sys_mpy >> 8 & 3)
|
144
|
+
# simple to use version[-build] string
|
145
|
+
info["ver"] = f"v{info['version']}-{info['build']}" if info["build"] else f"v{info['version']}"
|
146
|
+
|
147
|
+
return info
|
148
|
+
|
149
|
+
|
150
|
+
def find_board(info: dict, board_descr: str, filename: str):
|
151
|
+
print("Find board '{}' in the provided board_info.csv file".format(board_descr))
|
152
|
+
with open(filename, "r") as file:
|
153
|
+
# ugly code to make testable in python and micropython
|
154
|
+
while 1:
|
155
|
+
line = file.readline()
|
156
|
+
if not line:
|
157
|
+
break
|
158
|
+
descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip()
|
159
|
+
if descr_ == board_descr:
|
160
|
+
info["board"] = board_
|
161
|
+
return True
|
162
|
+
return False
|
163
|
+
|
164
|
+
|
165
|
+
def file_exists(filename: str):
|
166
|
+
try:
|
167
|
+
if os.stat(filename)[0] >> 14:
|
168
|
+
return True
|
169
|
+
return False
|
170
|
+
except OSError:
|
171
|
+
return False
|
172
|
+
|
173
|
+
|
174
|
+
def _build(s):
|
175
|
+
# extract a build nr from a string
|
176
|
+
if not s:
|
177
|
+
return ""
|
178
|
+
if " on " in s:
|
179
|
+
s = s.split(" on ", 1)[0]
|
180
|
+
return s.split("-")[1] if "-" in s else ""
|
181
|
+
|
182
|
+
|
183
|
+
print(f"info: {_info()}")
|
stubber/codemod/enrich.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
"""
|
2
|
-
Enrich firmware stubs by copying docstrings and parameter
|
2
|
+
Enrich firmware stubs by copying docstrings and parameter information from doc-stubs or python source code.
|
3
3
|
Both (.py or .pyi) files are supported.
|
4
4
|
"""
|
5
5
|
|
@@ -10,7 +10,6 @@ from libcst.codemod import CodemodContext, diff_code, exec_transform_with_pretty
|
|
10
10
|
from libcst.tool import _default_config # type: ignore
|
11
11
|
from loguru import logger as log
|
12
12
|
|
13
|
-
# from stubber.codemod.merge_docstub import MergeCommand
|
14
13
|
import stubber.codemod.merge_docstub as merge_docstub
|
15
14
|
from stubber.utils.post import run_black
|
16
15
|
|
@@ -20,14 +19,16 @@ from stubber.utils.post import run_black
|
|
20
19
|
#########################################################################################
|
21
20
|
|
22
21
|
|
23
|
-
def enrich_file(
|
22
|
+
def enrich_file(
|
23
|
+
target_path: Path, docstub_path: Path, diff: bool = False, write_back: bool = False
|
24
|
+
) -> Optional[str]:
|
24
25
|
"""
|
25
26
|
Enrich a firmware stubs using the doc-stubs in another folder.
|
26
27
|
Both (.py or .pyi) files are supported.
|
27
28
|
|
28
29
|
Parameters:
|
29
30
|
source_path: the path to the firmware stub to enrich
|
30
|
-
docstub_path: the path to the folder
|
31
|
+
docstub_path: the path to the folder containing the doc-stubs
|
31
32
|
diff: if True, return the diff between the original and the enriched source file
|
32
33
|
write_back: if True, write the enriched source file back to the source_path
|
33
34
|
|
@@ -43,10 +44,13 @@ def enrich_file(target_path: Path, docstub_path: Path, diff: bool = False, write
|
|
43
44
|
for ext in [".py", ".pyi"]:
|
44
45
|
candidates = list(docstub_path.rglob(target_path.stem + ext))
|
45
46
|
if target_path.stem[0].lower() == "u":
|
46
|
-
# also look for candidates without leading u
|
47
|
+
# also look for candidates without leading u ( usys.py <- sys.py)
|
48
|
+
candidates += list(docstub_path.rglob(target_path.stem[1:] + ext))
|
49
|
+
elif target_path.stem[0] == "_":
|
50
|
+
# also look for candidates without leading _ ( _rp2.py <- rp2.py )
|
47
51
|
candidates += list(docstub_path.rglob(target_path.stem[1:] + ext))
|
48
52
|
else:
|
49
|
-
# also look for candidates with leading u
|
53
|
+
# also look for candidates with leading u ( sys.py <- usys.py)
|
50
54
|
candidates += list(docstub_path.rglob("u" + target_path.stem + ext))
|
51
55
|
|
52
56
|
for docstub_file in candidates:
|
@@ -54,18 +58,18 @@ def enrich_file(target_path: Path, docstub_path: Path, diff: bool = False, write
|
|
54
58
|
break
|
55
59
|
else:
|
56
60
|
docstub_file = None
|
57
|
-
if docstub_file
|
61
|
+
if not docstub_file:
|
58
62
|
raise FileNotFoundError(f"No doc-stub file found for {target_path}")
|
59
63
|
|
60
64
|
log.debug(f"Merge {target_path} from {docstub_file}")
|
61
65
|
# read source file
|
62
|
-
|
66
|
+
old_code = target_path.read_text()
|
63
67
|
|
64
68
|
codemod_instance = merge_docstub.MergeCommand(context, stub_file=docstub_file)
|
65
69
|
if not (
|
66
|
-
|
70
|
+
new_code := exec_transform_with_prettyprint(
|
67
71
|
codemod_instance,
|
68
|
-
|
72
|
+
old_code,
|
69
73
|
# include_generated=False,
|
70
74
|
generated_code_marker=config["generated_code_marker"],
|
71
75
|
# format_code=not args.no_format,
|
@@ -77,21 +81,29 @@ def enrich_file(target_path: Path, docstub_path: Path, diff: bool = False, write
|
|
77
81
|
if write_back:
|
78
82
|
log.trace(f"Write back enriched file {target_path}")
|
79
83
|
# write updated code to file
|
80
|
-
target_path.write_text(
|
81
|
-
return diff_code(
|
84
|
+
target_path.write_text(new_code, encoding="utf-8")
|
85
|
+
return diff_code(old_code, new_code, 5, filename=target_path.name) if diff else new_code
|
82
86
|
|
83
87
|
|
84
88
|
def enrich_folder(
|
85
|
-
|
89
|
+
source_path: Path,
|
90
|
+
docstub_path: Path,
|
91
|
+
show_diff: bool = False,
|
92
|
+
write_back: bool = False,
|
93
|
+
require_docstub: bool = False,
|
86
94
|
) -> int:
|
87
95
|
"""\
|
88
96
|
Enrich a folder with containing firmware stubs using the doc-stubs in another folder.
|
89
97
|
|
90
98
|
Returns the number of files enriched.
|
91
99
|
"""
|
100
|
+
if not source_path.exists():
|
101
|
+
raise FileNotFoundError(f"Source folder {source_path} does not exist")
|
102
|
+
if not docstub_path.exists():
|
103
|
+
raise FileNotFoundError(f"Docstub folder {docstub_path} does not exist")
|
92
104
|
count = 0
|
93
105
|
# list all the .py and .pyi files in the source folder
|
94
|
-
source_files = sorted(list(
|
106
|
+
source_files = sorted(list(source_path.rglob("**/*.py")) + list(source_path.rglob("**/*.pyi")))
|
95
107
|
for source_file in source_files:
|
96
108
|
try:
|
97
109
|
diff = enrich_file(source_file, docstub_path, diff=True, write_back=write_back)
|
@@ -104,7 +116,7 @@ def enrich_folder(
|
|
104
116
|
if require_docstub:
|
105
117
|
raise (FileNotFoundError(f"No doc-stub file found for {source_file}")) from e
|
106
118
|
# run black on the destination folder
|
107
|
-
|
108
|
-
|
119
|
+
run_black(source_path)
|
120
|
+
# DO NOT run Autoflake as this removes some relevant (unused) imports
|
109
121
|
|
110
122
|
return count
|
stubber/commands/build_cmd.py
CHANGED
@@ -7,7 +7,7 @@ from loguru import logger as log
|
|
7
7
|
from tabulate import tabulate
|
8
8
|
|
9
9
|
from stubber.commands.cli import stubber_cli
|
10
|
-
from stubber.publish.
|
10
|
+
from stubber.publish.defaults import GENERIC_U
|
11
11
|
from stubber.publish.publish import build_multiple
|
12
12
|
from stubber.utils.config import CONFIG
|
13
13
|
|
@@ -29,7 +29,7 @@ from stubber.utils.config import CONFIG
|
|
29
29
|
"-p",
|
30
30
|
"ports",
|
31
31
|
multiple=True,
|
32
|
-
default=["
|
32
|
+
default=["all"],
|
33
33
|
show_default=True,
|
34
34
|
help="multiple: ",
|
35
35
|
)
|
@@ -38,7 +38,7 @@ from stubber.utils.config import CONFIG
|
|
38
38
|
"-b",
|
39
39
|
"boards",
|
40
40
|
multiple=True,
|
41
|
-
default=[GENERIC_U], # or "
|
41
|
+
default=[GENERIC_U], # or "all" ?
|
42
42
|
show_default=True,
|
43
43
|
help="multiple: ",
|
44
44
|
)
|