micropython-stubber 1.23.1.post1__py3-none-any.whl → 1.23.2__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.23.1.post1.dist-info → micropython_stubber-1.23.2.dist-info}/LICENSE +30 -30
- {micropython_stubber-1.23.1.post1.dist-info → micropython_stubber-1.23.2.dist-info}/METADATA +4 -4
- micropython_stubber-1.23.2.dist-info/RECORD +158 -0
- mpflash/README.md +220 -220
- mpflash/libusb_flash.ipynb +203 -203
- mpflash/mpflash/add_firmware.py +98 -98
- mpflash/mpflash/ask_input.py +236 -236
- mpflash/mpflash/basicgit.py +284 -284
- mpflash/mpflash/bootloader/__init__.py +2 -2
- mpflash/mpflash/bootloader/activate.py +60 -60
- mpflash/mpflash/bootloader/detect.py +82 -82
- mpflash/mpflash/bootloader/manual.py +101 -101
- mpflash/mpflash/bootloader/micropython.py +12 -12
- mpflash/mpflash/bootloader/touch1200.py +36 -36
- mpflash/mpflash/cli_download.py +129 -129
- mpflash/mpflash/cli_flash.py +224 -216
- mpflash/mpflash/cli_group.py +111 -111
- mpflash/mpflash/cli_list.py +87 -87
- mpflash/mpflash/cli_main.py +39 -39
- mpflash/mpflash/common.py +210 -166
- mpflash/mpflash/config.py +44 -44
- mpflash/mpflash/connected.py +96 -77
- mpflash/mpflash/download.py +364 -364
- mpflash/mpflash/downloaded.py +130 -130
- mpflash/mpflash/errors.py +9 -9
- mpflash/mpflash/flash/__init__.py +55 -55
- mpflash/mpflash/flash/esp.py +59 -59
- mpflash/mpflash/flash/stm32.py +19 -19
- mpflash/mpflash/flash/stm32_dfu.py +104 -104
- mpflash/mpflash/flash/uf2/__init__.py +88 -88
- mpflash/mpflash/flash/uf2/boardid.py +15 -15
- mpflash/mpflash/flash/uf2/linux.py +136 -130
- mpflash/mpflash/flash/uf2/macos.py +42 -42
- mpflash/mpflash/flash/uf2/uf2disk.py +12 -12
- mpflash/mpflash/flash/uf2/windows.py +43 -43
- mpflash/mpflash/flash/worklist.py +170 -170
- mpflash/mpflash/list.py +106 -106
- mpflash/mpflash/logger.py +41 -41
- mpflash/mpflash/mpboard_id/__init__.py +93 -93
- mpflash/mpflash/mpboard_id/add_boards.py +251 -251
- mpflash/mpflash/mpboard_id/board.py +37 -37
- mpflash/mpflash/mpboard_id/board_id.py +86 -86
- mpflash/mpflash/mpboard_id/store.py +43 -43
- mpflash/mpflash/mpremoteboard/__init__.py +266 -266
- mpflash/mpflash/mpremoteboard/mpy_fw_info.py +141 -141
- mpflash/mpflash/mpremoteboard/runner.py +140 -140
- mpflash/mpflash/vendor/click_aliases.py +91 -91
- mpflash/mpflash/vendor/dfu.py +165 -165
- mpflash/mpflash/vendor/pydfu.py +605 -605
- mpflash/mpflash/vendor/readme.md +2 -2
- mpflash/mpflash/versions.py +135 -135
- mpflash/poetry.lock +1599 -1599
- mpflash/pyproject.toml +65 -65
- mpflash/stm32_udev_rules.md +62 -62
- stubber/__init__.py +3 -3
- stubber/board/board_info.csv +193 -193
- stubber/board/boot.py +34 -34
- stubber/board/createstubs.py +1004 -986
- stubber/board/createstubs_db.py +826 -825
- stubber/board/createstubs_db_min.py +332 -331
- stubber/board/createstubs_db_mpy.mpy +0 -0
- stubber/board/createstubs_lvgl.py +741 -741
- stubber/board/createstubs_lvgl_min.py +741 -741
- stubber/board/createstubs_mem.py +767 -766
- stubber/board/createstubs_mem_min.py +307 -306
- stubber/board/createstubs_mem_mpy.mpy +0 -0
- stubber/board/createstubs_min.py +295 -294
- stubber/board/createstubs_mpy.mpy +0 -0
- stubber/board/fw_info.py +141 -141
- stubber/board/info.py +183 -183
- stubber/board/main.py +19 -19
- stubber/board/modulelist.txt +247 -247
- stubber/board/pyrightconfig.json +34 -34
- stubber/bulk/mcu_stubber.py +437 -437
- stubber/codemod/_partials/__init__.py +48 -48
- stubber/codemod/_partials/db_main.py +147 -147
- stubber/codemod/_partials/lvgl_main.py +77 -77
- stubber/codemod/_partials/modules_reader.py +80 -80
- stubber/codemod/add_comment.py +53 -53
- stubber/codemod/add_method.py +65 -65
- stubber/codemod/board.py +317 -317
- stubber/codemod/enrich.py +151 -145
- stubber/codemod/merge_docstub.py +284 -284
- stubber/codemod/modify_list.py +54 -54
- stubber/codemod/utils.py +56 -56
- stubber/commands/build_cmd.py +94 -94
- stubber/commands/cli.py +49 -49
- stubber/commands/clone_cmd.py +78 -78
- stubber/commands/config_cmd.py +29 -29
- stubber/commands/enrich_folder_cmd.py +71 -71
- stubber/commands/get_core_cmd.py +71 -71
- stubber/commands/get_docstubs_cmd.py +92 -92
- stubber/commands/get_frozen_cmd.py +117 -117
- stubber/commands/get_mcu_cmd.py +102 -102
- stubber/commands/merge_cmd.py +66 -66
- stubber/commands/publish_cmd.py +118 -118
- stubber/commands/stub_cmd.py +31 -31
- stubber/commands/switch_cmd.py +62 -62
- stubber/commands/variants_cmd.py +48 -48
- stubber/cst_transformer.py +178 -178
- stubber/data/board_info.csv +193 -193
- stubber/data/board_info.json +1729 -1729
- stubber/data/micropython_tags.csv +15 -15
- stubber/data/requirements-core-micropython.txt +38 -38
- stubber/data/requirements-core-pycopy.txt +39 -39
- stubber/downloader.py +37 -37
- stubber/freeze/common.py +72 -72
- stubber/freeze/freeze_folder.py +69 -69
- stubber/freeze/freeze_manifest_2.py +126 -126
- stubber/freeze/get_frozen.py +131 -131
- stubber/get_cpython.py +112 -112
- stubber/get_lobo.py +59 -59
- stubber/minify.py +423 -423
- stubber/publish/bump.py +86 -86
- stubber/publish/candidates.py +275 -275
- stubber/publish/database.py +18 -18
- stubber/publish/defaults.py +40 -40
- stubber/publish/enums.py +24 -24
- stubber/publish/helpers.py +29 -29
- stubber/publish/merge_docstubs.py +136 -132
- stubber/publish/missing_class_methods.py +51 -51
- stubber/publish/package.py +150 -150
- stubber/publish/pathnames.py +51 -51
- stubber/publish/publish.py +120 -120
- stubber/publish/pypi.py +42 -42
- stubber/publish/stubpackage.py +1055 -1051
- stubber/rst/__init__.py +9 -9
- stubber/rst/classsort.py +78 -78
- stubber/rst/lookup.py +533 -531
- stubber/rst/output_dict.py +401 -401
- stubber/rst/reader.py +814 -814
- stubber/rst/report_return.py +77 -77
- stubber/rst/rst_utils.py +541 -541
- stubber/stubber.py +38 -38
- stubber/stubs_from_docs.py +90 -90
- stubber/tools/manifestfile.py +654 -654
- stubber/tools/readme.md +6 -6
- stubber/update_fallback.py +117 -117
- stubber/update_module_list.py +123 -123
- stubber/utils/__init__.py +6 -6
- stubber/utils/config.py +137 -137
- stubber/utils/makeversionhdr.py +54 -54
- stubber/utils/manifest.py +90 -90
- stubber/utils/post.py +80 -80
- stubber/utils/repos.py +156 -156
- stubber/utils/stubmaker.py +139 -139
- stubber/utils/typed_config_toml.py +80 -80
- stubber/variants.py +106 -106
- micropython_stubber-1.23.1.post1.dist-info/RECORD +0 -159
- mpflash/basicgit.py +0 -288
- {micropython_stubber-1.23.1.post1.dist-info → micropython_stubber-1.23.2.dist-info}/WHEEL +0 -0
- {micropython_stubber-1.23.1.post1.dist-info → micropython_stubber-1.23.2.dist-info}/entry_points.txt +0 -0
stubber/utils/stubmaker.py
CHANGED
@@ -1,139 +1,139 @@
|
|
1
|
-
"""Generate stub files for micropython modules using mypy/stubgen"""
|
2
|
-
|
3
|
-
import re
|
4
|
-
import sys
|
5
|
-
from pathlib import Path
|
6
|
-
|
7
|
-
import mypy.stubgen as stubgen
|
8
|
-
from mpflash.logger import log
|
9
|
-
from mypy.errors import CompileError
|
10
|
-
|
11
|
-
# default stubgen options
|
12
|
-
STUBGEN_OPT = stubgen.Options(
|
13
|
-
pyversion=(
|
14
|
-
3,
|
15
|
-
8,
|
16
|
-
), # documentation uses position-only argument indicator which requires 3.8 or higher
|
17
|
-
no_import=False,
|
18
|
-
include_private=True,
|
19
|
-
doc_dir="",
|
20
|
-
search_path=[],
|
21
|
-
interpreter=sys.executable,
|
22
|
-
parse_only=False,
|
23
|
-
ignore_errors=True,
|
24
|
-
modules=[],
|
25
|
-
packages=[],
|
26
|
-
files=[],
|
27
|
-
output_dir="",
|
28
|
-
verbose=True,
|
29
|
-
quiet=False,
|
30
|
-
export_less=False,
|
31
|
-
inspect=False, # inspect needs to import the module in CPython, which is not possible for frozen modules
|
32
|
-
include_docstrings=True, # include existing docstrings with the stubs
|
33
|
-
)
|
34
|
-
|
35
|
-
|
36
|
-
def generate_pyi_from_file(file: Path) -> bool:
|
37
|
-
"""Generate a .pyi stubfile from a single .py module using mypy/stubgen"""
|
38
|
-
|
39
|
-
sg_opt = STUBGEN_OPT
|
40
|
-
# Deal with generator passed in
|
41
|
-
assert isinstance(file, Path)
|
42
|
-
|
43
|
-
sg_opt.files = [str(file)]
|
44
|
-
sg_opt.output_dir = str(file.parent)
|
45
|
-
try:
|
46
|
-
log.debug(f"Calling stubgen on {str(file)}")
|
47
|
-
# TDOD: Stubgen.generate_stubs does not provide a way to return the errors
|
48
|
-
# such as `cannot perform relative import`
|
49
|
-
|
50
|
-
stubgen.generate_stubs(sg_opt)
|
51
|
-
return True
|
52
|
-
except (Exception, CompileError, SystemExit) as e:
|
53
|
-
# the only way to know if an error was encountered by generate_stubs
|
54
|
-
# TODO: Extract info from e.code or e.args[0] and add that to the manifest ?
|
55
|
-
log.warning(e.args[0])
|
56
|
-
return False
|
57
|
-
|
58
|
-
|
59
|
-
def generate_pyi_files(modules_folder: Path) -> bool:
|
60
|
-
"""
|
61
|
-
Generate typeshed files for all scripts in a folder using mypy/stubgen
|
62
|
-
|
63
|
-
Returns: False if one or more files had an issue generating a stub
|
64
|
-
"""
|
65
|
-
# stubgen cannot process folders with duplicate modules ( ie v1.14 and v1.15 )
|
66
|
-
# NOTE: FIX 1 add __init__.py to umqtt
|
67
|
-
if (modules_folder / "umqtt/robust.py").exists():
|
68
|
-
log.debug("add missing : umqtt/__init__.py")
|
69
|
-
with open(modules_folder / "umqtt" / "__init__.py", "a") as f:
|
70
|
-
f.write("")
|
71
|
-
|
72
|
-
# rx_const = re.compile(r"const\(([\w_\"']+)\)")
|
73
|
-
rx_const = re.compile(r"const\(([-*<.,:/\(\) \w_\"']+)\)")
|
74
|
-
# FIX 2 - replace `const(foo)` with `foo`
|
75
|
-
for f in modules_folder.rglob("*.py"):
|
76
|
-
if f.is_file():
|
77
|
-
with open(f, "r") as file:
|
78
|
-
data = file.read()
|
79
|
-
# regex Search for const\(([\w_"']+)\) and replace with (\1)
|
80
|
-
if rx_const.search(data):
|
81
|
-
log.debug(f"replace const() in {f}")
|
82
|
-
data = rx_const.sub(r"\1", data)
|
83
|
-
with open(f, "w") as file:
|
84
|
-
file.write(data)
|
85
|
-
|
86
|
-
module_list = list(modules_folder.glob("**/modules.json"))
|
87
|
-
r = True
|
88
|
-
if len(module_list) > 1:
|
89
|
-
# try to process each module separately
|
90
|
-
for mod_manifest in module_list:
|
91
|
-
## generate fyi files for folder
|
92
|
-
r = r and generate_pyi_files(mod_manifest.parent)
|
93
|
-
else: # one or less module manifests
|
94
|
-
## generate fyi files for folder
|
95
|
-
log.debug("::group::[stubgen] running stubgen on {0}".format(modules_folder))
|
96
|
-
|
97
|
-
run_per_file = False
|
98
|
-
sg_opt = STUBGEN_OPT
|
99
|
-
sg_opt.files = [str(modules_folder)]
|
100
|
-
sg_opt.output_dir = str(modules_folder)
|
101
|
-
try:
|
102
|
-
stubgen.generate_stubs(sg_opt)
|
103
|
-
except (Exception, CompileError, SystemExit) as e:
|
104
|
-
if isinstance(e, KeyboardInterrupt):
|
105
|
-
raise e
|
106
|
-
# the only way to know if an error was encountered by generate_stubs
|
107
|
-
# mypy.errors.CompileError and others ?
|
108
|
-
# TODO: Extract info from e.code or e.args[0]
|
109
|
-
log.warning(e.args[0])
|
110
|
-
run_per_file = True
|
111
|
-
|
112
|
-
if run_per_file:
|
113
|
-
# in case of failure ( duplicate module in subfolder) then Plan B
|
114
|
-
# - run stubgen on each *.py
|
115
|
-
log.debug("::group::[stubgen] Failure on folder, attempt to run stubgen per file")
|
116
|
-
py_files = list(modules_folder.rglob("*.py"))
|
117
|
-
for py in py_files:
|
118
|
-
generate_pyi_from_file(py)
|
119
|
-
# todo: report failures by adding to module manifest
|
120
|
-
|
121
|
-
# for py missing pyi:
|
122
|
-
py_files = list(modules_folder.rglob("*.py"))
|
123
|
-
pyi_files = list(modules_folder.rglob("*.pyi"))
|
124
|
-
|
125
|
-
work_list = pyi_files.copy()
|
126
|
-
for pyi in work_list:
|
127
|
-
# remove all py files that have been stubbed successfully from the list
|
128
|
-
try:
|
129
|
-
py_files.remove(pyi.with_suffix(".py"))
|
130
|
-
pyi_files.remove(pyi)
|
131
|
-
except ValueError:
|
132
|
-
log.debug(f"no matching py for : {str(pyi)}")
|
133
|
-
|
134
|
-
# note in some cases this will try a file twice - but that is better than failing
|
135
|
-
for py in py_files:
|
136
|
-
r = r and generate_pyi_from_file(py)
|
137
|
-
# todo: report failures by adding to module manifest
|
138
|
-
|
139
|
-
return r
|
1
|
+
"""Generate stub files for micropython modules using mypy/stubgen"""
|
2
|
+
|
3
|
+
import re
|
4
|
+
import sys
|
5
|
+
from pathlib import Path
|
6
|
+
|
7
|
+
import mypy.stubgen as stubgen
|
8
|
+
from mpflash.logger import log
|
9
|
+
from mypy.errors import CompileError
|
10
|
+
|
11
|
+
# default stubgen options
|
12
|
+
STUBGEN_OPT = stubgen.Options(
|
13
|
+
pyversion=(
|
14
|
+
3,
|
15
|
+
8,
|
16
|
+
), # documentation uses position-only argument indicator which requires 3.8 or higher
|
17
|
+
no_import=False,
|
18
|
+
include_private=True,
|
19
|
+
doc_dir="",
|
20
|
+
search_path=[],
|
21
|
+
interpreter=sys.executable,
|
22
|
+
parse_only=False,
|
23
|
+
ignore_errors=True,
|
24
|
+
modules=[],
|
25
|
+
packages=[],
|
26
|
+
files=[],
|
27
|
+
output_dir="",
|
28
|
+
verbose=True,
|
29
|
+
quiet=False,
|
30
|
+
export_less=False,
|
31
|
+
inspect=False, # inspect needs to import the module in CPython, which is not possible for frozen modules
|
32
|
+
include_docstrings=True, # include existing docstrings with the stubs
|
33
|
+
)
|
34
|
+
|
35
|
+
|
36
|
+
def generate_pyi_from_file(file: Path) -> bool:
|
37
|
+
"""Generate a .pyi stubfile from a single .py module using mypy/stubgen"""
|
38
|
+
|
39
|
+
sg_opt = STUBGEN_OPT
|
40
|
+
# Deal with generator passed in
|
41
|
+
assert isinstance(file, Path)
|
42
|
+
|
43
|
+
sg_opt.files = [str(file)]
|
44
|
+
sg_opt.output_dir = str(file.parent)
|
45
|
+
try:
|
46
|
+
log.debug(f"Calling stubgen on {str(file)}")
|
47
|
+
# TDOD: Stubgen.generate_stubs does not provide a way to return the errors
|
48
|
+
# such as `cannot perform relative import`
|
49
|
+
|
50
|
+
stubgen.generate_stubs(sg_opt)
|
51
|
+
return True
|
52
|
+
except (Exception, CompileError, SystemExit) as e:
|
53
|
+
# the only way to know if an error was encountered by generate_stubs
|
54
|
+
# TODO: Extract info from e.code or e.args[0] and add that to the manifest ?
|
55
|
+
log.warning(e.args[0])
|
56
|
+
return False
|
57
|
+
|
58
|
+
|
59
|
+
def generate_pyi_files(modules_folder: Path) -> bool:
|
60
|
+
"""
|
61
|
+
Generate typeshed files for all scripts in a folder using mypy/stubgen
|
62
|
+
|
63
|
+
Returns: False if one or more files had an issue generating a stub
|
64
|
+
"""
|
65
|
+
# stubgen cannot process folders with duplicate modules ( ie v1.14 and v1.15 )
|
66
|
+
# NOTE: FIX 1 add __init__.py to umqtt
|
67
|
+
if (modules_folder / "umqtt/robust.py").exists():
|
68
|
+
log.debug("add missing : umqtt/__init__.py")
|
69
|
+
with open(modules_folder / "umqtt" / "__init__.py", "a") as f:
|
70
|
+
f.write("")
|
71
|
+
|
72
|
+
# rx_const = re.compile(r"const\(([\w_\"']+)\)")
|
73
|
+
rx_const = re.compile(r"const\(([-*<.,:/\(\) \w_\"']+)\)")
|
74
|
+
# FIX 2 - replace `const(foo)` with `foo`
|
75
|
+
for f in modules_folder.rglob("*.py"):
|
76
|
+
if f.is_file():
|
77
|
+
with open(f, "r") as file:
|
78
|
+
data = file.read()
|
79
|
+
# regex Search for const\(([\w_"']+)\) and replace with (\1)
|
80
|
+
if rx_const.search(data):
|
81
|
+
log.debug(f"replace const() in {f}")
|
82
|
+
data = rx_const.sub(r"\1", data)
|
83
|
+
with open(f, "w") as file:
|
84
|
+
file.write(data)
|
85
|
+
|
86
|
+
module_list = list(modules_folder.glob("**/modules.json"))
|
87
|
+
r = True
|
88
|
+
if len(module_list) > 1:
|
89
|
+
# try to process each module separately
|
90
|
+
for mod_manifest in module_list:
|
91
|
+
## generate fyi files for folder
|
92
|
+
r = r and generate_pyi_files(mod_manifest.parent)
|
93
|
+
else: # one or less module manifests
|
94
|
+
## generate fyi files for folder
|
95
|
+
log.debug("::group::[stubgen] running stubgen on {0}".format(modules_folder))
|
96
|
+
|
97
|
+
run_per_file = False
|
98
|
+
sg_opt = STUBGEN_OPT
|
99
|
+
sg_opt.files = [str(modules_folder)]
|
100
|
+
sg_opt.output_dir = str(modules_folder)
|
101
|
+
try:
|
102
|
+
stubgen.generate_stubs(sg_opt)
|
103
|
+
except (Exception, CompileError, SystemExit) as e:
|
104
|
+
if isinstance(e, KeyboardInterrupt):
|
105
|
+
raise e
|
106
|
+
# the only way to know if an error was encountered by generate_stubs
|
107
|
+
# mypy.errors.CompileError and others ?
|
108
|
+
# TODO: Extract info from e.code or e.args[0]
|
109
|
+
log.warning(e.args[0])
|
110
|
+
run_per_file = True
|
111
|
+
|
112
|
+
if run_per_file:
|
113
|
+
# in case of failure ( duplicate module in subfolder) then Plan B
|
114
|
+
# - run stubgen on each *.py
|
115
|
+
log.debug("::group::[stubgen] Failure on folder, attempt to run stubgen per file")
|
116
|
+
py_files = list(modules_folder.rglob("*.py"))
|
117
|
+
for py in py_files:
|
118
|
+
generate_pyi_from_file(py)
|
119
|
+
# todo: report failures by adding to module manifest
|
120
|
+
|
121
|
+
# for py missing pyi:
|
122
|
+
py_files = list(modules_folder.rglob("*.py"))
|
123
|
+
pyi_files = list(modules_folder.rglob("*.pyi"))
|
124
|
+
|
125
|
+
work_list = pyi_files.copy()
|
126
|
+
for pyi in work_list:
|
127
|
+
# remove all py files that have been stubbed successfully from the list
|
128
|
+
try:
|
129
|
+
py_files.remove(pyi.with_suffix(".py"))
|
130
|
+
pyi_files.remove(pyi)
|
131
|
+
except ValueError:
|
132
|
+
log.debug(f"no matching py for : {str(pyi)}")
|
133
|
+
|
134
|
+
# note in some cases this will try a file twice - but that is better than failing
|
135
|
+
for py in py_files:
|
136
|
+
r = r and generate_pyi_from_file(py)
|
137
|
+
# todo: report failures by adding to module manifest
|
138
|
+
|
139
|
+
return r
|
@@ -1,80 +1,80 @@
|
|
1
|
-
"""
|
2
|
-
typed-config-toml
|
3
|
-
|
4
|
-
Extend typed-config to read configuration from .toml files
|
5
|
-
|
6
|
-
"""
|
7
|
-
|
8
|
-
# TODO : extend support for . notation in section names
|
9
|
-
|
10
|
-
from pathlib import Path
|
11
|
-
from typing import Dict, Optional
|
12
|
-
|
13
|
-
try:
|
14
|
-
import tomllib # type: ignore
|
15
|
-
except ModuleNotFoundError:
|
16
|
-
import tomli as tomllib # type: ignore
|
17
|
-
assert tomllib
|
18
|
-
|
19
|
-
from mpflash.logger import log
|
20
|
-
from typedconfig.source import ConfigSource
|
21
|
-
|
22
|
-
|
23
|
-
class TomlConfigSource(ConfigSource):
|
24
|
-
"""Read configuration from a .toml file
|
25
|
-
|
26
|
-
prefix is used to allow for toml nested configuration
|
27
|
-
a common prefix = "tool."
|
28
|
-
|
29
|
-
```
|
30
|
-
#pyproject.toml
|
31
|
-
[tool.deadparrot]
|
32
|
-
species = "Norwegian Blue"
|
33
|
-
state = "resting"
|
34
|
-
details = ["pinging","Lovely plumage","3"]
|
35
|
-
```
|
36
|
-
Use the below code to retrieve:
|
37
|
-
```
|
38
|
-
# TODO sample code
|
39
|
-
```
|
40
|
-
"""
|
41
|
-
|
42
|
-
def __init__(self, filename: str, prefix: Optional[str] = None, must_exist: bool = True):
|
43
|
-
self.filename = filename
|
44
|
-
toml_dict = {}
|
45
|
-
if Path(self.filename).exists():
|
46
|
-
# Read data - will raise an exception if problem with file
|
47
|
-
try:
|
48
|
-
with open(filename, "rb") as f:
|
49
|
-
toml_dict = tomllib.load(f)
|
50
|
-
except tomllib.TOMLDecodeError: # pragma: no cover
|
51
|
-
log.warning("unable to read ")
|
52
|
-
elif must_exist:
|
53
|
-
raise FileNotFoundError(f"Could not find config file {self.filename}")
|
54
|
-
if not prefix or len(prefix) == 0:
|
55
|
-
self.data = toml_dict
|
56
|
-
else:
|
57
|
-
# common prefix = "tool."
|
58
|
-
try:
|
59
|
-
self.data = toml_dict[prefix.rstrip(".")]
|
60
|
-
except KeyError: # pragma: no cover
|
61
|
-
self.data = {}
|
62
|
-
|
63
|
-
# Quick checks on data format
|
64
|
-
assert isinstance(self.data, Dict)
|
65
|
-
for k, v in self.data.items():
|
66
|
-
assert isinstance(k, str)
|
67
|
-
assert isinstance(v, Dict)
|
68
|
-
for v_k, v_v in v.items(): # type: ignore
|
69
|
-
assert isinstance(v_k, str)
|
70
|
-
# do not assume/require that all values are strings
|
71
|
-
# assert isinstance(v_v, str)
|
72
|
-
# Convert all keys to lowercase
|
73
|
-
self.data = {
|
74
|
-
k.lower(): {v_k.lower(): v_v for v_k, v_v in v.items()} for k, v in self.data.items()
|
75
|
-
}
|
76
|
-
|
77
|
-
def get_config_value(self, section_name: str, key_name: str) -> Optional[str]:
|
78
|
-
# Extract info from data which we read in during __init__
|
79
|
-
section = self.data.get(section_name.lower(), None)
|
80
|
-
return None if section is None else section.get(key_name.lower(), None)
|
1
|
+
"""
|
2
|
+
typed-config-toml
|
3
|
+
|
4
|
+
Extend typed-config to read configuration from .toml files
|
5
|
+
|
6
|
+
"""
|
7
|
+
|
8
|
+
# TODO : extend support for . notation in section names
|
9
|
+
|
10
|
+
from pathlib import Path
|
11
|
+
from typing import Dict, Optional
|
12
|
+
|
13
|
+
try:
|
14
|
+
import tomllib # type: ignore
|
15
|
+
except ModuleNotFoundError:
|
16
|
+
import tomli as tomllib # type: ignore
|
17
|
+
assert tomllib
|
18
|
+
|
19
|
+
from mpflash.logger import log
|
20
|
+
from typedconfig.source import ConfigSource
|
21
|
+
|
22
|
+
|
23
|
+
class TomlConfigSource(ConfigSource):
|
24
|
+
"""Read configuration from a .toml file
|
25
|
+
|
26
|
+
prefix is used to allow for toml nested configuration
|
27
|
+
a common prefix = "tool."
|
28
|
+
|
29
|
+
```
|
30
|
+
#pyproject.toml
|
31
|
+
[tool.deadparrot]
|
32
|
+
species = "Norwegian Blue"
|
33
|
+
state = "resting"
|
34
|
+
details = ["pinging","Lovely plumage","3"]
|
35
|
+
```
|
36
|
+
Use the below code to retrieve:
|
37
|
+
```
|
38
|
+
# TODO sample code
|
39
|
+
```
|
40
|
+
"""
|
41
|
+
|
42
|
+
def __init__(self, filename: str, prefix: Optional[str] = None, must_exist: bool = True):
|
43
|
+
self.filename = filename
|
44
|
+
toml_dict = {}
|
45
|
+
if Path(self.filename).exists():
|
46
|
+
# Read data - will raise an exception if problem with file
|
47
|
+
try:
|
48
|
+
with open(filename, "rb") as f:
|
49
|
+
toml_dict = tomllib.load(f)
|
50
|
+
except tomllib.TOMLDecodeError: # pragma: no cover
|
51
|
+
log.warning("unable to read ")
|
52
|
+
elif must_exist:
|
53
|
+
raise FileNotFoundError(f"Could not find config file {self.filename}")
|
54
|
+
if not prefix or len(prefix) == 0:
|
55
|
+
self.data = toml_dict
|
56
|
+
else:
|
57
|
+
# common prefix = "tool."
|
58
|
+
try:
|
59
|
+
self.data = toml_dict[prefix.rstrip(".")]
|
60
|
+
except KeyError: # pragma: no cover
|
61
|
+
self.data = {}
|
62
|
+
|
63
|
+
# Quick checks on data format
|
64
|
+
assert isinstance(self.data, Dict)
|
65
|
+
for k, v in self.data.items():
|
66
|
+
assert isinstance(k, str)
|
67
|
+
assert isinstance(v, Dict)
|
68
|
+
for v_k, v_v in v.items(): # type: ignore
|
69
|
+
assert isinstance(v_k, str)
|
70
|
+
# do not assume/require that all values are strings
|
71
|
+
# assert isinstance(v_v, str)
|
72
|
+
# Convert all keys to lowercase
|
73
|
+
self.data = {
|
74
|
+
k.lower(): {v_k.lower(): v_v for v_k, v_v in v.items()} for k, v in self.data.items()
|
75
|
+
}
|
76
|
+
|
77
|
+
def get_config_value(self, section_name: str, key_name: str) -> Optional[str]:
|
78
|
+
# Extract info from data which we read in during __init__
|
79
|
+
section = self.data.get(section_name.lower(), None)
|
80
|
+
return None if section is None else section.get(key_name.lower(), None)
|
stubber/variants.py
CHANGED
@@ -1,106 +1,106 @@
|
|
1
|
-
"""
|
2
|
-
Create all variants of createstubs.py
|
3
|
-
- and minify them
|
4
|
-
- and cross compile them
|
5
|
-
"""
|
6
|
-
|
7
|
-
import shutil
|
8
|
-
from pathlib import Path
|
9
|
-
from typing import List, Optional
|
10
|
-
|
11
|
-
import libcst as cst
|
12
|
-
import libcst.codemod as codemod
|
13
|
-
from mpflash.logger import log
|
14
|
-
|
15
|
-
from stubber.codemod.board import CreateStubsCodemod, CreateStubsVariant
|
16
|
-
from stubber.codemod.modify_list import ListChangeSet # type: ignore
|
17
|
-
from stubber.minify import cross_compile, minify
|
18
|
-
from stubber.update_module_list import update_module_list
|
19
|
-
from stubber.utils.post import run_black
|
20
|
-
|
21
|
-
ALL_VARIANTS = list(CreateStubsVariant)
|
22
|
-
|
23
|
-
|
24
|
-
def create_variants(
|
25
|
-
base_path: Path,
|
26
|
-
*,
|
27
|
-
target_path: Optional[Path] = None,
|
28
|
-
version: str = "",
|
29
|
-
make_variants: List[CreateStubsVariant] = ALL_VARIANTS[:3],
|
30
|
-
update_modules: bool = True,
|
31
|
-
):
|
32
|
-
"""
|
33
|
-
Create variants of createstubs.py and optionally minify and cross compile them.
|
34
|
-
|
35
|
-
Parameters
|
36
|
-
----------
|
37
|
-
base_path : Path
|
38
|
-
Path to the base createstubs.py file
|
39
|
-
target_path : Path, optional
|
40
|
-
Path to write the variants to, by default None
|
41
|
-
version : str, optional
|
42
|
-
Version of mpy-cross to use, by default uses the latest published version
|
43
|
-
|
44
|
-
"""
|
45
|
-
if target_path is None:
|
46
|
-
target_path = base_path
|
47
|
-
if update_modules:
|
48
|
-
update_module_list()
|
49
|
-
|
50
|
-
ctx = codemod.CodemodContext()
|
51
|
-
base_file = base_path / "createstubs.py"
|
52
|
-
log.info(f"Reading : {base_file}")
|
53
|
-
base_txt = (base_path / "createstubs.py").read_text(encoding="utf-8")
|
54
|
-
base_module = cst.parse_module(base_txt)
|
55
|
-
|
56
|
-
for var in make_variants:
|
57
|
-
# Transform base to createstubs.py variant
|
58
|
-
|
59
|
-
suffix = "" if var == CreateStubsVariant.BASE else f"_{var.value}"
|
60
|
-
|
61
|
-
variant_path = target_path / f"createstubs{suffix}.py"
|
62
|
-
minified_path = target_path / f"createstubs{suffix}_min.py"
|
63
|
-
mpy_path = target_path / f"createstubs{suffix}_mpy.mpy" # intentional
|
64
|
-
|
65
|
-
if var == CreateStubsVariant.BASE and target_path != base_path:
|
66
|
-
log.info(f"Copying base file to {variant_path}")
|
67
|
-
variant_path.write_text(base_txt)
|
68
|
-
# copy modules.txt to target_path
|
69
|
-
shutil.copyfile(base_path / "modulelist.txt", target_path / "modulelist.txt")
|
70
|
-
|
71
|
-
if var != CreateStubsVariant.BASE:
|
72
|
-
# No need to create base variant as it is the same as the base file
|
73
|
-
log.info(f"Transforming to {var.value} variant")
|
74
|
-
cm = CreateStubsCodemod(ctx, variant=var)
|
75
|
-
variant = cm.transform_module(base_module)
|
76
|
-
|
77
|
-
# write low_mem_variant.code to file
|
78
|
-
log.info(f"Write variant {var.value} to {variant_path}")
|
79
|
-
with open(variant_path, "w") as f:
|
80
|
-
f.write(variant.code)
|
81
|
-
|
82
|
-
# format file with black
|
83
|
-
run_black(variant_path, capture_output=True)
|
84
|
-
# TODO: check with pyright if it is valid python
|
85
|
-
|
86
|
-
# Minify file with pyminifier
|
87
|
-
log.info(f"Minifying to {minified_path.name}")
|
88
|
-
minify(variant_path, minified_path, keep_report=False, diff=False)
|
89
|
-
|
90
|
-
# str -> path
|
91
|
-
# read minified file
|
92
|
-
minified_txt = minified_path.read_text(encoding="utf-8")
|
93
|
-
cross_compile(minified_txt, mpy_path, version=version)
|
94
|
-
|
95
|
-
|
96
|
-
if __name__ == "__main__":
|
97
|
-
# read base createstubs.py
|
98
|
-
base_path = Path.cwd() / "src" / "stubber" / "board"
|
99
|
-
create_variants(base_path)
|
100
|
-
|
101
|
-
# if 0:
|
102
|
-
# # custom modules (and skip defaults).
|
103
|
-
# custom_stubs = ListChangeSet.from_strings(add=["mycoolpackage", "othermodule"], replace=True)
|
104
|
-
# custom_variant = CreateStubsCodemod(ctx, modules=custom_stubs).transform_module(base_module)
|
105
|
-
|
106
|
-
# print(custom_variant.code)
|
1
|
+
"""
|
2
|
+
Create all variants of createstubs.py
|
3
|
+
- and minify them
|
4
|
+
- and cross compile them
|
5
|
+
"""
|
6
|
+
|
7
|
+
import shutil
|
8
|
+
from pathlib import Path
|
9
|
+
from typing import List, Optional
|
10
|
+
|
11
|
+
import libcst as cst
|
12
|
+
import libcst.codemod as codemod
|
13
|
+
from mpflash.logger import log
|
14
|
+
|
15
|
+
from stubber.codemod.board import CreateStubsCodemod, CreateStubsVariant
|
16
|
+
from stubber.codemod.modify_list import ListChangeSet # type: ignore
|
17
|
+
from stubber.minify import cross_compile, minify
|
18
|
+
from stubber.update_module_list import update_module_list
|
19
|
+
from stubber.utils.post import run_black
|
20
|
+
|
21
|
+
ALL_VARIANTS = list(CreateStubsVariant)
|
22
|
+
|
23
|
+
|
24
|
+
def create_variants(
|
25
|
+
base_path: Path,
|
26
|
+
*,
|
27
|
+
target_path: Optional[Path] = None,
|
28
|
+
version: str = "",
|
29
|
+
make_variants: List[CreateStubsVariant] = ALL_VARIANTS[:3],
|
30
|
+
update_modules: bool = True,
|
31
|
+
):
|
32
|
+
"""
|
33
|
+
Create variants of createstubs.py and optionally minify and cross compile them.
|
34
|
+
|
35
|
+
Parameters
|
36
|
+
----------
|
37
|
+
base_path : Path
|
38
|
+
Path to the base createstubs.py file
|
39
|
+
target_path : Path, optional
|
40
|
+
Path to write the variants to, by default None
|
41
|
+
version : str, optional
|
42
|
+
Version of mpy-cross to use, by default uses the latest published version
|
43
|
+
|
44
|
+
"""
|
45
|
+
if target_path is None:
|
46
|
+
target_path = base_path
|
47
|
+
if update_modules:
|
48
|
+
update_module_list()
|
49
|
+
|
50
|
+
ctx = codemod.CodemodContext()
|
51
|
+
base_file = base_path / "createstubs.py"
|
52
|
+
log.info(f"Reading : {base_file}")
|
53
|
+
base_txt = (base_path / "createstubs.py").read_text(encoding="utf-8")
|
54
|
+
base_module = cst.parse_module(base_txt)
|
55
|
+
|
56
|
+
for var in make_variants:
|
57
|
+
# Transform base to createstubs.py variant
|
58
|
+
|
59
|
+
suffix = "" if var == CreateStubsVariant.BASE else f"_{var.value}"
|
60
|
+
|
61
|
+
variant_path = target_path / f"createstubs{suffix}.py"
|
62
|
+
minified_path = target_path / f"createstubs{suffix}_min.py"
|
63
|
+
mpy_path = target_path / f"createstubs{suffix}_mpy.mpy" # intentional
|
64
|
+
|
65
|
+
if var == CreateStubsVariant.BASE and target_path != base_path:
|
66
|
+
log.info(f"Copying base file to {variant_path}")
|
67
|
+
variant_path.write_text(base_txt)
|
68
|
+
# copy modules.txt to target_path
|
69
|
+
shutil.copyfile(base_path / "modulelist.txt", target_path / "modulelist.txt")
|
70
|
+
|
71
|
+
if var != CreateStubsVariant.BASE:
|
72
|
+
# No need to create base variant as it is the same as the base file
|
73
|
+
log.info(f"Transforming to {var.value} variant")
|
74
|
+
cm = CreateStubsCodemod(ctx, variant=var)
|
75
|
+
variant = cm.transform_module(base_module)
|
76
|
+
|
77
|
+
# write low_mem_variant.code to file
|
78
|
+
log.info(f"Write variant {var.value} to {variant_path}")
|
79
|
+
with open(variant_path, "w") as f:
|
80
|
+
f.write(variant.code)
|
81
|
+
|
82
|
+
# format file with black
|
83
|
+
run_black(variant_path, capture_output=True)
|
84
|
+
# TODO: check with pyright if it is valid python
|
85
|
+
|
86
|
+
# Minify file with pyminifier
|
87
|
+
log.info(f"Minifying to {minified_path.name}")
|
88
|
+
minify(variant_path, minified_path, keep_report=False, diff=False)
|
89
|
+
|
90
|
+
# str -> path
|
91
|
+
# read minified file
|
92
|
+
minified_txt = minified_path.read_text(encoding="utf-8")
|
93
|
+
cross_compile(minified_txt, mpy_path, version=version)
|
94
|
+
|
95
|
+
|
96
|
+
if __name__ == "__main__":
|
97
|
+
# read base createstubs.py
|
98
|
+
base_path = Path.cwd() / "src" / "stubber" / "board"
|
99
|
+
create_variants(base_path)
|
100
|
+
|
101
|
+
# if 0:
|
102
|
+
# # custom modules (and skip defaults).
|
103
|
+
# custom_stubs = ListChangeSet.from_strings(add=["mycoolpackage", "othermodule"], replace=True)
|
104
|
+
# custom_variant = CreateStubsCodemod(ctx, modules=custom_stubs).transform_module(base_module)
|
105
|
+
|
106
|
+
# print(custom_variant.code)
|