micropython-stubber 1.17.5__py3-none-any.whl → 1.19.0__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.
Files changed (74) hide show
  1. {micropython_stubber-1.17.5.dist-info → micropython_stubber-1.19.0.dist-info}/METADATA +7 -6
  2. {micropython_stubber-1.17.5.dist-info → micropython_stubber-1.19.0.dist-info}/RECORD +71 -52
  3. mpflash/README.md +22 -3
  4. mpflash/libusb_flash.ipynb +203 -0
  5. mpflash/mpflash/ask_input.py +234 -0
  6. mpflash/mpflash/cli_download.py +107 -0
  7. mpflash/mpflash/cli_flash.py +165 -0
  8. mpflash/mpflash/cli_group.py +41 -8
  9. mpflash/mpflash/cli_list.py +41 -0
  10. mpflash/mpflash/cli_main.py +13 -8
  11. mpflash/mpflash/common.py +33 -122
  12. mpflash/mpflash/config.py +9 -0
  13. mpflash/mpflash/{downloader.py → download.py} +112 -120
  14. mpflash/mpflash/downloaded.py +108 -0
  15. mpflash/mpflash/errors.py +5 -0
  16. mpflash/mpflash/flash.py +69 -0
  17. mpflash/mpflash/flash_esp.py +17 -23
  18. mpflash/mpflash/flash_stm32.py +16 -113
  19. mpflash/mpflash/flash_stm32_cube.py +111 -0
  20. mpflash/mpflash/flash_stm32_dfu.py +101 -0
  21. mpflash/mpflash/flash_uf2.py +8 -8
  22. mpflash/mpflash/flash_uf2_linux.py +25 -12
  23. mpflash/mpflash/flash_uf2_windows.py +24 -12
  24. mpflash/mpflash/list.py +34 -37
  25. mpflash/mpflash/logger.py +12 -13
  26. mpflash/mpflash/mpboard_id/__init__.py +96 -0
  27. mpflash/mpflash/mpboard_id/board_id.py +63 -0
  28. mpflash/mpflash/mpboard_id/board_info.csv +2213 -0
  29. mpflash/mpflash/mpboard_id/board_info.json +19910 -0
  30. mpflash/mpflash/mpremoteboard/__init__.py +208 -0
  31. mpflash/mpflash/mpremoteboard/mpy_fw_info.py +141 -0
  32. {stubber/bulk → mpflash/mpflash/mpremoteboard}/runner.py +22 -5
  33. mpflash/mpflash/vendor/dfu.py +164 -0
  34. mpflash/mpflash/vendor/pydfu.py +605 -0
  35. mpflash/mpflash/vendor/readme.md +3 -0
  36. mpflash/mpflash/vendor/versions.py +113 -0
  37. mpflash/mpflash/worklist.py +147 -0
  38. mpflash/poetry.lock +411 -595
  39. mpflash/pyproject.toml +24 -8
  40. mpflash/stm32_udev_rules.md +63 -0
  41. stubber/__init__.py +1 -1
  42. stubber/basicgit.py +1 -0
  43. stubber/board/createstubs.py +10 -4
  44. stubber/board/createstubs_db.py +11 -5
  45. stubber/board/createstubs_db_min.py +61 -58
  46. stubber/board/createstubs_db_mpy.mpy +0 -0
  47. stubber/board/createstubs_mem.py +11 -5
  48. stubber/board/createstubs_mem_min.py +56 -53
  49. stubber/board/createstubs_mem_mpy.mpy +0 -0
  50. stubber/board/createstubs_min.py +54 -51
  51. stubber/board/createstubs_mpy.mpy +0 -0
  52. stubber/bulk/mcu_stubber.py +9 -5
  53. stubber/codemod/_partials/db_main.py +14 -25
  54. stubber/codemod/_partials/lvgl_main.py +2 -2
  55. stubber/codemod/board.py +10 -3
  56. stubber/commands/clone_cmd.py +7 -7
  57. stubber/commands/config_cmd.py +3 -0
  58. stubber/freeze/get_frozen.py +0 -2
  59. stubber/publish/candidates.py +1 -1
  60. stubber/publish/package.py +1 -1
  61. stubber/publish/pathnames.py +1 -1
  62. stubber/publish/stubpackage.py +1 -0
  63. stubber/rst/lookup.py +1 -1
  64. stubber/tools/manifestfile.py +5 -3
  65. stubber/utils/config.py +26 -36
  66. stubber/utils/repos.py +2 -2
  67. stubber/utils/versions.py +1 -0
  68. mpflash/mpflash/flasher.py +0 -287
  69. stubber/bulk/board_id.py +0 -40
  70. stubber/bulk/mpremoteboard.py +0 -141
  71. {micropython_stubber-1.17.5.dist-info → micropython_stubber-1.19.0.dist-info}/LICENSE +0 -0
  72. {micropython_stubber-1.17.5.dist-info → micropython_stubber-1.19.0.dist-info}/WHEEL +0 -0
  73. {micropython_stubber-1.17.5.dist-info → micropython_stubber-1.19.0.dist-info}/entry_points.txt +0 -0
  74. /mpflash/mpflash/{uf2_boardid.py → flash_uf2_boardid.py} +0 -0
mpflash/mpflash/list.py CHANGED
@@ -1,75 +1,72 @@
1
- import json
2
1
  from typing import List
3
2
 
4
- import rich_click as click
5
3
  from rich import print
6
4
  from rich.progress import track
7
5
  from rich.table import Table
8
6
 
9
- # TODO: - refactor so that we do not need the entire stubber package
10
- from stubber.bulk.mpremoteboard import MPRemoteBoard
7
+ from mpflash.mpremoteboard import MPRemoteBoard
11
8
 
12
- from .cli_group import cli
13
9
  from .config import config
10
+ from .logger import console
14
11
 
15
12
 
16
- @cli.command("list", help="List the connected boards.")
17
- @click.option(
18
- "--json",
19
- "-j",
20
- "as_json",
21
- is_flag=True,
22
- default=False,
23
- show_default=True,
24
- help="""Output in json format""",
25
- )
26
- def list_boards(as_json: bool):
27
- conn_boards = [
28
- MPRemoteBoard(sp)
29
- for sp in MPRemoteBoard.connected_boards()
30
- if sp not in config.ignore_ports
31
- ]
13
+ def list_mcus(bluetooth: bool = False):
14
+ """
15
+ Retrieves information about connected microcontroller boards.
32
16
 
33
- for mcu in track(conn_boards, description="Getting board info"):
17
+ Returns:
18
+ List[MPRemoteBoard]: A list of MPRemoteBoard instances with board information.
19
+ Raises:
20
+ ConnectionError: If there is an error connecting to a board.
21
+ """
22
+ conn_mcus = [MPRemoteBoard(sp) for sp in MPRemoteBoard.connected_boards(bluetooth) if sp not in config.ignore_ports]
23
+
24
+ for mcu in track(conn_mcus, description="Getting board info", transient=True, update_period=0.1):
34
25
  try:
35
26
  mcu.get_mcu_info()
36
27
  except ConnectionError as e:
37
28
  print(f"Error: {e}")
38
29
  continue
39
- if as_json:
40
- print(json.dumps([mcu.__dict__ for mcu in conn_boards], indent=4))
41
- else:
42
- show_boards(conn_boards, refresh=False)
30
+ return conn_mcus
43
31
 
44
32
 
45
- def show_boards(
46
- conn_boards: List[MPRemoteBoard],
33
+ def show_mcus(
34
+ conn_mcus: List[MPRemoteBoard],
47
35
  title: str = "Connected boards",
48
36
  refresh: bool = True,
49
- ):
37
+ ): # sourcery skip: extract-duplicate-method
50
38
  """Show the list of connected boards in a nice table"""
51
- table = Table(title=title)
52
- table.add_column("Serial")
39
+ table = Table(
40
+ title=title,
41
+ title_style="bold",
42
+ header_style="bold blue",
43
+ collapse_padding=True,
44
+ width=110,
45
+ row_styles=["blue", "yellow"],
46
+ )
47
+ table.add_column("Serial", overflow="fold")
53
48
  table.add_column("Family")
54
49
  table.add_column("Port")
55
- table.add_column("Board")
50
+ table.add_column("Board", overflow="fold")
51
+ # table.add_column("Variant") # TODO: add variant
56
52
  table.add_column("CPU")
57
53
  table.add_column("Version")
58
- table.add_column("build")
54
+ table.add_column("build", justify="right")
59
55
 
60
- for mcu in track(conn_boards, transient=True, description="Updating board info"):
56
+ for mcu in track(conn_mcus, description="Updating board info", transient=True, update_period=0.1):
61
57
  if refresh:
62
58
  try:
63
59
  mcu.get_mcu_info()
64
60
  except ConnectionError:
65
61
  continue
66
62
  table.add_row(
67
- mcu.serialport,
63
+ mcu.serialport.replace("/dev/", ""),
68
64
  mcu.family,
69
65
  mcu.port,
70
- mcu.board,
66
+ f"{mcu.board}\n{mcu.description}".strip(),
67
+ # mcu.variant,
71
68
  mcu.cpu,
72
69
  mcu.version,
73
70
  mcu.build,
74
71
  )
75
- print(table)
72
+ console.print(table)
mpflash/mpflash/logger.py CHANGED
@@ -1,13 +1,15 @@
1
- import sys
1
+ """Logging."""
2
2
 
3
3
  from loguru import logger as log
4
4
  from rich.console import Console
5
5
 
6
+ from .config import config
7
+
6
8
  console = Console()
7
9
 
8
10
 
9
11
  def _log_formatter(record: dict) -> str:
10
- """Log message formatter"""
12
+ """Log message formatter to combine loguru and rich formatting."""
11
13
  color_map = {
12
14
  "TRACE": "dim blue",
13
15
  "DEBUG": "cyan",
@@ -19,8 +21,7 @@ def _log_formatter(record: dict) -> str:
19
21
  }
20
22
  lvl_color = color_map.get(record["level"].name, "cyan")
21
23
  return (
22
- "[not bold green]{time:HH:mm:ss}[/not bold green] | {level.icon}"
23
- + f" - [{lvl_color}]{{message}}[/{lvl_color}]"
24
+ "[not bold green]{time:HH:mm:ss}[/not bold green] | {level.icon} " + f"[{lvl_color}]{{message}}[/{lvl_color}]"
24
25
  )
25
26
 
26
27
 
@@ -30,13 +31,11 @@ def set_loglevel(loglevel: str):
30
31
  log.remove()
31
32
  except ValueError:
32
33
  pass
33
- log.add(
34
- console.print, level=loglevel.upper(), colorize=False, format=_log_formatter
35
- )
34
+ log.add(console.print, level=loglevel.upper(), colorize=False, format=_log_formatter) # type: ignore
35
+
36
36
 
37
- # log.add(
38
- # console.print,
39
- # level=loglevel.upper(),
40
- # format=_log_formatter,
41
- # colorize=True,
42
- # )
37
+ def make_quiet():
38
+ """Make the logger quiet"""
39
+ config.quiet = True
40
+ console.quiet = True
41
+ set_loglevel("CRITICAL")
@@ -0,0 +1,96 @@
1
+ """
2
+ Access to the micropython port and board information that is stored in the board_info.json file
3
+ that is included in the module.
4
+
5
+ """
6
+
7
+ import json
8
+ from functools import lru_cache
9
+ from pathlib import Path
10
+ from typing import List, Optional, Tuple, TypedDict, Union
11
+
12
+ from mpflash.errors import MPFlashError
13
+ from mpflash.common import PORT_FWTYPES
14
+ from mpflash.vendor.versions import clean_version
15
+
16
+
17
+ # Board based on the dataclass Board but changed to TypedDict
18
+ # - source : get_boardnames.py
19
+ class Board(TypedDict):
20
+ """MicroPython Board definition"""
21
+
22
+ description: str
23
+ port: str
24
+ board: str
25
+ board_name: str
26
+ mcu_name: str
27
+ path: Union[Path, str]
28
+ version: str
29
+ cpu: str
30
+
31
+
32
+ @lru_cache(maxsize=None)
33
+ def read_stored_boardinfo() -> List[Board]:
34
+ """Reads the board_info.json file and returns the data as a list of Board objects"""
35
+ with open(Path(__file__).parent / "board_info.json", "r") as file:
36
+ return json.load(file)
37
+
38
+
39
+ def local_mp_ports() -> List[str]:
40
+ # TODO: Filter for Version
41
+ mp_boards = read_stored_boardinfo()
42
+ # select the unique ports from info
43
+ ports = set({board["port"] for board in mp_boards if board["port"] in PORT_FWTYPES.keys()})
44
+ return sorted(list(ports))
45
+
46
+
47
+ def get_stored_boards_for_port(port: str, versions: Optional[List[str]] = None):
48
+ """
49
+ Returns a list of boards for the given port and version(s)
50
+
51
+ port : str : The Micropython port to filter for
52
+ versions : List[str] : The Micropython versions to filter for (actual versions required)"""
53
+ mp_boards = read_stored_boardinfo()
54
+
55
+ # filter for 'preview' as they are not in the board_info.json
56
+ # instead use stable version
57
+ versions = versions or []
58
+ if "preview" in versions:
59
+ versions.remove("preview")
60
+ versions.append("stable")
61
+ if versions:
62
+ # make sure of the v prefix
63
+ versions = [clean_version(v) for v in versions]
64
+ # filter for the version(s)
65
+ mp_boards = [board for board in mp_boards if board["version"] in versions]
66
+ # filter for the port
67
+ mp_boards = [board for board in mp_boards if board["port"] == port]
68
+ return mp_boards
69
+
70
+
71
+ def known_stored_boards(port: str, versions: Optional[List[str]] = None) -> List[Tuple[str, str]]:
72
+ """
73
+ Returns a list of tuples with the description and board name for the given port and version
74
+
75
+ port : str : The Micropython port to filter for
76
+ versions : List[str] : The Micropython versions to filter for (actual versions required)
77
+ """
78
+ mp_boards = get_stored_boards_for_port(port, versions)
79
+
80
+ boards = set({(f'{board["version"]} {board["description"]}', board["board"]) for board in mp_boards})
81
+ return sorted(list(boards))
82
+
83
+
84
+ @lru_cache(maxsize=20)
85
+ def find_stored_board(board_id: str) -> Board:
86
+ """Find the board for the given board_ID or 'board description' and return the board info as a Board object"""
87
+ info = read_stored_boardinfo()
88
+ for board_info in info:
89
+ if board_id in (board_info["board"], board_info["description"]):
90
+ if "cpu" not in board_info or not board_info["cpu"]:
91
+ if " with " in board_info["description"]:
92
+ board_info["cpu"] = board_info["description"].split(" with ")[-1]
93
+ else:
94
+ board_info["cpu"] = board_info["port"]
95
+ return board_info
96
+ raise MPFlashError(f"Board {board_id} not found")
@@ -0,0 +1,63 @@
1
+ """
2
+ Translate board description to board designator
3
+ """
4
+
5
+ import functools
6
+ import json
7
+ from pathlib import Path
8
+ from typing import Optional
9
+
10
+ from mpflash.errors import MPFlashError
11
+ from mpflash.vendor.versions import clean_version
12
+
13
+ ###############################################################################################
14
+ HERE = Path(__file__).parent
15
+ ###############################################################################################
16
+
17
+
18
+ def find_board_id(
19
+ descr: str, short_descr: str, board_info: Optional[Path] = None, version: str = "stable"
20
+ ) -> Optional[str]:
21
+ # TODO: use the json file instead of the csv and get the cpu
22
+ boards = find_board_by_description(
23
+ descr=descr,
24
+ short_descr=short_descr,
25
+ board_info=board_info,
26
+ version=clean_version(version),
27
+ )
28
+ return boards[-1]["board"]
29
+
30
+
31
+ @functools.lru_cache(maxsize=20)
32
+ def find_board_by_description(*, descr: str, short_descr: str, version="v1.21.0", board_info: Optional[Path] = None):
33
+ """
34
+ Find the MicroPython BOARD designator based on the description in the firmware
35
+ using the pre-built board_info.json file
36
+ """
37
+ if not board_info:
38
+ board_info = HERE / "board_info.json"
39
+ if not board_info.exists():
40
+ raise FileNotFoundError(f"Board info file not found: {board_info}")
41
+
42
+ info = _read_board_info(board_info)
43
+
44
+ # filter for matching version
45
+ if version == "preview":
46
+ # TODO: match last stable
47
+ version = "v1.22.2"
48
+ version_matches = [b for b in info if b["version"].startswith(version)]
49
+ if not version_matches:
50
+ raise MPFlashError(f"No board info found for version {version}")
51
+ matches = [b for b in version_matches if b["description"] == descr]
52
+ if not matches and short_descr:
53
+ matches = [b for b in version_matches if b["description"] == short_descr]
54
+ if not matches:
55
+ raise MPFlashError(f"No board info found for description {descr}")
56
+ return sorted(matches, key=lambda x: x["version"])
57
+
58
+
59
+ @functools.lru_cache(maxsize=20)
60
+ def _read_board_info(board_info):
61
+ with open(board_info, "r") as file:
62
+ info = json.load(file)
63
+ return info