micropython-stubber 1.15.0__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.
@@ -1,23 +1,24 @@
1
- w='pyb'
2
- v='{}/{}'
3
- u='logging'
4
- t='sys'
5
- s='method'
6
- r='function'
7
- q='bool'
8
- p='str'
9
- o='float'
10
- n='int'
11
- m='port'
12
- l=NameError
13
- k=sorted
14
- j=NotImplementedError
15
- b='pycom'
16
- a=',\n'
17
- Z='dict'
18
- Y='list'
19
- X='tuple'
20
- W='micropython'
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 c
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 d
46
- except N:from ucollections import OrderedDict as d
47
- __version__='v1.15.0'
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=[K,'/lib','/sd/lib','/flash/lib','lib']
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 j('MicroPython 1.13.0 cannot be stubbed')
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[m]));J('Board: {}'.format(A.info[I]));C.collect()
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]==W:A._fwid='{family}-{ver}-{port}-{board}'.format(**A.info)
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:e(path+G)
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{n,o,p,q,X,Y,Z}:G=1
79
- elif F in{r,s}:G=2
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=k([A for A in D if not A[0].startswith('__')],key=lambda x:x[4]);C.collect();return D,J
86
- def add_modules(A,modules):A.modules=k(set(A.modules)|set(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
- e(H)
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',t,u,'gc'}:
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)<=y*4:
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,r,'closure'])):
130
- W=b;a=B
131
- if P>0:a='self, '
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,a,W)
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[p,n,o,q,'bytearray','bytes']:A=d.format(D,E,K,I)
139
- elif I in[Z,Y,X]:e={Z:'{}',Y:'[]',X:'()'};A=d.format(D,E,e[I],I)
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,l):pass
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=v.format(path,D)
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=v.format(B.path,filename);C.collect()
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(c({A:B.info})[1:-1]);f.write(a);f.write(c({'stubber':{D:__version__},'stubtype':A})[1:-1]);f.write(a);f.write('"modules" :[\n')
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(a)
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 e(path):
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]==x:
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';h='pycopy';e='GENERIC';c='arch';a='cpu';Z='ver';V='with';G='mpy';F='build';A=d({L:sys.implementation.name,D:B,F:B,Z:B,m:'stm32'if sys.platform.startswith(w)else sys.platform,I:e,a:B,G:B,c:B})
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:X=sys.implementation._machine if'_machine'in O(sys.implementation)else os.uname().machine;A[I]=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
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 z]:
203
- if g(M):
203
+ for M in [A+'/board_info.csv'for A in A0]:
204
+ if h(M):
204
205
  J=A[I].strip()
205
- if f(A,J,M):break
206
+ if g(A,J,M):break
206
207
  if V in J:
207
208
  J=J.split(V)[0].strip()
208
- if f(A,J,M):break
209
- A[I]=e
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,n) in [(h,h,'const'),(b,b,'FAT'),(i,'pybricks.hubs','EV3Brick')]:
221
- try:o=__import__(l,E,E,n);A[L]=k;del o;break
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]==W:
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[c]=Y
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 f(info,board_descr,filename):
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 g(filename):
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 h():sys.exit(1)
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:h()
259
- elif R(sys.argv)==2:h()
259
+ else:i()
260
+ elif R(sys.argv)==2:i()
260
261
  return path
261
- def i():
262
- try:B=bytes('abc',encoding='utf8');C=i.__module__;return A
263
- except (j,H):return M
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',u,'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',t,'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()
265
- if __name__=='__main__'or i():
266
- try:logging.basicConfig(level=logging.INFO)
267
- except l:pass
268
- if not g('no_auto_stubber.txt'):
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/minify.py CHANGED
@@ -80,17 +80,17 @@ def edit_lines(content: str, edits: LineEdits, diff: bool = False):
80
80
  """Handles edits that require multiline comments
81
81
 
82
82
  Example:
83
- self._log.debug("info: {} {}".format(
83
+ self.log.debug("info: {} {}".format(
84
84
  1,
85
85
  2
86
86
  ))
87
- Here, only commenting out the first self._log line will raise
87
+ Here, only commenting out the first self.log line will raise
88
88
  an error. So this function returns all lines that need to
89
89
  be commented out instead.
90
90
 
91
91
  It also checks for situations such as this:
92
92
  if condition:
93
- self._log.debug('message')
93
+ self.log.debug('message')
94
94
 
95
95
  Here, since the only functionality of the conditional is the call log,
96
96
  both lines would be returned to comment out.
@@ -129,9 +129,9 @@ def edit_lines(content: str, edits: LineEdits, diff: bool = False):
129
129
  try:
130
130
  something()
131
131
  except:
132
- self._log.debug('some message')
132
+ self.log.debug('some message')
133
133
 
134
- Simply removing the self._log call would create a syntax error,
134
+ Simply removing the self.log call would create a syntax error,
135
135
  which is what this function checks for.
136
136
 
137
137
  """
@@ -214,33 +214,33 @@ def minify_script(source_script: StubSource, keep_report: bool = True, diff: boo
214
214
  ("comment", "import logging"),
215
215
  # report keepers may be inserted here
216
216
  # do report errors
217
- ("rprint", "self._log.error"),
218
- ("rprint", "_log.error"),
217
+ ("rprint", "self.log.error"),
218
+ ("rprint", "log.error"),
219
219
  ]
220
220
  if keep_report:
221
221
  # insert report keepers after the comment modifiers
222
222
  edits += [
223
223
  # keepers
224
- ("rprint", 'self._log.info("Stub module: '),
225
- ("rprint", 'self._log.warning("{}Skip module:'),
226
- ("rprint", 'self._log.info("Clean/remove files in folder:'),
227
- ("rprint", 'self._log.info("Created stubs for'),
228
- ("rprint", 'self._log.info("Family: '),
229
- ("rprint", 'self._log.info("Version: '),
230
- ("rprint", 'self._log.info("Port: '),
231
- ("rprint", 'self._log.info("Board: '),
224
+ ("rprint", 'self.log.info("Stub module: '),
225
+ ("rprint", 'self.log.warning("{}Skip module:'),
226
+ ("rprint", 'self.log.info("Clean/remove files in folder:'),
227
+ ("rprint", 'self.log.info("Created stubs for'),
228
+ ("rprint", 'self.log.info("Family: '),
229
+ ("rprint", 'self.log.info("Version: '),
230
+ ("rprint", 'self.log.info("Port: '),
231
+ ("rprint", 'self.log.info("Board: '),
232
232
  # all others
233
- ("comment", "self._log."),
233
+ ("comment", "self.log."),
234
234
  ("comment", "_log ="),
235
235
  ]
236
236
  else:
237
237
  edits += [
238
238
  # remove first full
239
- ("comment", "self._log ="),
240
- ("comment", "self._log("),
241
- ("comment", "self._log.debug"),
242
- ("comment", "self._log.info"),
243
- ("comment", "self._log.warning"),
239
+ ("comment", "self.log ="),
240
+ ("comment", "self.log("),
241
+ ("comment", "self.log.debug"),
242
+ ("comment", "self.log.info"),
243
+ ("comment", "self.log.warning"),
244
244
  # then short versions
245
245
  ("comment", "_log ="),
246
246
  ("comment", "_log.debug"),
@@ -342,15 +342,15 @@ def cross_compile(
342
342
  # target must be a Path object
343
343
  _target = get_temp_file(suffix=".mpy")
344
344
 
345
- cmd = ["pipx", "run", f"mpy-cross=={version}"] if version else ["pipx", "run", "mpy-cross"]
346
- # Add params
347
- cmd += ["-O2", str(source_file), "-o", str(_target), "-s", "createstubs.py"]
348
- log.trace(" ".join(cmd))
349
- result = subprocess.run(cmd, capture_output=True, text=True)
345
+ result = pipx_mpy_cross(version, source_file, _target)
346
+ if result.stderr and "No matching distribution found for mpy-cross==" in result.stderr:
347
+ log.warning(f"mpy-cross=={version} not found, using latest")
348
+ result = pipx_mpy_cross("latest", source_file, _target)
349
+
350
350
  if result.returncode == 0:
351
351
  log.debug(f"mpy-cross compiled to : {_target.name}")
352
352
  else:
353
- log.error("mpy-cross failed to compile:")
353
+ log.error(f"mpy-cross failed to compile:{result.returncode} \n{result.stderr}")
354
354
 
355
355
  if isinstance(target, BytesIO):
356
356
  # copy the byte contents of the temp file to the target file-like object
@@ -361,6 +361,21 @@ def cross_compile(
361
361
  return result.returncode
362
362
 
363
363
 
364
+ def pipx_mpy_cross(version, source_file, _target):
365
+ """Run mpy-cross using pipx"""
366
+ if version == "latest":
367
+ version = ""
368
+ if version:
369
+ version = "==" + version
370
+
371
+ cmd = ["pipx", "run", f"mpy-cross{version}"] if version else ["pipx", "run", "mpy-cross"]
372
+ # Add params
373
+ cmd += ["-O2", str(source_file), "-o", str(_target), "-s", "createstubs.py"]
374
+ log.trace(" ".join(cmd))
375
+ result = subprocess.run(cmd, capture_output=True, text=True)
376
+ return result
377
+
378
+
364
379
  def write_to_temp_file(source: str):
365
380
  """Writes a string to a temp file and returns the Path object"""
366
381
  _, temp_file = tempfile.mkstemp(suffix=".py", prefix="mpy_cross_")
@@ -318,7 +318,8 @@ class StubPackage:
318
318
  if (CONFIG.stub_path / fw_path).exists():
319
319
  updated_sources.append((stub_type, fw_path))
320
320
  else:
321
- updated_sources.append((stub_type, fw_path.with_name("GENERIC")))
321
+ if fw_path.with_name("GENERIC").exists():
322
+ updated_sources.append((stub_type, fw_path.with_name("GENERIC")))
322
323
  elif stub_type == StubSource.MERGED:
323
324
  # Use the default board folder instead of the GENERIC board folder (if it exists)
324
325
  if self.board.upper() == GENERIC_U:
stubber/rst/lookup.py CHANGED
@@ -20,7 +20,7 @@ __all__ = [
20
20
 
21
21
  # all possible Types needed for the stubs - exxess types should be removed later , and otherwise won't do much harm
22
22
  TYPING_IMPORT: List[str] = [
23
- "from typing import IO, Any, Callable, Coroutine, Dict, Generator, Iterator, List, NoReturn, Optional, Tuple, Union, NamedTuple, TypeVar, Iterator",
23
+ "from typing import IO, Any, Callable, Coroutine, Dict, Generator, Iterator, List, NoReturn, Optional, Tuple, Union, NamedTuple, TypeVar",
24
24
  "from _typeshed import Incomplete",
25
25
  ]
26
26