micropython-stubber 1.16.3__py3-none-any.whl → 1.17.0__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.16.3.dist-info → micropython_stubber-1.17.0.dist-info}/METADATA +1 -1
- {micropython_stubber-1.16.3.dist-info → micropython_stubber-1.17.0.dist-info}/RECORD +48 -49
- stubber/__init__.py +1 -1
- stubber/basicgit.py +11 -13
- stubber/board/createstubs.py +138 -97
- stubber/board/createstubs_db.py +211 -239
- stubber/board/createstubs_db_min.py +322 -844
- stubber/board/createstubs_db_mpy.mpy +0 -0
- stubber/board/createstubs_lvgl.py +91 -137
- stubber/board/createstubs_lvgl_min.py +87 -129
- stubber/board/createstubs_lvgl_mpy.mpy +0 -0
- stubber/board/createstubs_mem.py +164 -199
- stubber/board/createstubs_mem_min.py +297 -791
- stubber/board/createstubs_mem_mpy.mpy +0 -0
- stubber/board/createstubs_min.py +286 -1009
- stubber/board/createstubs_mpy.mpy +0 -0
- stubber/board/modulelist.txt +1 -2
- stubber/codemod/_partials/__init__.py +1 -1
- stubber/codemod/_partials/db_main.py +90 -72
- stubber/codemod/_partials/modules_reader.py +29 -17
- stubber/codemod/board.py +2 -4
- stubber/codemod/enrich.py +1 -1
- stubber/commands/build_cmd.py +6 -4
- stubber/commands/get_docstubs_cmd.py +6 -11
- stubber/commands/get_frozen_cmd.py +6 -11
- stubber/commands/switch_cmd.py +6 -4
- stubber/freeze/freeze_manifest_2.py +2 -1
- stubber/freeze/get_frozen.py +28 -13
- stubber/minify.py +51 -38
- stubber/publish/candidates.py +15 -23
- stubber/publish/defaults.py +2 -2
- stubber/publish/merge_docstubs.py +5 -7
- stubber/publish/missing_class_methods.py +2 -2
- stubber/publish/pathnames.py +2 -2
- stubber/publish/publish.py +2 -1
- stubber/publish/stubpackage.py +20 -41
- stubber/rst/lookup.py +9 -7
- stubber/rst/reader.py +2 -1
- stubber/stubber.py +5 -6
- stubber/update_fallback.py +3 -1
- stubber/utils/__init__.py +1 -1
- stubber/utils/config.py +7 -9
- stubber/utils/repos.py +6 -5
- stubber/utils/versions.py +48 -7
- stubber/variants.py +3 -3
- stubber/board/logging.py +0 -99
- {micropython_stubber-1.16.3.dist-info → micropython_stubber-1.17.0.dist-info}/LICENSE +0 -0
- {micropython_stubber-1.16.3.dist-info → micropython_stubber-1.17.0.dist-info}/WHEEL +0 -0
- {micropython_stubber-1.16.3.dist-info → micropython_stubber-1.17.0.dist-info}/entry_points.txt +0 -0
stubber/board/createstubs_db.py
CHANGED
@@ -18,12 +18,11 @@ Create stubs for (all) modules on a MicroPython board.
|
|
18
18
|
- cross compilation, using mpy-cross, to avoid the compilation step on the micropython device
|
19
19
|
|
20
20
|
|
21
|
-
This variant was generated from createstubs.py by micropython-stubber v1.
|
21
|
+
This variant was generated from createstubs.py by micropython-stubber v1.17.0
|
22
22
|
"""
|
23
23
|
# Copyright (c) 2019-2023 Jos Verlinde
|
24
24
|
|
25
25
|
import gc
|
26
|
-
import logging
|
27
26
|
import os
|
28
27
|
import sys
|
29
28
|
from time import sleep
|
@@ -43,26 +42,49 @@ try:
|
|
43
42
|
except ImportError:
|
44
43
|
from ucollections import OrderedDict # type: ignore
|
45
44
|
|
46
|
-
|
47
|
-
|
45
|
+
__version__ = "v1.17.0"
|
46
|
+
ENOENT = 2
|
47
|
+
_MAX_CLASS_LEVEL = 2 # Max class nesting
|
48
|
+
LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."]
|
48
49
|
|
49
|
-
wdt = WDT()
|
50
50
|
|
51
|
-
|
51
|
+
# our own logging module to avoid dependency on and interfering with logging module
|
52
|
+
class logging:
|
53
|
+
# DEBUG = 10
|
54
|
+
INFO = 20
|
55
|
+
WARNING = 30
|
56
|
+
ERROR = 40
|
57
|
+
level = INFO
|
58
|
+
prnt = print
|
52
59
|
|
53
|
-
|
54
|
-
|
55
|
-
|
60
|
+
@staticmethod
|
61
|
+
def getLogger(name):
|
62
|
+
return logging()
|
56
63
|
|
57
|
-
|
64
|
+
@classmethod
|
65
|
+
def basicConfig(cls, level):
|
66
|
+
cls.level = level
|
58
67
|
|
68
|
+
# def debug(self, msg):
|
69
|
+
# if self.level <= logging.DEBUG:
|
70
|
+
# self.prnt("DEBUG :", msg)
|
59
71
|
|
60
|
-
|
72
|
+
def info(self, msg):
|
73
|
+
if self.level <= logging.INFO:
|
74
|
+
self.prnt("INFO :", msg)
|
61
75
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
76
|
+
def warning(self, msg):
|
77
|
+
if self.level <= logging.WARNING:
|
78
|
+
self.prnt("WARN :", msg)
|
79
|
+
|
80
|
+
def error(self, msg):
|
81
|
+
if self.level <= logging.ERROR:
|
82
|
+
self.prnt("ERROR :", msg)
|
83
|
+
|
84
|
+
|
85
|
+
log = logging.getLogger("stubber")
|
86
|
+
logging.basicConfig(level=logging.INFO)
|
87
|
+
# logging.basicConfig(level=logging.DEBUG)
|
66
88
|
|
67
89
|
|
68
90
|
class Stubber:
|
@@ -74,13 +96,10 @@ class Stubber:
|
|
74
96
|
raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed")
|
75
97
|
except AttributeError:
|
76
98
|
pass
|
77
|
-
self.log = logging.getLogger("stubber")
|
78
|
-
self._report = [] # type: list[str]
|
79
99
|
self.info = _info()
|
80
|
-
|
81
|
-
|
100
|
+
log.info("Port: {}".format(self.info["port"]))
|
101
|
+
log.info("Board: {}".format(self.info["board"]))
|
82
102
|
gc.collect()
|
83
|
-
wdt.feed()
|
84
103
|
if firmware_id:
|
85
104
|
self._fwid = firmware_id.lower()
|
86
105
|
else:
|
@@ -97,11 +116,11 @@ class Stubber:
|
|
97
116
|
path = get_root()
|
98
117
|
|
99
118
|
self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/")
|
100
|
-
|
119
|
+
# log.debug(self.path)
|
101
120
|
try:
|
102
121
|
ensure_folder(path + "/")
|
103
122
|
except OSError:
|
104
|
-
|
123
|
+
log.error("error creating stub folder {}".format(path))
|
105
124
|
self.problematic = [
|
106
125
|
"upip",
|
107
126
|
"upysh",
|
@@ -120,21 +139,23 @@ class Stubber:
|
|
120
139
|
]
|
121
140
|
# there is no option to discover modules from micropython, list is read from an external file.
|
122
141
|
self.modules = [] # type: list[str]
|
142
|
+
self._json_name = None
|
143
|
+
self._json_first = False
|
123
144
|
|
124
145
|
def get_obj_attributes(self, item_instance: object):
|
125
146
|
"extract information of the objects members and attributes"
|
126
147
|
# name_, repr_(value), type as text, item_instance
|
127
148
|
_result = []
|
128
149
|
_errors = []
|
129
|
-
|
150
|
+
# log.debug("get attributes {} {}".format(repr(item_instance), item_instance))
|
130
151
|
for name in dir(item_instance):
|
131
|
-
if name.startswith("
|
152
|
+
if name.startswith("__") and not name in self.modules:
|
132
153
|
continue
|
133
|
-
|
154
|
+
# log.debug("get attribute {}".format(name))
|
134
155
|
try:
|
135
156
|
val = getattr(item_instance, name)
|
136
157
|
# name , item_repr(value) , type as text, item_instance, order
|
137
|
-
|
158
|
+
# log.debug("attribute {}:{}".format(name, val))
|
138
159
|
try:
|
139
160
|
type_text = repr(type(val)).split("'")[1]
|
140
161
|
except IndexError:
|
@@ -167,22 +188,23 @@ class Stubber:
|
|
167
188
|
|
168
189
|
def create_all_stubs(self):
|
169
190
|
"Create stubs for all configured modules"
|
170
|
-
|
191
|
+
log.info("Start micropython-stubber {} on {}".format(__version__, self._fwid))
|
192
|
+
self.report_start()
|
171
193
|
gc.collect()
|
172
194
|
for module_name in self.modules:
|
173
195
|
self.create_one_stub(module_name)
|
174
|
-
self.
|
196
|
+
self.report_end()
|
197
|
+
log.info("Finally done")
|
175
198
|
|
176
199
|
def create_one_stub(self, module_name: str):
|
177
|
-
wdt.feed()
|
178
200
|
if module_name in self.problematic:
|
179
|
-
|
201
|
+
log.warning("Skip module: {:<25} : Known problematic".format(module_name))
|
180
202
|
return False
|
181
203
|
if module_name in self.excluded:
|
182
|
-
|
204
|
+
log.warning("Skip module: {:<25} : Excluded".format(module_name))
|
183
205
|
return False
|
184
206
|
|
185
|
-
file_name = "{}/{}.
|
207
|
+
file_name = "{}/{}.pyi".format(self.path, module_name.replace(".", "/"))
|
186
208
|
gc.collect()
|
187
209
|
result = False
|
188
210
|
try:
|
@@ -197,10 +219,10 @@ class Stubber:
|
|
197
219
|
|
198
220
|
Args:
|
199
221
|
- module_name (str): name of the module to document. This module will be imported.
|
200
|
-
- file_name (Optional[str]): the 'path/filename.
|
222
|
+
- file_name (Optional[str]): the 'path/filename.pyi' to write to. If omitted will be created based on the module name.
|
201
223
|
"""
|
202
224
|
if file_name is None:
|
203
|
-
fname = module_name.replace(".", "_") + ".
|
225
|
+
fname = module_name.replace(".", "_") + ".pyi"
|
204
226
|
file_name = self.path + "/" + fname
|
205
227
|
else:
|
206
228
|
fname = file_name.split("/")[-1]
|
@@ -214,10 +236,10 @@ class Stubber:
|
|
214
236
|
try:
|
215
237
|
new_module = __import__(module_name, None, None, ("*"))
|
216
238
|
m1 = gc.mem_free() # type: ignore
|
217
|
-
|
239
|
+
log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1))
|
218
240
|
|
219
241
|
except ImportError:
|
220
|
-
|
242
|
+
# log.debug("Skip module: {:<25} {:<79}".format(module_name, "Module not found."))
|
221
243
|
return False
|
222
244
|
|
223
245
|
# Start a new file
|
@@ -227,22 +249,18 @@ class Stubber:
|
|
227
249
|
info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}")
|
228
250
|
s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__)
|
229
251
|
fp.write(s)
|
230
|
-
fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n")
|
252
|
+
fp.write("from __future__ import annotations\nfrom typing import Any, Generator\nfrom _typeshed import Incomplete\n\n")
|
231
253
|
self.write_object_stub(fp, new_module, module_name, "")
|
232
254
|
|
233
|
-
self.
|
255
|
+
self.report_add(module_name, file_name)
|
234
256
|
|
235
257
|
if module_name not in {"os", "sys", "logging", "gc"}:
|
236
258
|
# try to unload the module unless we use it
|
237
259
|
try:
|
238
260
|
del new_module
|
239
261
|
except (OSError, KeyError): # lgtm [py/unreachable-statement]
|
240
|
-
|
241
|
-
#
|
242
|
-
# try:
|
243
|
-
# del sys.modules[module_name]
|
244
|
-
# except KeyError:
|
245
|
-
# self.log.warning("could not del sys.modules[{}]".format(module_name))
|
262
|
+
log.warning("could not del new_module")
|
263
|
+
# do not try to delete from sys.modules - most times it does not work anyway
|
246
264
|
gc.collect()
|
247
265
|
return True
|
248
266
|
|
@@ -250,14 +268,14 @@ class Stubber:
|
|
250
268
|
"Write a module/object stub to an open file. Can be called recursive."
|
251
269
|
gc.collect()
|
252
270
|
if object_expr in self.problematic:
|
253
|
-
|
271
|
+
log.warning("SKIPPING problematic module:{}".format(object_expr))
|
254
272
|
return
|
255
273
|
|
256
|
-
#
|
274
|
+
# # log.debug("DUMP : {}".format(object_expr))
|
257
275
|
items, errors = self.get_obj_attributes(object_expr)
|
258
276
|
|
259
277
|
if errors:
|
260
|
-
|
278
|
+
log.error(errors)
|
261
279
|
|
262
280
|
for item_name, item_repr, item_type_txt, item_instance, _ in items:
|
263
281
|
# name_, repr_(value), type as text, item_instance, order
|
@@ -265,7 +283,7 @@ class Stubber:
|
|
265
283
|
# do not create stubs for these primitives
|
266
284
|
continue
|
267
285
|
if item_name[0].isdigit():
|
268
|
-
|
286
|
+
log.warning("NameError: invalid name {}".format(item_name))
|
269
287
|
continue
|
270
288
|
# Class expansion only on first 3 levels (bit of a hack)
|
271
289
|
if (
|
@@ -274,7 +292,7 @@ class Stubber:
|
|
274
292
|
# and not obj_name.endswith(".Pin")
|
275
293
|
# avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms
|
276
294
|
):
|
277
|
-
|
295
|
+
# log.debug("{0}class {1}:".format(indent, item_name))
|
278
296
|
superclass = ""
|
279
297
|
is_exception = (
|
280
298
|
item_name.endswith("Exception")
|
@@ -297,7 +315,7 @@ class Stubber:
|
|
297
315
|
# write classdef
|
298
316
|
fp.write(s)
|
299
317
|
# first write the class literals and methods
|
300
|
-
|
318
|
+
# log.debug("# recursion over class {0}".format(item_name))
|
301
319
|
self.write_object_stub(
|
302
320
|
fp,
|
303
321
|
item_instance,
|
@@ -311,7 +329,7 @@ class Stubber:
|
|
311
329
|
s += indent + " ...\n\n"
|
312
330
|
fp.write(s)
|
313
331
|
elif any(word in item_type_txt for word in ["method", "function", "closure"]):
|
314
|
-
|
332
|
+
# log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name))
|
315
333
|
# module Function or class method
|
316
334
|
# will accept any number of params
|
317
335
|
# return type Any/Incomplete
|
@@ -327,7 +345,7 @@ class Stubber:
|
|
327
345
|
s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret)
|
328
346
|
s += indent + " ...\n\n"
|
329
347
|
fp.write(s)
|
330
|
-
|
348
|
+
# log.debug("\n" + s)
|
331
349
|
elif item_type_txt == "<class 'module'>":
|
332
350
|
# Skip imported modules
|
333
351
|
# fp.write("# import {}\n".format(item_name))
|
@@ -337,28 +355,32 @@ class Stubber:
|
|
337
355
|
t = item_type_txt[8:-2]
|
338
356
|
s = ""
|
339
357
|
|
340
|
-
if t in
|
358
|
+
if t in ("str", "int", "float", "bool", "bytearray", "bytes"):
|
341
359
|
# known type: use actual value
|
342
|
-
s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t)
|
343
|
-
|
360
|
+
# s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, item_repr, t)
|
361
|
+
s = "{0}{1}: {3} = {2}\n".format(indent, item_name, item_repr, t)
|
362
|
+
elif t in ("dict", "list", "tuple"):
|
344
363
|
# dict, list , tuple: use empty value
|
345
364
|
ev = {"dict": "{}", "list": "[]", "tuple": "()"}
|
346
|
-
s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t)
|
365
|
+
# s = "{0}{1} = {2} # type: {3}\n".format(indent, item_name, ev[t], t)
|
366
|
+
s = "{0}{1}: {3} = {2}\n".format(indent, item_name, ev[t], t)
|
347
367
|
else:
|
348
368
|
# something else
|
349
|
-
if t in
|
369
|
+
if t in ("object", "set", "frozenset", "Pin", "generator"): # "FileIO"
|
350
370
|
# https://docs.python.org/3/tutorial/classes.html#item_instance-objects
|
351
|
-
#
|
352
|
-
|
371
|
+
# use these types for the attribute
|
372
|
+
if t == "generator":
|
373
|
+
t = "Generator"
|
374
|
+
s = "{0}{1}: {2} ## = {4}\n".format(indent, item_name, t, item_type_txt, item_repr)
|
353
375
|
else:
|
354
376
|
# Requires Python 3.6 syntax, which is OK for the stubs/pyi
|
355
377
|
t = "Incomplete"
|
356
|
-
s = "{0}{1}
|
378
|
+
s = "{0}{1}: {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr)
|
357
379
|
fp.write(s)
|
358
|
-
|
380
|
+
# log.debug("\n" + s)
|
359
381
|
else:
|
360
382
|
# keep only the name
|
361
|
-
|
383
|
+
# log.debug("# all other, type = '{0}'".format(item_type_txt))
|
362
384
|
fp.write("# all other, type = '{0}'\n".format(item_type_txt))
|
363
385
|
|
364
386
|
fp.write(indent + item_name + " # type: Incomplete\n")
|
@@ -382,10 +404,9 @@ class Stubber:
|
|
382
404
|
|
383
405
|
def clean(self, path: str = None): # type: ignore
|
384
406
|
"Remove all files from the stub folder"
|
385
|
-
wdt.feed()
|
386
407
|
if path is None:
|
387
408
|
path = self.path
|
388
|
-
|
409
|
+
log.info("Clean/remove files in folder: {}".format(path))
|
389
410
|
try:
|
390
411
|
os.stat(path) # TEMP workaround mpremote listdir bug -
|
391
412
|
items = os.listdir(path)
|
@@ -403,42 +424,53 @@ class Stubber:
|
|
403
424
|
except OSError:
|
404
425
|
pass
|
405
426
|
|
406
|
-
def
|
407
|
-
"
|
408
|
-
|
409
|
-
self.
|
410
|
-
|
411
|
-
self.
|
427
|
+
def report_start(self, filename: str = "modules.json"):
|
428
|
+
"""Start a report of the modules that have been stubbed
|
429
|
+
"create json with list of exported modules"""
|
430
|
+
self._json_name = "{}/{}".format(self.path, filename)
|
431
|
+
self._json_first = True
|
432
|
+
ensure_folder(self._json_name)
|
433
|
+
log.info("Report file: {}".format(self._json_name))
|
412
434
|
gc.collect()
|
413
435
|
try:
|
414
436
|
# write json by node to reduce memory requirements
|
415
|
-
with open(
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
self.
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
437
|
+
with open(self._json_name, "w") as f:
|
438
|
+
f.write("{")
|
439
|
+
f.write(dumps({"firmware": self.info})[1:-1])
|
440
|
+
f.write(",\n")
|
441
|
+
f.write(dumps({"stubber": {"version": __version__}, "stubtype": "firmware"})[1:-1])
|
442
|
+
f.write(",\n")
|
443
|
+
f.write('"modules" :[\n')
|
444
|
+
|
445
|
+
except OSError as e:
|
446
|
+
log.error("Failed to create the report.")
|
447
|
+
self._json_name = None
|
448
|
+
raise e
|
449
|
+
|
450
|
+
def report_add(self, module_name: str, stub_file: str):
|
451
|
+
"Add a module to the report"
|
452
|
+
# write json by node to reduce memory requirements
|
453
|
+
if not self._json_name:
|
454
|
+
raise Exception("No report file")
|
455
|
+
try:
|
456
|
+
with open(self._json_name, "a") as f:
|
457
|
+
if not self._json_first:
|
458
|
+
f.write(",\n")
|
459
|
+
else:
|
460
|
+
self._json_first = False
|
461
|
+
line = '{{"module": "{}", "file": "{}"}}'.format(module_name, stub_file.replace("\\", "/"))
|
462
|
+
f.write(line)
|
434
463
|
|
435
|
-
|
436
|
-
|
437
|
-
f.write(",\n")
|
438
|
-
f.write(n)
|
464
|
+
except OSError:
|
465
|
+
log.error("Failed to create the report.")
|
439
466
|
|
440
|
-
def
|
441
|
-
|
467
|
+
def report_end(self):
|
468
|
+
if not self._json_name:
|
469
|
+
raise Exception("No report file")
|
470
|
+
with open(self._json_name, "a") as f:
|
471
|
+
f.write("\n]}")
|
472
|
+
# is used as sucess indicator
|
473
|
+
log.info("Path: {}".format(self.path))
|
442
474
|
|
443
475
|
|
444
476
|
def ensure_folder(path: str):
|
@@ -484,7 +516,7 @@ def _build(s):
|
|
484
516
|
def _info(): # type:() -> dict[str, str]
|
485
517
|
info = OrderedDict(
|
486
518
|
{
|
487
|
-
"family": sys.implementation.name,
|
519
|
+
"family": sys.implementation.name, # type: ignore
|
488
520
|
"version": "",
|
489
521
|
"build": "",
|
490
522
|
"ver": "",
|
@@ -512,9 +544,9 @@ def _info(): # type:() -> dict[str, str]
|
|
512
544
|
info["board"] = _machine
|
513
545
|
info["cpu"] = _machine.split("with")[-1].strip()
|
514
546
|
info["mpy"] = (
|
515
|
-
sys.implementation._mpy
|
547
|
+
sys.implementation._mpy # type: ignore
|
516
548
|
if "_mpy" in dir(sys.implementation)
|
517
|
-
else sys.implementation.mpy
|
549
|
+
else sys.implementation.mpy # type: ignore
|
518
550
|
if "mpy" in dir(sys.implementation)
|
519
551
|
else ""
|
520
552
|
)
|
@@ -608,79 +640,16 @@ def version_str(version: tuple): # -> str:
|
|
608
640
|
return v_str
|
609
641
|
|
610
642
|
|
611
|
-
def
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
info["board"] = data.strip()
|
622
|
-
found = True
|
623
|
-
break
|
624
|
-
if not found:
|
625
|
-
print("Board not found, guessing board name")
|
626
|
-
descr = ""
|
627
|
-
# descr = desc or info["board"].strip()
|
628
|
-
# if "with " + info["cpu"].upper() in descr:
|
629
|
-
# # remove the with cpu part
|
630
|
-
# descr = descr.split("with " + info["cpu"].upper())[0].strip()
|
631
|
-
info["board"] = descr
|
632
|
-
|
633
|
-
|
634
|
-
# def read_boardname(info, desc: str = ""):
|
635
|
-
# wdt.feed()
|
636
|
-
# # print("look up the board name in the file", filename)
|
637
|
-
# if file_exists(filename):
|
638
|
-
# descr = desc or info["board"].strip()
|
639
|
-
# pos = descr.rfind(" with")
|
640
|
-
# if pos != -1:
|
641
|
-
# short_descr = descr[:pos].strip()
|
642
|
-
# else:
|
643
|
-
# short_descr = ""
|
644
|
-
# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr))
|
645
|
-
# if find_board(info, descr, filename, short_descr):
|
646
|
-
# found = True
|
647
|
-
# break
|
648
|
-
# if not found:
|
649
|
-
# print("Board not found, guessing board name")
|
650
|
-
# descr = desc or info["board"].strip()
|
651
|
-
# if "with " + info["cpu"].upper() in descr:
|
652
|
-
# # remove the with cpu part
|
653
|
-
# descr = descr.split("with " + info["cpu"].upper())[0].strip()
|
654
|
-
# info["board"] = descr
|
655
|
-
# info["board"] = info["board"].replace(" ", "_")
|
656
|
-
# gc.collect()
|
657
|
-
|
658
|
-
|
659
|
-
# def find_board(info: dict, descr: str, filename: str, short_descr: str):
|
660
|
-
# "Find the board in the provided board_info.csv file"
|
661
|
-
# short_hit = ""
|
662
|
-
# with open(filename, "r") as file:
|
663
|
-
# # ugly code to make testable in python and micropython
|
664
|
-
# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file)
|
665
|
-
# while 1:
|
666
|
-
# line = file.readline()
|
667
|
-
# if not line:
|
668
|
-
# break
|
669
|
-
# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip()
|
670
|
-
# if descr_ == descr:
|
671
|
-
# info["board"] = board_
|
672
|
-
# return True
|
673
|
-
# elif short_descr and descr_ == short_descr:
|
674
|
-
# if "with" in short_descr:
|
675
|
-
# # Good enough - no need to trawl the entire file
|
676
|
-
# info["board"] = board_
|
677
|
-
# return True
|
678
|
-
# # good enough if not found in the rest of the file (but slow)
|
679
|
-
# short_hit = board_
|
680
|
-
# if short_hit:
|
681
|
-
# info["board"] = short_hit
|
682
|
-
# return True
|
683
|
-
# return False
|
643
|
+
def get_boardname() -> str:
|
644
|
+
"Read the board name from the boardname.py file that may have been created upfront"
|
645
|
+
try:
|
646
|
+
from boardname import BOARDNAME # type: ignore
|
647
|
+
|
648
|
+
log.info("Found BOARDNAME: {}".format(BOARDNAME))
|
649
|
+
except ImportError:
|
650
|
+
log.warning("BOARDNAME not found")
|
651
|
+
BOARDNAME = ""
|
652
|
+
return BOARDNAME
|
684
653
|
|
685
654
|
|
686
655
|
def get_root() -> str: # sourcery skip: use-assigned-variable
|
@@ -733,10 +702,6 @@ def is_micropython() -> bool:
|
|
733
702
|
# pylint: disable=unused-variable,eval-used
|
734
703
|
try:
|
735
704
|
# either test should fail on micropython
|
736
|
-
# a) https://docs.micropython.org/en/latest/genrst/syntax.html#spaces
|
737
|
-
# Micropython : SyntaxError
|
738
|
-
# a = eval("1and 0") # lgtm [py/unused-local-variable]
|
739
|
-
# Eval blocks some minification aspects
|
740
705
|
|
741
706
|
# b) https://docs.micropython.org/en/latest/genrst/builtin_types.html#bytes-with-keywords-not-implemented
|
742
707
|
# Micropython: NotImplementedError
|
@@ -750,92 +715,99 @@ def is_micropython() -> bool:
|
|
750
715
|
return True
|
751
716
|
|
752
717
|
|
753
|
-
|
754
|
-
|
718
|
+
SKIP_FILE = "modulelist.done"
|
719
|
+
|
755
720
|
|
721
|
+
def get_modules(skip=0):
|
722
|
+
# new
|
723
|
+
for p in LIBS:
|
724
|
+
fname = p + "/modulelist.txt"
|
725
|
+
if not file_exists(fname):
|
726
|
+
continue
|
727
|
+
try:
|
728
|
+
with open(fname) as f:
|
729
|
+
i = 0
|
730
|
+
while True:
|
731
|
+
line = f.readline().strip()
|
732
|
+
if not line:
|
733
|
+
break
|
734
|
+
if len(line) > 0 and line[0] == "#":
|
735
|
+
continue
|
736
|
+
i += 1
|
737
|
+
if i < skip:
|
738
|
+
continue
|
739
|
+
yield line
|
740
|
+
break
|
741
|
+
except OSError:
|
742
|
+
pass
|
743
|
+
|
744
|
+
|
745
|
+
def write_skip(done):
|
746
|
+
# write count of modules already processed to file
|
747
|
+
with open(SKIP_FILE, "w") as f:
|
748
|
+
f.write(str(done) + "\n")
|
749
|
+
|
750
|
+
|
751
|
+
def read_skip():
|
752
|
+
# read count of modules already processed from file
|
753
|
+
done = 0
|
756
754
|
try:
|
757
|
-
|
758
|
-
|
759
|
-
print("Opened existing db")
|
755
|
+
with open(SKIP_FILE) as f:
|
756
|
+
done = int(f.readline().strip())
|
760
757
|
except OSError:
|
761
|
-
|
762
|
-
|
763
|
-
|
758
|
+
pass
|
759
|
+
return done
|
760
|
+
|
761
|
+
|
762
|
+
def main():
|
763
|
+
import machine # type: ignore
|
764
|
+
|
765
|
+
was_running = file_exists(SKIP_FILE)
|
766
|
+
if was_running:
|
767
|
+
log.info("Continue from last run")
|
768
|
+
else:
|
769
|
+
log.info("Starting new run")
|
770
|
+
# try:
|
771
|
+
# f = open("modulelist.done", "r+b")
|
772
|
+
# was_running = True
|
773
|
+
# print("Continue from last run")
|
774
|
+
# except OSError:
|
775
|
+
# f = open("modulelist.done", "w+b")
|
776
|
+
# was_running = False
|
764
777
|
stubber = Stubber(path=read_path())
|
765
778
|
|
766
779
|
# f_name = "{}/{}".format(stubber.path, "modules.json")
|
780
|
+
skip = 0
|
767
781
|
if not was_running:
|
768
782
|
# Only clean folder if this is a first run
|
769
783
|
stubber.clean()
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
# not optimal , but works on mpremote and esp8266
|
777
|
-
for line in f.read().split("\n"):
|
778
|
-
line = line.strip()
|
779
|
-
gc.collect()
|
780
|
-
if len(line) > 0:
|
781
|
-
key, value = line.split("=", 1)
|
782
|
-
modules_done[key] = value
|
783
|
-
except (OSError, SyntaxError):
|
784
|
-
pass
|
785
|
-
gc.collect()
|
786
|
-
# see if we can continue from where we left off
|
787
|
-
modules = [m for m in stubber.modules if m not in modules_done.keys()]
|
788
|
-
gc.collect()
|
789
|
-
for modulename in modules:
|
784
|
+
stubber.report_start("modules.json")
|
785
|
+
else:
|
786
|
+
skip = read_skip()
|
787
|
+
stubber._json_name = "{}/{}".format(stubber.path, "modules.json")
|
788
|
+
|
789
|
+
for modulename in get_modules(skip):
|
790
790
|
# ------------------------------------
|
791
791
|
# do epic shit
|
792
792
|
# but sometimes things fail / run out of memory and reboot
|
793
|
-
ok = False
|
794
793
|
try:
|
795
|
-
|
794
|
+
stubber.create_one_stub(modulename)
|
796
795
|
except MemoryError:
|
797
796
|
# RESET AND HOPE THAT IN THE NEXT CYCLE WE PROGRESS FURTHER
|
798
797
|
machine.reset()
|
799
798
|
# -------------------------------------
|
800
799
|
gc.collect()
|
801
|
-
modules_done[modulename] = str(stubber._report[-1] if ok else "failed")
|
802
|
-
with open("modulelist.done", "a") as f:
|
803
|
-
|
800
|
+
# modules_done[modulename] = str(stubber._report[-1] if ok else "failed")
|
801
|
+
# with open("modulelist.done", "a") as f:
|
802
|
+
# f.write("{}={}\n".format(modulename, "ok" if ok else "failed"))
|
803
|
+
skip += 1
|
804
|
+
write_skip(skip)
|
804
805
|
|
805
|
-
|
806
|
-
|
807
|
-
# stubber.write_json_end(mod_fp)
|
808
|
-
stubber._report = [v for _, v in modules_done.items() if v != "failed"]
|
809
|
-
stubber.report()
|
810
|
-
|
811
|
-
|
812
|
-
def get_modulelist(stubber):
|
813
|
-
stubber.modules = [] # avoid duplicates
|
814
|
-
for p in LIBS:
|
815
|
-
try:
|
816
|
-
with open(p + "/modulelist.txt") as f:
|
817
|
-
print("DEBUG: list of modules: " + p + "/modulelist.txt")
|
818
|
-
for line in f.read().split("\n"):
|
819
|
-
line = line.strip()
|
820
|
-
if len(line) > 0 and line[0] != "#":
|
821
|
-
stubber.modules.append(line)
|
822
|
-
gc.collect()
|
823
|
-
break
|
824
|
-
except OSError:
|
825
|
-
pass
|
826
|
-
if not stubber.modules:
|
827
|
-
stubber.modules = ["micropython"]
|
828
|
-
_log.warn("Could not find modulelist.txt, using default modules")
|
829
|
-
gc.collect()
|
806
|
+
print("All modules have been processed, Finalizing report")
|
807
|
+
stubber.report_end()
|
830
808
|
|
831
809
|
|
832
810
|
if __name__ == "__main__" or is_micropython():
|
833
|
-
try:
|
834
|
-
log = logging.getLogger("stubber")
|
835
|
-
logging.basicConfig(level=logging.INFO)
|
836
|
-
# logging.basicConfig(level=logging.DEBUG)
|
837
|
-
except NameError:
|
838
|
-
pass
|
839
811
|
if not file_exists("no_auto_stubber.txt"):
|
840
812
|
try:
|
841
813
|
gc.threshold(4 * 1024) # type: ignore
|