micropython-stubber 1.24.1__py3-none-any.whl → 1.24.4__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 (90) hide show
  1. {micropython_stubber-1.24.1.dist-info → micropython_stubber-1.24.4.dist-info}/METADATA +9 -29
  2. micropython_stubber-1.24.4.dist-info/RECORD +107 -0
  3. {micropython_stubber-1.24.1.dist-info → micropython_stubber-1.24.4.dist-info}/WHEEL +1 -1
  4. stubber/__init__.py +1 -1
  5. stubber/board/createstubs.py +44 -38
  6. stubber/board/createstubs_db.py +17 -12
  7. stubber/board/createstubs_db_min.py +63 -63
  8. stubber/board/createstubs_db_mpy.mpy +0 -0
  9. stubber/board/createstubs_mem.py +17 -12
  10. stubber/board/createstubs_mem_min.py +99 -99
  11. stubber/board/createstubs_mem_mpy.mpy +0 -0
  12. stubber/board/createstubs_min.py +111 -112
  13. stubber/board/createstubs_mpy.mpy +0 -0
  14. stubber/board/modulelist.txt +27 -27
  15. stubber/codemod/board.py +1 -1
  16. stubber/codemod/enrich.py +13 -13
  17. stubber/codemod/merge_docstub.py +83 -53
  18. stubber/codemod/visitors/type_helpers.py +143 -41
  19. stubber/commands/enrich_folder_cmd.py +17 -17
  20. stubber/commands/get_docstubs_cmd.py +27 -9
  21. stubber/commands/get_frozen_cmd.py +1 -0
  22. stubber/commands/merge_cmd.py +2 -4
  23. stubber/merge_config.py +5 -36
  24. stubber/minify.py +3 -3
  25. stubber/modcat.py +118 -0
  26. stubber/publish/merge_docstubs.py +22 -5
  27. stubber/publish/stubpackage.py +33 -28
  28. stubber/rst/lookup.py +6 -23
  29. stubber/rst/reader.py +8 -13
  30. stubber/stubs_from_docs.py +2 -1
  31. stubber/tools/manifestfile.py +2 -1
  32. stubber/{cst_transformer.py → typing_collector.py} +36 -4
  33. micropython_stubber-1.24.1.dist-info/RECORD +0 -161
  34. mpflash/README.md +0 -220
  35. mpflash/libusb_flash.ipynb +0 -203
  36. mpflash/mpflash/__init__.py +0 -0
  37. mpflash/mpflash/add_firmware.py +0 -98
  38. mpflash/mpflash/ask_input.py +0 -236
  39. mpflash/mpflash/basicgit.py +0 -324
  40. mpflash/mpflash/bootloader/__init__.py +0 -2
  41. mpflash/mpflash/bootloader/activate.py +0 -60
  42. mpflash/mpflash/bootloader/detect.py +0 -82
  43. mpflash/mpflash/bootloader/manual.py +0 -101
  44. mpflash/mpflash/bootloader/micropython.py +0 -12
  45. mpflash/mpflash/bootloader/touch1200.py +0 -36
  46. mpflash/mpflash/cli_download.py +0 -129
  47. mpflash/mpflash/cli_flash.py +0 -224
  48. mpflash/mpflash/cli_group.py +0 -111
  49. mpflash/mpflash/cli_list.py +0 -87
  50. mpflash/mpflash/cli_main.py +0 -39
  51. mpflash/mpflash/common.py +0 -217
  52. mpflash/mpflash/config.py +0 -44
  53. mpflash/mpflash/connected.py +0 -96
  54. mpflash/mpflash/download.py +0 -364
  55. mpflash/mpflash/downloaded.py +0 -138
  56. mpflash/mpflash/errors.py +0 -9
  57. mpflash/mpflash/flash/__init__.py +0 -55
  58. mpflash/mpflash/flash/esp.py +0 -59
  59. mpflash/mpflash/flash/stm32.py +0 -19
  60. mpflash/mpflash/flash/stm32_dfu.py +0 -104
  61. mpflash/mpflash/flash/uf2/__init__.py +0 -88
  62. mpflash/mpflash/flash/uf2/boardid.py +0 -15
  63. mpflash/mpflash/flash/uf2/linux.py +0 -136
  64. mpflash/mpflash/flash/uf2/macos.py +0 -42
  65. mpflash/mpflash/flash/uf2/uf2disk.py +0 -12
  66. mpflash/mpflash/flash/uf2/windows.py +0 -43
  67. mpflash/mpflash/flash/worklist.py +0 -170
  68. mpflash/mpflash/list.py +0 -106
  69. mpflash/mpflash/logger.py +0 -41
  70. mpflash/mpflash/mpboard_id/__init__.py +0 -98
  71. mpflash/mpflash/mpboard_id/add_boards.py +0 -262
  72. mpflash/mpflash/mpboard_id/board.py +0 -37
  73. mpflash/mpflash/mpboard_id/board_id.py +0 -90
  74. mpflash/mpflash/mpboard_id/board_info.zip +0 -0
  75. mpflash/mpflash/mpboard_id/store.py +0 -48
  76. mpflash/mpflash/mpremoteboard/__init__.py +0 -271
  77. mpflash/mpflash/mpremoteboard/mpy_fw_info.py +0 -152
  78. mpflash/mpflash/mpremoteboard/runner.py +0 -140
  79. mpflash/mpflash/vendor/board_database.py +0 -185
  80. mpflash/mpflash/vendor/click_aliases.py +0 -91
  81. mpflash/mpflash/vendor/dfu.py +0 -165
  82. mpflash/mpflash/vendor/pydfu.py +0 -605
  83. mpflash/mpflash/vendor/readme.md +0 -12
  84. mpflash/mpflash/versions.py +0 -123
  85. mpflash/poetry.lock +0 -2603
  86. mpflash/pyproject.toml +0 -66
  87. mpflash/stm32_udev_rules.md +0 -63
  88. stubber/codemod/test_enrich.py +0 -87
  89. {micropython_stubber-1.24.1.dist-info → micropython_stubber-1.24.4.dist-info}/LICENSE +0 -0
  90. {micropython_stubber-1.24.1.dist-info → micropython_stubber-1.24.4.dist-info}/entry_points.txt +0 -0
@@ -1,111 +0,0 @@
1
- """
2
- Main entry point for the CLI group.
3
- Additional comands are added in the submodules.
4
- """
5
-
6
- import rich_click as click
7
-
8
- from mpflash.vendor.click_aliases import ClickAliasedGroup
9
-
10
- from .config import __version__, config
11
- from .logger import log, make_quiet, set_loglevel
12
-
13
-
14
- def cb_verbose(ctx, param, value):
15
- """Callback to set the log level to DEBUG if verbose is set"""
16
- if value and not config.quiet:
17
- # log.debug(f"Setting verbose mode to {value}")
18
- config.verbose = True
19
- if value > 1:
20
- set_loglevel("TRACE")
21
- else:
22
- set_loglevel("DEBUG")
23
- log.debug(f"version: {__version__}")
24
- else:
25
- set_loglevel("INFO")
26
- config.verbose = False
27
- return value
28
-
29
-
30
- def cb_interactive(ctx, param, value: bool):
31
- log.trace(f"Setting interactive mode to {value}")
32
- config.interactive = value
33
- return value
34
-
35
-
36
- def cb_test(ctx, param, value):
37
- if value:
38
- log.trace(f"Setting tests to {value}")
39
- config.tests = value
40
- return value
41
-
42
- def cb_usb(ctx, param, value: bool):
43
- config.usb = bool(value)
44
- return value
45
-
46
-
47
- def cb_quiet(ctx, param, value):
48
- log.trace(f"Setting quiet mode to {value}")
49
- if value:
50
- make_quiet()
51
- return value
52
-
53
-
54
- @click.group(cls=ClickAliasedGroup)
55
- # @click.group()
56
- @click.version_option(package_name="mpflash")
57
- @click.option(
58
- "--quiet",
59
- "-q",
60
- is_eager=True,
61
- is_flag=True,
62
- help="Suppresses all output.",
63
- callback=cb_quiet,
64
- envvar="MPFLASH_QUIET",
65
- show_default=True,
66
- )
67
- @click.option(
68
- "--interactive/--no-interactive",
69
- "-i/-x",
70
- is_eager=True,
71
- help="Suppresses all request for Input.",
72
- callback=cb_interactive,
73
- # envvar="MPFLASH_QUIET",
74
- default=True,
75
- show_default=True,
76
- )
77
- @click.option(
78
- "-V",
79
- "--verbose",
80
- is_eager=True,
81
- count=True,
82
- help="Enables verbose mode.",
83
- callback=cb_verbose,
84
- )
85
- @click.option(
86
- "--usb",
87
- "-u",
88
- is_eager=True,
89
- is_flag=True,
90
- default=False,
91
- help="Shows USB location of the connected boards.",
92
- callback=cb_usb,
93
- show_default=True,
94
- )
95
- @click.option(
96
- "--test",
97
- is_eager=True,
98
- help="Test a specific feature.",
99
- callback=cb_test,
100
- multiple=True,
101
- default=[],
102
- envvar="MPFLASH_TEST",
103
- metavar="FLAG",
104
- )
105
- def cli(**kwargs):
106
- """mpflash - MicroPython flashing tool.
107
-
108
- A CLI to download and flash MicroPython firmware to different ports and boards.
109
- """
110
- # all functionality is added in the submodules
111
- pass
@@ -1,87 +0,0 @@
1
- import json
2
- from typing import List
3
-
4
- import rich_click as click
5
- from rich import print
6
-
7
- from .cli_group import cli
8
- from .connected import list_mcus
9
- from .list import show_mcus
10
- from .logger import make_quiet
11
-
12
-
13
- @cli.command(
14
- "list",
15
- help="List the connected MCU boards. alias: devs",
16
- aliases=["devs"],
17
- )
18
- @click.option(
19
- "--json",
20
- "-j",
21
- "as_json",
22
- is_flag=True,
23
- default=False,
24
- show_default=True,
25
- help="""Output in json format""",
26
- )
27
- @click.option(
28
- "--serial",
29
- "--serial-port",
30
- "-s",
31
- "serial",
32
- default=["*"],
33
- multiple=True,
34
- show_default=True,
35
- help="Serial port(s) (or globs) to list. ",
36
- metavar="SERIALPORT",
37
- )
38
- @click.option(
39
- "--ignore",
40
- "-i",
41
- is_eager=True,
42
- help="Serial port(s) (or globs) to ignore. Defaults to MPFLASH_IGNORE.",
43
- multiple=True,
44
- default=[],
45
- envvar="MPFLASH_IGNORE",
46
- show_default=True,
47
- metavar="SERIALPORT",
48
- )
49
- @click.option(
50
- "--bluetooth/--no-bluetooth",
51
- "-b/-nb",
52
- is_flag=True,
53
- default=False,
54
- show_default=True,
55
- help="""Include bluetooth ports in the list""",
56
- )
57
- @click.option(
58
- "--progress/--no-progress",
59
- # "-p/-np", -p is already used for --port
60
- "progress",
61
- is_flag=True,
62
- default=True,
63
- show_default=True,
64
- help="""Show progress""",
65
- )
66
- def cli_list_mcus(serial: List[str], ignore: List[str], bluetooth: bool, as_json: bool, progress: bool = True) -> int:
67
- """List the connected MCU boards, and output in a nice table or json."""
68
- serial = list(serial)
69
- ignore = list(ignore)
70
- if as_json:
71
- # avoid noise in json output
72
- make_quiet()
73
- # TODO? Ask user to select a serialport if [?] is given ?
74
-
75
- conn_mcus = list_mcus(ignore=ignore, include=serial, bluetooth=bluetooth)
76
- # ignore boards that have the [micropython-stubber] ignore flag set
77
- conn_mcus = [item for item in conn_mcus if not (item.toml.get("mpflash", {}).get("ignore", False))]
78
- if as_json:
79
- # remove the path and firmware attibutes from the json output as they are always empty
80
- for mcu in conn_mcus:
81
- del mcu.path
82
- del mcu.firmware
83
- print(json.dumps([mcu.__dict__ for mcu in conn_mcus], indent=4))
84
- progress = False
85
- if progress:
86
- show_mcus(conn_mcus, refresh=False)
87
- return 0 if conn_mcus else 1
@@ -1,39 +0,0 @@
1
- """mpflash is a CLI to download and flash MicroPython firmware to various boards."""
2
-
3
- import os
4
-
5
- import click.exceptions as click_exceptions
6
- from loguru import logger as log
7
-
8
- from .cli_download import cli_download
9
- from .cli_flash import cli_flash_board
10
- from .cli_group import cli
11
- from .cli_list import cli_list_mcus
12
-
13
-
14
- def mpflash():
15
- cli.add_command(cli_list_mcus)
16
- cli.add_command(cli_download)
17
- cli.add_command(cli_flash_board)
18
-
19
- # cli(auto_envvar_prefix="MPFLASH")
20
- if False and os.environ.get("COMPUTERNAME").startswith("JOSVERL"):
21
- # intentional less error suppression on dev machine
22
- result = cli(standalone_mode=False)
23
- else:
24
- try:
25
- result = cli(standalone_mode=True)
26
- exit(result)
27
- except AttributeError as e:
28
- log.error(f"Error: {e}")
29
- exit(-1)
30
- except click_exceptions.ClickException as e:
31
- log.error(f"Error: {e}")
32
- exit(-2)
33
- except click_exceptions.Abort as e:
34
- # Aborted - Ctrl-C
35
- exit(-3)
36
-
37
-
38
- if __name__ == "__main__":
39
- mpflash()
mpflash/mpflash/common.py DELETED
@@ -1,217 +0,0 @@
1
- import fnmatch
2
- import glob
3
- import os
4
- import platform
5
- from dataclasses import dataclass, field
6
- from enum import Enum
7
- from pathlib import Path
8
- from typing import List, Optional, Union
9
-
10
- from serial.tools import list_ports
11
- from serial.tools.list_ports_common import ListPortInfo
12
-
13
- from mpflash.basicgit import GH_CLIENT as GH_CLIENT
14
-
15
- from .logger import log
16
-
17
- # from mpflash.mpremoteboard import MPRemoteBoard
18
-
19
- PORT_FWTYPES = {
20
- "stm32": [".dfu"], # need .dfu for pydfu.py - .hex for cube cli/GUI
21
- "esp32": [".bin"],
22
- "esp8266": [".bin"],
23
- "rp2": [".uf2"],
24
- "samd": [".uf2"],
25
- # below this not yet implemented / tested
26
- "mimxrt": [".hex"],
27
- "nrf": [".uf2"],
28
- "renesas-ra": [".hex"],
29
- }
30
-
31
-
32
- @dataclass
33
- class FWInfo:
34
- """
35
- Downloaded Firmware information
36
- is somewhat related to the BOARD class in the mpboard_id module
37
- """
38
-
39
- port: str # MicroPython port
40
- board: str # MicroPython board
41
- filename: str = field(default="") # relative filename of the firmware image
42
- firmware: str = field(default="") # url or path to original firmware image
43
- variant: str = field(default="") # MicroPython variant
44
- preview: bool = field(default=False) # True if the firmware is a preview version
45
- version: str = field(default="") # MicroPython version (NO v prefix)
46
- url: str = field(default="") # url to the firmware image download folder
47
- build: str = field(default="0") # The build = number of commits since the last release
48
- ext: str = field(default="") # the file extension of the firmware
49
- family: str = field(default="micropython") # The family of the firmware
50
- custom: bool = field(default=False) # True if the firmware is a custom build
51
- description: str = field(default="") # Description used by this firmware (custom only)
52
-
53
- def to_dict(self) -> dict:
54
- """Convert the object to a dictionary"""
55
- return self.__dict__
56
-
57
- @classmethod
58
- def from_dict(cls, data: dict) -> "FWInfo":
59
- """Create a FWInfo object from a dictionary"""
60
- # add missing keys
61
- if "ext" not in data:
62
- data["ext"] = Path(data["firmware"]).suffix
63
- if "family" not in data:
64
- data["family"] = "micropython"
65
- return cls(**data)
66
-
67
-
68
- @dataclass
69
- class Params:
70
- """Common parameters for downloading and flashing firmware"""
71
-
72
- ports: List[str] = field(default_factory=list)
73
- boards: List[str] = field(default_factory=list)
74
- versions: List[str] = field(default_factory=list)
75
- fw_folder: Path = Path()
76
- serial: List[str] = field(default_factory=list)
77
- ignore: List[str] = field(default_factory=list)
78
- bluetooth: bool = False
79
-
80
-
81
- @dataclass
82
- class DownloadParams(Params):
83
- """Parameters for downloading firmware"""
84
-
85
- clean: bool = False
86
- force: bool = False
87
-
88
-
89
- class BootloaderMethod(Enum):
90
- AUTO = "auto"
91
- MANUAL = "manual"
92
- MPY = "mpy"
93
- TOUCH_1200 = "touch1200"
94
- NONE = "none"
95
-
96
-
97
- @dataclass
98
- class FlashParams(Params):
99
- """Parameters for flashing a board"""
100
-
101
- erase: bool = True
102
- bootloader: BootloaderMethod = BootloaderMethod.NONE
103
- cpu: str = ""
104
-
105
- def __post_init__(self):
106
- if isinstance(self.bootloader, str):
107
- self.bootloader = BootloaderMethod(self.bootloader)
108
-
109
-
110
- ParamType = Union[DownloadParams, FlashParams]
111
-
112
-
113
- def filtered_comports(
114
- ignore: Optional[List[str]] = None,
115
- include: Optional[List[str]] = None,
116
- bluetooth: bool = False,
117
- ) -> List[ListPortInfo]: # sourcery skip: assign-if-exp
118
- """
119
- Get a list of filtered comports using the include and ignore lists.
120
- both can be globs (e.g. COM*) or exact port names (e.g. COM1)
121
- """
122
- if not ignore:
123
- ignore = []
124
- elif not isinstance(ignore, list): # type: ignore
125
- ignore = list(ignore)
126
- if not include:
127
- include = ["*"]
128
- elif not isinstance(include, list): # type: ignore
129
- include = list(include)
130
-
131
- if ignore == [] and platform.system() == "Darwin":
132
- # By default ignore some of the irrelevant ports on macOS
133
- ignore = [
134
- "/dev/*.debug-console",
135
- ]
136
-
137
- # remove ports that are to be ignored
138
- log.trace(f"{include=}, {ignore=}, {bluetooth=}")
139
-
140
- comports = [
141
- p for p in list_ports.comports() if not any(fnmatch.fnmatch(p.device, i) for i in ignore)
142
- ]
143
-
144
- if False:
145
- import jsons
146
-
147
- print(jsons.dumps(comports).replace('{"description":', '\n{"description":'))
148
-
149
- if platform.system() == "Linux":
150
- # use p.location to filter out the bogus ports on newer Linux kernels
151
- # filter out the bogus ports on newer Linux kernels
152
- comports = [p for p in comports if p.location]
153
-
154
- log.trace(f"comports: {[p.device for p in comports]}")
155
- # remove bluetooth ports
156
-
157
- if include != ["*"]:
158
- # if there are explicit ports to include, add them to the list
159
- explicit = [
160
- p for p in list_ports.comports() if any(fnmatch.fnmatch(p.device, i) for i in include)
161
- ]
162
- log.trace(f"explicit: {[p.device for p in explicit]}")
163
- if ignore == []:
164
- # if nothing to ignore, just use the explicit list as a sinple sane default
165
- comports = explicit
166
- else:
167
- # if there are ports to ignore, add the explicit list to the filtered list
168
- comports = list(set(explicit) | set(comports))
169
- if platform.system() == "Darwin":
170
- # Failsafe: filter out debug-console ports
171
- comports = [p for p in comports if not p.description.endswith(".debug-console")]
172
-
173
- if not bluetooth:
174
- # filter out bluetooth ports
175
- comports = [p for p in comports if "bluetooth" not in p.description.lower()]
176
- comports = [p for p in comports if "BTHENUM" not in p.hwid]
177
- if platform.system() == "Darwin":
178
- comports = [p for p in comports if ".Bluetooth" not in p.device]
179
- # filter out ports with no hwid
180
- comports = [p for p in comports if p.hwid != "n/a"]
181
- log.debug(f"filtered_comports: {[p.device for p in comports]}")
182
- # sort
183
- if platform.system() == "Windows":
184
- # Windows sort of comports by number - but fallback to device name
185
- return sorted(
186
- comports,
187
- key=lambda x: int(x.device.split()[0][3:]) if x.device.split()[0][3:].isdigit() else x,
188
- )
189
- # sort by device name
190
- return sorted(comports, key=lambda x: x.device)
191
-
192
-
193
- def find_serial_by_path(target_port: str):
194
- """Find the symbolic link path of a serial port by its device path."""
195
- # sourcery skip: use-next
196
-
197
- if platform.system() == "Windows":
198
- return None
199
- # List all available serial ports
200
- available_ports = list_ports.comports()
201
- # Filter to get the device path of the target port
202
- target_device_path = None
203
- for port in available_ports:
204
- if port.device == target_port:
205
- target_device_path = port.device
206
- break
207
-
208
- if not target_device_path:
209
- return None # Target port not found among available ports
210
-
211
- # Search for all symbolic links in /dev/serial/by-path/
212
- for symlink in glob.glob("/dev/serial/by-path/*"):
213
- # Resolve the symbolic link to its target
214
- if os.path.realpath(symlink) == target_device_path:
215
- return symlink # Return the matching symlink path
216
-
217
- return None # Return None if no match is found
mpflash/mpflash/config.py DELETED
@@ -1,44 +0,0 @@
1
- """centralized configuration for mpflash"""
2
-
3
- import os
4
- from importlib.metadata import version
5
- from pathlib import Path
6
- from typing import List
7
-
8
- import platformdirs
9
-
10
- from mpflash.logger import log
11
-
12
-
13
- def get_version():
14
- name = __package__ or "mpflash"
15
- return version(name)
16
-
17
-
18
- class MPtoolConfig:
19
- """Centralized configuration for mpflash"""
20
-
21
- quiet: bool = False
22
- verbose: bool = False
23
- usb: bool = False
24
- ignore_ports: List[str] = []
25
- firmware_folder: Path = platformdirs.user_downloads_path() / "firmware"
26
- # test options specified on the commandline
27
- tests: List[str] = []
28
- _interactive: bool = True
29
-
30
- @property
31
- def interactive(self):
32
- # No interactions in CI
33
- if os.getenv("GITHUB_ACTIONS") == "true":
34
- log.warning("Disabling interactive mode in CI")
35
- return False
36
- return self._interactive
37
-
38
- @interactive.setter
39
- def interactive(self, value: bool):
40
- self._interactive = value
41
-
42
-
43
- config = MPtoolConfig()
44
- __version__ = get_version()
@@ -1,96 +0,0 @@
1
- from typing import List, Tuple
2
-
3
- from rich import print
4
- from rich.progress import BarColumn, Progress, SpinnerColumn, TextColumn, TimeElapsedColumn
5
- from rich.table import Column
6
-
7
- from mpflash.common import filtered_comports
8
- from mpflash.mpremoteboard import MPRemoteBoard
9
-
10
- from mpflash.common import find_serial_by_path
11
-
12
-
13
- def connected_ports_boards(
14
- *, include: List[str], ignore: List[str], bluetooth: bool = False
15
- ) -> Tuple[List[str], List[str], List[MPRemoteBoard]]:
16
- """
17
- Returns a tuple containing lists of unique ports and boards from the connected MCUs.
18
- Boards that are physically connected, but give no tangible response are ignored.
19
-
20
- Returns:
21
- A tuple containing three lists:
22
- - A list of unique ports where MCUs are connected.
23
- - A list of unique board names of the connected MCUs.
24
- - A list of MPRemoteBoard instances of the connected MCUs.
25
- """
26
- conn_mcus = [
27
- b for b in list_mcus(include=include, ignore=ignore, bluetooth=bluetooth) if b.connected
28
- ]
29
- # ignore boards that have the [micropython-stubber] ignore flag set
30
- conn_mcus = [
31
- item for item in conn_mcus if not (item.toml.get("mpflash", {}).get("ignore", False))
32
- ]
33
-
34
- ports = list({b.port for b in conn_mcus})
35
- boards = list({b.board for b in conn_mcus})
36
- return (ports, boards, conn_mcus)
37
-
38
-
39
- # #########################################################################################################
40
- rp_spinner = SpinnerColumn(finished_text="✅")
41
- rp_text = TextColumn("{task.description} {task.fields[device]}", table_column=Column())
42
- rp_bar = BarColumn(bar_width=None, table_column=Column())
43
-
44
-
45
- def list_mcus(
46
- *, ignore: List[str], include: List[str], bluetooth: bool = False
47
- ) -> List[MPRemoteBoard]:
48
- """
49
- Retrieves information about connected microcontroller boards.
50
-
51
- Returns:
52
- List[MPRemoteBoard]: A list of MPRemoteBoard instances with board information.
53
- Raises:
54
- ConnectionError: If there is an error connecting to a board.
55
- """
56
- # conn_mcus = [MPRemoteBoard(sp) for sp in MPRemoteBoard.connected_boards(bluetooth) if sp not in config.ignore_ports]
57
-
58
- comports = filtered_comports(
59
- ignore=ignore,
60
- include=include,
61
- bluetooth=bluetooth,
62
- )
63
- connected_mcus = [
64
- MPRemoteBoard(
65
- c.device,
66
- location=find_serial_by_path(c.device) or c.location or c.hwid or "?",
67
- )
68
- for c in comports
69
- ]
70
-
71
- # a lot of boilerplate to show a progress bar with the comport currently scanned
72
- # low update rate to facilitate screen readers/narration
73
- with Progress(
74
- rp_spinner,
75
- rp_text,
76
- rp_bar,
77
- TimeElapsedColumn(),
78
- refresh_per_second=1,
79
- ) as progress:
80
- tsk_scan = progress.add_task("[green]Scanning", visible=False, total=None)
81
- progress.tasks[tsk_scan].fields["device"] = "..."
82
- progress.tasks[tsk_scan].visible = True
83
- progress.start_task(tsk_scan)
84
- try:
85
- for mcu in connected_mcus:
86
- progress.update(tsk_scan, device=mcu.serialport.replace("/dev/tty", "tty"))
87
- try:
88
- mcu.get_mcu_info()
89
- except ConnectionError as e:
90
- print(f"Error: {e}")
91
- continue
92
- finally:
93
- # transient
94
- progress.stop_task(tsk_scan)
95
- progress.tasks[tsk_scan].visible = False
96
- return connected_mcus