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
Binary file
|
@@ -3,12 +3,11 @@ Create stubs for the lvgl modules on a MicroPython board.
|
|
3
3
|
|
4
4
|
Note that the stubs can be very large, and it may be best to directly store them on an SD card if your device supports this.
|
5
5
|
|
6
|
-
This variant was generated from createstubs.py by micropython-stubber v1.16.
|
6
|
+
This variant was generated from createstubs.py by micropython-stubber v1.16.3
|
7
7
|
"""
|
8
8
|
# Copyright (c) 2019-2023 Jos Verlinde
|
9
9
|
|
10
10
|
import gc
|
11
|
-
import logging
|
12
11
|
import os
|
13
12
|
import sys
|
14
13
|
from time import sleep
|
@@ -28,26 +27,61 @@ try:
|
|
28
27
|
except ImportError:
|
29
28
|
from ucollections import OrderedDict # type: ignore
|
30
29
|
|
31
|
-
|
32
|
-
|
30
|
+
__version__ = "v1.16.3"
|
31
|
+
ENOENT = 2
|
32
|
+
_MAX_CLASS_LEVEL = 2 # Max class nesting
|
33
|
+
LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."]
|
34
|
+
|
35
|
+
|
36
|
+
# our own logging module to avoid dependency on and interfering with logging module
|
37
|
+
class logging:
|
38
|
+
DEBUG = 10
|
39
|
+
TRACE = 15
|
40
|
+
INFO = 20
|
41
|
+
WARNING = 30
|
42
|
+
ERROR = 40
|
43
|
+
CRITICAL = 50
|
44
|
+
level = INFO
|
45
|
+
prnt = print
|
46
|
+
|
47
|
+
@staticmethod
|
48
|
+
def getLogger(name):
|
49
|
+
return logging()
|
50
|
+
|
51
|
+
@classmethod
|
52
|
+
def basicConfig(cls, level):
|
53
|
+
cls.level = level
|
54
|
+
pass
|
33
55
|
|
34
|
-
|
56
|
+
def trace(self, msg):
|
57
|
+
if self.level <= logging.TRACE:
|
58
|
+
self.prnt("TRACE :", msg)
|
35
59
|
|
36
|
-
|
60
|
+
def debug(self, msg):
|
61
|
+
if self.level <= logging.DEBUG:
|
62
|
+
self.prnt("DEBUG :", msg)
|
37
63
|
|
38
|
-
|
39
|
-
|
40
|
-
|
64
|
+
def info(self, msg):
|
65
|
+
if self.level <= logging.INFO:
|
66
|
+
self.prnt("INFO :", msg)
|
41
67
|
|
42
|
-
|
68
|
+
def warning(self, msg):
|
69
|
+
if self.level <= logging.WARNING:
|
70
|
+
self.prnt("WARN :", msg)
|
43
71
|
|
72
|
+
def error(self, msg):
|
73
|
+
if self.level <= logging.ERROR:
|
74
|
+
self.prnt("ERROR :", msg)
|
44
75
|
|
45
|
-
|
76
|
+
def critical(self, msg):
|
77
|
+
if self.level <= logging.CRITICAL:
|
78
|
+
self.prnt("CRIT :", msg)
|
46
79
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
80
|
+
|
81
|
+
log = logging.getLogger("stubber")
|
82
|
+
logging.basicConfig(level=logging.INFO)
|
83
|
+
# logging.basicConfig(level=logging.TRACE)
|
84
|
+
# logging.basicConfig(level=logging.DEBUG)
|
51
85
|
|
52
86
|
|
53
87
|
class Stubber:
|
@@ -59,13 +93,11 @@ class Stubber:
|
|
59
93
|
raise NotImplementedError("MicroPython 1.13.0 cannot be stubbed")
|
60
94
|
except AttributeError:
|
61
95
|
pass
|
62
|
-
self.log = logging.getLogger("stubber")
|
63
96
|
self._report = [] # type: list[str]
|
64
97
|
self.info = _info()
|
65
|
-
|
66
|
-
|
98
|
+
log.info("Port: {}".format(self.info["port"]))
|
99
|
+
log.info("Board: {}".format(self.info["board"]))
|
67
100
|
gc.collect()
|
68
|
-
wdt.feed()
|
69
101
|
if firmware_id:
|
70
102
|
self._fwid = firmware_id.lower()
|
71
103
|
else:
|
@@ -82,11 +114,11 @@ class Stubber:
|
|
82
114
|
path = get_root()
|
83
115
|
|
84
116
|
self.path = "{}/stubs/{}".format(path, self.flat_fwid).replace("//", "/")
|
85
|
-
|
117
|
+
log.debug(self.path)
|
86
118
|
try:
|
87
119
|
ensure_folder(path + "/")
|
88
120
|
except OSError:
|
89
|
-
|
121
|
+
log.error("error creating stub folder {}".format(path))
|
90
122
|
self.problematic = [
|
91
123
|
"upip",
|
92
124
|
"upysh",
|
@@ -111,15 +143,15 @@ class Stubber:
|
|
111
143
|
# name_, repr_(value), type as text, item_instance
|
112
144
|
_result = []
|
113
145
|
_errors = []
|
114
|
-
|
146
|
+
log.debug("get attributes {} {}".format(repr(item_instance), item_instance))
|
115
147
|
for name in dir(item_instance):
|
116
148
|
if name.startswith("_") and not name in self.modules:
|
117
149
|
continue
|
118
|
-
|
150
|
+
log.debug("get attribute {}".format(name))
|
119
151
|
try:
|
120
152
|
val = getattr(item_instance, name)
|
121
153
|
# name , item_repr(value) , type as text, item_instance, order
|
122
|
-
|
154
|
+
log.debug("attribute {}:{}".format(name, val))
|
123
155
|
try:
|
124
156
|
type_text = repr(type(val)).split("'")[1]
|
125
157
|
except IndexError:
|
@@ -152,19 +184,18 @@ class Stubber:
|
|
152
184
|
|
153
185
|
def create_all_stubs(self):
|
154
186
|
"Create stubs for all configured modules"
|
155
|
-
|
187
|
+
log.info("Start micropython-stubber v{} on {}".format(__version__, self._fwid))
|
156
188
|
gc.collect()
|
157
189
|
for module_name in self.modules:
|
158
190
|
self.create_one_stub(module_name)
|
159
|
-
|
191
|
+
log.info("Finally done")
|
160
192
|
|
161
193
|
def create_one_stub(self, module_name: str):
|
162
|
-
wdt.feed()
|
163
194
|
if module_name in self.problematic:
|
164
|
-
|
195
|
+
log.warning("Skip module: {:<25} : Known problematic".format(module_name))
|
165
196
|
return False
|
166
197
|
if module_name in self.excluded:
|
167
|
-
|
198
|
+
log.warning("Skip module: {:<25} : Excluded".format(module_name))
|
168
199
|
return False
|
169
200
|
|
170
201
|
file_name = "{}/{}.py".format(self.path, module_name.replace(".", "/"))
|
@@ -199,10 +230,10 @@ class Stubber:
|
|
199
230
|
try:
|
200
231
|
new_module = __import__(module_name, None, None, ("*"))
|
201
232
|
m1 = gc.mem_free() # type: ignore
|
202
|
-
|
233
|
+
log.info("Stub module: {:<25} to file: {:<70} mem:{:>5}".format(module_name, fname, m1))
|
203
234
|
|
204
235
|
except ImportError:
|
205
|
-
|
236
|
+
log.trace("Skip module: {:<25} {:<79}".format(module_name, "Module not found."))
|
206
237
|
return False
|
207
238
|
|
208
239
|
# Start a new file
|
@@ -210,9 +241,7 @@ class Stubber:
|
|
210
241
|
with open(file_name, "w") as fp:
|
211
242
|
# todo: improve header
|
212
243
|
info_ = str(self.info).replace("OrderedDict(", "").replace("})", "}")
|
213
|
-
s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(
|
214
|
-
module_name, self._fwid, info_, __version__
|
215
|
-
)
|
244
|
+
s = '"""\nModule: \'{0}\' on {1}\n"""\n# MCU: {2}\n# Stubber: {3}\n'.format(module_name, self._fwid, info_, __version__)
|
216
245
|
fp.write(s)
|
217
246
|
fp.write("from __future__ import annotations\nfrom typing import Any\nfrom _typeshed import Incomplete\n\n")
|
218
247
|
self.write_object_stub(fp, new_module, module_name, "")
|
@@ -224,12 +253,12 @@ class Stubber:
|
|
224
253
|
try:
|
225
254
|
del new_module
|
226
255
|
except (OSError, KeyError): # lgtm [py/unreachable-statement]
|
227
|
-
|
256
|
+
log.warning("could not del new_module")
|
228
257
|
# lets not try - most times it does not work anyway
|
229
258
|
# try:
|
230
259
|
# del sys.modules[module_name]
|
231
260
|
# except KeyError:
|
232
|
-
#
|
261
|
+
# log.warning("could not del sys.modules[{}]".format(module_name))
|
233
262
|
gc.collect()
|
234
263
|
return True
|
235
264
|
|
@@ -237,14 +266,14 @@ class Stubber:
|
|
237
266
|
"Write a module/object stub to an open file. Can be called recursive."
|
238
267
|
gc.collect()
|
239
268
|
if object_expr in self.problematic:
|
240
|
-
|
269
|
+
log.warning("SKIPPING problematic module:{}".format(object_expr))
|
241
270
|
return
|
242
271
|
|
243
|
-
#
|
272
|
+
# log.debug("DUMP : {}".format(object_expr))
|
244
273
|
items, errors = self.get_obj_attributes(object_expr)
|
245
274
|
|
246
275
|
if errors:
|
247
|
-
|
276
|
+
log.error(errors)
|
248
277
|
|
249
278
|
for item_name, item_repr, item_type_txt, item_instance, _ in items:
|
250
279
|
# name_, repr_(value), type as text, item_instance, order
|
@@ -252,7 +281,7 @@ class Stubber:
|
|
252
281
|
# do not create stubs for these primitives
|
253
282
|
continue
|
254
283
|
if item_name[0].isdigit():
|
255
|
-
|
284
|
+
log.warning("NameError: invalid name {}".format(item_name))
|
256
285
|
continue
|
257
286
|
# Class expansion only on first 3 levels (bit of a hack)
|
258
287
|
if (
|
@@ -261,7 +290,7 @@ class Stubber:
|
|
261
290
|
# and not obj_name.endswith(".Pin")
|
262
291
|
# avoid expansion of Pin.cpu / Pin.board to avoid crashes on most platforms
|
263
292
|
):
|
264
|
-
|
293
|
+
log.trace("{0}class {1}:".format(indent, item_name))
|
265
294
|
superclass = ""
|
266
295
|
is_exception = (
|
267
296
|
item_name.endswith("Exception")
|
@@ -284,7 +313,7 @@ class Stubber:
|
|
284
313
|
# write classdef
|
285
314
|
fp.write(s)
|
286
315
|
# first write the class literals and methods
|
287
|
-
|
316
|
+
log.debug("# recursion over class {0}".format(item_name))
|
288
317
|
self.write_object_stub(
|
289
318
|
fp,
|
290
319
|
item_instance,
|
@@ -298,7 +327,7 @@ class Stubber:
|
|
298
327
|
s += indent + " ...\n\n"
|
299
328
|
fp.write(s)
|
300
329
|
elif any(word in item_type_txt for word in ["method", "function", "closure"]):
|
301
|
-
|
330
|
+
log.debug("# def {1} function/method/closure, type = '{0}'".format(item_type_txt, item_name))
|
302
331
|
# module Function or class method
|
303
332
|
# will accept any number of params
|
304
333
|
# return type Any/Incomplete
|
@@ -309,14 +338,12 @@ class Stubber:
|
|
309
338
|
first = "self, "
|
310
339
|
# class method - add function decoration
|
311
340
|
if "bound_method" in item_type_txt or "bound_method" in item_repr:
|
312
|
-
s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(
|
313
|
-
indent, item_name, ret
|
314
|
-
)
|
341
|
+
s = "{}@classmethod\n".format(indent) + "{}def {}(cls, *args, **kwargs) -> {}:\n".format(indent, item_name, ret)
|
315
342
|
else:
|
316
343
|
s = "{}def {}({}*args, **kwargs) -> {}:\n".format(indent, item_name, first, ret)
|
317
344
|
s += indent + " ...\n\n"
|
318
345
|
fp.write(s)
|
319
|
-
|
346
|
+
log.debug("\n" + s)
|
320
347
|
elif item_type_txt == "<class 'module'>":
|
321
348
|
# Skip imported modules
|
322
349
|
# fp.write("# import {}\n".format(item_name))
|
@@ -344,10 +371,10 @@ class Stubber:
|
|
344
371
|
t = "Incomplete"
|
345
372
|
s = "{0}{1} : {2} ## {3} = {4}\n".format(indent, item_name, t, item_type_txt, item_repr)
|
346
373
|
fp.write(s)
|
347
|
-
|
374
|
+
log.debug("\n" + s)
|
348
375
|
else:
|
349
376
|
# keep only the name
|
350
|
-
|
377
|
+
log.debug("# all other, type = '{0}'".format(item_type_txt))
|
351
378
|
fp.write("# all other, type = '{0}'\n".format(item_type_txt))
|
352
379
|
|
353
380
|
fp.write(indent + item_name + " # type: Incomplete\n")
|
@@ -371,10 +398,9 @@ class Stubber:
|
|
371
398
|
|
372
399
|
def clean(self, path: str = None): # type: ignore
|
373
400
|
"Remove all files from the stub folder"
|
374
|
-
wdt.feed()
|
375
401
|
if path is None:
|
376
402
|
path = self.path
|
377
|
-
|
403
|
+
log.info("Clean/remove files in folder: {}".format(path))
|
378
404
|
try:
|
379
405
|
os.stat(path) # TEMP workaround mpremote listdir bug -
|
380
406
|
items = os.listdir(path)
|
@@ -394,12 +420,9 @@ class Stubber:
|
|
394
420
|
|
395
421
|
def report(self, filename: str = "modules.json"):
|
396
422
|
"create json with list of exported modules"
|
397
|
-
|
398
|
-
self.log.info(
|
399
|
-
"Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path)
|
400
|
-
)
|
423
|
+
log.info("Created stubs for {} modules on board {}\nPath: {}".format(len(self._report), self._fwid, self.path))
|
401
424
|
f_name = "{}/{}".format(self.path, filename)
|
402
|
-
|
425
|
+
log.info("Report file: {}".format(f_name))
|
403
426
|
gc.collect()
|
404
427
|
try:
|
405
428
|
# write json by node to reduce memory requirements
|
@@ -411,9 +434,9 @@ class Stubber:
|
|
411
434
|
first = False
|
412
435
|
self.write_json_end(f)
|
413
436
|
used = self._start_free - gc.mem_free() # type: ignore
|
414
|
-
|
437
|
+
log.trace("Memory used: {0} Kb".format(used // 1024))
|
415
438
|
except OSError:
|
416
|
-
|
439
|
+
log.error("Failed to create the report.")
|
417
440
|
|
418
441
|
def write_json_header(self, f):
|
419
442
|
f.write("{")
|
@@ -599,79 +622,16 @@ def version_str(version: tuple): # -> str:
|
|
599
622
|
return v_str
|
600
623
|
|
601
624
|
|
602
|
-
def
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
info["board"] = data.strip()
|
613
|
-
found = True
|
614
|
-
break
|
615
|
-
if not found:
|
616
|
-
print("Board not found, guessing board name")
|
617
|
-
descr = ""
|
618
|
-
# descr = desc or info["board"].strip()
|
619
|
-
# if "with " + info["cpu"].upper() in descr:
|
620
|
-
# # remove the with cpu part
|
621
|
-
# descr = descr.split("with " + info["cpu"].upper())[0].strip()
|
622
|
-
info["board"] = descr
|
623
|
-
|
624
|
-
|
625
|
-
# def read_boardname(info, desc: str = ""):
|
626
|
-
# wdt.feed()
|
627
|
-
# # print("look up the board name in the file", filename)
|
628
|
-
# if file_exists(filename):
|
629
|
-
# descr = desc or info["board"].strip()
|
630
|
-
# pos = descr.rfind(" with")
|
631
|
-
# if pos != -1:
|
632
|
-
# short_descr = descr[:pos].strip()
|
633
|
-
# else:
|
634
|
-
# short_descr = ""
|
635
|
-
# print("searching info file: {} for: '{}' or '{}'".format(filename, descr, short_descr))
|
636
|
-
# if find_board(info, descr, filename, short_descr):
|
637
|
-
# found = True
|
638
|
-
# break
|
639
|
-
# if not found:
|
640
|
-
# print("Board not found, guessing board name")
|
641
|
-
# descr = desc or info["board"].strip()
|
642
|
-
# if "with " + info["cpu"].upper() in descr:
|
643
|
-
# # remove the with cpu part
|
644
|
-
# descr = descr.split("with " + info["cpu"].upper())[0].strip()
|
645
|
-
# info["board"] = descr
|
646
|
-
# info["board"] = info["board"].replace(" ", "_")
|
647
|
-
# gc.collect()
|
648
|
-
|
649
|
-
|
650
|
-
# def find_board(info: dict, descr: str, filename: str, short_descr: str):
|
651
|
-
# "Find the board in the provided board_info.csv file"
|
652
|
-
# short_hit = ""
|
653
|
-
# with open(filename, "r") as file:
|
654
|
-
# # ugly code to make testable in python and micropython
|
655
|
-
# # TODO: This is VERY slow on micropython whith MPREMOTE mount on esp32 (2-3 minutes to read file)
|
656
|
-
# while 1:
|
657
|
-
# line = file.readline()
|
658
|
-
# if not line:
|
659
|
-
# break
|
660
|
-
# descr_, board_ = line.split(",")[0].strip(), line.split(",")[1].strip()
|
661
|
-
# if descr_ == descr:
|
662
|
-
# info["board"] = board_
|
663
|
-
# return True
|
664
|
-
# elif short_descr and descr_ == short_descr:
|
665
|
-
# if "with" in short_descr:
|
666
|
-
# # Good enough - no need to trawl the entire file
|
667
|
-
# info["board"] = board_
|
668
|
-
# return True
|
669
|
-
# # good enough if not found in the rest of the file (but slow)
|
670
|
-
# short_hit = board_
|
671
|
-
# if short_hit:
|
672
|
-
# info["board"] = short_hit
|
673
|
-
# return True
|
674
|
-
# return False
|
625
|
+
def get_boardname() -> str:
|
626
|
+
"Read the board name from the boardname.py file that may have been created upfront"
|
627
|
+
try:
|
628
|
+
from boardname import BOARDNAME # type: ignore
|
629
|
+
|
630
|
+
log.info("Found BOARDNAME: {}".format(BOARDNAME))
|
631
|
+
except ImportError:
|
632
|
+
log.warning("BOARDNAME not found")
|
633
|
+
BOARDNAME = ""
|
634
|
+
return BOARDNAME
|
675
635
|
|
676
636
|
|
677
637
|
def get_root() -> str: # sourcery skip: use-assigned-variable
|
@@ -772,12 +732,6 @@ def main():
|
|
772
732
|
|
773
733
|
|
774
734
|
if __name__ == "__main__" or is_micropython():
|
775
|
-
try:
|
776
|
-
log = logging.getLogger("stubber")
|
777
|
-
logging.basicConfig(level=logging.INFO)
|
778
|
-
# logging.basicConfig(level=logging.DEBUG)
|
779
|
-
except NameError:
|
780
|
-
pass
|
781
735
|
if not file_exists("no_auto_stubber.txt"):
|
782
736
|
try:
|
783
737
|
gc.threshold(4 * 1024) # type: ignore
|