mpflash 1.25.0rc4__py3-none-any.whl → 1.25.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.
- mpflash/basicgit.py +19 -0
- mpflash/cli_add.py +131 -0
- mpflash/cli_download.py +3 -14
- mpflash/cli_flash.py +44 -26
- mpflash/cli_group.py +1 -0
- mpflash/cli_list.py +2 -0
- mpflash/cli_main.py +7 -0
- mpflash/common.py +14 -2
- mpflash/config.py +22 -1
- mpflash/connected.py +8 -6
- mpflash/custom/__init__.py +144 -0
- mpflash/custom/naming.py +91 -0
- mpflash/db/core.py +84 -6
- mpflash/db/gather_boards.py +6 -4
- mpflash/db/loader.py +4 -3
- mpflash/db/meta.py +4 -3
- mpflash/db/micropython_boards.zip +0 -0
- mpflash/db/models.py +2 -0
- mpflash/download/__init__.py +58 -1
- mpflash/download/fwinfo.py +1 -1
- mpflash/download/jid.py +1 -1
- mpflash/downloaded.py +8 -4
- mpflash/flash/__init__.py +10 -1
- mpflash/flash/uf2/windows.py +1 -1
- mpflash/flash/worklist.py +40 -19
- mpflash/list.py +2 -0
- mpflash/logger.py +27 -7
- mpflash/mpboard_id/board_id.py +13 -17
- mpflash/mpboard_id/known.py +8 -2
- mpflash/mpremoteboard/__init__.py +61 -3
- mpflash/mpremoteboard/runner.py +1 -0
- {mpflash-1.25.0rc4.dist-info → mpflash-1.25.2.dist-info}/METADATA +63 -10
- {mpflash-1.25.0rc4.dist-info → mpflash-1.25.2.dist-info}/RECORD +36 -34
- {mpflash-1.25.0rc4.dist-info → mpflash-1.25.2.dist-info}/WHEEL +1 -1
- mpflash/add_firmware.py +0 -125
- {mpflash-1.25.0rc4.dist-info → mpflash-1.25.2.dist-info}/LICENSE +0 -0
- {mpflash-1.25.0rc4.dist-info → mpflash-1.25.2.dist-info}/entry_points.txt +0 -0
mpflash/basicgit.py
CHANGED
@@ -135,6 +135,25 @@ def get_local_tags(repo: Optional[Path] = None, minver: Optional[str] = None) ->
|
|
135
135
|
return sorted(tags)
|
136
136
|
|
137
137
|
|
138
|
+
def get_current_branch(repo: Optional[Union[Path, str]] = None) -> Optional[str]:
|
139
|
+
"""
|
140
|
+
Get the current branch name of a local repository.
|
141
|
+
|
142
|
+
Args:
|
143
|
+
repo: Path to the repository directory
|
144
|
+
|
145
|
+
Returns:
|
146
|
+
Current branch name or None if error
|
147
|
+
"""
|
148
|
+
cmd = ["git", "branch", "--show-current"]
|
149
|
+
result = _run_local_git(cmd, repo=repo, expect_stderr=True)
|
150
|
+
if not result:
|
151
|
+
return None
|
152
|
+
|
153
|
+
branch = result.stdout.strip()
|
154
|
+
return branch if branch else None
|
155
|
+
|
156
|
+
|
138
157
|
@cachetools.func.ttl_cache(maxsize=16, ttl=60) # 60 seconds
|
139
158
|
def get_tags(repo: str, minver: Optional[str] = None) -> List[str]:
|
140
159
|
"""
|
mpflash/cli_add.py
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
"""CLI to add a custom MicroPython firmware."""
|
2
|
+
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import Union
|
5
|
+
|
6
|
+
import rich_click as click
|
7
|
+
from loguru import logger as log
|
8
|
+
|
9
|
+
from mpflash.connected import connected_ports_boards_variants
|
10
|
+
from mpflash.custom import Firmware, add_firmware, custom_fw_from_path
|
11
|
+
from mpflash.downloaded import clean_downloaded_firmwares
|
12
|
+
from mpflash.errors import MPFlashError
|
13
|
+
from mpflash.mpboard_id import find_known_board
|
14
|
+
from mpflash.mpboard_id.alternate import add_renamed_boards
|
15
|
+
from mpflash.versions import clean_version
|
16
|
+
|
17
|
+
from .ask_input import ask_missing_params
|
18
|
+
from .cli_group import cli
|
19
|
+
from .config import config
|
20
|
+
from .download import download
|
21
|
+
|
22
|
+
|
23
|
+
@cli.command(
|
24
|
+
"add",
|
25
|
+
help="Add a custom MicroPython firmware.",
|
26
|
+
)
|
27
|
+
# @click.option(
|
28
|
+
# "--version",
|
29
|
+
# "-v",
|
30
|
+
# "versions",
|
31
|
+
# default=["stable"],
|
32
|
+
# multiple=False,
|
33
|
+
# show_default=True,
|
34
|
+
# help="The version of MicroPython to to download.",
|
35
|
+
# metavar="SEMVER, 'stable', 'preview' or '?'",
|
36
|
+
# )
|
37
|
+
@click.option(
|
38
|
+
"--path",
|
39
|
+
"-p",
|
40
|
+
"fw_path",
|
41
|
+
multiple=False,
|
42
|
+
default="",
|
43
|
+
show_default=False,
|
44
|
+
help="a local path to the firmware file to add.",
|
45
|
+
metavar="FIRMWARE_PATH",
|
46
|
+
)
|
47
|
+
@click.option(
|
48
|
+
"--description",
|
49
|
+
"-d",
|
50
|
+
"description",
|
51
|
+
default="",
|
52
|
+
help="An Optional description for the firmware.",
|
53
|
+
metavar="TXT",
|
54
|
+
)
|
55
|
+
# @click.option(
|
56
|
+
# "--board",
|
57
|
+
# "-b",
|
58
|
+
# "boards",
|
59
|
+
# multiple=True,
|
60
|
+
# default=[],
|
61
|
+
# show_default=True,
|
62
|
+
# help="The board(s) to download the firmware for.",
|
63
|
+
# metavar="BOARD_ID or ?",
|
64
|
+
# )
|
65
|
+
# @click.option(
|
66
|
+
# "--serial",
|
67
|
+
# "--serial-port",
|
68
|
+
# "-s",
|
69
|
+
# "serial",
|
70
|
+
# default=["*"],
|
71
|
+
# show_default=True,
|
72
|
+
# multiple=True,
|
73
|
+
# help="Which serial port(s) (or globs) to flash",
|
74
|
+
# metavar="SERIALPORT",
|
75
|
+
# )
|
76
|
+
# @click.option(
|
77
|
+
# "--ignore",
|
78
|
+
# "-i",
|
79
|
+
# is_eager=True,
|
80
|
+
# help="Serial port(s) to ignore. Defaults to MPFLASH_IGNORE.",
|
81
|
+
# multiple=True,
|
82
|
+
# default=[],
|
83
|
+
# envvar="MPFLASH_IGNORE",
|
84
|
+
# show_default=True,
|
85
|
+
# metavar="SERIALPORT",
|
86
|
+
# )
|
87
|
+
# @click.option(
|
88
|
+
# "--clean/--no-clean",
|
89
|
+
# default=True,
|
90
|
+
# show_default=True,
|
91
|
+
# help="""Remove dates and hashes from the downloaded firmware filenames.""",
|
92
|
+
# )
|
93
|
+
@click.option(
|
94
|
+
"--force",
|
95
|
+
"-f",
|
96
|
+
default=False,
|
97
|
+
is_flag=True,
|
98
|
+
show_default=True,
|
99
|
+
help="""Overwrite existing firmware.""",
|
100
|
+
)
|
101
|
+
def cli_add_custom(
|
102
|
+
fw_path: Union[Path, str],
|
103
|
+
force: bool = False,
|
104
|
+
description: str = "",
|
105
|
+
) -> int:
|
106
|
+
"""Add a custom MicroPython firmware from a local file."""
|
107
|
+
if not fw_path:
|
108
|
+
log.error("No firmware path provided. Use --path to specify a firmware file.")
|
109
|
+
return 1
|
110
|
+
fw_path = Path(fw_path).expanduser().resolve()
|
111
|
+
if not fw_path.exists():
|
112
|
+
log.error(f"Firmware file does not exist: {fw_path}")
|
113
|
+
return 1
|
114
|
+
|
115
|
+
try:
|
116
|
+
fw_dict = custom_fw_from_path(fw_path)
|
117
|
+
if description:
|
118
|
+
fw_dict["description"] = description
|
119
|
+
if add_firmware(
|
120
|
+
source=fw_path,
|
121
|
+
fw_info=fw_dict,
|
122
|
+
custom=True,
|
123
|
+
force=force,
|
124
|
+
):
|
125
|
+
log.success(f"Added custom firmware: {fw_dict['custom_id']} for {fw_dict['firmware_file']}")
|
126
|
+
return 0
|
127
|
+
else:
|
128
|
+
return 1
|
129
|
+
except MPFlashError as e:
|
130
|
+
log.error(f"{e}")
|
131
|
+
return 1
|
mpflash/cli_download.py
CHANGED
@@ -2,10 +2,11 @@
|
|
2
2
|
|
3
3
|
from pathlib import Path
|
4
4
|
|
5
|
+
from pytest import param
|
5
6
|
import rich_click as click
|
6
7
|
from loguru import logger as log
|
7
8
|
|
8
|
-
from mpflash.connected import
|
9
|
+
from mpflash.connected import connected_ports_boards_variants
|
9
10
|
from mpflash.downloaded import clean_downloaded_firmwares
|
10
11
|
from mpflash.errors import MPFlashError
|
11
12
|
from mpflash.mpboard_id import find_known_board
|
@@ -23,15 +24,6 @@ from .download import download
|
|
23
24
|
"download",
|
24
25
|
help="Download MicroPython firmware for specific ports, boards and versions.",
|
25
26
|
)
|
26
|
-
@click.option(
|
27
|
-
"--destination",
|
28
|
-
"-d",
|
29
|
-
"fw_folder",
|
30
|
-
type=click.Path(file_okay=False, dir_okay=True, path_type=Path),
|
31
|
-
default=None,
|
32
|
-
show_default=False,
|
33
|
-
help="The folder to download the firmware to.",
|
34
|
-
)
|
35
27
|
@click.option(
|
36
28
|
"--version",
|
37
29
|
"-v",
|
@@ -94,9 +86,6 @@ def cli_download(**kwargs) -> int:
|
|
94
86
|
params.boards = list(params.boards)
|
95
87
|
params.serial = list(params.serial)
|
96
88
|
params.ignore = list(params.ignore)
|
97
|
-
if params.fw_folder:
|
98
|
-
config.firmware_folder = Path(params.fw_folder)
|
99
|
-
# all_boards: List[MPRemoteBoard] = []
|
100
89
|
if params.boards:
|
101
90
|
if not params.ports:
|
102
91
|
# no ports specified - resolve ports from specified boards by resolving board IDs
|
@@ -109,7 +98,7 @@ def cli_download(**kwargs) -> int:
|
|
109
98
|
log.error(f"{e}")
|
110
99
|
else:
|
111
100
|
# no boards specified - detect connected ports and boards
|
112
|
-
params.ports, params.boards, _ =
|
101
|
+
params.ports, params.boards, _ , _ = connected_ports_boards_variants(include=params.serial, ignore=params.ignore)
|
113
102
|
|
114
103
|
params = ask_missing_params(params)
|
115
104
|
if not params: # Cancelled by user
|
mpflash/cli_flash.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
from pathlib import Path
|
2
1
|
from typing import List
|
3
2
|
|
4
3
|
import rich_click as click
|
@@ -7,11 +6,10 @@ from loguru import logger as log
|
|
7
6
|
import mpflash.download.jid as jid
|
8
7
|
import mpflash.mpboard_id as mpboard_id
|
9
8
|
from mpflash.ask_input import ask_missing_params
|
10
|
-
from mpflash.cli_download import
|
9
|
+
from mpflash.cli_download import connected_ports_boards_variants
|
11
10
|
from mpflash.cli_group import cli
|
12
11
|
from mpflash.cli_list import show_mcus
|
13
|
-
from mpflash.common import BootloaderMethod, FlashParams,
|
14
|
-
from mpflash.config import config
|
12
|
+
from mpflash.common import BootloaderMethod, FlashParams, filtered_comports
|
15
13
|
from mpflash.errors import MPFlashError
|
16
14
|
from mpflash.flash import flash_list
|
17
15
|
from mpflash.flash.worklist import WorkList, full_auto_worklist, manual_worklist, single_auto_worklist
|
@@ -27,15 +25,6 @@ from mpflash.versions import clean_version
|
|
27
25
|
"flash",
|
28
26
|
short_help="Flash one or all connected MicroPython boards with a specific firmware and version.",
|
29
27
|
)
|
30
|
-
@click.option(
|
31
|
-
"--firmware",
|
32
|
-
"-f",
|
33
|
-
"fw_folder",
|
34
|
-
type=click.Path(file_okay=False, dir_okay=True, path_type=Path),
|
35
|
-
default=None,
|
36
|
-
show_default=False,
|
37
|
-
help="The folder to retrieve the firmware from.",
|
38
|
-
)
|
39
28
|
@click.option(
|
40
29
|
"--version",
|
41
30
|
"-v",
|
@@ -95,7 +84,7 @@ from mpflash.versions import clean_version
|
|
95
84
|
)
|
96
85
|
@click.option(
|
97
86
|
"--variant",
|
98
|
-
"
|
87
|
+
"--var",
|
99
88
|
"variant", # single board
|
100
89
|
multiple=False,
|
101
90
|
help="The board VARIANT to flash or '-'. If not specified will try to read the variant from the connected MCU.",
|
@@ -104,7 +93,6 @@ from mpflash.versions import clean_version
|
|
104
93
|
@click.option(
|
105
94
|
"--cpu",
|
106
95
|
"--chip",
|
107
|
-
"-c",
|
108
96
|
"cpu",
|
109
97
|
help="The CPU type to flash. If not specified will try to read the CPU from the connected MCU.",
|
110
98
|
metavar="CPU",
|
@@ -134,12 +122,20 @@ from mpflash.versions import clean_version
|
|
134
122
|
)
|
135
123
|
@click.option(
|
136
124
|
"--flash_mode",
|
137
|
-
"
|
125
|
+
"--fm",
|
138
126
|
type=click.Choice(["keep", "qio", "qout", "dio", "dout"]),
|
139
127
|
default="keep",
|
140
128
|
show_default=True,
|
141
129
|
help="""Flash mode for ESP boards. (default: keep)""",
|
142
130
|
)
|
131
|
+
@click.option(
|
132
|
+
"--custom",
|
133
|
+
"-c",
|
134
|
+
default=False,
|
135
|
+
is_flag=True,
|
136
|
+
show_default=True,
|
137
|
+
help="""Flash a custom firmware""",
|
138
|
+
)
|
143
139
|
def cli_flash_board(**kwargs) -> int:
|
144
140
|
# version to versions, board to boards
|
145
141
|
kwargs["versions"] = [kwargs.pop("version")] if kwargs["version"] is not None else []
|
@@ -164,16 +160,18 @@ def cli_flash_board(**kwargs) -> int:
|
|
164
160
|
# No bard specified
|
165
161
|
params.boards = ["?"]
|
166
162
|
|
167
|
-
if params.fw_folder:
|
168
|
-
config.firmware_folder = Path(params.fw_folder)
|
169
163
|
# Detect connected boards if not specified,
|
170
164
|
# and ask for input if boards cannot be detected
|
171
165
|
all_boards: List[MPRemoteBoard] = []
|
172
166
|
if not params.boards:
|
173
167
|
# nothing specified - detect connected boards
|
174
|
-
params.ports, params.boards, all_boards =
|
175
|
-
include=params.ports,
|
168
|
+
params.ports, params.boards, variants, all_boards = connected_ports_boards_variants(
|
169
|
+
include=params.ports,
|
170
|
+
ignore=params.ignore,
|
171
|
+
bluetooth=params.bluetooth,
|
176
172
|
)
|
173
|
+
if variants and len(variants) >= 1:
|
174
|
+
params.variant = variants[0]
|
177
175
|
if params.boards == []:
|
178
176
|
# No MicroPython boards detected, but it could be unflashed or in bootloader mode
|
179
177
|
# Ask for serial port and board_id to flash
|
@@ -197,11 +195,27 @@ def cli_flash_board(**kwargs) -> int:
|
|
197
195
|
params.versions = [clean_version(v) for v in params.versions]
|
198
196
|
worklist: WorkList = []
|
199
197
|
|
198
|
+
if len(params.versions) == 1 and len(params.boards) == 1 and params.serial == ["*"]:
|
199
|
+
# A one or more serial port including the board / variant
|
200
|
+
comports = filtered_comports(
|
201
|
+
ignore=params.ignore,
|
202
|
+
include=params.serial,
|
203
|
+
bluetooth=params.bluetooth,
|
204
|
+
)
|
205
|
+
board_id = f"{params.boards[0]}-{params.variant}" if params.variant else params.boards[0]
|
206
|
+
log.info(f"Flashing {board_id} {params.versions[0]} to {len(comports)} serial ports")
|
207
|
+
log.info(f"Target ports: {', '.join(comports)}")
|
208
|
+
worklist = manual_worklist(
|
209
|
+
comports,
|
210
|
+
board_id=board_id,
|
211
|
+
version=params.versions[0],
|
212
|
+
custom=params.custom,
|
213
|
+
)
|
200
214
|
# if serial port == auto and there are one or more specified/detected boards
|
201
|
-
|
215
|
+
elif params.serial == ["*"] and params.boards:
|
202
216
|
if not all_boards:
|
203
217
|
log.trace("No boards detected yet, scanning for connected boards")
|
204
|
-
_, _, all_boards =
|
218
|
+
_, _, _, all_boards = connected_ports_boards_variants(include=params.ports, ignore=params.ignore)
|
205
219
|
# if variant id provided on the cmdline, treat is as an override
|
206
220
|
if params.variant:
|
207
221
|
for b in all_boards:
|
@@ -215,8 +229,13 @@ def cli_flash_board(**kwargs) -> int:
|
|
215
229
|
)
|
216
230
|
elif params.versions[0] and params.boards[0] and params.serial:
|
217
231
|
# A one or more serial port including the board / variant
|
232
|
+
comports = filtered_comports(
|
233
|
+
ignore=params.ignore,
|
234
|
+
include=params.ports,
|
235
|
+
bluetooth=params.bluetooth,
|
236
|
+
)
|
218
237
|
worklist = manual_worklist(
|
219
|
-
|
238
|
+
comports,
|
220
239
|
board_id=params.boards[0],
|
221
240
|
version=params.versions[0],
|
222
241
|
)
|
@@ -226,7 +245,8 @@ def cli_flash_board(**kwargs) -> int:
|
|
226
245
|
serial=params.serial[0],
|
227
246
|
version=params.versions[0],
|
228
247
|
)
|
229
|
-
|
248
|
+
if not params.custom:
|
249
|
+
jid.ensure_firmware_downloaded(worklist, version=params.versions[0], force=params.force)
|
230
250
|
if flashed := flash_list(
|
231
251
|
worklist,
|
232
252
|
params.erase,
|
@@ -239,5 +259,3 @@ def cli_flash_board(**kwargs) -> int:
|
|
239
259
|
else:
|
240
260
|
log.error("No boards were flashed")
|
241
261
|
return 1
|
242
|
-
|
243
|
-
|
mpflash/cli_group.py
CHANGED
mpflash/cli_list.py
CHANGED
@@ -86,6 +86,8 @@ def cli_list_mcus(serial: List[str], ignore: List[str], bluetooth: bool, as_json
|
|
86
86
|
if mcu.family == "circuitpython":
|
87
87
|
# CircuitPython boards need a special reset command
|
88
88
|
mcu.run_command(["exec", "--no-follow", "import microcontroller,time;time.sleep(0.01);microcontroller.reset()"], resume=False)
|
89
|
+
elif mcu.family == "unknown":
|
90
|
+
continue
|
89
91
|
else:
|
90
92
|
mcu.run_command("reset")
|
91
93
|
return 0 if conn_mcus else 1
|
mpflash/cli_main.py
CHANGED
@@ -5,6 +5,9 @@ import os
|
|
5
5
|
import click.exceptions as click_exceptions
|
6
6
|
from loguru import logger as log
|
7
7
|
|
8
|
+
from mpflash.errors import MPFlashError
|
9
|
+
|
10
|
+
from .cli_add import cli_add_custom
|
8
11
|
from .cli_download import cli_download
|
9
12
|
from .cli_flash import cli_flash_board
|
10
13
|
from .cli_group import cli
|
@@ -19,6 +22,7 @@ def mpflash():
|
|
19
22
|
cli.add_command(cli_list_mcus)
|
20
23
|
cli.add_command(cli_download)
|
21
24
|
cli.add_command(cli_flash_board)
|
25
|
+
cli.add_command(cli_add_custom)
|
22
26
|
|
23
27
|
# cli(auto_envvar_prefix="MPFLASH")
|
24
28
|
if False and os.environ.get("COMPUTERNAME").upper().startswith("JOSVERL"):
|
@@ -37,6 +41,9 @@ def mpflash():
|
|
37
41
|
except click_exceptions.Abort:
|
38
42
|
# Aborted - Ctrl-C
|
39
43
|
exit(-3)
|
44
|
+
except MPFlashError as e:
|
45
|
+
log.error(f"MPFlashError: {e}")
|
46
|
+
exit(-4)
|
40
47
|
|
41
48
|
|
42
49
|
if __name__ == "__main__":
|
mpflash/common.py
CHANGED
@@ -4,7 +4,6 @@ import os
|
|
4
4
|
import platform
|
5
5
|
from dataclasses import dataclass, field
|
6
6
|
from enum import Enum
|
7
|
-
from pathlib import Path
|
8
7
|
from typing import List, Optional, Union
|
9
8
|
|
10
9
|
from serial.tools import list_ports
|
@@ -36,7 +35,6 @@ class Params:
|
|
36
35
|
boards: List[str] = field(default_factory=list)
|
37
36
|
variant: str = ""
|
38
37
|
versions: List[str] = field(default_factory=list)
|
39
|
-
fw_folder: Optional[Path] = None
|
40
38
|
serial: List[str] = field(default_factory=list)
|
41
39
|
ignore: List[str] = field(default_factory=list)
|
42
40
|
bluetooth: bool = False
|
@@ -66,6 +64,7 @@ class FlashParams(Params):
|
|
66
64
|
bootloader: BootloaderMethod = BootloaderMethod.NONE
|
67
65
|
cpu: str = ""
|
68
66
|
flash_mode: str = "keep" # keep, qio, qout, dio, dout
|
67
|
+
custom: bool = False
|
69
68
|
|
70
69
|
def __post_init__(self):
|
71
70
|
if isinstance(self.bootloader, str):
|
@@ -79,11 +78,24 @@ def filtered_comports(
|
|
79
78
|
ignore: Optional[List[str]] = None,
|
80
79
|
include: Optional[List[str]] = None,
|
81
80
|
bluetooth: bool = False,
|
81
|
+
) -> List[str]:
|
82
|
+
"""
|
83
|
+
Get a list of filtered comports using the include and ignore lists.
|
84
|
+
both can be globs (e.g. COM*) or exact port names (e.g. COM1)
|
85
|
+
"""
|
86
|
+
return [p.device for p in filtered_portinfos(ignore, include, bluetooth)]
|
87
|
+
|
88
|
+
|
89
|
+
def filtered_portinfos(
|
90
|
+
ignore: Optional[List[str]] = None,
|
91
|
+
include: Optional[List[str]] = None,
|
92
|
+
bluetooth: bool = False,
|
82
93
|
) -> List[ListPortInfo]: # sourcery skip: assign-if-exp
|
83
94
|
"""
|
84
95
|
Get a list of filtered comports using the include and ignore lists.
|
85
96
|
both can be globs (e.g. COM*) or exact port names (e.g. COM1)
|
86
97
|
"""
|
98
|
+
log.trace(f"filtered_portinfos: {ignore=}, {include=}, {bluetooth=}")
|
87
99
|
if not ignore:
|
88
100
|
ignore = []
|
89
101
|
elif not isinstance(ignore, list): # type: ignore
|
mpflash/config.py
CHANGED
@@ -7,6 +7,8 @@ from typing import List, Optional
|
|
7
7
|
|
8
8
|
import platformdirs
|
9
9
|
|
10
|
+
from mpflash.errors import MPFlashError
|
11
|
+
|
10
12
|
|
11
13
|
def get_version():
|
12
14
|
name = __package__ or "mpflash"
|
@@ -44,7 +46,18 @@ class MPFlashConfig:
|
|
44
46
|
def firmware_folder(self) -> Path:
|
45
47
|
"""The folder where firmware files are stored"""
|
46
48
|
if not self._firmware_folder:
|
47
|
-
|
49
|
+
from mpflash.logger import log
|
50
|
+
|
51
|
+
# Check if MPFLASH_FIRMWARE environment variable is set
|
52
|
+
env_firmware_path = os.getenv("MPFLASH_FIRMWARE")
|
53
|
+
if env_firmware_path:
|
54
|
+
firmware_path = Path(env_firmware_path).expanduser().resolve()
|
55
|
+
if firmware_path.exists() and firmware_path.is_dir():
|
56
|
+
self._firmware_folder = firmware_path
|
57
|
+
else:
|
58
|
+
log.warning(
|
59
|
+
f"Environment variable MPFLASH_FIRMWARE points to invalid directory: {env_firmware_path}. Using default location."
|
60
|
+
)
|
48
61
|
# allow testing in CI
|
49
62
|
if Path(os.getenv("GITHUB_ACTIONS", "")).as_posix().lower() == "true":
|
50
63
|
workspace = os.getenv("GITHUB_WORKSPACE")
|
@@ -53,6 +66,13 @@ class MPFlashConfig:
|
|
53
66
|
ws_path.mkdir(parents=True, exist_ok=True)
|
54
67
|
print(f"Detected GitHub Actions environment. Using workspace path: {ws_path}")
|
55
68
|
self._firmware_folder = ws_path
|
69
|
+
if not self._firmware_folder:
|
70
|
+
self._firmware_folder = platformdirs.user_downloads_path() / "firmware"
|
71
|
+
if not self._firmware_folder.exists():
|
72
|
+
log.info(f"Creating firmware folder at {self._firmware_folder}")
|
73
|
+
self._firmware_folder.mkdir(parents=True, exist_ok=True)
|
74
|
+
if not self._firmware_folder.is_dir():
|
75
|
+
raise MPFlashError(f"Firmware folder {self._firmware_folder} is not a directory.")
|
56
76
|
return self._firmware_folder
|
57
77
|
|
58
78
|
@firmware_folder.setter
|
@@ -67,6 +87,7 @@ class MPFlashConfig:
|
|
67
87
|
def db_path(self) -> Path:
|
68
88
|
"""The path to the database file"""
|
69
89
|
return self.firmware_folder / "mpflash.db"
|
90
|
+
|
70
91
|
@property
|
71
92
|
def db_version(self) -> str:
|
72
93
|
return "1.24.1"
|
mpflash/connected.py
CHANGED
@@ -4,13 +4,13 @@ from rich import print
|
|
4
4
|
from rich.progress import BarColumn, Progress, SpinnerColumn, TextColumn, TimeElapsedColumn
|
5
5
|
from rich.table import Column
|
6
6
|
|
7
|
-
from mpflash.common import
|
7
|
+
from mpflash.common import filtered_portinfos, find_serial_by_path
|
8
8
|
from mpflash.mpremoteboard import MPRemoteBoard
|
9
9
|
|
10
10
|
|
11
|
-
def
|
11
|
+
def connected_ports_boards_variants(
|
12
12
|
*, include: List[str], ignore: List[str], bluetooth: bool = False
|
13
|
-
) -> Tuple[List[str], List[str], List[MPRemoteBoard]]:
|
13
|
+
) -> Tuple[List[str], List[str], List[str], List[MPRemoteBoard]]:
|
14
14
|
"""
|
15
15
|
Returns a tuple containing lists of unique ports and boards from the connected MCUs.
|
16
16
|
Boards that are physically connected, but give no tangible response are ignored.
|
@@ -21,13 +21,15 @@ def connected_ports_boards(
|
|
21
21
|
- A list of unique board names of the connected MCUs.
|
22
22
|
- A list of MPRemoteBoard instances of the connected MCUs.
|
23
23
|
"""
|
24
|
+
# conn_mcus = [b for b in list_mcus(include=include, ignore=ignore, bluetooth=bluetooth)]
|
24
25
|
conn_mcus = [b for b in list_mcus(include=include, ignore=ignore, bluetooth=bluetooth) if b.connected]
|
25
26
|
# ignore boards that have the [mpflash] ignore flag set
|
26
27
|
conn_mcus = [item for item in conn_mcus if not (item.toml.get("mpflash", {}).get("ignore", False))]
|
27
28
|
|
28
29
|
ports = list({b.port for b in conn_mcus})
|
29
30
|
boards = list({b.board for b in conn_mcus})
|
30
|
-
|
31
|
+
variants = list({b.variant for b in conn_mcus if b.variant})
|
32
|
+
return (ports, boards, variants, conn_mcus)
|
31
33
|
|
32
34
|
|
33
35
|
# #########################################################################################################
|
@@ -46,8 +48,8 @@ def list_mcus(*, ignore: List[str], include: List[str], bluetooth: bool = False)
|
|
46
48
|
ConnectionError: If there is an error connecting to a board.
|
47
49
|
"""
|
48
50
|
# conn_mcus = [MPRemoteBoard(sp) for sp in MPRemoteBoard.connected_boards(bluetooth) if sp not in config.ignore_ports]
|
49
|
-
|
50
|
-
comports =
|
51
|
+
vid_pid = True
|
52
|
+
comports = filtered_portinfos(
|
51
53
|
ignore=ignore,
|
52
54
|
include=include,
|
53
55
|
bluetooth=bluetooth,
|