micropython-stubber 1.23.0__py3-none-any.whl → 1.23.1.post1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {micropython_stubber-1.23.0.dist-info → micropython_stubber-1.23.1.post1.dist-info}/METADATA +32 -14
- micropython_stubber-1.23.1.post1.dist-info/RECORD +159 -0
- micropython_stubber-1.23.1.post1.dist-info/entry_points.txt +5 -0
- mpflash/README.md +40 -4
- mpflash/mpflash/add_firmware.py +1 -1
- mpflash/mpflash/ask_input.py +1 -1
- {stubber → mpflash/mpflash}/basicgit.py +3 -13
- mpflash/mpflash/bootloader/__init__.py +2 -37
- mpflash/mpflash/bootloader/activate.py +60 -0
- mpflash/mpflash/bootloader/detect.py +82 -0
- mpflash/mpflash/bootloader/manual.py +10 -11
- mpflash/mpflash/bootloader/micropython.py +2 -0
- mpflash/mpflash/bootloader/touch1200.py +13 -22
- mpflash/mpflash/cli_download.py +2 -2
- mpflash/mpflash/cli_flash.py +13 -16
- mpflash/mpflash/cli_group.py +18 -5
- mpflash/mpflash/cli_list.py +8 -2
- mpflash/mpflash/cli_main.py +3 -5
- mpflash/mpflash/common.py +3 -1
- mpflash/mpflash/config.py +2 -1
- mpflash/mpflash/connected.py +11 -8
- mpflash/mpflash/download.py +9 -5
- mpflash/mpflash/downloaded.py +1 -1
- mpflash/mpflash/{flash.py → flash/__init__.py} +3 -3
- mpflash/mpflash/{flash_esp.py → flash/esp.py} +1 -1
- mpflash/mpflash/{flash_stm32.py → flash/stm32.py} +4 -3
- mpflash/mpflash/{flash_stm32_dfu.py → flash/stm32_dfu.py} +1 -1
- mpflash/mpflash/{flash_uf2.py → flash/uf2/__init__.py} +19 -20
- mpflash/mpflash/{flash_uf2_linux.py → flash/uf2/linux.py} +12 -11
- mpflash/mpflash/{flash_uf2_macos.py → flash/uf2/macos.py} +11 -6
- mpflash/mpflash/{flash_uf2_windows.py → flash/uf2/windows.py} +11 -6
- mpflash/mpflash/{worklist.py → flash/worklist.py} +8 -9
- mpflash/mpflash/list.py +26 -9
- mpflash/mpflash/mpboard_id/__init__.py +1 -1
- mpflash/mpflash/mpboard_id/add_boards.py +3 -7
- mpflash/mpflash/mpboard_id/board_id.py +1 -1
- mpflash/mpflash/mpremoteboard/__init__.py +57 -17
- {stubber/utils → mpflash/mpflash}/versions.py +31 -24
- mpflash/poetry.lock +16 -5
- mpflash/pyproject.toml +4 -3
- stubber/__init__.py +1 -1
- stubber/board/createstubs.py +4 -4
- stubber/board/createstubs_db.py +5 -5
- stubber/board/createstubs_db_min.py +1 -1
- stubber/board/createstubs_db_mpy.mpy +0 -0
- stubber/board/createstubs_mem.py +5 -5
- stubber/board/createstubs_mem_min.py +1 -1
- stubber/board/createstubs_mem_mpy.mpy +0 -0
- stubber/board/createstubs_min.py +1 -1
- stubber/board/createstubs_mpy.mpy +0 -0
- stubber/bulk/mcu_stubber.py +28 -45
- stubber/codemod/enrich.py +1 -1
- stubber/codemod/merge_docstub.py +1 -1
- stubber/codemod/utils.py +2 -3
- stubber/commands/build_cmd.py +1 -1
- stubber/commands/cli.py +6 -12
- stubber/commands/clone_cmd.py +3 -2
- stubber/commands/config_cmd.py +1 -1
- stubber/commands/enrich_folder_cmd.py +1 -1
- stubber/commands/get_core_cmd.py +1 -1
- stubber/commands/get_docstubs_cmd.py +6 -3
- stubber/commands/get_frozen_cmd.py +6 -3
- stubber/commands/get_mcu_cmd.py +53 -12
- stubber/commands/merge_cmd.py +2 -3
- stubber/commands/publish_cmd.py +2 -3
- stubber/commands/stub_cmd.py +1 -1
- stubber/commands/switch_cmd.py +2 -2
- stubber/commands/variants_cmd.py +2 -3
- stubber/downloader.py +2 -1
- stubber/freeze/common.py +7 -3
- stubber/freeze/freeze_folder.py +2 -2
- stubber/freeze/freeze_manifest_2.py +19 -6
- stubber/freeze/get_frozen.py +8 -4
- stubber/get_cpython.py +15 -4
- stubber/minify.py +11 -6
- stubber/publish/candidates.py +20 -7
- stubber/publish/defaults.py +4 -9
- stubber/publish/merge_docstubs.py +4 -2
- stubber/publish/missing_class_methods.py +5 -3
- stubber/publish/package.py +8 -4
- stubber/publish/pathnames.py +2 -2
- stubber/publish/publish.py +2 -2
- stubber/publish/pypi.py +6 -2
- stubber/publish/stubpackage.py +39 -17
- stubber/rst/classsort.py +2 -1
- stubber/rst/lookup.py +1 -0
- stubber/rst/reader.py +12 -20
- stubber/rst/report_return.py +12 -4
- stubber/rst/rst_utils.py +2 -1
- stubber/stubs_from_docs.py +1 -1
- stubber/tools/manifestfile.py +1 -2
- stubber/update_fallback.py +2 -2
- stubber/update_module_list.py +1 -1
- stubber/utils/__init__.py +2 -1
- stubber/utils/config.py +18 -8
- stubber/utils/manifest.py +2 -4
- stubber/utils/post.py +2 -1
- stubber/utils/repos.py +4 -5
- stubber/utils/stubmaker.py +1 -1
- stubber/utils/typed_config_toml.py +5 -2
- stubber/variants.py +1 -1
- micropython_stubber-1.23.0.dist-info/RECORD +0 -159
- micropython_stubber-1.23.0.dist-info/entry_points.txt +0 -3
- mpflash/mpflash/flash_stm32_cube.py +0 -111
- mpflash/mpflash/vendor/versions.py +0 -119
- {micropython_stubber-1.23.0.dist-info → micropython_stubber-1.23.1.post1.dist-info}/LICENSE +0 -0
- {micropython_stubber-1.23.0.dist-info → micropython_stubber-1.23.1.post1.dist-info}/WHEEL +0 -0
- /mpflash/{mpflash/vendor/basicgit.py → basicgit.py} +0 -0
- /mpflash/mpflash/{flash_uf2_boardid.py → flash/uf2/boardid.py} +0 -0
- /mpflash/mpflash/{uf2disk.py → flash/uf2/uf2disk.py} +0 -0
@@ -12,7 +12,7 @@ from typing import List
|
|
12
12
|
from loguru import logger as log
|
13
13
|
from rich.progress import track
|
14
14
|
|
15
|
-
from .
|
15
|
+
from .boardid import get_board_id
|
16
16
|
from .uf2disk import UF2Disk
|
17
17
|
|
18
18
|
glb_dismount_me: List[UF2Disk] = []
|
@@ -42,10 +42,7 @@ def get_uf2_drives():
|
|
42
42
|
uf2.mountpoint = uf2_part["mountpoint"]
|
43
43
|
yield uf2
|
44
44
|
elif disk["type"] == "disk" and disk.get("children") and len(disk.get("children")) > 0:
|
45
|
-
if (
|
46
|
-
disk.get("children")[0]["type"] == "part"
|
47
|
-
and disk.get("children")[0]["fstype"] == "vfat"
|
48
|
-
):
|
45
|
+
if disk.get("children")[0]["type"] == "part" and disk.get("children")[0]["fstype"] == "vfat":
|
49
46
|
uf2_part = disk.get("children")[0]
|
50
47
|
# print( json.dumps(uf2_part, indent=4))
|
51
48
|
uf2 = UF2Disk()
|
@@ -98,16 +95,17 @@ def dismount_uf2_linux():
|
|
98
95
|
glb_dismount_me = []
|
99
96
|
|
100
97
|
|
101
|
-
def wait_for_UF2_linux(s_max: int = 10):
|
98
|
+
def wait_for_UF2_linux(board_id: str, s_max: int = 10):
|
102
99
|
destination = ""
|
103
100
|
wait = 10
|
104
101
|
uf2_drives = []
|
105
102
|
# while not destination and wait > 0:
|
106
103
|
for _ in track(
|
107
104
|
range(s_max),
|
108
|
-
description="Waiting for mcu to mount as a drive",
|
105
|
+
description=f"Waiting for mcu to mount as a drive ({s_max}s)",
|
109
106
|
transient=True,
|
110
|
-
|
107
|
+
show_speed=False,
|
108
|
+
refresh_per_second=1,
|
111
109
|
total=s_max,
|
112
110
|
):
|
113
111
|
uf2_drives += list(get_uf2_drives())
|
@@ -116,9 +114,12 @@ def wait_for_UF2_linux(s_max: int = 10):
|
|
116
114
|
time.sleep(1)
|
117
115
|
try:
|
118
116
|
if Path(drive.mountpoint, "INFO_UF2.TXT").exists():
|
119
|
-
|
120
|
-
|
121
|
-
|
117
|
+
this_board_id = get_board_id(Path(drive.mountpoint))
|
118
|
+
if not board_id or board_id.upper() in this_board_id.upper():
|
119
|
+
# is it the correct board?
|
120
|
+
destination = Path(drive.mountpoint)
|
121
|
+
break
|
122
|
+
continue
|
122
123
|
except PermissionError:
|
123
124
|
log.debug(f"Permission error on {drive.mountpoint}")
|
124
125
|
continue
|
@@ -9,26 +9,31 @@ from typing import Optional
|
|
9
9
|
|
10
10
|
from rich.progress import track
|
11
11
|
|
12
|
+
from .boardid import get_board_id
|
12
13
|
|
13
|
-
|
14
|
+
|
15
|
+
def wait_for_UF2_macos(board_id: str, s_max: int = 10) -> Optional[Path]:
|
14
16
|
"""Wait for the MCU to mount as a drive"""
|
15
17
|
if s_max < 1:
|
16
18
|
s_max = 10
|
17
19
|
destination = None
|
18
20
|
for _ in track(
|
19
21
|
range(s_max),
|
20
|
-
description="Waiting for mcu to mount as a drive",
|
22
|
+
description=f"Waiting for mcu to mount as a drive ({s_max}s)",
|
21
23
|
transient=True,
|
22
|
-
|
24
|
+
show_speed=False,
|
25
|
+
refresh_per_second=1,
|
23
26
|
total=s_max,
|
24
27
|
):
|
25
|
-
# log.info(f"Waiting for mcu to mount as a drive : {n} seconds left")
|
26
28
|
vol_mounts = Path("/Volumes").iterdir()
|
27
29
|
for vol in vol_mounts:
|
28
30
|
try:
|
29
31
|
if Path(vol, "INFO_UF2.TXT").exists():
|
30
|
-
|
31
|
-
|
32
|
+
this_board_id = get_board_id(Path(vol))
|
33
|
+
if not board_id or board_id.upper() in this_board_id.upper():
|
34
|
+
destination = Path(vol)
|
35
|
+
break
|
36
|
+
continue
|
32
37
|
except OSError:
|
33
38
|
pass
|
34
39
|
if destination:
|
@@ -7,29 +7,34 @@ import time
|
|
7
7
|
from pathlib import Path
|
8
8
|
from typing import Optional
|
9
9
|
|
10
|
+
from .boardid import get_board_id
|
10
11
|
import psutil
|
11
12
|
from rich.progress import track
|
12
13
|
|
13
14
|
|
14
|
-
def wait_for_UF2_windows(s_max: int = 10)
|
15
|
+
def wait_for_UF2_windows(board_id: str, s_max: int = 10)-> Optional[Path]:
|
15
16
|
"""Wait for the MCU to mount as a drive"""
|
16
17
|
if s_max < 1:
|
17
18
|
s_max = 10
|
18
19
|
destination = None
|
19
20
|
for _ in track(
|
20
21
|
range(s_max),
|
21
|
-
description="Waiting for mcu to mount as a drive",
|
22
|
+
description=f"Waiting for mcu to mount as a drive ({s_max}s)",
|
22
23
|
transient=True,
|
23
|
-
|
24
|
+
show_speed=False,
|
25
|
+
refresh_per_second=1,
|
24
26
|
total=s_max,
|
25
27
|
):
|
26
|
-
# log.info(f"Waiting for mcu to mount as a drive : {n} seconds left")
|
27
28
|
drives = [drive.device for drive in psutil.disk_partitions()]
|
28
29
|
for drive in drives:
|
29
30
|
try:
|
30
31
|
if Path(drive, "INFO_UF2.TXT").exists():
|
31
|
-
|
32
|
-
|
32
|
+
this_board_id = get_board_id(Path(drive))
|
33
|
+
if not board_id or board_id.upper() in this_board_id.upper():
|
34
|
+
# is it the correct board?
|
35
|
+
destination = Path(drive)
|
36
|
+
break
|
37
|
+
continue
|
33
38
|
except OSError:
|
34
39
|
pass
|
35
40
|
if destination:
|
@@ -1,15 +1,16 @@
|
|
1
|
+
"""Worklist for updating boards"""
|
2
|
+
|
1
3
|
from pathlib import Path
|
2
4
|
from typing import Dict, List, Optional, Tuple
|
3
5
|
|
4
6
|
from loguru import logger as log
|
5
7
|
|
6
|
-
from mpflash.common import FWInfo, filtered_comports
|
8
|
+
from mpflash.common import FWInfo, filtered_comports
|
9
|
+
from mpflash.downloaded import find_downloaded_firmware
|
7
10
|
from mpflash.errors import MPFlashError
|
8
|
-
|
9
|
-
from .
|
10
|
-
from .
|
11
|
-
from .mpboard_id import find_known_board
|
12
|
-
from .mpremoteboard import MPRemoteBoard
|
11
|
+
from mpflash.list import show_mcus
|
12
|
+
from mpflash.mpboard_id import find_known_board
|
13
|
+
from mpflash.mpremoteboard import MPRemoteBoard
|
13
14
|
|
14
15
|
# #########################################################################################################
|
15
16
|
WorkList = List[Tuple[MPRemoteBoard, FWInfo]]
|
@@ -39,9 +40,7 @@ def auto_update(
|
|
39
40
|
wl: WorkList = []
|
40
41
|
for mcu in conn_boards:
|
41
42
|
if mcu.family not in ("micropython", "unknown"):
|
42
|
-
log.warning(
|
43
|
-
f"Skipping flashing {mcu.family} {mcu.port} {mcu.board} on {mcu.serialport} as it is not a MicroPython firmware"
|
44
|
-
)
|
43
|
+
log.warning(f"Skipping flashing {mcu.family} {mcu.port} {mcu.board} on {mcu.serialport} as it is not a MicroPython firmware")
|
45
44
|
continue
|
46
45
|
board_firmwares = find_downloaded_firmware(
|
47
46
|
fw_folder=fw_folder,
|
mpflash/mpflash/list.py
CHANGED
@@ -3,8 +3,9 @@ from typing import List
|
|
3
3
|
from rich.progress import track
|
4
4
|
from rich.table import Table
|
5
5
|
|
6
|
+
from mpflash.config import config
|
6
7
|
from mpflash.mpremoteboard import MPRemoteBoard
|
7
|
-
from mpflash.
|
8
|
+
from mpflash.versions import clean_version
|
8
9
|
|
9
10
|
from .logger import console
|
10
11
|
|
@@ -37,11 +38,25 @@ def mcu_table(
|
|
37
38
|
- Serial Yes Yes
|
38
39
|
- Family abbrv. Yes
|
39
40
|
- Port - yes
|
40
|
-
- Board Yes Yes BOARD_ID and Description
|
41
|
+
- Board Yes Yes BOARD_ID and Description, and the description from board_info.toml
|
41
42
|
- CPU - Yes
|
42
43
|
- Version Yes Yes
|
43
44
|
- Build * * only if any of the mcus have a build
|
45
|
+
- Location - - only if --usb is given
|
44
46
|
"""
|
47
|
+
# refresh if requested
|
48
|
+
if refresh:
|
49
|
+
for mcu in track(
|
50
|
+
conn_mcus,
|
51
|
+
description="Updating board info",
|
52
|
+
transient=True,
|
53
|
+
show_speed=False,
|
54
|
+
refresh_per_second=1,
|
55
|
+
):
|
56
|
+
try:
|
57
|
+
mcu.get_mcu_info()
|
58
|
+
except ConnectionError:
|
59
|
+
continue
|
45
60
|
table = Table(
|
46
61
|
title=title,
|
47
62
|
title_style="magenta",
|
@@ -49,6 +64,7 @@ def mcu_table(
|
|
49
64
|
collapse_padding=True,
|
50
65
|
padding=(0, 0),
|
51
66
|
)
|
67
|
+
# Build the table
|
52
68
|
# check if the terminal is wide enough to show all columns or if we need to collapse some
|
53
69
|
is_wide = console.width > 99
|
54
70
|
needs_build = any(mcu.build for mcu in conn_mcus)
|
@@ -64,14 +80,13 @@ def mcu_table(
|
|
64
80
|
table.add_column("Version", overflow="fold", min_width=5, max_width=16)
|
65
81
|
if needs_build:
|
66
82
|
table.add_column("Build" if is_wide else "Bld", justify="right")
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
mcu.get_mcu_info()
|
72
|
-
except ConnectionError:
|
73
|
-
continue
|
83
|
+
if config.usb:
|
84
|
+
table.add_column("Location", overflow="fold", max_width=40)
|
85
|
+
# fill the table with the data
|
86
|
+
for mcu in conn_mcus:
|
74
87
|
description = f"[italic bright_cyan]{mcu.description}" if mcu.description else ""
|
88
|
+
if "description" in mcu.toml:
|
89
|
+
description += f"\n[italic bright_green]{mcu.toml['description']}"
|
75
90
|
row = [
|
76
91
|
mcu.serialport.replace("/dev/", ""),
|
77
92
|
abbrv_family(mcu.family, is_wide),
|
@@ -84,6 +99,8 @@ def mcu_table(
|
|
84
99
|
row.append(clean_version(mcu.version))
|
85
100
|
if needs_build:
|
86
101
|
row.append(mcu.build)
|
102
|
+
if config.usb:
|
103
|
+
row.append(mcu.location)
|
87
104
|
|
88
105
|
table.add_row(*row)
|
89
106
|
return table
|
@@ -10,7 +10,7 @@ from typing import List, Optional, Tuple
|
|
10
10
|
from mpflash.errors import MPFlashError
|
11
11
|
from mpflash.mpboard_id.board import Board
|
12
12
|
from mpflash.mpboard_id.store import read_known_boardinfo
|
13
|
-
from mpflash.
|
13
|
+
from mpflash.versions import clean_version
|
14
14
|
|
15
15
|
# KNOWN ports and boards are sourced from the micropython repo,
|
16
16
|
# this info is stored in the board_info.json file
|
@@ -12,11 +12,11 @@ import rich.table
|
|
12
12
|
from rich.console import Console
|
13
13
|
from rich.progress import track
|
14
14
|
|
15
|
-
import mpflash.
|
15
|
+
import mpflash.basicgit as git
|
16
16
|
from mpflash.logger import log
|
17
17
|
from mpflash.mpboard_id import Board
|
18
18
|
from mpflash.mpboard_id.store import write_boardinfo_json
|
19
|
-
from mpflash.
|
19
|
+
from mpflash.versions import micropython_versions
|
20
20
|
|
21
21
|
# look for all mpconfigboard.h files and extract the board name
|
22
22
|
# from the #define MICROPY_HW_BOARD_NAME "PYBD_SF6"
|
@@ -222,11 +222,7 @@ def make_table(board_list: List[Board]) -> rich.table.Table:
|
|
222
222
|
|
223
223
|
def ask_mpy_path():
|
224
224
|
"""Ask the user for the path to the MicroPython repository."""
|
225
|
-
questions = [
|
226
|
-
inquirer.Text(
|
227
|
-
"mpy_path", message="Enter the path to the MicroPython repository", default=".\\repos\\micropython"
|
228
|
-
)
|
229
|
-
]
|
225
|
+
questions = [inquirer.Text("mpy_path", message="Enter the path to the MicroPython repository", default=".\\repos\\micropython")]
|
230
226
|
if answers := inquirer.prompt(questions):
|
231
227
|
return Path(answers["mpy_path"])
|
232
228
|
else:
|
@@ -9,7 +9,7 @@ from typing import Optional
|
|
9
9
|
from mpflash.errors import MPFlashError
|
10
10
|
from mpflash.logger import log
|
11
11
|
from mpflash.mpboard_id.store import read_known_boardinfo
|
12
|
-
from mpflash.
|
12
|
+
from mpflash.versions import clean_version, get_stable_mp_version
|
13
13
|
|
14
14
|
|
15
15
|
def find_board_id_by_description(
|
@@ -8,16 +8,20 @@ from pathlib import Path
|
|
8
8
|
from typing import List, Optional, Union
|
9
9
|
|
10
10
|
import serial.tools.list_ports
|
11
|
-
from loguru import logger as log
|
12
11
|
from rich.progress import track
|
13
12
|
from tenacity import retry, stop_after_attempt, wait_fixed
|
14
13
|
|
15
14
|
from mpflash.errors import MPFlashError
|
15
|
+
from mpflash.logger import log
|
16
16
|
from mpflash.mpboard_id.board_id import find_board_id_by_description
|
17
17
|
from mpflash.mpremoteboard.runner import run
|
18
18
|
|
19
|
+
if sys.version_info >= (3, 11):
|
20
|
+
import tomllib # type: ignore
|
21
|
+
else:
|
22
|
+
import tomli as tomllib # type: ignore
|
23
|
+
|
19
24
|
###############################################################################################
|
20
|
-
# TODO : make this a bit nicer
|
21
25
|
HERE = Path(__file__).parent
|
22
26
|
|
23
27
|
OK = 0
|
@@ -29,7 +33,7 @@ RETRIES = 3
|
|
29
33
|
class MPRemoteBoard:
|
30
34
|
"""Class to run mpremote commands"""
|
31
35
|
|
32
|
-
def __init__(self, serialport: str = "", update: bool = False):
|
36
|
+
def __init__(self, serialport: str = "", update: bool = False, *, location: str = ""):
|
33
37
|
"""
|
34
38
|
Initialize MPRemoteBoard object.
|
35
39
|
|
@@ -37,7 +41,7 @@ class MPRemoteBoard:
|
|
37
41
|
- serialport (str): The serial port to connect to. Default is an empty string.
|
38
42
|
- update (bool): Whether to update the MCU information. Default is False.
|
39
43
|
"""
|
40
|
-
self.serialport = serialport
|
44
|
+
self.serialport: str = serialport
|
41
45
|
self.firmware = {}
|
42
46
|
|
43
47
|
self.connected = False
|
@@ -51,6 +55,8 @@ class MPRemoteBoard:
|
|
51
55
|
self.arch = ""
|
52
56
|
self.mpy = ""
|
53
57
|
self.build = ""
|
58
|
+
self.location = location
|
59
|
+
self.toml = {}
|
54
60
|
if update:
|
55
61
|
self.get_mcu_info()
|
56
62
|
|
@@ -91,9 +97,7 @@ class MPRemoteBoard:
|
|
91
97
|
|
92
98
|
if sys.platform == "win32":
|
93
99
|
# Windows sort of comports by number - but fallback to device name
|
94
|
-
return sorted(
|
95
|
-
output, key=lambda x: int(x.split()[0][3:]) if x.split()[0][3:].isdigit() else x
|
96
|
-
)
|
100
|
+
return sorted(output, key=lambda x: int(x.split()[0][3:]) if x.split()[0][3:].isdigit() else x)
|
97
101
|
# sort by device name
|
98
102
|
return sorted(output)
|
99
103
|
|
@@ -112,13 +116,14 @@ class MPRemoteBoard:
|
|
112
116
|
["run", str(HERE / "mpy_fw_info.py")],
|
113
117
|
no_info=True,
|
114
118
|
timeout=timeout,
|
119
|
+
resume=True, # Avoid restarts
|
115
120
|
)
|
116
121
|
if rc != OK:
|
117
122
|
raise ConnectionError(f"Failed to get mcu_info for {self.serialport}")
|
118
123
|
# Ok we have the info, now parse it
|
119
|
-
|
120
|
-
if
|
121
|
-
info = eval(
|
124
|
+
raw_info = result[0].strip()
|
125
|
+
if raw_info.startswith("{") and raw_info.endswith("}"):
|
126
|
+
info = eval(raw_info)
|
122
127
|
self.family = info["family"]
|
123
128
|
self.version = info["version"]
|
124
129
|
self.build = info["build"]
|
@@ -129,12 +134,47 @@ class MPRemoteBoard:
|
|
129
134
|
self.description = descr = info["board"]
|
130
135
|
pos = descr.rfind(" with")
|
131
136
|
short_descr = descr[:pos].strip() if pos != -1 else ""
|
132
|
-
if board_name := find_board_id_by_description(
|
133
|
-
descr, short_descr, version=self.version
|
134
|
-
):
|
137
|
+
if board_name := find_board_id_by_description(descr, short_descr, version=self.version):
|
135
138
|
self.board = board_name
|
136
139
|
else:
|
137
140
|
self.board = "UNKNOWN_BOARD"
|
141
|
+
# get the board_info.toml
|
142
|
+
self.get_board_info_toml()
|
143
|
+
# now we know the board is connected
|
144
|
+
self.connected = True
|
145
|
+
|
146
|
+
@retry(stop=stop_after_attempt(RETRIES), wait=wait_fixed(0.2), reraise=True) # type: ignore ## retry_error_cls=ConnectionError,
|
147
|
+
def get_board_info_toml(self, timeout: int = 1):
|
148
|
+
"""
|
149
|
+
Reads the content of the board_info.toml file from the connected board,
|
150
|
+
and adds that to the board object.
|
151
|
+
|
152
|
+
Parameters:
|
153
|
+
- timeout (int): The timeout value in seconds.
|
154
|
+
|
155
|
+
Raises:
|
156
|
+
- ConnectionError: If failed to communicate with the serial port.
|
157
|
+
"""
|
158
|
+
try:
|
159
|
+
rc, result = self.run_command(
|
160
|
+
["cat", ":board_info.toml"],
|
161
|
+
no_info=True,
|
162
|
+
timeout=timeout,
|
163
|
+
log_errors=False,
|
164
|
+
)
|
165
|
+
except Exception as e:
|
166
|
+
raise ConnectionError(f"Failed to get board_info.toml for {self.serialport}: {e}")
|
167
|
+
# this is optional - so only parse if we got the file
|
168
|
+
self.toml = {}
|
169
|
+
if rc in [OK]: # sometimes we get an -9 ???
|
170
|
+
try:
|
171
|
+
# Ok we have the info, now parse it
|
172
|
+
self.toml = tomllib.loads("".join(result))
|
173
|
+
log.debug(f"board_info.toml: {self.toml}")
|
174
|
+
except Exception as e:
|
175
|
+
log.error(f"Failed to parse board_info.toml: {e}")
|
176
|
+
else:
|
177
|
+
log.trace(f"Failed to read board_info.toml: {result}")
|
138
178
|
|
139
179
|
def disconnect(self) -> bool:
|
140
180
|
"""
|
@@ -162,6 +202,7 @@ class MPRemoteBoard:
|
|
162
202
|
log_errors: bool = True,
|
163
203
|
no_info: bool = False,
|
164
204
|
timeout: int = 60,
|
205
|
+
resume: bool = False,
|
165
206
|
**kwargs,
|
166
207
|
):
|
167
208
|
"""
|
@@ -182,7 +223,7 @@ class MPRemoteBoard:
|
|
182
223
|
if self.serialport:
|
183
224
|
prefix += ["connect", self.serialport]
|
184
225
|
# if connected add resume to keep state between commands
|
185
|
-
if self.connected:
|
226
|
+
if self.connected or resume:
|
186
227
|
prefix += ["resume"]
|
187
228
|
cmd = prefix + cmd
|
188
229
|
log.debug(" ".join(cmd))
|
@@ -211,11 +252,10 @@ class MPRemoteBoard:
|
|
211
252
|
"""wait for the board to restart"""
|
212
253
|
for _ in track(
|
213
254
|
range(timeout),
|
214
|
-
description="Waiting for the board to restart",
|
255
|
+
description=f"Waiting for the board to restart ({timeout}s)",
|
215
256
|
transient=True,
|
216
|
-
get_time=lambda: time.time(),
|
217
257
|
show_speed=False,
|
218
|
-
refresh_per_second=
|
258
|
+
refresh_per_second=1,
|
219
259
|
total=timeout,
|
220
260
|
):
|
221
261
|
time.sleep(1)
|
@@ -1,14 +1,17 @@
|
|
1
|
-
"""
|
1
|
+
"""
|
2
|
+
#############################################################
|
3
|
+
# Version handling copied from stubber/utils/versions.py
|
4
|
+
#############################################################
|
5
|
+
"""
|
2
6
|
|
3
|
-
from functools import lru_cache
|
4
7
|
from pathlib import Path
|
5
8
|
|
6
|
-
from
|
9
|
+
from cache_to_disk import NoCacheCondition, cache_to_disk
|
7
10
|
from loguru import logger as log
|
8
11
|
from packaging.version import parse
|
9
12
|
|
10
|
-
import
|
11
|
-
|
13
|
+
import mpflash.basicgit as git
|
14
|
+
from mpflash.common import GH_CLIENT
|
12
15
|
|
13
16
|
OLDEST_VERSION = "1.16"
|
14
17
|
"This is the oldest MicroPython version to build the stubs on"
|
@@ -27,7 +30,7 @@ def clean_version(
|
|
27
30
|
commit: bool = False,
|
28
31
|
drop_v: bool = False,
|
29
32
|
flat: bool = False,
|
30
|
-
):
|
33
|
+
): # sourcery skip: assign-if-exp
|
31
34
|
"Clean up and transform the many flavours of versions"
|
32
35
|
# 'v1.13.0-103-gb137d064e' --> 'v1.13-103'
|
33
36
|
if version in {"", "-"}:
|
@@ -48,14 +51,12 @@ def clean_version(
|
|
48
51
|
if len(nibbles) == 1:
|
49
52
|
version = nibbles[0]
|
50
53
|
elif build and not is_preview:
|
54
|
+
# HACK: this is not always right, but good enough most of the time
|
51
55
|
version = "-".join(nibbles) if commit else "-".join(nibbles[:-1])
|
56
|
+
elif is_preview:
|
57
|
+
version = "-".join((nibbles[0], V_PREVIEW))
|
52
58
|
else:
|
53
|
-
|
54
|
-
# HACK: this is not always right, but good enough most of the time
|
55
|
-
if is_preview:
|
56
|
-
version = "-".join((nibbles[0], V_PREVIEW))
|
57
|
-
else:
|
58
|
-
version = V_PREVIEW
|
59
|
+
version = V_PREVIEW
|
59
60
|
if flat:
|
60
61
|
version = version.strip().replace(".", "_").replace("-", "_")
|
61
62
|
else:
|
@@ -70,20 +71,12 @@ def clean_version(
|
|
70
71
|
return version
|
71
72
|
|
72
73
|
|
73
|
-
@
|
74
|
-
def checkedout_version(path: Path, flat: bool = False) -> str:
|
75
|
-
"""Get the checked-out version of the repo"""
|
76
|
-
version = git.get_local_tag(path.as_posix())
|
77
|
-
if not version:
|
78
|
-
raise ValueError("No valid Tag found")
|
79
|
-
version = utils.clean_version(version, flat=flat, drop_v=False)
|
80
|
-
return version
|
81
|
-
|
82
|
-
|
74
|
+
@cache_to_disk(n_days_to_cache=1)
|
83
75
|
def micropython_versions(minver: str = "v1.20", reverse: bool = False):
|
84
76
|
"""Get the list of micropython versions from github tags"""
|
77
|
+
cache_it = True
|
85
78
|
try:
|
86
|
-
gh_client =
|
79
|
+
gh_client = GH_CLIENT
|
87
80
|
repo = gh_client.get_repo("micropython/micropython")
|
88
81
|
versions = [tag.name for tag in repo.get_tags() if parse(tag.name) >= parse(minver)]
|
89
82
|
# Only keep the last preview
|
@@ -109,10 +102,15 @@ def micropython_versions(minver: str = "v1.20", reverse: bool = False):
|
|
109
102
|
"v1.11",
|
110
103
|
"v1.10",
|
111
104
|
]
|
105
|
+
cache_it = False
|
112
106
|
versions = [v for v in versions if parse(v) >= parse(minver)]
|
113
107
|
# remove all but the most recent (preview) version
|
114
108
|
versions = versions[:1] + [v for v in versions if "preview" not in v]
|
115
|
-
|
109
|
+
versions = sorted(versions, reverse=reverse)
|
110
|
+
if cache_it:
|
111
|
+
return versions
|
112
|
+
# returns - but does not cache
|
113
|
+
raise NoCacheCondition(function_value=versions)
|
116
114
|
|
117
115
|
|
118
116
|
def get_stable_mp_version() -> str:
|
@@ -126,3 +124,12 @@ def get_preview_mp_version() -> str:
|
|
126
124
|
all_versions = micropython_versions(minver=OLDEST_VERSION)
|
127
125
|
return [v for v in all_versions if v.endswith(V_PREVIEW)][-1]
|
128
126
|
|
127
|
+
|
128
|
+
# Do not cache , same path will have different versions checked out
|
129
|
+
def checkedout_version(path: Path, flat: bool = False) -> str:
|
130
|
+
"""Get the checked-out version of the repo"""
|
131
|
+
version = git.get_local_tag(path.as_posix())
|
132
|
+
if not version:
|
133
|
+
raise ValueError("No valid Tag found")
|
134
|
+
version = clean_version(version, flat=flat, drop_v=False)
|
135
|
+
return version
|
mpflash/poetry.lock
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# This file is automatically @generated by Poetry 1.8.
|
1
|
+
# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
|
2
2
|
|
3
3
|
[[package]]
|
4
4
|
name = "ansicon"
|
@@ -249,6 +249,17 @@ files = [
|
|
249
249
|
{file = "blkinfo-0.2.0.tar.gz", hash = "sha256:322a906595f78832d6725ac74a0b9fd2794df3388584d9f05c1a2f8e19324851"},
|
250
250
|
]
|
251
251
|
|
252
|
+
[[package]]
|
253
|
+
name = "cache-to-disk"
|
254
|
+
version = "2.0.0"
|
255
|
+
description = "Local disk caching decorator for python function."
|
256
|
+
optional = false
|
257
|
+
python-versions = "*"
|
258
|
+
files = [
|
259
|
+
{file = "cache_to_disk-2.0.0-py3-none-any.whl", hash = "sha256:ea5afe13d4284cb4a06169b0807fbc60547cbe19c54563bf90e1d44f24029481"},
|
260
|
+
{file = "cache_to_disk-2.0.0.tar.gz", hash = "sha256:79e19ea9b72eedc5cec83bb8aa55374afc671493e7d13d541f3b63eb3a13fb32"},
|
261
|
+
]
|
262
|
+
|
252
263
|
[[package]]
|
253
264
|
name = "cachetools"
|
254
265
|
version = "5.3.3"
|
@@ -1452,13 +1463,13 @@ test = ["codecov", "coverage", "mypy", "nptyping (>=1.3.0)", "numpy", "pycodesty
|
|
1452
1463
|
|
1453
1464
|
[[package]]
|
1454
1465
|
name = "urllib3"
|
1455
|
-
version = "2.2.
|
1466
|
+
version = "2.2.2"
|
1456
1467
|
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
1457
1468
|
optional = false
|
1458
1469
|
python-versions = ">=3.8"
|
1459
1470
|
files = [
|
1460
|
-
{file = "urllib3-2.2.
|
1461
|
-
{file = "urllib3-2.2.
|
1471
|
+
{file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
|
1472
|
+
{file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
|
1462
1473
|
]
|
1463
1474
|
|
1464
1475
|
[package.extras]
|
@@ -1585,4 +1596,4 @@ files = [
|
|
1585
1596
|
[metadata]
|
1586
1597
|
lock-version = "2.0"
|
1587
1598
|
python-versions = ">=3.8.1,<4.0"
|
1588
|
-
content-hash = "
|
1599
|
+
content-hash = "e0f5697e08c8c691e538c586c7a478cdc93de23d56435373b56abdd2147bda87"
|
mpflash/pyproject.toml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "mpflash"
|
3
|
-
version = "0.
|
3
|
+
version = "1.0.0"
|
4
4
|
description = "Flash and download tool for MicroPython firmwares"
|
5
5
|
authors = ["Jos Verlinde <jos_verlinde@hotmail.com>"]
|
6
6
|
license = "MIT"
|
@@ -26,18 +26,19 @@ esptool = "^4.7.0"
|
|
26
26
|
inquirer = "^3.2.4"
|
27
27
|
jsonlines = "^4.0.0"
|
28
28
|
jsons = "^1.6.3"
|
29
|
-
libusb = {version = "^1.0.27", platform = "win32"}
|
29
|
+
libusb = { version = "^1.0.27", platform = "win32" }
|
30
30
|
loguru = "^0.7.2"
|
31
31
|
mpremote = "^1.22.0"
|
32
32
|
packaging = "23.2"
|
33
33
|
platformdirs = "^4.2.0"
|
34
34
|
psutil = "^5.9.8"
|
35
35
|
pygithub = "^2.1.1"
|
36
|
-
python =
|
36
|
+
python = ">=3.8.1,<4.0"
|
37
37
|
pyusb = "^1.2.1"
|
38
38
|
requests = "^2.31.0"
|
39
39
|
rich-click = "^1.8.1"
|
40
40
|
tenacity = "8.2.3"
|
41
|
+
cache-to-disk = "^2.0.0"
|
41
42
|
|
42
43
|
|
43
44
|
[tool.poetry.group.dev]
|
stubber/__init__.py
CHANGED
stubber/board/createstubs.py
CHANGED
@@ -24,7 +24,7 @@ try:
|
|
24
24
|
except ImportError:
|
25
25
|
from ucollections import OrderedDict # type: ignore
|
26
26
|
|
27
|
-
__version__ = "v1.23.
|
27
|
+
__version__ = "v1.23.1"
|
28
28
|
ENOENT = 2
|
29
29
|
_MAX_CLASS_LEVEL = 2 # Max class nesting
|
30
30
|
LIBS = ["lib", "/lib", "/sd/lib", "/flash/lib", "."]
|
@@ -488,7 +488,7 @@ def ensure_folder(path: str):
|
|
488
488
|
|
489
489
|
def _build(s):
|
490
490
|
# extract build from sys.version or os.uname().version if available
|
491
|
-
# sys.version: 'MicroPython v1.23.
|
491
|
+
# sys.version: 'MicroPython v1.23.1-preview.6.g3d0b6276f'
|
492
492
|
# sys.implementation.version: 'v1.13-103-gb137d064e'
|
493
493
|
if not s:
|
494
494
|
return ""
|
@@ -595,10 +595,10 @@ def _info(): # type:() -> dict[str, str]
|
|
595
595
|
if (
|
596
596
|
info["version"]
|
597
597
|
and info["version"].endswith(".0")
|
598
|
-
and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.23.
|
598
|
+
and info["version"] >= "1.10.0" # versions from 1.10.0 to 1.23.1 do not have a micro .0
|
599
599
|
and info["version"] <= "1.19.9"
|
600
600
|
):
|
601
|
-
# versions from 1.10.0 to 1.23.
|
601
|
+
# versions from 1.10.0 to 1.23.1 do not have a micro .0
|
602
602
|
info["version"] = info["version"][:-2]
|
603
603
|
|
604
604
|
# spell-checker: disable
|