micropython-stubber 1.20.4__py3-none-any.whl → 1.20.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {micropython_stubber-1.20.4.dist-info → micropython_stubber-1.20.5.dist-info}/METADATA +4 -4
- {micropython_stubber-1.20.4.dist-info → micropython_stubber-1.20.5.dist-info}/RECORD +44 -39
- mpflash/mpflash/ask_input.py +24 -14
- mpflash/mpflash/bootloader/__init__.py +36 -0
- mpflash/mpflash/bootloader/manual.py +102 -0
- mpflash/mpflash/bootloader/micropython.py +10 -0
- mpflash/mpflash/bootloader/touch1200.py +45 -0
- mpflash/mpflash/cli_download.py +1 -0
- mpflash/mpflash/cli_flash.py +16 -9
- mpflash/mpflash/cli_group.py +10 -4
- mpflash/mpflash/cli_list.py +6 -2
- mpflash/mpflash/cli_main.py +5 -2
- mpflash/mpflash/common.py +14 -1
- mpflash/mpflash/config.py +17 -1
- mpflash/mpflash/download.py +2 -3
- mpflash/mpflash/downloaded.py +3 -3
- mpflash/mpflash/errors.py +5 -1
- mpflash/mpflash/flash.py +10 -27
- mpflash/mpflash/flash_uf2_macos.py +0 -3
- mpflash/mpflash/vendor/click_aliases.py +91 -0
- mpflash/poetry.lock +102 -137
- mpflash/pyproject.toml +1 -1
- stubber/__init__.py +1 -1
- stubber/board/createstubs.py +3 -4
- stubber/board/createstubs_db.py +4 -5
- stubber/board/createstubs_db_min.py +1 -1
- stubber/board/createstubs_db_mpy.mpy +0 -0
- stubber/board/createstubs_mem.py +4 -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 +0 -1
- stubber/codemod/_partials/__init__.py +0 -2
- stubber/publish/candidates.py +7 -28
- stubber/publish/enums.py +0 -6
- stubber/publish/package.py +15 -46
- stubber/publish/publish.py +1 -2
- stubber/rst/lookup.py +7 -7
- stubber/rst/reader.py +26 -27
- stubber/update_module_list.py +0 -2
- {micropython_stubber-1.20.4.dist-info → micropython_stubber-1.20.5.dist-info}/LICENSE +0 -0
- {micropython_stubber-1.20.4.dist-info → micropython_stubber-1.20.5.dist-info}/WHEEL +0 -0
- {micropython_stubber-1.20.4.dist-info → micropython_stubber-1.20.5.dist-info}/entry_points.txt +0 -0
mpflash/mpflash/common.py
CHANGED
@@ -2,6 +2,7 @@ import fnmatch
|
|
2
2
|
import os
|
3
3
|
import sys
|
4
4
|
from dataclasses import dataclass, field
|
5
|
+
from enum import Enum
|
5
6
|
from pathlib import Path
|
6
7
|
from typing import List, Optional, Union
|
7
8
|
|
@@ -90,14 +91,26 @@ class DownloadParams(Params):
|
|
90
91
|
force: bool = False
|
91
92
|
|
92
93
|
|
94
|
+
class BootloaderMethod(Enum):
|
95
|
+
MANUAL = "manual"
|
96
|
+
MPY = "mpy"
|
97
|
+
TOUCH_1200 = "touch1200"
|
98
|
+
NONE = "none"
|
99
|
+
|
100
|
+
|
101
|
+
|
93
102
|
@dataclass
|
94
103
|
class FlashParams(Params):
|
95
104
|
"""Parameters for flashing a board"""
|
96
105
|
|
97
106
|
erase: bool = True
|
98
|
-
bootloader:
|
107
|
+
bootloader: BootloaderMethod = BootloaderMethod.NONE
|
99
108
|
cpu: str = ""
|
100
109
|
|
110
|
+
def __post_init__(self):
|
111
|
+
if isinstance(self.bootloader, str):
|
112
|
+
self.bootloader = BootloaderMethod(self.bootloader)
|
113
|
+
|
101
114
|
|
102
115
|
ParamType = Union[DownloadParams, FlashParams]
|
103
116
|
|
mpflash/mpflash/config.py
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
"""centralized configuration for mpflash"""
|
2
2
|
|
3
|
+
import os
|
3
4
|
from pathlib import Path
|
4
5
|
from typing import List
|
5
6
|
|
6
7
|
import pkg_resources
|
7
8
|
import platformdirs
|
8
9
|
|
10
|
+
from mpflash.logger import log
|
11
|
+
|
9
12
|
|
10
13
|
def get_version():
|
11
14
|
name = __package__ or "mpflash"
|
@@ -21,10 +24,23 @@ class MPtoolConfig:
|
|
21
24
|
quiet: bool = False
|
22
25
|
verbose: bool = False
|
23
26
|
ignore_ports: List[str] = []
|
24
|
-
interactive: bool = True
|
25
27
|
firmware_folder: Path = platformdirs.user_downloads_path() / "firmware"
|
26
28
|
# test options specified on the commandline
|
27
29
|
tests: List[str] = []
|
30
|
+
_interactive: bool = True
|
31
|
+
|
32
|
+
@property
|
33
|
+
def interactive(self):
|
34
|
+
# No interactions in CI
|
35
|
+
if os.getenv('GITHUB_ACTIONS') == 'true':
|
36
|
+
log.warning("Disabling interactive mode in CI")
|
37
|
+
return False
|
38
|
+
return self._interactive
|
39
|
+
|
40
|
+
@interactive.setter
|
41
|
+
def interactive(self, value:bool):
|
42
|
+
self._interactive = value
|
43
|
+
|
28
44
|
|
29
45
|
|
30
46
|
config = MPtoolConfig()
|
mpflash/mpflash/download.py
CHANGED
@@ -19,7 +19,6 @@ from loguru import logger as log
|
|
19
19
|
from rich.progress import track
|
20
20
|
|
21
21
|
from mpflash.common import PORT_FWTYPES, FWInfo
|
22
|
-
from mpflash.downloaded import clean_downloaded_firmwares
|
23
22
|
from mpflash.errors import MPFlashError
|
24
23
|
from mpflash.mpboard_id import get_known_ports
|
25
24
|
from mpflash.vendor.versions import clean_version
|
@@ -246,8 +245,8 @@ def download_firmwares(
|
|
246
245
|
continue
|
247
246
|
writer.write(board.to_dict())
|
248
247
|
downloaded += 1
|
249
|
-
if downloaded > 0:
|
250
|
-
|
248
|
+
# if downloaded > 0:
|
249
|
+
# clean_downloaded_firmwares(firmware_folder)
|
251
250
|
log.success(f"Downloaded {downloaded} firmwares, skipped {skipped} existing files.")
|
252
251
|
return downloaded + skipped
|
253
252
|
|
mpflash/mpflash/downloaded.py
CHANGED
@@ -103,9 +103,9 @@ def filter_downloaded_fwlist(
|
|
103
103
|
# never get a preview for an older version
|
104
104
|
fw_list = [fw for fw in fw_list if fw.preview]
|
105
105
|
else:
|
106
|
-
# FWInfo version has no v1.2.3 prefix
|
107
|
-
|
108
|
-
fw_list = [fw for fw in fw_list if fw.version in
|
106
|
+
# older FWInfo version has no v1.2.3 prefix
|
107
|
+
either = [clean_version(version, drop_v=False), clean_version(version, drop_v=True)]
|
108
|
+
fw_list = [fw for fw in fw_list if fw.version in either]
|
109
109
|
log.trace(f"Filtering firmware for {version} : {len(fw_list)} found.")
|
110
110
|
# filter by port
|
111
111
|
if port:
|
mpflash/mpflash/errors.py
CHANGED
mpflash/mpflash/flash.py
CHANGED
@@ -1,10 +1,9 @@
|
|
1
|
-
import time
|
2
1
|
from pathlib import Path
|
3
2
|
|
4
3
|
from loguru import logger as log
|
5
4
|
|
6
|
-
from mpflash.
|
7
|
-
from mpflash.
|
5
|
+
from mpflash.bootloader import enter_bootloader
|
6
|
+
from mpflash.common import PORT_FWTYPES, BootloaderMethod
|
8
7
|
|
9
8
|
from .flash_esp import flash_esp
|
10
9
|
from .flash_stm32 import flash_stm32
|
@@ -14,13 +13,15 @@ from .worklist import WorkList
|
|
14
13
|
# #########################################################################################################
|
15
14
|
|
16
15
|
|
16
|
+
|
17
17
|
def flash_list(
|
18
18
|
todo: WorkList,
|
19
19
|
fw_folder: Path,
|
20
20
|
erase: bool,
|
21
|
-
bootloader:
|
21
|
+
bootloader: BootloaderMethod,
|
22
22
|
):
|
23
23
|
"""Flash a list of boards with the specified firmware."""
|
24
|
+
UF2_PORTS = [port for port, exts in PORT_FWTYPES.items() if ".uf2" in exts]
|
24
25
|
flashed = []
|
25
26
|
for mcu, fw_info in todo:
|
26
27
|
fw_file = fw_folder / fw_info.filename
|
@@ -30,14 +31,13 @@ def flash_list(
|
|
30
31
|
log.info(f"Updating {mcu.board} on {mcu.serialport} to {fw_info.version}")
|
31
32
|
updated = None
|
32
33
|
# try:
|
33
|
-
if mcu.port in
|
34
|
-
|
35
|
-
|
36
|
-
enter_bootloader(mcu)
|
34
|
+
if mcu.port in UF2_PORTS and fw_file.suffix == ".uf2":
|
35
|
+
if not enter_bootloader(mcu, bootloader):
|
36
|
+
continue
|
37
37
|
updated = flash_uf2(mcu, fw_file=fw_file, erase=erase)
|
38
38
|
elif mcu.port in ["stm32"]:
|
39
|
-
if bootloader:
|
40
|
-
|
39
|
+
if not enter_bootloader(mcu, bootloader):
|
40
|
+
continue
|
41
41
|
updated = flash_stm32(mcu, fw_file, erase=erase)
|
42
42
|
elif mcu.port in ["esp32", "esp8266"]:
|
43
43
|
# bootloader is handled by esptool for esp32/esp8266
|
@@ -50,20 +50,3 @@ def flash_list(
|
|
50
50
|
else:
|
51
51
|
log.error(f"Failed to flash {mcu.board} on {mcu.serialport}")
|
52
52
|
return flashed
|
53
|
-
|
54
|
-
|
55
|
-
def enter_bootloader(mcu: MPRemoteBoard, timeout: int = 10, wait_after: int = 2):
|
56
|
-
"""Enter the bootloader mode for the board"""
|
57
|
-
log.info(f"Entering bootloader on {mcu.board} on {mcu.serialport}")
|
58
|
-
mcu.run_command("bootloader", timeout=timeout)
|
59
|
-
time.sleep(wait_after)
|
60
|
-
|
61
|
-
|
62
|
-
# TODO:
|
63
|
-
# flash from some sort of queue to allow different images to be flashed to the same board
|
64
|
-
# - flash variant 1
|
65
|
-
# - stub variant 1
|
66
|
-
# - flash variant 2
|
67
|
-
# - stub variant 2
|
68
|
-
#
|
69
|
-
# JIT download / download any missing firmwares based on the detected boards
|
@@ -3,15 +3,12 @@
|
|
3
3
|
# sourcery skip: snake-case-functions
|
4
4
|
from __future__ import annotations
|
5
5
|
|
6
|
-
import sys
|
7
6
|
import time
|
8
7
|
from pathlib import Path
|
9
8
|
from typing import Optional
|
10
9
|
|
11
|
-
from loguru import logger as log
|
12
10
|
from rich.progress import track
|
13
11
|
|
14
|
-
from .flash_uf2_boardid import get_board_id
|
15
12
|
|
16
13
|
|
17
14
|
def wait_for_UF2_macos(s_max: int = 10) -> Optional[Path]:
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# Copyright (c) 2016 Robbin Bonthond
|
2
|
+
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
# The above copyright notice and this permission notice shall be included in all
|
11
|
+
# copies or substantial portions of the Software.
|
12
|
+
# ------------------------------------------------------------------------------------
|
13
|
+
# modified to avoid conflcts with rich_click
|
14
|
+
|
15
|
+
# sourcery skip: assign-if-exp, use-named-expression
|
16
|
+
|
17
|
+
import rich_click as click
|
18
|
+
|
19
|
+
_click7 = click.__version__[0] >= "7"
|
20
|
+
|
21
|
+
|
22
|
+
class ClickAliasedGroup(click.RichGroup):
|
23
|
+
def __init__(self, *args, **kwargs):
|
24
|
+
super().__init__(*args, **kwargs)
|
25
|
+
self._commands = {}
|
26
|
+
self._aliases = {}
|
27
|
+
|
28
|
+
def add_command(self, *args, **kwargs):
|
29
|
+
aliases = kwargs.pop("aliases", [])
|
30
|
+
super().add_command(*args, **kwargs)
|
31
|
+
if aliases:
|
32
|
+
cmd = args[0]
|
33
|
+
name = args[1] if len(args) > 1 else None
|
34
|
+
name = name or cmd.name
|
35
|
+
if name is None:
|
36
|
+
raise TypeError("Command has no name.")
|
37
|
+
|
38
|
+
self._commands[name] = aliases
|
39
|
+
for alias in aliases:
|
40
|
+
self._aliases[alias] = cmd.name
|
41
|
+
|
42
|
+
def command(self, *args, **kwargs):
|
43
|
+
aliases = kwargs.pop("aliases", [])
|
44
|
+
decorator = super().command(*args, **kwargs)
|
45
|
+
if not aliases:
|
46
|
+
return decorator
|
47
|
+
|
48
|
+
def _decorator(f):
|
49
|
+
cmd = decorator(f)
|
50
|
+
if aliases:
|
51
|
+
self._commands[cmd.name] = aliases
|
52
|
+
for alias in aliases:
|
53
|
+
self._aliases[alias] = cmd.name
|
54
|
+
return cmd
|
55
|
+
|
56
|
+
return _decorator
|
57
|
+
|
58
|
+
def group(self, *args, **kwargs):
|
59
|
+
aliases = kwargs.pop("aliases", [])
|
60
|
+
decorator = super().group(*args, **kwargs)
|
61
|
+
if not aliases:
|
62
|
+
return decorator
|
63
|
+
|
64
|
+
def _decorator(f):
|
65
|
+
cmd = decorator(f)
|
66
|
+
if aliases:
|
67
|
+
self._commands[cmd.name] = aliases
|
68
|
+
for alias in aliases:
|
69
|
+
self._aliases[alias] = cmd.name
|
70
|
+
return cmd
|
71
|
+
|
72
|
+
return _decorator
|
73
|
+
|
74
|
+
def resolve_alias(self, cmd_name):
|
75
|
+
if cmd_name in self._aliases:
|
76
|
+
return self._aliases[cmd_name]
|
77
|
+
return cmd_name
|
78
|
+
|
79
|
+
def get_command(self, ctx, cmd_name):
|
80
|
+
cmd_name = self.resolve_alias(cmd_name)
|
81
|
+
command = super().get_command(ctx, cmd_name)
|
82
|
+
if command:
|
83
|
+
return command
|
84
|
+
return None
|
85
|
+
|
86
|
+
# def format_commands(self, ctx, formatter):
|
87
|
+
# TODO: output alias with commands - but that is a significant re-write
|
88
|
+
# for now add alias to help text
|
89
|
+
|
90
|
+
|
91
|
+
# ------------------------------------------------------------------------------------
|