mpflash 0.4.0.post2__py3-none-any.whl → 0.4.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/ask_input.py +163 -0
- mpflash/cli_download.py +18 -10
- mpflash/cli_flash.py +122 -72
- mpflash/cli_group.py +20 -1
- mpflash/cli_list.py +5 -4
- mpflash/cli_main.py +5 -4
- mpflash/common.py +24 -9
- mpflash/config.py +5 -3
- mpflash/download.py +59 -13
- mpflash/flash.py +36 -24
- mpflash/flash_esp.py +11 -11
- mpflash/flash_stm32.py +1 -1
- mpflash/flash_stm32_dfu.py +4 -7
- mpflash/flash_uf2.py +1 -1
- mpflash/mpboard_id/api.py +52 -10
- mpflash/mpboard_id/board_info.csv +2036 -16
- mpflash/mpboard_id/board_info.json +19435 -1255
- mpflash/vendored/dfu.py +9 -8
- mpflash/vendored/pydfu.py +1 -1
- {mpflash-0.4.0.post2.dist-info → mpflash-0.4.2.dist-info}/METADATA +1 -1
- mpflash-0.4.2.dist-info/RECORD +35 -0
- mpflash/basic.py +0 -41
- mpflash/download_input.py +0 -68
- mpflash/inq.py +0 -66
- mpflash/mpboard_id/get_boardnames.py +0 -213
- mpflash-0.4.0.post2.dist-info/RECORD +0 -38
- {mpflash-0.4.0.post2.dist-info → mpflash-0.4.2.dist-info}/LICENSE +0 -0
- {mpflash-0.4.0.post2.dist-info → mpflash-0.4.2.dist-info}/WHEEL +0 -0
- {mpflash-0.4.0.post2.dist-info → mpflash-0.4.2.dist-info}/entry_points.txt +0 -0
mpflash/common.py
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
import os
|
1
2
|
import time
|
3
|
+
from functools import lru_cache
|
2
4
|
from typing import TypedDict
|
3
5
|
|
4
|
-
from github import Github
|
6
|
+
from github import Auth, Github
|
5
7
|
from loguru import logger as log
|
6
8
|
from packaging.version import parse
|
7
9
|
from rich.progress import track
|
@@ -19,6 +21,14 @@ PORT_FWTYPES = {
|
|
19
21
|
"renesas-ra": [".hex"],
|
20
22
|
}
|
21
23
|
|
24
|
+
# Token with no permissions to avoid throttling
|
25
|
+
# https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#getting-a-higher-rate-limit
|
26
|
+
PAT_NO_ACCESS = (
|
27
|
+
"github_pat" + "_11AAHPVFQ0qAkDnSUaMKSp" + "_ZkDl5NRRwBsUN6EYg9ahp1Dvj4FDDONnXVgimxC2EtpY7Q7BUKBoQ0Jq72X"
|
28
|
+
)
|
29
|
+
PAT = os.environ.get("GITHUB_TOKEN") or PAT_NO_ACCESS
|
30
|
+
GH_CLIENT = Github(auth=Auth.Token(PAT))
|
31
|
+
|
22
32
|
|
23
33
|
class FWInfo(TypedDict):
|
24
34
|
filename: str
|
@@ -27,6 +37,7 @@ class FWInfo(TypedDict):
|
|
27
37
|
variant: str
|
28
38
|
preview: bool
|
29
39
|
version: str
|
40
|
+
build: str
|
30
41
|
|
31
42
|
|
32
43
|
#############################################################
|
@@ -52,7 +63,7 @@ def clean_version(
|
|
52
63
|
if version in {"", "-"}:
|
53
64
|
return version
|
54
65
|
if version.lower() == "stable":
|
55
|
-
_v =
|
66
|
+
_v = get_stable_mp_version()
|
56
67
|
if not _v:
|
57
68
|
log.warning("Could not determine the latest stable version")
|
58
69
|
return "stable"
|
@@ -89,12 +100,12 @@ def clean_version(
|
|
89
100
|
return version
|
90
101
|
|
91
102
|
|
92
|
-
|
103
|
+
@lru_cache(maxsize=10)
|
104
|
+
def micropython_versions(minver: str = "v1.20"):
|
93
105
|
"""Get the list of micropython versions from github tags"""
|
94
106
|
try:
|
95
|
-
|
96
|
-
|
97
|
-
repo = g.get_repo("micropython/micropython")
|
107
|
+
gh_client = GH_CLIENT
|
108
|
+
repo = gh_client.get_repo("micropython/micropython")
|
98
109
|
versions = [tag.name for tag in repo.get_tags() if parse(tag.name) >= parse(minver)]
|
99
110
|
except Exception:
|
100
111
|
versions = [
|
@@ -116,19 +127,23 @@ def micropython_versions(minver: str = "v1.9.2"):
|
|
116
127
|
"v1.12",
|
117
128
|
"v1.11",
|
118
129
|
"v1.10",
|
119
|
-
"v1.9.4",
|
120
|
-
"v1.9.3",
|
121
130
|
]
|
122
131
|
versions = [v for v in versions if parse(v) >= parse(minver)]
|
123
132
|
return sorted(versions)
|
124
133
|
|
125
134
|
|
126
|
-
def
|
135
|
+
def get_stable_mp_version() -> str:
|
127
136
|
# read the versions from the git tags
|
128
137
|
all_versions = micropython_versions(minver="v1.17")
|
129
138
|
return [v for v in all_versions if not v.endswith(V_PREVIEW)][-1]
|
130
139
|
|
131
140
|
|
141
|
+
def get_preview_mp_version() -> str:
|
142
|
+
# read the versions from the git tags
|
143
|
+
all_versions = micropython_versions(minver="v1.17")
|
144
|
+
return [v for v in all_versions if v.endswith(V_PREVIEW)][-1]
|
145
|
+
|
146
|
+
|
132
147
|
#############################################################
|
133
148
|
def wait_for_restart(mcu: MPRemoteBoard, timeout: int = 10):
|
134
149
|
"""wait for the board to restart"""
|
mpflash/config.py
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
"""centralized configuration for mpflash"""
|
2
2
|
|
3
|
-
import platformdirs
|
4
|
-
|
5
|
-
from typing import List
|
6
3
|
from pathlib import Path
|
4
|
+
from typing import List
|
5
|
+
|
6
|
+
import platformdirs
|
7
7
|
|
8
8
|
|
9
9
|
class MPtoolConfig:
|
10
10
|
"""Centralized configuration for mpflash"""
|
11
11
|
|
12
12
|
quiet: bool = False
|
13
|
+
verbose: bool = False
|
13
14
|
ignore_ports: List[str] = []
|
15
|
+
interactive: bool = True
|
14
16
|
firmware_folder: Path = platformdirs.user_downloads_path() / "firmware"
|
15
17
|
|
16
18
|
|
mpflash/download.py
CHANGED
@@ -5,18 +5,24 @@ Uses the micropython.org website to get the available versions and locations to
|
|
5
5
|
|
6
6
|
import functools
|
7
7
|
import itertools
|
8
|
-
import json
|
9
8
|
import re
|
10
9
|
from pathlib import Path
|
11
10
|
from typing import Dict, List, Optional
|
12
11
|
from urllib.parse import urljoin
|
13
12
|
|
13
|
+
# #########################################################################################################
|
14
|
+
# make sure that jsonlines does not mistake the MicroPython ujson for the CPython ujson
|
15
|
+
import jsonlines
|
14
16
|
import requests
|
15
17
|
from bs4 import BeautifulSoup
|
16
18
|
from loguru import logger as log
|
17
19
|
from rich.progress import track
|
18
20
|
|
19
|
-
from .common import PORT_FWTYPES
|
21
|
+
from mpflash.common import PORT_FWTYPES
|
22
|
+
|
23
|
+
jsonlines.ujson = None # type: ignore
|
24
|
+
# #########################################################################################################
|
25
|
+
|
20
26
|
|
21
27
|
MICROPYTHON_ORG_URL = "https://micropython.org/"
|
22
28
|
|
@@ -77,6 +83,18 @@ FirmwareInfo = Dict[str, str]
|
|
77
83
|
# The first run takes ~60 seconds to run for 4 ports , all boards
|
78
84
|
# so it makes sense to cache the results and skip boards as soon as possible
|
79
85
|
def get_boards(ports: List[str], boards: List[str], clean: bool) -> List[FirmwareInfo]:
|
86
|
+
"""
|
87
|
+
Retrieves a list of firmware information for the specified ports and boards.
|
88
|
+
|
89
|
+
Args:
|
90
|
+
ports (List[str]): The list of ports to check for firmware.
|
91
|
+
boards (List[str]): The list of boards to retrieve firmware information for.
|
92
|
+
clean (bool): A flag indicating whether to perform a clean retrieval.
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
List[FirmwareInfo]: A list of firmware information for the specified ports and boards.
|
96
|
+
|
97
|
+
"""
|
80
98
|
board_urls: List[FirmwareInfo] = []
|
81
99
|
for port in ports:
|
82
100
|
download_page_url = f"{MICROPYTHON_ORG_URL}download/?port={port}"
|
@@ -133,14 +151,13 @@ def download_firmwares(
|
|
133
151
|
boards: List[str],
|
134
152
|
versions: Optional[List[str]] = None,
|
135
153
|
*,
|
136
|
-
preview: bool = False,
|
137
154
|
force: bool = False,
|
138
155
|
clean: bool = True,
|
139
156
|
):
|
140
157
|
skipped = downloaded = 0
|
141
158
|
if versions is None:
|
142
159
|
versions = []
|
143
|
-
unique_boards = get_firmware_list(ports, boards, versions,
|
160
|
+
unique_boards = get_firmware_list(ports, boards, versions, clean)
|
144
161
|
|
145
162
|
for b in unique_boards:
|
146
163
|
log.debug(b["filename"])
|
@@ -150,7 +167,7 @@ def download_firmwares(
|
|
150
167
|
|
151
168
|
firmware_folder.mkdir(exist_ok=True)
|
152
169
|
|
153
|
-
with open(firmware_folder / "firmware.jsonl", "a"
|
170
|
+
with jsonlines.open(firmware_folder / "firmware.jsonl", "a") as writer:
|
154
171
|
for board in unique_boards:
|
155
172
|
filename = firmware_folder / board["port"] / board["filename"]
|
156
173
|
filename.parent.mkdir(exist_ok=True)
|
@@ -168,16 +185,28 @@ def download_firmwares(
|
|
168
185
|
except requests.RequestException as e:
|
169
186
|
log.exception(e)
|
170
187
|
continue
|
171
|
-
|
172
|
-
json_str = json.dumps(board) + "\n"
|
173
|
-
f_jsonl.write(json_str)
|
188
|
+
writer.write(board)
|
174
189
|
downloaded += 1
|
175
190
|
log.info(f"Downloaded {downloaded} firmwares, skipped {skipped} existing files.")
|
176
191
|
|
177
192
|
|
178
|
-
def get_firmware_list(ports: List[str], boards: List[str], versions: List[str],
|
179
|
-
|
193
|
+
def get_firmware_list(ports: List[str], boards: List[str], versions: List[str], clean: bool):
|
194
|
+
"""
|
195
|
+
Retrieves a list of unique firmware information based on the specified ports, boards, versions, and clean flag.
|
196
|
+
|
197
|
+
Args:
|
198
|
+
ports : The list of ports to check for firmware.
|
199
|
+
boards : The list of boards to filter the firmware by.
|
200
|
+
versions : The list of versions to filter the firmware by.
|
201
|
+
clean : A flag indicating whether to perform a clean check.
|
180
202
|
|
203
|
+
Returns:
|
204
|
+
List[FirmwareInfo]: A list of unique firmware information.
|
205
|
+
|
206
|
+
"""
|
207
|
+
|
208
|
+
log.trace("Checking MicroPython download pages")
|
209
|
+
preview = "preview" in versions
|
181
210
|
board_urls = sorted(get_boards(ports, boards, clean), key=key_fw_ver_pre_ext_bld)
|
182
211
|
|
183
212
|
log.debug(f"Total {len(board_urls)} firmwares")
|
@@ -205,15 +234,32 @@ def download(
|
|
205
234
|
versions: List[str],
|
206
235
|
force: bool,
|
207
236
|
clean: bool,
|
208
|
-
preview: bool,
|
209
237
|
):
|
238
|
+
"""
|
239
|
+
Downloads firmware files based on the specified destination, ports, boards, versions, force flag, and clean flag.
|
240
|
+
|
241
|
+
Args:
|
242
|
+
destination : The destination folder to save the downloaded firmware files.
|
243
|
+
ports : The list of ports to check for firmware.
|
244
|
+
boards : The list of boards to download firmware for.
|
245
|
+
versions : The list of versions to download firmware for.
|
246
|
+
force : A flag indicating whether to force the download even if the firmware file already exists.
|
247
|
+
clean : A flag indicating whether to perform a clean download.
|
248
|
+
|
249
|
+
Returns:
|
250
|
+
None
|
251
|
+
|
252
|
+
Raises:
|
253
|
+
SystemExit: If no boards are found or specified.
|
254
|
+
|
255
|
+
"""
|
210
256
|
if not boards:
|
211
257
|
log.critical("No boards found, please connect a board or specify boards to download firmware for.")
|
212
258
|
exit(1)
|
213
|
-
versions = [clean_version(v, drop_v=True) for v in versions] # remove leading v from version
|
259
|
+
# versions = [clean_version(v, drop_v=True) for v in versions] # remove leading v from version
|
214
260
|
try:
|
215
261
|
destination.mkdir(exist_ok=True, parents=True)
|
216
262
|
except (PermissionError, FileNotFoundError) as e:
|
217
263
|
log.critical(f"Could not create folder {destination}\n{e}")
|
218
264
|
exit(1)
|
219
|
-
download_firmwares(destination, ports, boards, versions,
|
265
|
+
download_firmwares(destination, ports, boards, versions, force=force, clean=clean)
|
mpflash/flash.py
CHANGED
@@ -5,9 +5,10 @@ from typing import Dict, List, Optional, Tuple
|
|
5
5
|
import jsonlines
|
6
6
|
from loguru import logger as log
|
7
7
|
|
8
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
9
|
+
|
8
10
|
from .common import FWInfo, clean_version
|
9
11
|
from .config import config
|
10
|
-
from .mpremoteboard import MPRemoteBoard
|
11
12
|
|
12
13
|
# #########################################################################################################
|
13
14
|
WorkList = List[Tuple[MPRemoteBoard, FWInfo]]
|
@@ -32,12 +33,11 @@ def find_firmware(
|
|
32
33
|
board: str,
|
33
34
|
version: str = "",
|
34
35
|
port: str = "",
|
35
|
-
preview: bool = False,
|
36
36
|
variants: bool = False,
|
37
37
|
fw_folder: Optional[Path] = None,
|
38
38
|
trie: int = 1,
|
39
39
|
selector: Optional[Dict[str, str]] = None,
|
40
|
-
):
|
40
|
+
) -> List[FWInfo]:
|
41
41
|
if selector is None:
|
42
42
|
selector = {}
|
43
43
|
fw_folder = fw_folder or config.firmware_folder
|
@@ -48,24 +48,8 @@ def find_firmware(
|
|
48
48
|
return []
|
49
49
|
# filter by version
|
50
50
|
version = clean_version(version, drop_v=True)
|
51
|
-
|
52
|
-
# never get a preview for an older version
|
53
|
-
fw_list = [fw for fw in fw_list if fw["preview"]]
|
54
|
-
else:
|
55
|
-
fw_list = [fw for fw in fw_list if fw["version"] == version]
|
51
|
+
fw_list = filter_fwlist(fw_list, board, version, port, variants, selector)
|
56
52
|
|
57
|
-
# filter by port
|
58
|
-
if port:
|
59
|
-
fw_list = [fw for fw in fw_list if fw["port"] == port]
|
60
|
-
|
61
|
-
if board:
|
62
|
-
if variants:
|
63
|
-
fw_list = [fw for fw in fw_list if fw["board"] == board]
|
64
|
-
else:
|
65
|
-
# the variant should match exactly the board name
|
66
|
-
fw_list = [fw for fw in fw_list if fw["variant"] == board]
|
67
|
-
if selector and port in selector:
|
68
|
-
fw_list = [fw for fw in fw_list if fw["filename"].endswith(selector[port])]
|
69
53
|
if not fw_list and trie < 2:
|
70
54
|
board_id = board.replace("_", "-")
|
71
55
|
# ESP board naming conventions have changed by adding a PORT refix
|
@@ -75,13 +59,12 @@ def find_firmware(
|
|
75
59
|
if port == "rp2" and not board_id.startswith("RPI_"):
|
76
60
|
board_id = f"RPI_{board_id}"
|
77
61
|
|
78
|
-
log.
|
62
|
+
log.info(f"Try ({trie}) to find a firmware for the board {board_id}")
|
79
63
|
fw_list = find_firmware(
|
80
64
|
fw_folder=fw_folder,
|
81
65
|
board=board_id,
|
82
66
|
version=version,
|
83
67
|
port=port,
|
84
|
-
preview=preview,
|
85
68
|
trie=trie + 1,
|
86
69
|
selector=selector,
|
87
70
|
)
|
@@ -91,6 +74,37 @@ def find_firmware(
|
|
91
74
|
return fw_list
|
92
75
|
|
93
76
|
|
77
|
+
def filter_fwlist(
|
78
|
+
fw_list: List[FWInfo],
|
79
|
+
board: str,
|
80
|
+
version: str,
|
81
|
+
port: str,
|
82
|
+
# preview: bool,
|
83
|
+
variants: bool,
|
84
|
+
selector: dict,
|
85
|
+
) -> List[FWInfo]:
|
86
|
+
"""Filter the firmware list based on the provided parameters"""
|
87
|
+
if "preview" in version:
|
88
|
+
# never get a preview for an older version
|
89
|
+
fw_list = [fw for fw in fw_list if fw["preview"]]
|
90
|
+
else:
|
91
|
+
fw_list = [fw for fw in fw_list if fw["version"] == version]
|
92
|
+
|
93
|
+
# filter by port
|
94
|
+
if port:
|
95
|
+
fw_list = [fw for fw in fw_list if fw["port"] == port]
|
96
|
+
|
97
|
+
if board:
|
98
|
+
if variants:
|
99
|
+
fw_list = [fw for fw in fw_list if fw["board"] == board]
|
100
|
+
else:
|
101
|
+
# the variant should match exactly the board name
|
102
|
+
fw_list = [fw for fw in fw_list if fw["variant"] == board]
|
103
|
+
if selector and port in selector:
|
104
|
+
fw_list = [fw for fw in fw_list if fw["filename"].endswith(selector[port])]
|
105
|
+
return fw_list
|
106
|
+
|
107
|
+
|
94
108
|
# #########################################################################################################
|
95
109
|
#
|
96
110
|
|
@@ -100,7 +114,6 @@ def auto_update(
|
|
100
114
|
target_version: str,
|
101
115
|
fw_folder: Path,
|
102
116
|
*,
|
103
|
-
preview: bool = False,
|
104
117
|
selector: Optional[Dict[str, str]] = None,
|
105
118
|
) -> WorkList:
|
106
119
|
"""Builds a list of boards to update based on the connected boards and the firmware available"""
|
@@ -118,7 +131,6 @@ def auto_update(
|
|
118
131
|
board=mcu.board,
|
119
132
|
version=target_version,
|
120
133
|
port=mcu.port,
|
121
|
-
preview=preview or "preview" in target_version,
|
122
134
|
selector=selector,
|
123
135
|
)
|
124
136
|
|
mpflash/flash_esp.py
CHANGED
@@ -4,26 +4,28 @@
|
|
4
4
|
# #########################################################################################################
|
5
5
|
"""
|
6
6
|
|
7
|
-
import time
|
8
7
|
from pathlib import Path
|
9
8
|
from typing import List, Optional
|
10
9
|
|
11
10
|
import esptool
|
12
11
|
from loguru import logger as log
|
13
12
|
|
14
|
-
from .
|
13
|
+
from mpflash.mpboard_id.api import find_mp_board
|
14
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
15
|
+
|
15
16
|
from .common import wait_for_restart
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
) -> Optional[MPRemoteBoard]:
|
18
|
+
|
19
|
+
def flash_esp(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool = True) -> Optional[MPRemoteBoard]:
|
20
20
|
if mcu.port not in ["esp32", "esp8266"] or mcu.board in ["ARDUINO_NANO_ESP32"]:
|
21
|
-
log.error(
|
22
|
-
f"esptool not supported for {mcu.port} {mcu.board} on {mcu.serialport}"
|
23
|
-
)
|
21
|
+
log.error(f"esptool not supported for {mcu.port} {mcu.board} on {mcu.serialport}")
|
24
22
|
return None
|
25
23
|
|
26
24
|
log.info(f"Flashing {fw_file} on {mcu.board} on {mcu.serialport}")
|
25
|
+
if not mcu.cpu:
|
26
|
+
# Lookup CPU based on the board name
|
27
|
+
mcu.cpu = find_mp_board(mcu.board)["cpu"]
|
28
|
+
|
27
29
|
if mcu.port == "esp8266":
|
28
30
|
baud_rate = str(460_800)
|
29
31
|
else:
|
@@ -31,9 +33,7 @@ def flash_esp(
|
|
31
33
|
# baud_rate = str(115_200)
|
32
34
|
cmds: List[List[str]] = []
|
33
35
|
if erase:
|
34
|
-
cmds.append(
|
35
|
-
f"esptool --chip {mcu.cpu} --port {mcu.serialport} erase_flash".split()
|
36
|
-
)
|
36
|
+
cmds.append(f"esptool --chip {mcu.cpu} --port {mcu.serialport} erase_flash".split())
|
37
37
|
|
38
38
|
if mcu.cpu.upper() in ("ESP32", "ESP32S2"):
|
39
39
|
start_addr = "0x1000"
|
mpflash/flash_stm32.py
CHANGED
@@ -8,7 +8,7 @@ from mpflash.common import wait_for_restart
|
|
8
8
|
|
9
9
|
# from .flash_stm32_cube import flash_stm32_cubecli
|
10
10
|
from .flash_stm32_dfu import dfu_init, flash_stm32_dfu
|
11
|
-
from .mpremoteboard import MPRemoteBoard
|
11
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
12
12
|
|
13
13
|
|
14
14
|
def flash_stm32(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool, stm32_dfu: bool = True):
|
mpflash/flash_stm32_dfu.py
CHANGED
@@ -1,26 +1,23 @@
|
|
1
1
|
import platform
|
2
|
-
import sys
|
3
|
-
import time
|
4
2
|
from pathlib import Path
|
5
3
|
from typing import Optional
|
6
4
|
|
7
5
|
from loguru import logger as log
|
8
6
|
|
9
|
-
from .
|
10
|
-
from .mpremoteboard import MPRemoteBoard
|
7
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
11
8
|
|
12
9
|
|
13
|
-
def init_libusb_windows():
|
10
|
+
def init_libusb_windows() -> bool:
|
14
11
|
# on windows we need to initialze the libusb backend with the correct dll
|
15
|
-
import libusb
|
12
|
+
import libusb # type: ignore
|
16
13
|
import usb.backend.libusb1 as libusb1
|
17
14
|
|
18
15
|
arch = "x64" if platform.architecture()[0] == "64bit" else "x86"
|
19
16
|
libusb1_dll = Path(libusb.__file__).parent / f"_platform\\_windows\\{arch}\\libusb-1.0.dll"
|
20
17
|
if not libusb1_dll.exists():
|
21
18
|
raise FileNotFoundError(f"libusb1.dll not found at {libusb1_dll}")
|
22
|
-
|
23
19
|
backend = libusb1.get_backend(find_library=lambda x: libusb1_dll.as_posix())
|
20
|
+
return backend is not None
|
24
21
|
|
25
22
|
|
26
23
|
try:
|
mpflash/flash_uf2.py
CHANGED
@@ -11,7 +11,7 @@ from typing import Optional
|
|
11
11
|
from loguru import logger as log
|
12
12
|
from rich.progress import track
|
13
13
|
|
14
|
-
from .mpremoteboard import MPRemoteBoard
|
14
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
15
15
|
|
16
16
|
from .common import PORT_FWTYPES
|
17
17
|
from .flash_uf2_linux import dismount_uf2, wait_for_UF2_linux
|
mpflash/mpboard_id/api.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
import json
|
2
2
|
from functools import lru_cache
|
3
3
|
from pathlib import Path
|
4
|
-
from typing import List, Tuple, TypedDict, Union
|
4
|
+
from typing import List, Optional, Tuple, TypedDict, Union
|
5
5
|
|
6
|
-
from mpflash.common import PORT_FWTYPES
|
6
|
+
from mpflash.common import PORT_FWTYPES, clean_version
|
7
7
|
|
8
8
|
|
9
9
|
# Board based on the dataclass Board but changed to TypedDict
|
@@ -18,30 +18,72 @@ class Board(TypedDict):
|
|
18
18
|
mcu_name: str
|
19
19
|
path: Union[Path, str]
|
20
20
|
version: str
|
21
|
+
cpu: str
|
21
22
|
|
22
23
|
|
23
24
|
@lru_cache(maxsize=None)
|
24
25
|
def read_boardinfo() -> List[Board]:
|
26
|
+
"""Reads the board_info.json file and returns the data as a list of Board objects"""
|
25
27
|
with open(Path(__file__).parent / "board_info.json", "r") as file:
|
26
28
|
return json.load(file)
|
27
29
|
|
28
30
|
|
29
31
|
def known_mp_ports() -> List[str]:
|
30
|
-
|
32
|
+
# TODO: Filter for Version
|
33
|
+
mp_boards = read_boardinfo()
|
31
34
|
# select the unique ports from info
|
32
|
-
ports = set({board["port"] for board in
|
35
|
+
ports = set({board["port"] for board in mp_boards if board["port"] in PORT_FWTYPES.keys()})
|
33
36
|
return sorted(list(ports))
|
34
37
|
|
35
38
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
+
def get_mp_boards_for_port(port: str, versions: Optional[List[str]] = None):
|
40
|
+
"""
|
41
|
+
Returns a list of boards for the given port and version(s)
|
42
|
+
|
43
|
+
port : str : The Micropython port to filter for
|
44
|
+
versions : List[str] : The Micropython versions to filter for (actual versions required)"""
|
45
|
+
mp_boards = read_boardinfo()
|
46
|
+
|
47
|
+
# filter for 'preview' as they are not in the board_info.json
|
48
|
+
# instead use stable version
|
49
|
+
versions = versions or []
|
50
|
+
if "preview" in versions:
|
51
|
+
versions.remove("preview")
|
52
|
+
versions.append("stable")
|
53
|
+
if versions:
|
54
|
+
# make sure of the v prefix
|
55
|
+
versions = [clean_version(v) for v in versions]
|
56
|
+
# filter for the version(s)
|
57
|
+
mp_boards = [board for board in mp_boards if board["version"] in versions]
|
58
|
+
# filter for the port
|
59
|
+
mp_boards = [board for board in mp_boards if board["port"] == port]
|
60
|
+
return mp_boards
|
61
|
+
|
62
|
+
|
63
|
+
def known_mp_boards(port: str, versions: Optional[List[str]] = None) -> List[Tuple[str, str]]:
|
64
|
+
"""
|
65
|
+
Returns a list of tuples with the description and board name for the given port and version
|
66
|
+
|
67
|
+
port : str : The Micropython port to filter for
|
68
|
+
versions : List[str] : The Micropython versions to filter for (actual versions required)
|
69
|
+
"""
|
70
|
+
mp_boards = get_mp_boards_for_port(port, versions)
|
71
|
+
|
72
|
+
boards = set(
|
73
|
+
{(f'{board["description"]} [board["board"]] {board["version"]}', board["board"]) for board in mp_boards}
|
74
|
+
)
|
39
75
|
return sorted(list(boards))
|
40
76
|
|
41
77
|
|
42
|
-
def
|
78
|
+
def find_mp_board(board: str) -> Board:
|
79
|
+
"""Find the board for the given board"""
|
43
80
|
info = read_boardinfo()
|
44
81
|
for board_info in info:
|
45
82
|
if board_info["board"] == board:
|
46
|
-
|
47
|
-
|
83
|
+
if "cpu" not in board_info or not board_info["cpu"]:
|
84
|
+
if " with " in board_info["description"]:
|
85
|
+
board_info["cpu"] = board_info["description"].split(" with ")[-1]
|
86
|
+
else:
|
87
|
+
board_info["cpu"] = board_info["port"]
|
88
|
+
return board_info
|
89
|
+
raise LookupError(f"Board {board} not found")
|