micropython-stubber 1.20.1__py3-none-any.whl → 1.20.4__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.20.1.dist-info → micropython_stubber-1.20.4.dist-info}/METADATA +4 -3
- {micropython_stubber-1.20.1.dist-info → micropython_stubber-1.20.4.dist-info}/RECORD +58 -51
- {micropython_stubber-1.20.1.dist-info → micropython_stubber-1.20.4.dist-info}/WHEEL +1 -1
- mpflash/README.md +16 -5
- mpflash/mpflash/add_firmware.py +98 -0
- mpflash/mpflash/ask_input.py +97 -120
- mpflash/mpflash/cli_download.py +42 -25
- mpflash/mpflash/cli_flash.py +70 -32
- mpflash/mpflash/cli_group.py +17 -14
- mpflash/mpflash/cli_list.py +39 -3
- mpflash/mpflash/cli_main.py +17 -6
- mpflash/mpflash/common.py +125 -12
- mpflash/mpflash/config.py +12 -0
- mpflash/mpflash/connected.py +74 -0
- mpflash/mpflash/download.py +132 -51
- mpflash/mpflash/downloaded.py +36 -15
- mpflash/mpflash/flash.py +2 -2
- mpflash/mpflash/flash_esp.py +2 -2
- mpflash/mpflash/flash_uf2.py +14 -8
- mpflash/mpflash/flash_uf2_boardid.py +2 -1
- mpflash/mpflash/flash_uf2_linux.py +5 -16
- mpflash/mpflash/flash_uf2_macos.py +37 -0
- mpflash/mpflash/flash_uf2_windows.py +5 -5
- mpflash/mpflash/list.py +57 -57
- mpflash/mpflash/mpboard_id/__init__.py +41 -44
- mpflash/mpflash/mpboard_id/add_boards.py +255 -0
- mpflash/mpflash/mpboard_id/board.py +37 -0
- mpflash/mpflash/mpboard_id/board_id.py +54 -34
- mpflash/mpflash/mpboard_id/board_info.zip +0 -0
- mpflash/mpflash/mpboard_id/store.py +43 -0
- mpflash/mpflash/mpremoteboard/__init__.py +18 -6
- mpflash/mpflash/uf2disk.py +12 -0
- mpflash/mpflash/vendor/basicgit.py +288 -0
- mpflash/mpflash/vendor/dfu.py +1 -0
- mpflash/mpflash/vendor/versions.py +7 -3
- mpflash/mpflash/worklist.py +71 -48
- mpflash/poetry.lock +164 -138
- mpflash/pyproject.toml +18 -15
- stubber/__init__.py +1 -1
- stubber/board/createstubs.py +13 -3
- stubber/board/createstubs_db.py +5 -7
- stubber/board/createstubs_db_min.py +329 -825
- stubber/board/createstubs_db_mpy.mpy +0 -0
- stubber/board/createstubs_mem.py +6 -7
- stubber/board/createstubs_mem_min.py +304 -765
- stubber/board/createstubs_mem_mpy.mpy +0 -0
- stubber/board/createstubs_min.py +293 -975
- stubber/board/createstubs_mpy.mpy +0 -0
- stubber/board/modulelist.txt +10 -0
- stubber/commands/get_core_cmd.py +7 -6
- stubber/commands/get_docstubs_cmd.py +8 -3
- stubber/commands/get_frozen_cmd.py +5 -2
- stubber/publish/publish.py +18 -7
- stubber/update_module_list.py +2 -24
- stubber/utils/makeversionhdr.py +3 -2
- stubber/utils/versions.py +2 -1
- mpflash/mpflash/mpboard_id/board_info.csv +0 -2213
- mpflash/mpflash/mpboard_id/board_info.json +0 -19910
- {micropython_stubber-1.20.1.dist-info → micropython_stubber-1.20.4.dist-info}/LICENSE +0 -0
- {micropython_stubber-1.20.1.dist-info → micropython_stubber-1.20.4.dist-info}/entry_points.txt +0 -0
mpflash/mpflash/ask_input.py
CHANGED
@@ -5,97 +5,85 @@ Note: The prompts can use "{version}" and "{action}" to insert the version and a
|
|
5
5
|
The values are provided from the answers dictionary.
|
6
6
|
"""
|
7
7
|
|
8
|
-
from
|
9
|
-
from pathlib import Path
|
10
|
-
from typing import Dict, List, Sequence, Tuple, Union
|
8
|
+
from typing import List, Sequence, Tuple, Union
|
11
9
|
|
12
10
|
from loguru import logger as log
|
13
11
|
|
14
|
-
from
|
15
|
-
from
|
16
|
-
from
|
17
|
-
from
|
18
|
-
|
19
|
-
|
20
|
-
@dataclass
|
21
|
-
class Params:
|
22
|
-
ports: List[str] = field(default_factory=list)
|
23
|
-
boards: List[str] = field(default_factory=list)
|
24
|
-
versions: List[str] = field(default_factory=list)
|
25
|
-
fw_folder: Path = Path()
|
26
|
-
|
27
|
-
|
28
|
-
@dataclass
|
29
|
-
class DownloadParams(Params):
|
30
|
-
clean: bool = False
|
31
|
-
force: bool = False
|
32
|
-
|
33
|
-
|
34
|
-
@dataclass
|
35
|
-
class FlashParams(Params):
|
36
|
-
# TODO: Should Serial port be a list?
|
37
|
-
serial: str = ""
|
38
|
-
erase: bool = True
|
39
|
-
bootloader: bool = True
|
40
|
-
cpu: str = ""
|
41
|
-
|
42
|
-
|
43
|
-
ParamType = Union[DownloadParams, FlashParams]
|
12
|
+
from .common import DownloadParams, FlashParams, ParamType
|
13
|
+
from .config import config
|
14
|
+
from .mpboard_id import get_known_boards_for_port, get_known_ports, known_stored_boards
|
15
|
+
from .mpremoteboard import MPRemoteBoard
|
16
|
+
from .vendor.versions import micropython_versions
|
44
17
|
|
45
18
|
|
46
19
|
def ask_missing_params(
|
47
20
|
params: ParamType,
|
48
|
-
action: str = "download",
|
49
21
|
) -> ParamType:
|
50
22
|
"""
|
51
23
|
Asks the user for parameters that have not been supplied on the commandline and returns the updated params.
|
52
24
|
|
53
25
|
Args:
|
54
26
|
params (ParamType): The parameters to be updated.
|
55
|
-
action (str, optional): The action to be performed. Defaults to "download".
|
56
27
|
|
57
28
|
Returns:
|
58
29
|
ParamType: The updated parameters.
|
59
30
|
"""
|
31
|
+
import inquirer
|
32
|
+
|
33
|
+
log.trace(f"ask_missing_params: {params}")
|
34
|
+
|
35
|
+
# if action flash, single input
|
36
|
+
# if action download, multiple input
|
37
|
+
multi_select = isinstance(params, DownloadParams)
|
38
|
+
action = "download" if isinstance(params, DownloadParams) else "flash"
|
60
39
|
if not config.interactive:
|
61
40
|
# no interactivity allowed
|
62
41
|
return params
|
63
|
-
# import only when needed to reduce load time
|
64
|
-
import inquirer
|
65
42
|
|
66
43
|
questions = []
|
67
|
-
answers = {"action": action}
|
68
|
-
if
|
44
|
+
answers: dict[str, Union[str, List]] = {"action": action}
|
45
|
+
if not multi_select:
|
69
46
|
if not params.serial or "?" in params.serial:
|
70
|
-
ask_serialport(
|
47
|
+
questions.append(ask_serialport(multi_select=False, bluetooth=False))
|
71
48
|
else:
|
72
49
|
answers["serial"] = params.serial
|
73
50
|
|
74
|
-
if
|
75
|
-
|
51
|
+
if params.versions == [] or "?" in params.versions:
|
52
|
+
questions.append(ask_mp_version(multi_select=multi_select, action=action))
|
76
53
|
else:
|
77
54
|
# versions is used to show only the boards for the selected versions
|
78
55
|
answers["versions"] = params.versions # type: ignore
|
79
56
|
|
80
57
|
if not params.boards or "?" in params.boards:
|
81
|
-
ask_port_board(
|
82
|
-
|
83
|
-
|
58
|
+
questions.extend(ask_port_board(multi_select=multi_select, action=action))
|
59
|
+
if questions:
|
60
|
+
answers = inquirer.prompt(questions, answers=answers) # type: ignore
|
84
61
|
if not answers:
|
85
62
|
# input cancelled by user
|
86
63
|
return [] # type: ignore
|
87
|
-
|
64
|
+
log.trace(f"answers: {answers}")
|
88
65
|
if isinstance(params, FlashParams) and "serial" in answers:
|
89
|
-
|
66
|
+
if isinstance(answers["serial"], str):
|
67
|
+
answers["serial"] = [answers["serial"]]
|
68
|
+
params.serial = [s.split()[0] for s in answers["serial"]] # split to remove the description
|
90
69
|
if "port" in answers:
|
91
|
-
params.ports = [
|
70
|
+
params.ports = [p for p in params.ports if p != "?"] # remove the "?" if present
|
71
|
+
params.ports.extend(answers["port"])
|
92
72
|
if "boards" in answers:
|
93
|
-
params.boards =
|
73
|
+
params.boards = [b for b in params.boards if b != "?"] # remove the "?" if present
|
74
|
+
params.boards.extend(answers["boards"] if isinstance(answers["boards"], list) else [answers["boards"]])
|
94
75
|
if "versions" in answers:
|
76
|
+
params.versions = [v for v in params.versions if v != "?"] # remove the "?" if present
|
95
77
|
# make sure it is a list
|
96
|
-
|
97
|
-
|
98
|
-
|
78
|
+
if isinstance(answers["versions"], (list, tuple)):
|
79
|
+
params.versions.extend(answers["versions"])
|
80
|
+
else:
|
81
|
+
params.versions.append(answers["versions"])
|
82
|
+
# remove duplicates
|
83
|
+
params.ports = list(set(params.ports))
|
84
|
+
params.boards = list(set(params.boards))
|
85
|
+
params.versions = list(set(params.versions))
|
86
|
+
log.trace(f"ask_missing_params returns: {params}")
|
99
87
|
|
100
88
|
return params
|
101
89
|
|
@@ -110,19 +98,18 @@ def filter_matching_boards(answers: dict) -> Sequence[Tuple[str, str]]:
|
|
110
98
|
Returns:
|
111
99
|
Sequence[Tuple[str, str]]: The filtered boards.
|
112
100
|
"""
|
101
|
+
versions = None
|
113
102
|
# if version is not asked ; then need to get the version from the inputs
|
114
103
|
if "versions" in answers:
|
115
|
-
|
116
|
-
if "stable" in
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
else:
|
125
|
-
some_boards = known_stored_boards(answers["port"])
|
104
|
+
versions = list(answers["versions"])
|
105
|
+
if "stable" in versions:
|
106
|
+
versions.remove("stable")
|
107
|
+
versions.append(micropython_versions()[-2]) # latest stable
|
108
|
+
elif "preview" in versions:
|
109
|
+
versions.remove("preview")
|
110
|
+
versions.extend((micropython_versions()[-1], micropython_versions()[-2])) # latest preview and stable
|
111
|
+
|
112
|
+
some_boards = known_stored_boards(answers["port"], versions) # or known_mp_boards(answers["port"])
|
126
113
|
|
127
114
|
if some_boards:
|
128
115
|
# Create a dictionary where the keys are the second elements of the tuples
|
@@ -131,11 +118,11 @@ def filter_matching_boards(answers: dict) -> Sequence[Tuple[str, str]]:
|
|
131
118
|
# Get the values of the dictionary, which are the unique items from the original list
|
132
119
|
some_boards = list(unique_dict.values())
|
133
120
|
else:
|
134
|
-
some_boards = [(f"No {answers['port']} boards found for version(s) {
|
121
|
+
some_boards = [(f"No {answers['port']} boards found for version(s) {versions}", "")]
|
135
122
|
return some_boards
|
136
123
|
|
137
124
|
|
138
|
-
def ask_port_board(
|
125
|
+
def ask_port_board(*, multi_select: bool, action: str):
|
139
126
|
"""
|
140
127
|
Asks the user for the port and board selection.
|
141
128
|
|
@@ -149,31 +136,28 @@ def ask_port_board(questions: list, *, action: str):
|
|
149
136
|
# import only when needed to reduce load time
|
150
137
|
import inquirer
|
151
138
|
|
152
|
-
#
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
if action == "flash"
|
167
|
-
else "?"
|
168
|
-
),
|
169
|
-
choices=filter_matching_boards,
|
170
|
-
validate=lambda _, x: True if x else "Please select at least one board", # type: ignore
|
139
|
+
# if action flash, single input
|
140
|
+
# if action download, multiple input
|
141
|
+
inquirer_ux = inquirer.Checkbox if multi_select else inquirer.List
|
142
|
+
return [
|
143
|
+
inquirer.List(
|
144
|
+
"port",
|
145
|
+
message="Which port do you want to {action} " + "to {serial} ?" if action == "flash" else "?",
|
146
|
+
choices=get_known_ports(),
|
147
|
+
# autocomplete=True,
|
148
|
+
),
|
149
|
+
inquirer_ux(
|
150
|
+
"boards",
|
151
|
+
message=(
|
152
|
+
"Which {port} board firmware do you want to {action} " + "to {serial} ?" if action == "flash" else "?"
|
171
153
|
),
|
172
|
-
|
173
|
-
|
154
|
+
choices=filter_matching_boards,
|
155
|
+
validate=lambda _, x: True if x else "Please select at least one board", # type: ignore
|
156
|
+
),
|
157
|
+
]
|
174
158
|
|
175
159
|
|
176
|
-
def
|
160
|
+
def ask_mp_version(multi_select: bool, action: str):
|
177
161
|
"""
|
178
162
|
Asks the user for the version selection.
|
179
163
|
|
@@ -182,46 +166,43 @@ def ask_versions(questions: list, *, action: str):
|
|
182
166
|
action (str): The action to be performed.
|
183
167
|
|
184
168
|
Returns:
|
185
|
-
|
169
|
+
|
186
170
|
"""
|
187
171
|
# import only when needed to reduce load time
|
188
172
|
import inquirer
|
189
173
|
import inquirer.errors
|
190
174
|
|
191
|
-
input_ux = inquirer.Checkbox if
|
175
|
+
input_ux = inquirer.Checkbox if multi_select else inquirer.List
|
176
|
+
|
192
177
|
mp_versions: List[str] = micropython_versions()
|
193
|
-
mp_versions
|
178
|
+
mp_versions.reverse() # newest first
|
194
179
|
|
195
180
|
# remove the versions for which there are no known boards in the board_info.json
|
196
181
|
# todo: this may be a little slow
|
197
|
-
mp_versions = [v for v in mp_versions if
|
198
|
-
|
199
|
-
mp_versions.append("preview")
|
200
|
-
mp_versions.reverse() # newest first
|
182
|
+
mp_versions = [v for v in mp_versions if "preview" in v or get_known_boards_for_port("stm32", [v])]
|
201
183
|
|
202
184
|
def at_least_one_validation(answers, current) -> bool:
|
203
185
|
if not current:
|
204
186
|
raise inquirer.errors.ValidationError("", reason="Please select at least one version")
|
205
|
-
if isinstance(current, list):
|
206
|
-
|
207
|
-
raise inquirer.errors.ValidationError("", reason="Please select at least one version")
|
187
|
+
if isinstance(current, list) and not any(current):
|
188
|
+
raise inquirer.errors.ValidationError("", reason="Please select at least one version")
|
208
189
|
return True
|
209
190
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
)
|
191
|
+
message = "Which version(s) do you want to {action} " + ("to {serial} ?" if action == "flash" else "?")
|
192
|
+
q = input_ux(
|
193
|
+
# inquirer.List(
|
194
|
+
"versions",
|
195
|
+
message=message,
|
196
|
+
# Hints would be nice , but needs a hint for each and every option
|
197
|
+
# hints=["Use space to select multiple options"],
|
198
|
+
choices=mp_versions,
|
199
|
+
autocomplete=True,
|
200
|
+
validate=at_least_one_validation, # type: ignore
|
221
201
|
)
|
202
|
+
return q
|
222
203
|
|
223
204
|
|
224
|
-
def ask_serialport(
|
205
|
+
def ask_serialport(*, multi_select: bool = False, bluetooth: bool = False):
|
225
206
|
"""
|
226
207
|
Asks the user for the serial port selection.
|
227
208
|
|
@@ -235,15 +216,11 @@ def ask_serialport(questions: list, *, action: str):
|
|
235
216
|
# import only when needed to reduce load time
|
236
217
|
import inquirer
|
237
218
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
validate=lambda _, x: True if x else "Please select or enter a serial port", # type: ignore
|
246
|
-
)
|
219
|
+
comports = MPRemoteBoard.connected_boards(bluetooth=bluetooth, description=True)
|
220
|
+
return inquirer.List(
|
221
|
+
"serial",
|
222
|
+
message="Which serial port do you want to {action} ?",
|
223
|
+
choices=comports,
|
224
|
+
other=True,
|
225
|
+
validate=lambda _, x: True if x else "Please select or enter a serial port", # type: ignore
|
247
226
|
)
|
248
|
-
|
249
|
-
return questions
|
mpflash/mpflash/cli_download.py
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
"""CLI to Download MicroPython firmware for specific ports, boards and versions."""
|
2
2
|
|
3
3
|
from pathlib import Path
|
4
|
-
from typing import List, Tuple
|
5
4
|
|
6
5
|
import rich_click as click
|
7
6
|
from loguru import logger as log
|
8
7
|
|
8
|
+
from mpflash.connected import connected_ports_boards
|
9
9
|
from mpflash.errors import MPFlashError
|
10
|
-
from mpflash.mpboard_id import
|
10
|
+
from mpflash.mpboard_id import find_known_board
|
11
11
|
from mpflash.vendor.versions import clean_version
|
12
12
|
|
13
|
-
from .ask_input import
|
13
|
+
from .ask_input import ask_missing_params
|
14
14
|
from .cli_group import cli
|
15
|
-
from .
|
15
|
+
from .common import DownloadParams
|
16
16
|
from .config import config
|
17
17
|
from .download import download
|
18
18
|
|
@@ -50,6 +50,28 @@ from .download import download
|
|
50
50
|
help="The board(s) to download the firmware for.",
|
51
51
|
metavar="BOARD_ID or ?",
|
52
52
|
)
|
53
|
+
@click.option(
|
54
|
+
"--serial",
|
55
|
+
"--serial-port",
|
56
|
+
"-s",
|
57
|
+
"serial",
|
58
|
+
default=["*"],
|
59
|
+
show_default=True,
|
60
|
+
multiple=True,
|
61
|
+
help="Which serial port(s) to flash",
|
62
|
+
metavar="SERIALPORT",
|
63
|
+
)
|
64
|
+
@click.option(
|
65
|
+
"--ignore",
|
66
|
+
"-i",
|
67
|
+
is_eager=True,
|
68
|
+
help="Serial port(s) to ignore. Defaults to MPFLASH_IGNORE.",
|
69
|
+
multiple=True,
|
70
|
+
default=[],
|
71
|
+
envvar="MPFLASH_IGNORE",
|
72
|
+
show_default=True,
|
73
|
+
metavar="SERIALPORT",
|
74
|
+
)
|
53
75
|
@click.option(
|
54
76
|
"--clean/--no-clean",
|
55
77
|
default=True,
|
@@ -67,14 +89,25 @@ def cli_download(**kwargs) -> int:
|
|
67
89
|
params = DownloadParams(**kwargs)
|
68
90
|
params.versions = list(params.versions)
|
69
91
|
params.boards = list(params.boards)
|
92
|
+
params.serial = list(params.serial)
|
93
|
+
params.ignore = list(params.ignore)
|
94
|
+
|
95
|
+
# all_boards: List[MPRemoteBoard] = []
|
70
96
|
if params.boards:
|
71
|
-
|
72
|
-
|
97
|
+
if not params.ports:
|
98
|
+
# no ports specified - resolve ports from specified boards by resolving board IDs
|
99
|
+
for board in params.boards:
|
100
|
+
if board != "?":
|
101
|
+
try:
|
102
|
+
board_ = find_known_board(board)
|
103
|
+
params.ports.append(board_.port)
|
104
|
+
except MPFlashError as e:
|
105
|
+
log.error(f"{e}")
|
73
106
|
else:
|
74
|
-
# no boards specified - detect connected boards
|
75
|
-
params.ports, params.boards = connected_ports_boards()
|
107
|
+
# no boards specified - detect connected ports and boards
|
108
|
+
params.ports, params.boards, _ = connected_ports_boards(include=params.serial, ignore=params.ignore)
|
76
109
|
|
77
|
-
params = ask_missing_params(params
|
110
|
+
params = ask_missing_params(params)
|
78
111
|
if not params: # Cancelled by user
|
79
112
|
return 2
|
80
113
|
params.versions = [clean_version(v, drop_v=True) for v in params.versions]
|
@@ -93,19 +126,3 @@ def cli_download(**kwargs) -> int:
|
|
93
126
|
except MPFlashError as e:
|
94
127
|
log.error(f"{e}")
|
95
128
|
return 1
|
96
|
-
|
97
|
-
|
98
|
-
def connected_ports_boards() -> Tuple[List[str], List[str]]:
|
99
|
-
"""
|
100
|
-
Returns a tuple containing lists of unique ports and boards from the connected MCUs.
|
101
|
-
Boards that are physically connected, but give no tangible response are ignored.
|
102
|
-
|
103
|
-
Returns:
|
104
|
-
A tuple containing two lists:
|
105
|
-
- A list of unique ports where MCUs are connected.
|
106
|
-
- A list of unique board names of the connected MCUs.
|
107
|
-
"""
|
108
|
-
mpr_boards = [b for b in list_mcus() if b.connected]
|
109
|
-
ports = list({b.port for b in mpr_boards})
|
110
|
-
boards = list({b.board for b in mpr_boards})
|
111
|
-
return ports, boards
|
mpflash/mpflash/cli_flash.py
CHANGED
@@ -1,19 +1,23 @@
|
|
1
1
|
from pathlib import Path
|
2
|
+
from typing import List
|
2
3
|
|
3
4
|
import rich_click as click
|
4
5
|
from loguru import logger as log
|
5
6
|
|
7
|
+
# from mpflash.common import filtered_comports
|
6
8
|
from mpflash.errors import MPFlashError
|
7
|
-
from mpflash.mpboard_id import
|
9
|
+
from mpflash.mpboard_id import find_known_board
|
10
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
8
11
|
from mpflash.vendor.versions import clean_version
|
9
12
|
|
10
|
-
from .ask_input import
|
13
|
+
from .ask_input import ask_missing_params
|
11
14
|
from .cli_download import connected_ports_boards
|
12
15
|
from .cli_group import cli
|
13
16
|
from .cli_list import show_mcus
|
17
|
+
from .common import FlashParams
|
14
18
|
from .config import config
|
15
19
|
from .flash import flash_list
|
16
|
-
from .worklist import
|
20
|
+
from .worklist import WorkList, full_auto_worklist, manual_worklist, single_auto_worklist
|
17
21
|
|
18
22
|
# #########################################################################################################
|
19
23
|
# CLI
|
@@ -48,10 +52,22 @@ from .worklist import MPRemoteBoard, WorkList, full_auto_worklist, manual_workli
|
|
48
52
|
"--serial-port",
|
49
53
|
"-s",
|
50
54
|
"serial",
|
51
|
-
default="
|
55
|
+
default=["*"],
|
56
|
+
multiple=True,
|
52
57
|
show_default=True,
|
53
58
|
help="Which serial port(s) to flash",
|
54
|
-
metavar="
|
59
|
+
metavar="SERIALPORT",
|
60
|
+
)
|
61
|
+
@click.option(
|
62
|
+
"--ignore",
|
63
|
+
"-i",
|
64
|
+
is_eager=True,
|
65
|
+
help="Serial port(s) to ignore. Defaults to MPFLASH_IGNORE.",
|
66
|
+
multiple=True,
|
67
|
+
default=[],
|
68
|
+
envvar="MPFLASH_IGNORE",
|
69
|
+
show_default=True,
|
70
|
+
metavar="SERIALPORT",
|
55
71
|
)
|
56
72
|
@click.option(
|
57
73
|
"--port",
|
@@ -101,31 +117,31 @@ def cli_flash_board(**kwargs) -> int:
|
|
101
117
|
kwargs["boards"] = [kwargs.pop("board")]
|
102
118
|
|
103
119
|
params = FlashParams(**kwargs)
|
120
|
+
params.versions = list(params.versions)
|
121
|
+
params.boards = list(params.boards)
|
122
|
+
params.serial = list(params.serial)
|
123
|
+
params.ignore = list(params.ignore)
|
124
|
+
|
125
|
+
# make it simple for the user to flash one board by asking for the serial port if not specified
|
126
|
+
if params.boards == ["?"] and params.serial == "*":
|
127
|
+
params.serial = ["?"]
|
128
|
+
|
129
|
+
# Detect connected boards if not specified,
|
130
|
+
# and ask for input if boards cannot be detected
|
131
|
+
all_boards: List[MPRemoteBoard] = []
|
104
132
|
if not params.boards or params.boards == []:
|
105
133
|
# nothing specified - detect connected boards
|
106
|
-
params.ports, params.boards = connected_ports_boards()
|
134
|
+
params.ports, params.boards, all_boards = connected_ports_boards(include=params.ports, ignore=params.ignore)
|
107
135
|
if params.boards == []:
|
108
136
|
# No MicroPython boards detected, but it could be unflashed or not in bootloader mode
|
109
137
|
# Ask for serial port and board_id to flash
|
110
|
-
params.serial = "?"
|
138
|
+
params.serial = ["?"]
|
111
139
|
params.boards = ["?"]
|
112
140
|
else:
|
113
|
-
|
114
|
-
if board_id == "":
|
115
|
-
params.boards.remove(board_id)
|
116
|
-
continue
|
117
|
-
if " " in board_id:
|
118
|
-
try:
|
119
|
-
info = find_stored_board(board_id)
|
120
|
-
if info:
|
121
|
-
log.info(f"Resolved board description: {info['board']}")
|
122
|
-
params.boards.remove(board_id)
|
123
|
-
params.boards.append(info["board"])
|
124
|
-
except Exception as e:
|
125
|
-
log.warning(f"unable to resolve board description: {e}")
|
141
|
+
resolve_board_ids(params)
|
126
142
|
|
127
143
|
# Ask for missing input if needed
|
128
|
-
params = ask_missing_params(params
|
144
|
+
params = ask_missing_params(params)
|
129
145
|
if not params: # Cancelled by user
|
130
146
|
return 2
|
131
147
|
# TODO: Just in time Download of firmware
|
@@ -135,27 +151,33 @@ def cli_flash_board(**kwargs) -> int:
|
|
135
151
|
if len(params.versions) > 1:
|
136
152
|
log.error(f"Only one version can be flashed at a time, not {params.versions}")
|
137
153
|
raise MPFlashError("Only one version can be flashed at a time")
|
138
|
-
# if len(params.boards) > 1:
|
139
|
-
# log.error(f"Only one board can be flashed at a time, not {params.boards}")
|
140
|
-
# raise MPFlashError("Only one board can be flashed at a time")
|
141
154
|
|
142
155
|
params.versions = [clean_version(v) for v in params.versions]
|
143
156
|
worklist: WorkList = []
|
144
157
|
# if serial port == auto and there are one or more specified/detected boards
|
145
|
-
if params.serial == "
|
146
|
-
|
158
|
+
if params.serial == ["*"] and params.boards:
|
159
|
+
if not all_boards:
|
160
|
+
log.trace("No boards detected yet, scanning for connected boards")
|
161
|
+
_, _, all_boards = connected_ports_boards(include=params.ports, ignore=params.ignore)
|
162
|
+
worklist = full_auto_worklist(
|
163
|
+
all_boards=all_boards,
|
164
|
+
version=params.versions[0],
|
165
|
+
fw_folder=params.fw_folder,
|
166
|
+
include=params.serial,
|
167
|
+
ignore=params.ignore,
|
168
|
+
)
|
147
169
|
elif params.versions[0] and params.boards[0] and params.serial:
|
148
|
-
# A
|
170
|
+
# A one or more serial port including the board / variant
|
149
171
|
worklist = manual_worklist(
|
150
|
-
params.
|
151
|
-
params.
|
152
|
-
params.
|
153
|
-
params.
|
172
|
+
params.serial[0],
|
173
|
+
board_id=params.boards[0],
|
174
|
+
version=params.versions[0],
|
175
|
+
fw_folder=params.fw_folder,
|
154
176
|
)
|
155
177
|
else:
|
156
178
|
# just this serial port on auto
|
157
179
|
worklist = single_auto_worklist(
|
158
|
-
|
180
|
+
serial=params.serial[0],
|
159
181
|
version=params.versions[0],
|
160
182
|
fw_folder=params.fw_folder,
|
161
183
|
)
|
@@ -172,3 +194,19 @@ def cli_flash_board(**kwargs) -> int:
|
|
172
194
|
else:
|
173
195
|
log.error("No boards were flashed")
|
174
196
|
return 1
|
197
|
+
|
198
|
+
|
199
|
+
def resolve_board_ids(params):
|
200
|
+
"""Resolve board descriptions to board_id, and remove empty strings from list of boards"""
|
201
|
+
for board_id in params.boards:
|
202
|
+
if board_id == "":
|
203
|
+
params.boards.remove(board_id)
|
204
|
+
continue
|
205
|
+
if " " in board_id:
|
206
|
+
try:
|
207
|
+
if info := find_known_board(board_id):
|
208
|
+
log.info(f"Resolved board description: {info.board_id}")
|
209
|
+
params.boards.remove(board_id)
|
210
|
+
params.boards.append(info.board_id)
|
211
|
+
except Exception as e:
|
212
|
+
log.warning(f"Unable to resolve board description: {e}")
|
mpflash/mpflash/cli_group.py
CHANGED
@@ -5,30 +5,34 @@ Additional comands are added in the submodules.
|
|
5
5
|
|
6
6
|
import rich_click as click
|
7
7
|
|
8
|
-
from .config import config
|
9
|
-
from .logger import make_quiet, set_loglevel
|
8
|
+
from .config import __version__, config
|
9
|
+
from .logger import log, make_quiet, set_loglevel
|
10
10
|
|
11
11
|
|
12
12
|
def cb_verbose(ctx, param, value):
|
13
13
|
"""Callback to set the log level to DEBUG if verbose is set"""
|
14
14
|
if value and not config.quiet:
|
15
|
-
set_loglevel("DEBUG")
|
16
15
|
config.verbose = True
|
16
|
+
if value > 1:
|
17
|
+
set_loglevel("TRACE")
|
18
|
+
else:
|
19
|
+
set_loglevel("DEBUG")
|
20
|
+
log.debug(f"version: {__version__}")
|
17
21
|
else:
|
18
22
|
set_loglevel("INFO")
|
19
23
|
config.verbose = False
|
20
24
|
return value
|
21
25
|
|
22
26
|
|
23
|
-
def
|
27
|
+
def cb_interactive(ctx, param, value):
|
24
28
|
if value:
|
25
|
-
config.
|
29
|
+
config.interactive = value
|
26
30
|
return value
|
27
31
|
|
28
32
|
|
29
|
-
def
|
33
|
+
def cb_test(ctx, param, value):
|
30
34
|
if value:
|
31
|
-
config.
|
35
|
+
config.tests = value
|
32
36
|
return value
|
33
37
|
|
34
38
|
|
@@ -64,21 +68,20 @@ def cb_quiet(ctx, param, value):
|
|
64
68
|
"-V",
|
65
69
|
"--verbose",
|
66
70
|
is_eager=True,
|
67
|
-
|
71
|
+
count=True,
|
68
72
|
help="Enables verbose mode.",
|
69
73
|
callback=cb_verbose,
|
70
74
|
)
|
71
75
|
@click.option(
|
72
|
-
"--
|
73
|
-
"-i",
|
76
|
+
"--test",
|
74
77
|
is_eager=True,
|
75
|
-
help="
|
76
|
-
callback=
|
78
|
+
help="test a specific feature",
|
79
|
+
callback=cb_test,
|
77
80
|
multiple=True,
|
78
81
|
default=[],
|
79
|
-
envvar="
|
82
|
+
envvar="MPFLASH_TEST",
|
80
83
|
show_default=True,
|
81
|
-
metavar="
|
84
|
+
metavar="TEST",
|
82
85
|
)
|
83
86
|
def cli(**kwargs):
|
84
87
|
"""mpflash - MicroPython Tool.
|