mpflash 1.24.5__py3-none-any.whl → 1.24.6__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 +22 -2
- mpflash/common.py +4 -13
- mpflash/downloaded.py +10 -2
- mpflash/mpboard_id/add_boards.py +25 -14
- mpflash/mpboard_id/board.py +2 -2
- mpflash/mpboard_id/board_info.zip +0 -0
- mpflash/mpremoteboard/__init__.py +13 -8
- mpflash/vendor/board_database.py +185 -0
- mpflash/vendor/readme.md +10 -1
- mpflash/versions.py +16 -32
- {mpflash-1.24.5.dist-info → mpflash-1.24.6.dist-info}/METADATA +7 -5
- {mpflash-1.24.5.dist-info → mpflash-1.24.6.dist-info}/RECORD +15 -14
- {mpflash-1.24.5.dist-info → mpflash-1.24.6.dist-info}/WHEEL +1 -1
- {mpflash-1.24.5.dist-info → mpflash-1.24.6.dist-info}/LICENSE +0 -0
- {mpflash-1.24.5.dist-info → mpflash-1.24.6.dist-info}/entry_points.txt +0 -0
mpflash/basicgit.py
CHANGED
@@ -136,6 +136,9 @@ def get_local_tags(repo: Optional[Path] = None, minver: Optional[str] = None) ->
|
|
136
136
|
return sorted(tags)
|
137
137
|
|
138
138
|
|
139
|
+
from github.GithubException import BadCredentialsException
|
140
|
+
|
141
|
+
|
139
142
|
@cachetools.func.ttl_cache(maxsize=16, ttl=60) # 60 seconds
|
140
143
|
def get_tags(repo: str, minver: Optional[str] = None) -> List[str]:
|
141
144
|
"""
|
@@ -176,7 +179,7 @@ def checkout_tag(tag: str, repo: Optional[Union[str, Path]] = None) -> bool:
|
|
176
179
|
return True
|
177
180
|
|
178
181
|
|
179
|
-
def sync_submodules(repo:
|
182
|
+
def sync_submodules(repo: Union[Path, str]) -> bool:
|
180
183
|
"""
|
181
184
|
make sure any submodules are in sync
|
182
185
|
"""
|
@@ -191,9 +194,26 @@ def sync_submodules(repo: Optional[Union[Path, str]] = None) -> bool:
|
|
191
194
|
log.debug(result.stderr)
|
192
195
|
else:
|
193
196
|
return False
|
197
|
+
checkout_arduino_lib(Path(repo))
|
194
198
|
return True
|
195
199
|
|
196
200
|
|
201
|
+
def checkout_arduino_lib(mpy_path: Path):
|
202
|
+
"""
|
203
|
+
Checkout the arduino-lib submodule repo if it exists
|
204
|
+
|
205
|
+
This is needed as some of the arduino boards freeze modules originationg from the arduino-lib
|
206
|
+
"""
|
207
|
+
# arduino_lib_path = mpy_path / "lib/arduino-lib"
|
208
|
+
if (mpy_path / "lib/arduino-lib").exists():
|
209
|
+
cmd = ["git", "submodule", "update", "--init", "lib/arduino-lib"]
|
210
|
+
try:
|
211
|
+
result = subprocess.run(cmd, cwd=mpy_path, check=True)
|
212
|
+
log.info(f"checkout arduino-lib: {result.returncode}")
|
213
|
+
except subprocess.CalledProcessError as e:
|
214
|
+
log.warning("Could not check out arduino-lib, error: ", e)
|
215
|
+
|
216
|
+
|
197
217
|
def checkout_commit(commit_hash: str, repo: Optional[Union[Path, str]] = None) -> bool:
|
198
218
|
"""
|
199
219
|
Checkout a specific commit
|
@@ -242,7 +262,7 @@ def switch_branch(branch: str, repo: Optional[Union[Path, str]] = None) -> bool:
|
|
242
262
|
|
243
263
|
def fetch(repo: Union[Path, str]) -> bool:
|
244
264
|
"""
|
245
|
-
fetches a repo
|
265
|
+
fetches a repo and all tags
|
246
266
|
repo should be in the form of : path/.git
|
247
267
|
repo = '../micropython/.git'
|
248
268
|
returns True on success
|
mpflash/common.py
CHANGED
@@ -7,10 +7,11 @@ from enum import Enum
|
|
7
7
|
from pathlib import Path
|
8
8
|
from typing import List, Optional, Union
|
9
9
|
|
10
|
-
from github import Auth, Github
|
11
10
|
from serial.tools import list_ports
|
12
11
|
from serial.tools.list_ports_common import ListPortInfo
|
13
12
|
|
13
|
+
from mpflash.basicgit import GH_CLIENT as GH_CLIENT
|
14
|
+
|
14
15
|
from .logger import log
|
15
16
|
|
16
17
|
# from mpflash.mpremoteboard import MPRemoteBoard
|
@@ -27,17 +28,6 @@ PORT_FWTYPES = {
|
|
27
28
|
"renesas-ra": [".hex"],
|
28
29
|
}
|
29
30
|
|
30
|
-
# Token with no permissions to avoid throttling
|
31
|
-
# 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
|
32
|
-
PAT_NO_ACCESS = (
|
33
|
-
"github_pat_"
|
34
|
-
+ "11AAHPVFQ0G4NTaQ73Bw5J"
|
35
|
-
+ "_fAp7K9sZ1qL8VFnI9g78eUlCdmOXHB3WzSdj2jtEYb4XF3N7PDJBl32qIxq"
|
36
|
-
)
|
37
|
-
|
38
|
-
PAT = os.environ.get("GITHUB_TOKEN") or PAT_NO_ACCESS
|
39
|
-
GH_CLIENT = Github(auth=Auth.Token(PAT))
|
40
|
-
|
41
31
|
|
42
32
|
@dataclass
|
43
33
|
class FWInfo:
|
@@ -150,9 +140,10 @@ def filtered_comports(
|
|
150
140
|
comports = [
|
151
141
|
p for p in list_ports.comports() if not any(fnmatch.fnmatch(p.device, i) for i in ignore)
|
152
142
|
]
|
153
|
-
|
143
|
+
|
154
144
|
if False:
|
155
145
|
import jsons
|
146
|
+
|
156
147
|
print(jsons.dumps(comports).replace('{"description":', '\n{"description":'))
|
157
148
|
|
158
149
|
if platform.system() == "Linux":
|
mpflash/downloaded.py
CHANGED
@@ -14,11 +14,15 @@ from .config import config
|
|
14
14
|
def downloaded_firmwares(fw_folder: Path) -> List[FWInfo]:
|
15
15
|
"""Load a list of locally downloaded firmwares from the jsonl file"""
|
16
16
|
firmwares: List[FWInfo] = []
|
17
|
+
log.debug(f"Reading {fw_folder / 'firmware.jsonl' }")
|
17
18
|
try:
|
18
19
|
with jsonlines.open(fw_folder / "firmware.jsonl") as reader:
|
19
20
|
firmwares = [FWInfo.from_dict(item) for item in reader]
|
20
21
|
except FileNotFoundError:
|
21
22
|
log.error(f"No firmware.jsonl found in {fw_folder}")
|
23
|
+
except jsonlines.InvalidLineError as e:
|
24
|
+
log.error(f"Invalid firmware.jsonl found in {fw_folder} : {e}")
|
25
|
+
|
22
26
|
# sort by filename
|
23
27
|
firmwares.sort(key=lambda x: x.filename)
|
24
28
|
return firmwares
|
@@ -109,7 +113,11 @@ def filter_downloaded_fwlist(
|
|
109
113
|
log.trace(f"Filtering firmware for {version} : {len(fw_list)} found.")
|
110
114
|
# filter by port
|
111
115
|
if port:
|
112
|
-
fw_list = [
|
116
|
+
fw_list = [
|
117
|
+
fw
|
118
|
+
for fw in fw_list
|
119
|
+
if fw.port == port and Path(fw.firmware).suffix in PORT_FWTYPES[port]
|
120
|
+
]
|
113
121
|
log.trace(f"Filtering firmware for {port} : {len(fw_list)} found.")
|
114
122
|
|
115
123
|
if board_id:
|
@@ -120,7 +128,7 @@ def filter_downloaded_fwlist(
|
|
120
128
|
# the firmware variant should match exactly the board_id
|
121
129
|
fw_list = [fw for fw in fw_list if fw.variant == board_id]
|
122
130
|
log.trace(f"Filtering firmware for {board_id} : {len(fw_list)} found.")
|
123
|
-
|
131
|
+
|
124
132
|
if selector and port in selector:
|
125
133
|
fw_list = [fw for fw in fw_list if fw.filename.endswith(selector[port])]
|
126
134
|
return fw_list
|
mpflash/mpboard_id/add_boards.py
CHANGED
@@ -23,9 +23,10 @@ from mpflash.versions import micropython_versions
|
|
23
23
|
# and the #define MICROPY_HW_MCU_NAME "STM32F767xx"
|
24
24
|
RE_H_MICROPY_HW_BOARD_NAME = re.compile(r"#define\s+MICROPY_HW_BOARD_NAME\s+\"(.+)\"")
|
25
25
|
RE_H_MICROPY_HW_MCU_NAME = re.compile(r"#define\s+MICROPY_HW_MCU_NAME\s+\"(.+)\"")
|
26
|
-
# find in the mpconfigboard
|
27
|
-
|
28
|
-
|
26
|
+
# find boards and variants in the mpconfigboard*.cmake files
|
27
|
+
RE_CMAKE_MICROPY_HW_BOARD_NAME = re.compile(
|
28
|
+
r"MICROPY_HW_BOARD_NAME\s?=\s?\"(?P<variant>[\w\s\S]*)\""
|
29
|
+
)
|
29
30
|
RE_CMAKE_MICROPY_HW_MCU_NAME = re.compile(r"MICROPY_HW_MCU_NAME\s?=\s?\"(?P<variant>[\w\s\S]*)\"")
|
30
31
|
# TODO: normal make files
|
31
32
|
|
@@ -42,10 +43,8 @@ def boards_from_repo(mpy_path: Path, version: str, family: Optional[str] = None)
|
|
42
43
|
"""
|
43
44
|
if not mpy_path.exists() or not mpy_path.is_dir():
|
44
45
|
raise FileNotFoundError(f"MicroPython path {mpy_path} does not exist.")
|
45
|
-
|
46
|
-
|
47
|
-
if not version:
|
48
|
-
version = git.get_local_tag() # type: ignore
|
46
|
+
family = family or "micropython"
|
47
|
+
version = version or git.get_local_tag() # type: ignore
|
49
48
|
if not version:
|
50
49
|
raise ValueError("No version provided and no local tag found.")
|
51
50
|
|
@@ -53,9 +52,10 @@ def boards_from_repo(mpy_path: Path, version: str, family: Optional[str] = None)
|
|
53
52
|
# look in mpconfigboard.h files
|
54
53
|
board_list = boards_from_cmake(mpy_path, version, family)
|
55
54
|
|
56
|
-
# look for
|
55
|
+
# look for boards in the .cmake files
|
57
56
|
board_list.extend(boards_from_headers(mpy_path, version, family))
|
58
|
-
|
57
|
+
|
58
|
+
# TODO:? look for variants in the board.json files
|
59
59
|
|
60
60
|
return board_list
|
61
61
|
|
@@ -63,7 +63,7 @@ def boards_from_repo(mpy_path: Path, version: str, family: Optional[str] = None)
|
|
63
63
|
def boards_from_cmake(mpy_path: Path, version: str, family: str):
|
64
64
|
"""Get boards from the mpconfigboard.cmake files to the board_list."""
|
65
65
|
board_list = []
|
66
|
-
for path in mpy_path.glob("ports/**/mpconfigboard
|
66
|
+
for path in mpy_path.glob("ports/**/mpconfigboard*.cmake"):
|
67
67
|
board = path.parent.name
|
68
68
|
port = path.parent.parent.parent.name
|
69
69
|
with open(path, "r") as f:
|
@@ -118,7 +118,9 @@ def boards_from_headers(mpy_path: Path, version: str, family: str):
|
|
118
118
|
mcu_name = match[1]
|
119
119
|
found += 1
|
120
120
|
if found == 2:
|
121
|
-
description =
|
121
|
+
description = (
|
122
|
+
f"{board_name} with {mcu_name}" if mcu_name != "-" else board_name
|
123
|
+
)
|
122
124
|
board_list.append(
|
123
125
|
Board(
|
124
126
|
board_id=board,
|
@@ -160,6 +162,8 @@ def boards_for_versions(versions: List[str], mpy_path: Path):
|
|
160
162
|
List[Board]: The list of Board objects.
|
161
163
|
"""
|
162
164
|
board_list: List[Board] = []
|
165
|
+
# first fetch all tags from the repository
|
166
|
+
git.fetch(mpy_path)
|
163
167
|
for version in track(versions, description="Searching MicroPython versions"):
|
164
168
|
if git.checkout_tag(tag=version, repo=mpy_path):
|
165
169
|
new_ones = boards_from_repo(mpy_path, version, family="micropython")
|
@@ -197,9 +201,10 @@ def make_table(board_list: List[Board]) -> rich.table.Table:
|
|
197
201
|
is_wide = True
|
198
202
|
|
199
203
|
table = rich.table.Table(title="MicroPython Board Information")
|
204
|
+
table.add_column("Port", justify="left", style="magenta")
|
200
205
|
table.add_column("BOARD_ID", justify="left", style="green")
|
206
|
+
table.add_column("Variant(s)", justify="left", style="blue")
|
201
207
|
table.add_column("Description", justify="left", style="cyan")
|
202
|
-
table.add_column("Port", justify="left", style="magenta")
|
203
208
|
table.add_column("Board Name", justify="left", style="blue")
|
204
209
|
if is_wide:
|
205
210
|
table.add_column("MCU Name", justify="left", style="blue")
|
@@ -209,7 +214,7 @@ def make_table(board_list: List[Board]) -> rich.table.Table:
|
|
209
214
|
table.add_column("Family", justify="left", style="blue")
|
210
215
|
|
211
216
|
for board in board_list:
|
212
|
-
row = [board.board_id, board.
|
217
|
+
row = [board.port, board.board_id, board.variant, board.description, board.board_name]
|
213
218
|
if is_wide:
|
214
219
|
row.append(board.mcu_name)
|
215
220
|
row.extend((str(Path(board.path).suffix), board.version))
|
@@ -222,7 +227,13 @@ def make_table(board_list: List[Board]) -> rich.table.Table:
|
|
222
227
|
|
223
228
|
def ask_mpy_path():
|
224
229
|
"""Ask the user for the path to the MicroPython repository."""
|
225
|
-
questions = [
|
230
|
+
questions = [
|
231
|
+
inquirer.Text(
|
232
|
+
"mpy_path",
|
233
|
+
message="Enter the path to the MicroPython repository",
|
234
|
+
default=".\\repos\\micropython",
|
235
|
+
)
|
236
|
+
]
|
226
237
|
if answers := inquirer.prompt(questions):
|
227
238
|
return Path(answers["mpy_path"])
|
228
239
|
else:
|
mpflash/mpboard_id/board.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from dataclasses import dataclass, field
|
2
2
|
from pathlib import Path
|
3
|
-
from typing import
|
3
|
+
from typing import Union
|
4
4
|
|
5
5
|
|
6
6
|
# - source : get_boardnames.py
|
@@ -20,7 +20,7 @@ class Board:
|
|
20
20
|
family: str = field(default="micropython")
|
21
21
|
mcu_name: str = field(default="")
|
22
22
|
cpu: str = field(default="")
|
23
|
-
|
23
|
+
variant: str = field(default="")
|
24
24
|
|
25
25
|
def __post_init__(self):
|
26
26
|
if not self.cpu:
|
Binary file
|
@@ -55,7 +55,7 @@ class MPRemoteBoard:
|
|
55
55
|
self.arch = ""
|
56
56
|
self.mpy = ""
|
57
57
|
self.build = ""
|
58
|
-
self.location = location
|
58
|
+
self.location = location # USB location
|
59
59
|
self.toml = {}
|
60
60
|
if update:
|
61
61
|
self.get_mcu_info()
|
@@ -97,7 +97,9 @@ class MPRemoteBoard:
|
|
97
97
|
|
98
98
|
if sys.platform == "win32":
|
99
99
|
# Windows sort of comports by number - but fallback to device name
|
100
|
-
return sorted(
|
100
|
+
return sorted(
|
101
|
+
output, key=lambda x: int(x.split()[0][3:]) if x.split()[0][3:].isdigit() else x
|
102
|
+
)
|
101
103
|
# sort by device name
|
102
104
|
return sorted(output)
|
103
105
|
|
@@ -116,9 +118,10 @@ class MPRemoteBoard:
|
|
116
118
|
["run", str(HERE / "mpy_fw_info.py")],
|
117
119
|
no_info=True,
|
118
120
|
timeout=timeout,
|
119
|
-
resume=
|
121
|
+
resume=False, # Avoid restarts
|
120
122
|
)
|
121
|
-
if rc
|
123
|
+
if rc:
|
124
|
+
log.debug(f"rc: {rc}, result: {result}")
|
122
125
|
raise ConnectionError(f"Failed to get mcu_info for {self.serialport}")
|
123
126
|
# Ok we have the info, now parse it
|
124
127
|
raw_info = result[0].strip()
|
@@ -134,7 +137,9 @@ class MPRemoteBoard:
|
|
134
137
|
self.description = descr = info["board"]
|
135
138
|
pos = descr.rfind(" with")
|
136
139
|
short_descr = descr[:pos].strip() if pos != -1 else ""
|
137
|
-
if board_name := find_board_id_by_description(
|
140
|
+
if board_name := find_board_id_by_description(
|
141
|
+
descr, short_descr, version=self.version
|
142
|
+
):
|
138
143
|
self.board = board_name
|
139
144
|
else:
|
140
145
|
self.board = "UNKNOWN_BOARD"
|
@@ -174,7 +179,7 @@ class MPRemoteBoard:
|
|
174
179
|
except Exception as e:
|
175
180
|
log.error(f"Failed to parse board_info.toml: {e}")
|
176
181
|
else:
|
177
|
-
log.trace(f"
|
182
|
+
log.trace(f"Did not find a board_info.toml: {result}")
|
178
183
|
|
179
184
|
def disconnect(self) -> bool:
|
180
185
|
"""
|
@@ -202,7 +207,7 @@ class MPRemoteBoard:
|
|
202
207
|
log_errors: bool = True,
|
203
208
|
no_info: bool = False,
|
204
209
|
timeout: int = 60,
|
205
|
-
resume: bool =
|
210
|
+
resume: Optional[bool] = None,
|
206
211
|
**kwargs,
|
207
212
|
):
|
208
213
|
"""
|
@@ -223,7 +228,7 @@ class MPRemoteBoard:
|
|
223
228
|
if self.serialport:
|
224
229
|
prefix += ["connect", self.serialport]
|
225
230
|
# if connected add resume to keep state between commands
|
226
|
-
if self.connected or resume:
|
231
|
+
if (resume != False) and self.connected or resume:
|
227
232
|
prefix += ["resume"]
|
228
233
|
cmd = prefix + cmd
|
229
234
|
log.debug(" ".join(cmd))
|
@@ -0,0 +1,185 @@
|
|
1
|
+
"""
|
2
|
+
The micropython git repo contains many 'board.json' files.
|
3
|
+
|
4
|
+
This is an example:
|
5
|
+
ports/stm32/boards/PYBV11/board.json
|
6
|
+
|
7
|
+
{
|
8
|
+
"deploy": [
|
9
|
+
"../PYBV10/deploy.md"
|
10
|
+
],
|
11
|
+
"docs": "",
|
12
|
+
"features": [],
|
13
|
+
"images": [
|
14
|
+
"PYBv1_1.jpg",
|
15
|
+
"PYBv1_1-C.jpg",
|
16
|
+
"PYBv1_1-E.jpg"
|
17
|
+
],
|
18
|
+
"mcu": "stm32f4",
|
19
|
+
"product": "Pyboard v1.1",
|
20
|
+
"thumbnail": "",
|
21
|
+
"url": "https://store.micropython.org/product/PYBv1.1",
|
22
|
+
"variants": {
|
23
|
+
"DP": "Double-precision float",
|
24
|
+
"DP_THREAD": "Double precision float + Threads",
|
25
|
+
"NETWORK": "Wiznet 5200 Driver",
|
26
|
+
"THREAD": "Threading"
|
27
|
+
},
|
28
|
+
"vendor": "George Robotics"
|
29
|
+
}
|
30
|
+
|
31
|
+
This module implements `class Database` which reads all 'board.json' files and
|
32
|
+
provides a way to browse it's data.
|
33
|
+
"""
|
34
|
+
|
35
|
+
from __future__ import annotations
|
36
|
+
|
37
|
+
import json
|
38
|
+
from dataclasses import dataclass, field
|
39
|
+
from glob import glob
|
40
|
+
from pathlib import Path
|
41
|
+
|
42
|
+
|
43
|
+
@dataclass(order=True)
|
44
|
+
class Variant:
|
45
|
+
name: str
|
46
|
+
"""
|
47
|
+
Example: "DP_THREAD"
|
48
|
+
"""
|
49
|
+
text: str
|
50
|
+
"""
|
51
|
+
Example: "Double precision float + Threads"
|
52
|
+
"""
|
53
|
+
board: Board = field(repr=False)
|
54
|
+
|
55
|
+
|
56
|
+
@dataclass(order=True)
|
57
|
+
class Board:
|
58
|
+
name: str
|
59
|
+
"""
|
60
|
+
Example: "PYBV11"
|
61
|
+
"""
|
62
|
+
variants: list[Variant]
|
63
|
+
"""
|
64
|
+
List of variants available for this board.
|
65
|
+
Variants are sorted. May be an empty list if no variants are available.
|
66
|
+
Example key: "DP_THREAD"
|
67
|
+
"""
|
68
|
+
url: str
|
69
|
+
"""
|
70
|
+
Primary URL to link to this board.
|
71
|
+
"""
|
72
|
+
mcu: str
|
73
|
+
"""
|
74
|
+
Example: "stm32f4"
|
75
|
+
"""
|
76
|
+
product: str
|
77
|
+
"""
|
78
|
+
Example: "Pyboard v1.1"
|
79
|
+
"""
|
80
|
+
vendor: str
|
81
|
+
"""
|
82
|
+
Example: "George Robotics"
|
83
|
+
"""
|
84
|
+
images: list[str]
|
85
|
+
"""
|
86
|
+
Images of this board, stored in the micropython-media repository.
|
87
|
+
Example: ["PYBv1_1.jpg", "PYBv1_1-C.jpg", "PYBv1_1-E.jpg"]
|
88
|
+
"""
|
89
|
+
deploy: list[str]
|
90
|
+
"""
|
91
|
+
Files that explain how to deploy for this board:
|
92
|
+
Example: ["../PYBV10/deploy.md"]
|
93
|
+
"""
|
94
|
+
port: Port | None = field(default=None, compare=False)
|
95
|
+
|
96
|
+
@staticmethod
|
97
|
+
def factory(filename_json: Path) -> Board:
|
98
|
+
with filename_json.open() as f:
|
99
|
+
board_json = json.load(f)
|
100
|
+
|
101
|
+
board = Board(
|
102
|
+
name=filename_json.parent.name,
|
103
|
+
variants=[],
|
104
|
+
url=board_json["url"],
|
105
|
+
mcu=board_json["mcu"],
|
106
|
+
product=board_json["product"],
|
107
|
+
vendor=board_json["vendor"],
|
108
|
+
images=board_json["images"],
|
109
|
+
deploy=board_json["deploy"],
|
110
|
+
)
|
111
|
+
board.variants.extend(
|
112
|
+
sorted([Variant(*v, board) for v in board_json.get("variants", {}).items()]) # type: ignore
|
113
|
+
)
|
114
|
+
return board
|
115
|
+
|
116
|
+
|
117
|
+
@dataclass(order=True)
|
118
|
+
class Port:
|
119
|
+
name: str
|
120
|
+
"""
|
121
|
+
Example: "stm32"
|
122
|
+
"""
|
123
|
+
boards: dict[str, Board] = field(default_factory=dict, repr=False)
|
124
|
+
"""
|
125
|
+
Example key: "PYBV11"
|
126
|
+
"""
|
127
|
+
|
128
|
+
|
129
|
+
@dataclass
|
130
|
+
class Database:
|
131
|
+
"""
|
132
|
+
This database contains all information retrieved from all 'board.json' files.
|
133
|
+
"""
|
134
|
+
|
135
|
+
mpy_root_directory: Path = field(repr=False)
|
136
|
+
port_filter: str = field(default="", repr=False)
|
137
|
+
|
138
|
+
ports: dict[str, Port] = field(default_factory=dict)
|
139
|
+
boards: dict[str, Board] = field(default_factory=dict)
|
140
|
+
|
141
|
+
def __post_init__(self) -> None:
|
142
|
+
mpy_dir = self.mpy_root_directory
|
143
|
+
# Take care to avoid using Path.glob! Performance was 15x slower.
|
144
|
+
for p in glob(f"{mpy_dir}/ports/**/boards/**/board.json"):
|
145
|
+
filename_json = Path(p)
|
146
|
+
port_name = filename_json.parent.parent.parent.name
|
147
|
+
if self.port_filter and self.port_filter != port_name:
|
148
|
+
continue
|
149
|
+
|
150
|
+
# Create a port
|
151
|
+
port = self.ports.get(port_name, None)
|
152
|
+
if port is None:
|
153
|
+
port = Port(port_name)
|
154
|
+
self.ports[port_name] = port
|
155
|
+
|
156
|
+
# Load board.json and attach it to the board
|
157
|
+
board = Board.factory(filename_json)
|
158
|
+
board.port = port
|
159
|
+
|
160
|
+
port.boards[board.name] = board
|
161
|
+
self.boards[board.name] = board
|
162
|
+
|
163
|
+
# Add 'special' ports, that don't have boards
|
164
|
+
# TODO(mst) Tidy up later (variant descriptions etc)
|
165
|
+
for special_port_name in ["unix", "webassembly", "windows"]:
|
166
|
+
if self.port_filter and self.port_filter != special_port_name:
|
167
|
+
continue
|
168
|
+
path = Path(mpy_dir, "ports", special_port_name)
|
169
|
+
variant_names = [var.name for var in path.glob("variants/*") if var.is_dir()]
|
170
|
+
board = Board(
|
171
|
+
special_port_name,
|
172
|
+
[],
|
173
|
+
f"https://github.com/micropython/micropython/blob/master/ports/{special_port_name}/README.md",
|
174
|
+
"",
|
175
|
+
"",
|
176
|
+
"",
|
177
|
+
[],
|
178
|
+
[],
|
179
|
+
)
|
180
|
+
board.variants = [Variant(v, "", board) for v in variant_names]
|
181
|
+
port = Port(special_port_name, {special_port_name: board})
|
182
|
+
board.port = port
|
183
|
+
|
184
|
+
self.ports[special_port_name] = port
|
185
|
+
self.boards[board.name] = board
|
mpflash/vendor/readme.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
1
|
These modules are vendored from the following repositories:
|
2
2
|
|
3
|
-
micropython/micropython
|
3
|
+
- https://github.com/micropython/micropython (MIT)
|
4
|
+
- dfu.py
|
5
|
+
- pydfy.py
|
6
|
+
|
7
|
+
- https://github.com/mattytrentini/mpbuild (MIT)
|
8
|
+
- board_database.py
|
9
|
+
|
10
|
+
- https://github.com/click-contrib/click-aliases (Public Domain)
|
11
|
+
- click_aliases.py (Robbin Bonthond)
|
12
|
+
|
mpflash/versions.py
CHANGED
@@ -81,34 +81,16 @@ def micropython_versions(minver: str = "v1.20", reverse: bool = False, cache_it=
|
|
81
81
|
try:
|
82
82
|
gh_client = GH_CLIENT
|
83
83
|
repo = gh_client.get_repo("micropython/micropython")
|
84
|
-
|
84
|
+
tags = [tag.name for tag in repo.get_tags() if parse(tag.name) >= parse(minver)]
|
85
|
+
versions = [v for v in tags if not v.endswith(V_PREVIEW)]
|
85
86
|
# Only keep the last preview
|
86
|
-
|
87
|
+
preview = sorted([v for v in tags if v.endswith(V_PREVIEW)], reverse=True)[0]
|
88
|
+
versions.append(preview)
|
87
89
|
except Exception as e:
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
"v1.22.0",
|
93
|
-
"v1.21.1",
|
94
|
-
"v1.21.0",
|
95
|
-
"v1.20.0",
|
96
|
-
"v1.19.1",
|
97
|
-
"v1.19",
|
98
|
-
"v1.18",
|
99
|
-
"v1.17",
|
100
|
-
"v1.16",
|
101
|
-
"v1.15",
|
102
|
-
"v1.14",
|
103
|
-
"v1.13",
|
104
|
-
"v1.12",
|
105
|
-
"v1.11",
|
106
|
-
"v1.10",
|
107
|
-
]
|
108
|
-
cache_it = False
|
109
|
-
versions = [v for v in versions if parse(v) >= parse(minver)]
|
110
|
-
# remove all but the most recent (preview) version
|
111
|
-
versions = versions[:1] + [v for v in versions if "preview" not in v]
|
90
|
+
log.error(e)
|
91
|
+
versions = []
|
92
|
+
# returns - but does not cache
|
93
|
+
raise NoCacheCondition(function_value=versions)
|
112
94
|
# remove any duplicates and sort
|
113
95
|
versions = sorted(list(set(versions)), reverse=reverse, key=lambda s: (not is_version(s), s))
|
114
96
|
if cache_it:
|
@@ -117,16 +99,18 @@ def micropython_versions(minver: str = "v1.20", reverse: bool = False, cache_it=
|
|
117
99
|
raise NoCacheCondition(function_value=versions)
|
118
100
|
|
119
101
|
|
120
|
-
def get_stable_mp_version() -> str:
|
102
|
+
def get_stable_mp_version(cache_it=True) -> str:
|
121
103
|
# read the versions from the git tags
|
122
|
-
all_versions = micropython_versions(minver=OLDEST_VERSION)
|
123
|
-
|
104
|
+
all_versions = micropython_versions(minver=OLDEST_VERSION, cache_it=cache_it)
|
105
|
+
versions = [v for v in all_versions if not v.endswith(V_PREVIEW)]
|
106
|
+
return versions[-1] if versions else ""
|
124
107
|
|
125
108
|
|
126
|
-
def get_preview_mp_version() -> str:
|
109
|
+
def get_preview_mp_version(cache_it=True) -> str:
|
127
110
|
# read the versions from the git tags
|
128
|
-
all_versions = micropython_versions(minver=OLDEST_VERSION)
|
129
|
-
|
111
|
+
all_versions = micropython_versions(minver=OLDEST_VERSION, cache_it=cache_it)
|
112
|
+
versions = [v for v in all_versions if v.endswith(V_PREVIEW)]
|
113
|
+
return versions[0] if versions else ""
|
130
114
|
|
131
115
|
|
132
116
|
# Do not cache , same path will have different versions checked out
|
@@ -1,19 +1,19 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: mpflash
|
3
|
-
Version: 1.24.
|
3
|
+
Version: 1.24.6
|
4
4
|
Summary: Flash and download tool for MicroPython firmwares
|
5
|
-
Home-page: https://github.com/Josverl/micropython-stubber/blob/main/src/mpflash/README.md
|
6
5
|
License: MIT
|
7
6
|
Keywords: MicroPython,firmware,flash,download,UF2,esptool
|
8
7
|
Author: Jos Verlinde
|
9
8
|
Author-email: jos_verlinde@hotmail.com
|
10
|
-
Requires-Python: >=3.
|
9
|
+
Requires-Python: >=3.9,<4.0
|
11
10
|
Classifier: License :: OSI Approved :: MIT License
|
12
11
|
Classifier: Programming Language :: Python :: 3
|
13
12
|
Classifier: Programming Language :: Python :: 3.9
|
14
13
|
Classifier: Programming Language :: Python :: 3.10
|
15
14
|
Classifier: Programming Language :: Python :: 3.11
|
16
15
|
Classifier: Programming Language :: Python :: 3.12
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
17
17
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
18
18
|
Classifier: Programming Language :: Python :: Implementation :: MicroPython
|
19
19
|
Classifier: Topic :: Software Development :: Build Tools
|
@@ -29,14 +29,16 @@ Requires-Dist: jsons (>=1.6.3,<2.0.0)
|
|
29
29
|
Requires-Dist: libusb (>=1.0.27,<2.0.0) ; sys_platform == "win32"
|
30
30
|
Requires-Dist: loguru (>=0.7.2,<0.8.0)
|
31
31
|
Requires-Dist: mpremote (>=1.22.0,<2.0.0)
|
32
|
-
Requires-Dist: packaging (
|
32
|
+
Requires-Dist: packaging (>=24.2,<25.0)
|
33
33
|
Requires-Dist: platformdirs (>=4.2.0,<5.0.0)
|
34
|
+
Requires-Dist: poetry (>=2.0.1,<3.0.0)
|
34
35
|
Requires-Dist: psutil (>=5.9.8,<6.0.0)
|
35
36
|
Requires-Dist: pygithub (>=2.1.1,<3.0.0)
|
36
37
|
Requires-Dist: pyusb (>=1.2.1,<2.0.0)
|
37
38
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
38
39
|
Requires-Dist: rich-click (>=1.8.1,<2.0.0)
|
39
40
|
Requires-Dist: tenacity (==8.2.3)
|
41
|
+
Project-URL: Homepage, https://github.com/Josverl/micropython-stubber/blob/main/src/mpflash/README.md
|
40
42
|
Project-URL: Repository, https://github.com/Josverl/micropython-stubber
|
41
43
|
Description-Content-Type: text/markdown
|
42
44
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
mpflash/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
2
|
mpflash/add_firmware.py,sha256=1h0HsA-EVi3HXLmoEvzwY_a-GuWYzPwulTYHHBB8THg,3428
|
3
3
|
mpflash/ask_input.py,sha256=RJHGGrhYniSu-bdoKnKptE3DtpiCREJGRTZmFazvG-E,8946
|
4
|
-
mpflash/basicgit.py,sha256=
|
4
|
+
mpflash/basicgit.py,sha256=NO27JTPUsnMWQ2bKI_zsIFsFTfCZO3QKbvQ23kIehxU,10734
|
5
5
|
mpflash/bootloader/__init__.py,sha256=Qy3E6tETPnzMga9LgD5UgOvJ0zZIBEqhtEVb4v8CTWQ,107
|
6
6
|
mpflash/bootloader/activate.py,sha256=FlO4XQlKyoOuvmDdj_0u_mjNPhjGwB_K17jQ-8nSXRA,2361
|
7
7
|
mpflash/bootloader/detect.py,sha256=fBrILi7-ICRaregqms3PYqwiQVAJC0rXVhpyzDkoPQI,2690
|
@@ -13,11 +13,11 @@ mpflash/cli_flash.py,sha256=pVqEsDocDT3KmIMTpXdym-ZlzThLSIp6oVtYib65dys,7595
|
|
13
13
|
mpflash/cli_group.py,sha256=VWwYHiPVV19sQEr5lL8LlcPyZ-A6Gs79eMDJy8LLt90,2615
|
14
14
|
mpflash/cli_list.py,sha256=ja21AZ4yghGTtOHkEtV1EOmT6EYxOiU2gzJc-mZaDto,2427
|
15
15
|
mpflash/cli_main.py,sha256=5EkvzsqOUDXvNaW814oSUcPWeNhnwh78Sg0MteDv_fk,1133
|
16
|
-
mpflash/common.py,sha256=
|
16
|
+
mpflash/common.py,sha256=umTouKs5Wb7Q2zOaaoO9nqmlpHIaiDBRIGYIkZMBVO8,7558
|
17
17
|
mpflash/config.py,sha256=tdpvAvAlpco1GfeG2evn5tAKYluLEanqwrrvkir7QcQ,1073
|
18
18
|
mpflash/connected.py,sha256=woYhuXoWpfzRMDUpBLVQZbVTGtMsKWNd5z1rsR1ELXA,3578
|
19
19
|
mpflash/download.py,sha256=wE4uBSFFMAKOBH4jwHweL0wVYh4vi74t1673ku_IeoA,14305
|
20
|
-
mpflash/downloaded.py,sha256=
|
20
|
+
mpflash/downloaded.py,sha256=nxTWU4lvhcthqvVmzpYHnXCnjD8wJv0KFq2KtaoTO1A,5160
|
21
21
|
mpflash/errors.py,sha256=IAidY3qkZsXy6Pm1rdmVFmGyg81ywHhse3itaPctA2w,247
|
22
22
|
mpflash/flash/__init__.py,sha256=g4Fp8MiquaDZXIvRJwYRkkll1MMyRud7x6qmwCk9Lgo,2096
|
23
23
|
mpflash/flash/esp.py,sha256=_VfbyYIEaUgAjsD66tjbdgYL6ElkSAfpIMKz6q4QKig,2287
|
@@ -33,21 +33,22 @@ mpflash/flash/worklist.py,sha256=owS3xJbWC-SzbK9z6jQER0Kat3OIV09IxnV-f-tjGlY,599
|
|
33
33
|
mpflash/list.py,sha256=lP_S5xbC0Men9HsXcIxOsP0bFRlCYh5CynMLFJx8cEE,3607
|
34
34
|
mpflash/logger.py,sha256=dI_H_a7EOdQJyvoeRHQuYeZuTKYVUS3DUPTLhE9rkdM,1098
|
35
35
|
mpflash/mpboard_id/__init__.py,sha256=b9PJiKFqmfyYgfi0-pbWGp2mrljdgvO6DNy0ABS8izU,3898
|
36
|
-
mpflash/mpboard_id/add_boards.py,sha256=
|
37
|
-
mpflash/mpboard_id/board.py,sha256=
|
36
|
+
mpflash/mpboard_id/add_boards.py,sha256=Bc83FctlVl4u4j0xeKTfEkuQj0WWIqxtdUF1P5RTAvY,9900
|
37
|
+
mpflash/mpboard_id/board.py,sha256=JKb4T67HmK7widW-4c1PgilvywMbZYToLk9Fyokm-6Q,1163
|
38
38
|
mpflash/mpboard_id/board_id.py,sha256=MnDWPqp0OqCkWD3E1Mhg-g20qASgPVHdROOCdr5TpOU,3249
|
39
|
-
mpflash/mpboard_id/board_info.zip,sha256=
|
39
|
+
mpflash/mpboard_id/board_info.zip,sha256=DC_yHwL8A8IC0YsA2ZXjlRLZkLKiw03k4FR2HSTfBXw,21328
|
40
40
|
mpflash/mpboard_id/store.py,sha256=n85vnUAxGKv1C23wkm22ZFAFGK6AZZiCFvc1lGJJjis,1703
|
41
|
-
mpflash/mpremoteboard/__init__.py,sha256=
|
41
|
+
mpflash/mpremoteboard/__init__.py,sha256=Vydc7jZai32lrGTUjwylZT9U8yulsgLIk39mnuI_k9I,9666
|
42
42
|
mpflash/mpremoteboard/mpy_fw_info.py,sha256=eRjhqN7MpmYE9TiS4iukquZZs3QE_lD5zv_vOPSjNrk,4821
|
43
43
|
mpflash/mpremoteboard/runner.py,sha256=-PgzAeBGbyXaAUlwyiw4mcINsP2U1XRRjP1_QdBrxpg,4786
|
44
|
+
mpflash/vendor/board_database.py,sha256=QE3oXj96oTAsx94gNfHMYWu_RgBTHW1v9Wp5dq_Dt-Q,5253
|
44
45
|
mpflash/vendor/click_aliases.py,sha256=c853EHSlkE2DvFqeFvFpwXKuJj3_jsXDP7iotVOKaAw,3156
|
45
46
|
mpflash/vendor/dfu.py,sha256=ZXMcE6aH4-43Wh4tbQT4U-q-BU3RUiL3JAxmP_QAK2s,5755
|
46
47
|
mpflash/vendor/pydfu.py,sha256=_MdBRo1EeNeKDqFPSTB5tNL1jGSBJgsVeVjE5e7Pb8s,20542
|
47
|
-
mpflash/vendor/readme.md,sha256=
|
48
|
-
mpflash/versions.py,sha256=
|
49
|
-
mpflash-1.24.
|
50
|
-
mpflash-1.24.
|
51
|
-
mpflash-1.24.
|
52
|
-
mpflash-1.24.
|
53
|
-
mpflash-1.24.
|
48
|
+
mpflash/vendor/readme.md,sha256=KcCbOVb_-9V6Cwwd0J01Avx4LuZphe9UJ40Gs-Hocf4,327
|
49
|
+
mpflash/versions.py,sha256=qGkE2LTzQ1QDyHc9-wzsHsRrN7PWK69xt0Vq3EVojms,4452
|
50
|
+
mpflash-1.24.6.dist-info/entry_points.txt,sha256=Jk_visOhYOsZIcSP2Ms9hKqfKy1iorR-6dYltSoWCpY,52
|
51
|
+
mpflash-1.24.6.dist-info/LICENSE,sha256=mWpNhsIxWzetYNnTpr4eb3HtgsxGIC8KcYWxXEcxQvE,1077
|
52
|
+
mpflash-1.24.6.dist-info/METADATA,sha256=H5PkYQyib3lTOeIc2HPGJjP6PTNxUUVb02UP2GoY8TM,17757
|
53
|
+
mpflash-1.24.6.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
54
|
+
mpflash-1.24.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|