mpflash 1.25.0.post1__py3-none-any.whl → 1.25.0rc1__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 (50) hide show
  1. mpflash/add_firmware.py +43 -16
  2. mpflash/ask_input.py +4 -3
  3. mpflash/basicgit.py +1 -1
  4. mpflash/bootloader/manual.py +1 -1
  5. mpflash/cli_download.py +8 -5
  6. mpflash/cli_flash.py +17 -33
  7. mpflash/cli_group.py +3 -0
  8. mpflash/cli_list.py +2 -2
  9. mpflash/cli_main.py +4 -0
  10. mpflash/common.py +1 -36
  11. mpflash/config.py +21 -0
  12. mpflash/db/__init__.py +2 -0
  13. mpflash/db/core.py +56 -0
  14. mpflash/db/gather_boards.py +112 -0
  15. mpflash/db/loader.py +120 -0
  16. mpflash/db/meta.py +78 -0
  17. mpflash/db/micropython_boards.zip +0 -0
  18. mpflash/db/models.py +93 -0
  19. mpflash/db/tools.py +27 -0
  20. mpflash/download/__init__.py +46 -64
  21. mpflash/download/from_web.py +26 -36
  22. mpflash/download/fwinfo.py +41 -0
  23. mpflash/download/jid.py +53 -0
  24. mpflash/downloaded.py +79 -93
  25. mpflash/flash/__init__.py +7 -3
  26. mpflash/flash/esp.py +2 -1
  27. mpflash/flash/worklist.py +16 -28
  28. mpflash/list.py +3 -3
  29. mpflash/logger.py +2 -2
  30. mpflash/mpboard_id/__init__.py +3 -9
  31. mpflash/mpboard_id/alternate.py +56 -0
  32. mpflash/mpboard_id/board_id.py +11 -94
  33. mpflash/mpboard_id/known.py +44 -56
  34. mpflash/mpboard_id/resolve.py +19 -0
  35. mpflash/mpremoteboard/__init__.py +1 -1
  36. mpflash/mpremoteboard/mpy_fw_info.py +1 -0
  37. mpflash/mpremoteboard/runner.py +5 -2
  38. mpflash/vendor/pydfu.py +4 -5
  39. mpflash/versions.py +3 -0
  40. {mpflash-1.25.0.post1.dist-info → mpflash-1.25.0rc1.dist-info}/METADATA +2 -2
  41. mpflash-1.25.0rc1.dist-info/RECORD +69 -0
  42. mpflash/db/boards.py +0 -63
  43. mpflash/db/downloads.py +0 -87
  44. mpflash/mpboard_id/add_boards.py +0 -260
  45. mpflash/mpboard_id/board.py +0 -40
  46. mpflash/mpboard_id/store.py +0 -47
  47. mpflash-1.25.0.post1.dist-info/RECORD +0 -62
  48. {mpflash-1.25.0.post1.dist-info → mpflash-1.25.0rc1.dist-info}/LICENSE +0 -0
  49. {mpflash-1.25.0.post1.dist-info → mpflash-1.25.0rc1.dist-info}/WHEEL +0 -0
  50. {mpflash-1.25.0.post1.dist-info → mpflash-1.25.0rc1.dist-info}/entry_points.txt +0 -0
@@ -2,18 +2,14 @@
2
2
  Translate board description to board designator
3
3
  """
4
4
 
5
- import functools
6
- import re
7
- import sqlite3
8
- from pathlib import Path
5
+
9
6
  from typing import List, Optional
10
7
 
11
- from mpflash.config import config
8
+ from mpflash.db.core import Session
9
+ from mpflash.db.models import Board
12
10
  from mpflash.errors import MPFlashError
13
11
  from mpflash.logger import log
14
- from mpflash.mpboard_id.board import Board
15
- from mpflash.mpboard_id.store import read_known_boardinfo
16
- from mpflash.versions import clean_version, get_preview_mp_version, get_stable_mp_version
12
+ from mpflash.versions import clean_version
17
13
 
18
14
 
19
15
  def find_board_id_by_description(
@@ -21,7 +17,6 @@ def find_board_id_by_description(
21
17
  short_descr: str,
22
18
  *,
23
19
  version: str,
24
- board_info: Optional[Path] = None,
25
20
  ) -> Optional[str]:
26
21
  """Find the MicroPython BOARD_ID based on the description in the firmware"""
27
22
  version = clean_version(version) if version else ""
@@ -29,7 +24,6 @@ def find_board_id_by_description(
29
24
  boards = _find_board_id_by_description(
30
25
  descr=descr,
31
26
  short_descr=short_descr,
32
- db_path=board_info,
33
27
  version=version,
34
28
  )
35
29
  if not boards:
@@ -37,7 +31,6 @@ def find_board_id_by_description(
37
31
  boards = _find_board_id_by_description(
38
32
  descr=descr,
39
33
  short_descr=short_descr,
40
- db_path=board_info,
41
34
  version="%", # any version
42
35
  )
43
36
  return boards[0].board_id if boards else None
@@ -51,7 +44,6 @@ def _find_board_id_by_description(
51
44
  short_descr: str,
52
45
  version: Optional[str] = None,
53
46
  variant: str = "",
54
- db_path: Optional[Path] = None,
55
47
  ):
56
48
  short_descr = short_descr or ""
57
49
  boards: List[Board] = []
@@ -63,90 +55,15 @@ def _find_board_id_by_description(
63
55
  descriptions.append(descr[8:])
64
56
  descriptions.append(short_descr[8:])
65
57
 
66
- try:
67
- with sqlite3.connect(db_path or config.db_path) as conn:
68
- conn.row_factory = sqlite3.Row
69
- cursor = conn.cursor()
70
-
71
- qry = f"""
72
- SELECT
73
- *
74
- FROM board_downloaded
75
- WHERE
76
- board_id IN (
77
- SELECT DISTINCT board_id
78
- FROM board_downloaded
79
- WHERE description IN {str(tuple(descriptions))}
80
- )
81
- AND version like '{version}'
82
- AND variant like '{variant}'
83
- """
84
- cursor.execute(qry)
85
- rows = cursor.fetchall()
86
- for row in rows:
87
- r = dict(row)
58
+ with Session() as session:
59
+ qry = session.query(Board).filter(
60
+ Board.description.in_(descriptions),
61
+ Board.version.like(version),
62
+ Board.variant.like(variant),
63
+ )
64
+ boards = qry.all()
88
65
 
89
- boards.append(Board.from_dict(dict(row)))
90
- except sqlite3.OperationalError as e:
91
- raise MPFlashError("Database error") from e
92
66
  if not boards:
93
67
  raise MPFlashError(f"No board info found for description '{descr}' or '{short_descr}'")
94
68
  return boards
95
69
 
96
-
97
- @functools.lru_cache(maxsize=20)
98
- def _find_board_id_by_description_xx(
99
- *,
100
- descr: str,
101
- short_descr: str,
102
- version: Optional[str] = None,
103
- board_info: Optional[Path] = None,
104
- ):
105
- """
106
- Find the MicroPython BOARD_ID based on the description in the firmware
107
- using the pre-built board_info.json file
108
-
109
- Parameters:
110
- descr: str
111
- Description of the board
112
- short_descr: str
113
- Short description of the board (optional)
114
- version: str
115
- Version of the MicroPython firmware
116
- board_info: Path
117
- Path to the board_info.json file (optional)
118
-
119
- """
120
- # Some functional overlap with
121
- # src\mpflash\mpflash\mpboard_id\__init__.py find_known_board
122
-
123
- candidate_boards = read_known_boardinfo(board_info)
124
- if not short_descr and " with " in descr:
125
- short_descr = descr.split(" with ")[0]
126
- if version:
127
- # filter for matching version
128
- if version in ("stable"):
129
- version = get_stable_mp_version()
130
- if version in ("preview", "master"):
131
- version = get_preview_mp_version()
132
- known_versions = sorted({b.version for b in candidate_boards})
133
- if version not in known_versions:
134
- log.trace(known_versions)
135
- log.debug(f"Version {version} not found in board info, using latest stable version {get_stable_mp_version()}")
136
- version = ".".join(get_stable_mp_version().split(".")[:2]) # take only major.minor
137
- if version_matches := [b for b in candidate_boards if b.version.startswith(version)]:
138
- candidate_boards = version_matches
139
- else:
140
- raise MPFlashError(f"No board info found for version {version}")
141
- # First try full match on description, then partial match
142
- matches = [b for b in candidate_boards if b.description == descr]
143
- if not matches and short_descr:
144
- matches = [b for b in candidate_boards if b.description == short_descr]
145
- if not matches:
146
- # partial match (for added VARIANT)
147
- matches = [b for b in candidate_boards if b.description.startswith(descr)]
148
- if not matches and short_descr:
149
- matches = [b for b in candidate_boards if b.description.startswith(short_descr)]
150
- if not matches:
151
- raise MPFlashError(f"No board info found for description '{descr}' or '{short_descr}'")
152
- return sorted(matches, key=lambda x: x.version)
@@ -7,62 +7,50 @@ This module provides access to the board info and the known ports and boards."""
7
7
  from functools import lru_cache
8
8
  from typing import List, Optional, Tuple
9
9
 
10
- from mpflash.db.boards import find_board_id, find_board_info
10
+ from sqlalchemy import text
11
+
12
+ from mpflash.db.core import Session
13
+ from mpflash.db.models import Board
11
14
  from mpflash.errors import MPFlashError
12
- from mpflash.versions import clean_version
13
15
  from mpflash.logger import log
16
+ from mpflash.versions import clean_version
14
17
 
15
- from .board import Board
16
- from .store import read_known_boardinfo
17
18
 
19
+ def known_ports(version: str = "") -> list[str]:
20
+ """Return a list of known ports for a given version."""
21
+ version = clean_version(version) if version else "%%"
22
+ with Session() as session:
23
+ qry = text("SELECT distinct port FROM boards WHERE version like :version ORDER BY port;")
24
+ ports = session.execute(qry, {"version": version}).columns("port").fetchall()
25
+ return [row.port for row in ports]
18
26
 
19
- def get_known_ports() -> List[str]:
20
- # TODO: Filter for Version
21
- log.warning("get_known_ports() is deprecated")
22
- mp_boards = read_known_boardinfo()
23
- # select the unique ports from info
24
- ports = set({board.port for board in mp_boards if board.port})
25
- return sorted(list(ports))
26
27
 
28
+ def known_versions(port: str = "") -> list[str]:
29
+ """Return a list of known versions for a given port."""
30
+ port = port.strip() if port else "%%"
31
+ with Session() as session:
32
+ qry = text("SELECT distinct version FROM boards WHERE port like :port ORDER BY version;")
33
+ versions = session.execute(qry, {"port": port}).columns("version").fetchall()
34
+ return [row.version for row in versions]
27
35
 
28
- def get_known_boards_for_port(port: Optional[str] = "", versions: Optional[List[str]] = None) -> List[Board]:
36
+
37
+ def get_known_boards_for_port(port: str = "", versions: List[str] = []):
29
38
  """
30
39
  Returns a list of boards for the given port and version(s)
31
40
 
32
41
  port: The Micropython port to filter for
33
42
  versions: Optional, The Micropython versions to filter for (actual versions required)
34
43
  """
35
- mp_boards = read_known_boardinfo()
36
- if versions:
37
- preview_or_stable = "preview" in versions or "stable" in versions
38
- else:
39
- preview_or_stable = False
40
-
41
- # filter for 'preview' as they are not in the board_info.json
42
- # instead use stable version
43
- versions = versions or []
44
- if "preview" in versions:
45
- versions.remove("preview")
46
- versions.append("stable")
47
- # filter for the port
48
- if port:
49
- mp_boards = [board for board in mp_boards if board.port == port]
50
- if versions:
51
- # make sure of the v prefix
52
- versions = [clean_version(v) for v in versions]
53
- # filter for the version(s)
54
- mp_boards = [board for board in mp_boards if board.version in versions]
55
- if not mp_boards and preview_or_stable:
56
- # nothing found - perhaps there is a newer version for which we do not have the board info yet
57
- # use the latest known version from the board info
58
- mp_boards = read_known_boardinfo()
59
- last_known_version = sorted({b.version for b in mp_boards})[-1]
60
- mp_boards = [board for board in mp_boards if board.version == last_known_version]
61
-
62
- return mp_boards
63
-
64
-
65
- def known_stored_boards(port: str, versions: Optional[List[str]] = None) -> List[Tuple[str, str]]:
44
+ versions = [clean_version(v) for v in versions] if versions else []
45
+ with Session() as session:
46
+ qry = session.query(Board).filter(Board.port.like(port))
47
+ if versions:
48
+ qry = qry.filter(Board.version.in_(versions))
49
+ boards = qry.all()
50
+ return boards
51
+
52
+
53
+ def known_stored_boards(port: str, versions: List[str] = []) -> List[Tuple[str, str]]:
66
54
  """
67
55
  Returns a list of tuples with the description and board name for the given port and version
68
56
 
@@ -75,18 +63,18 @@ def known_stored_boards(port: str, versions: Optional[List[str]] = None) -> List
75
63
  return sorted(list(boards))
76
64
 
77
65
 
78
- @lru_cache(maxsize=20)
79
- def find_known_board(board_id: str, version ="") -> Board:
66
+ def find_known_board(board_id: str, version="") -> Board:
80
67
  """Find the board for the given BOARD_ID or 'board description' and return the board info as a Board object"""
81
- # Some functional overlap with:
82
- # mpboard_id\board_id.py _find_board_id_by_description
83
- # TODO: Refactor to search the SQLite DB instead of the JSON file
84
- board_ids = find_board_id(board_id = board_id, version = version or "%")
85
- boards = []
86
- for board_id in board_ids:
87
- # if we have a board_id, use it to find the board info
88
- boards += [Board.from_dict(dict(r)) for r in find_board_info(board_id = board_id)]
89
-
90
- if boards:
91
- return boards[0]
68
+ with Session() as session:
69
+ qry = session.query(Board).filter(Board.board_id == board_id)
70
+ if version:
71
+ qry = qry.filter(Board.version == version)
72
+ board = qry.first()
73
+ if not board:
74
+ # if no board found, try to find it by description
75
+ qry = session.query(Board).filter(Board.description == board_id)
76
+ if version:
77
+ qry = qry.filter(Board.version == version)
78
+ if board:
79
+ return board
92
80
  raise MPFlashError(f"Board {board_id} not found")
@@ -0,0 +1,19 @@
1
+ from logging import log
2
+ from mpflash.common import Params
3
+ from mpflash.mpboard_id import find_known_board
4
+
5
+
6
+ def resolve_board_ids(params: Params):
7
+ """Resolve board descriptions to board_id, and remove empty strings from list of boards"""
8
+ for board_id in params.boards:
9
+ if board_id == "":
10
+ params.boards.remove(board_id)
11
+ continue
12
+ if " " in board_id:
13
+ try:
14
+ if info := find_known_board(board_id):
15
+ log.info(f"Resolved board description: {info.board_id}")
16
+ params.boards.remove(board_id)
17
+ params.boards.append(info.board_id)
18
+ except Exception as e:
19
+ log.warning(f"Unable to resolve board description: {e}")
@@ -170,7 +170,7 @@ class MPRemoteBoard:
170
170
  self.cpu = info["cpu"]
171
171
  self.arch = info["arch"]
172
172
  self.mpy = info["mpy"]
173
- self.description = descr = info["board"]
173
+ self.description = descr = info["description"] if 'description' in info else info["board"]
174
174
  pos = descr.rfind(" with")
175
175
  short_descr = descr[:pos].strip() if pos != -1 else ""
176
176
  if info.get("board_id", None):
@@ -51,6 +51,7 @@ def _info(): # type:() -> dict[str, str]
51
51
  try:
52
52
  _machine = sys.implementation._machine if "_machine" in dir(sys.implementation) else os.uname().machine # type: ignore
53
53
  info["board"] = _machine.strip()
54
+ info["description"] = _machine.strip()
54
55
  si_build = sys.implementation._build if "_build" in dir(sys.implementation) else ""
55
56
  if si_build:
56
57
  info["board"] = si_build.split("-")[0]
@@ -91,11 +91,12 @@ def run(
91
91
  )
92
92
  except FileNotFoundError as e:
93
93
  raise FileNotFoundError(f"Failed to start {cmd[0]}") from e
94
-
94
+ _timed_out = False
95
95
  def timed_out():
96
- proc.kill()
96
+ _timed_out = True
97
97
  if log_warnings:
98
98
  log.warning(f"Command {cmd} timed out after {timeout} seconds")
99
+ proc.kill()
99
100
 
100
101
  timer = Timer(timeout, timed_out)
101
102
  try:
@@ -135,6 +136,8 @@ def run(
135
136
  log.error(f"Failed to decode output: {e}")
136
137
  finally:
137
138
  timer.cancel()
139
+ if _timed_out:
140
+ raise TimeoutError(f"Command {cmd} timed out after {timeout} seconds")
138
141
 
139
142
  proc.wait(timeout=1)
140
143
  return proc.returncode or 0, output
mpflash/vendor/pydfu.py CHANGED
@@ -338,7 +338,7 @@ def read_dfu_file(filename):
338
338
  # I uint32_t size Size of the DFU file (without suffix)
339
339
  # B uint8_t targets Number of targets
340
340
  dfu_prefix, data = consume("<5sBIB", data, "signature version size targets")
341
- print(" %(signature)s v%(version)d, image size: %(size)d, " "targets: %(targets)d" % dfu_prefix)
341
+ print(" %(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d" % dfu_prefix)
342
342
  for target_idx in range(dfu_prefix["targets"]):
343
343
  # Decode the Image Prefix
344
344
  #
@@ -350,15 +350,14 @@ def read_dfu_file(filename):
350
350
  # 255s char[255] name Name of the target
351
351
  # I uint32_t size Size of image (without prefix)
352
352
  # I uint32_t elements Number of elements in the image
353
- img_prefix, data = consume("<6sBI255s2I", data, "signature altsetting named name " "size elements")
353
+ img_prefix, data = consume("<6sBI255s2I", data, "signature altsetting named name size elements")
354
354
  img_prefix["num"] = target_idx
355
355
  if img_prefix["named"]:
356
356
  img_prefix["name"] = cstring(img_prefix["name"])
357
357
  else:
358
358
  img_prefix["name"] = ""
359
359
  print(
360
- " %(signature)s %(num)d, alt setting: %(altsetting)s, "
361
- 'name: "%(name)s", size: %(size)d, elements: %(elements)d' % img_prefix
360
+ ' %(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % img_prefix
362
361
  )
363
362
 
364
363
  target_size = img_prefix["size"]
@@ -395,7 +394,7 @@ def read_dfu_file(filename):
395
394
  # B uint8_t len 16
396
395
  # I uint32_t crc32 Checksum
397
396
  dfu_suffix = named(struct.unpack("<4H3sBI", data[:16]), "device product vendor dfu ufd len crc")
398
- print(" usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, " "dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x" % dfu_suffix)
397
+ print(" usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x" % dfu_suffix)
399
398
  if crc != dfu_suffix["crc"]:
400
399
  print("CRC ERROR: computed crc32 is 0x%08x" % crc)
401
400
  return
mpflash/versions.py CHANGED
@@ -78,6 +78,7 @@ def is_version(version: str):
78
78
  """Check if the version is a valid version string"""
79
79
  # Just in time import
80
80
  from packaging.version import Version
81
+
81
82
  return Version._regex.search(version) is not None
82
83
 
83
84
 
@@ -86,6 +87,7 @@ def micropython_versions(minver: str = "v1.20", reverse: bool = False, cache_it=
86
87
  """Get the list of micropython versions from github tags"""
87
88
  # Just in time import
88
89
  from packaging.version import parse
90
+
89
91
  try:
90
92
  gh_client = config.gh_client
91
93
  repo = gh_client.get_repo("micropython/micropython")
@@ -126,6 +128,7 @@ def checkedout_version(path: Path, flat: bool = False) -> str:
126
128
  """Get the checked-out version of the repo"""
127
129
  # Just in time import
128
130
  import mpflash.basicgit as git
131
+
129
132
  version = git.get_local_tag(path.as_posix())
130
133
  if not version:
131
134
  raise ValueError("No valid Tag found")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mpflash
3
- Version: 1.25.0.post1
3
+ Version: 1.25.0rc1
4
4
  Summary: Flash and download tool for MicroPython firmwares
5
5
  License: MIT
6
6
  Keywords: MicroPython,firmware,flash,download,UF2,esptool
@@ -29,13 +29,13 @@ Requires-Dist: loguru (>=0.7.2,<0.8.0)
29
29
  Requires-Dist: mpremote (>=1.22.0,<2.0.0)
30
30
  Requires-Dist: packaging (>=24.2,<25.0)
31
31
  Requires-Dist: platformdirs (>=4.2.0,<5.0.0)
32
- Requires-Dist: poetry (>=2.0.1,<3.0.0)
33
32
  Requires-Dist: psutil (>=5.9.8,<8.0.0)
34
33
  Requires-Dist: pygithub (>=2.1.1,<3.0.0)
35
34
  Requires-Dist: pyusb (>=1.2.1,<2.0.0)
36
35
  Requires-Dist: pywin32 (>=310,<311) ; sys_platform == "win32"
37
36
  Requires-Dist: requests (>=2.31.0,<3.0.0)
38
37
  Requires-Dist: rich-click (>=1.8.1,<2.0.0)
38
+ Requires-Dist: sqlalchemy (>=2.0.41,<3.0.0)
39
39
  Requires-Dist: tenacity (==9.0.0)
40
40
  Project-URL: Homepage, https://github.com/Josverl/mpflash/blob/main/README.md
41
41
  Project-URL: Repository, https://github.com/Josverl/mpflash
@@ -0,0 +1,69 @@
1
+ mpflash/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ mpflash/add_firmware.py,sha256=P1yaNUdExfzC_qnhE-P5ALZg1Uh7XT6Xf7NYccJP7Rc,4317
3
+ mpflash/ask_input.py,sha256=eoaFZf2F85RszyqcLBmuJvKtDe4PdT_T-nwOBFaWehg,8903
4
+ mpflash/basicgit.py,sha256=Aiz6rF6PVhQir-FU-T1NhbjsW803y39Js6xnWs8-yu4,9676
5
+ mpflash/bootloader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ mpflash/bootloader/activate.py,sha256=orQOw4XTkXVZI-rMInRb0T5Wp3qA_BlzbJUA2gyBToU,2361
7
+ mpflash/bootloader/detect.py,sha256=OagP2QVWeLLWkZt2paqEF6r4_x3QDcBGNCPOWfMy9NQ,2686
8
+ mpflash/bootloader/manual.py,sha256=WYC4x-dxrSwVUfgnKTlu34pCzckrWJKZnWsARDocycI,3169
9
+ mpflash/bootloader/micropython.py,sha256=v_kZkvg0uWZDbMrT78gmiYHbD83QLdnrctvEClI8iRg,529
10
+ mpflash/bootloader/touch1200.py,sha256=VND7_YniS9Vx6WEaAxjI72RZZ6WBOwmBTsKJkbuaAHk,1105
11
+ mpflash/cli_download.py,sha256=sMMIVTE4P9O2GpWB9jcbOiKQX-XJ0nu2bBylRbWu0X8,3872
12
+ mpflash/cli_flash.py,sha256=K2TEyQndibtKdwSkeeu_esDUsu8H0_4DB_37SF7DR9E,7657
13
+ mpflash/cli_group.py,sha256=Uf_1ZmeeSIsaGLuuKn3KPPPVi8fJVbIacJYFZx_oPHc,2684
14
+ mpflash/cli_list.py,sha256=XwX0j9JzFzm2o-_oEWLR07QaMMAUrS1a553_-IpCdj0,2352
15
+ mpflash/cli_main.py,sha256=NMhEtMtSe7ApE-210Q4p-g7ZgewgO-4z1Q-vNKLQ47Y,1277
16
+ mpflash/common.py,sha256=fEFxSy2KVAhBUlJv0GsWnUHdJtRckp2XGlYVPAhS8WE,5924
17
+ mpflash/config.py,sha256=bmwNSJzk27iHcI-r3C6hm6-TeOat2ymzbbv-Q-xuO2o,3048
18
+ mpflash/connected.py,sha256=oxZdk1o-AfNPhJsSxr3KrMH_gdYfrjqc_IpT6J8Ng9k,3496
19
+ mpflash/db/__init__.py,sha256=wnIlO4nOXsPGXMbn2OCqHRsR-hUmtJsko8VdqjH3ZUE,45
20
+ mpflash/db/core.py,sha256=2t6pE385d8WgVrG7Kp2jmGdVZ5n0FiK6mHWAWOqZXW4,1949
21
+ mpflash/db/gather_boards.py,sha256=8QS7NIt3n9ROqtgVAnoqU8YMeObLGaN2pvJL7d_kULA,3905
22
+ mpflash/db/loader.py,sha256=RUbcnJ51r6bDq61vdglAlvYZzIaoLLGtTtm3FrSFrTQ,4758
23
+ mpflash/db/meta.py,sha256=I7JycEx37MVVYowA0VFfUYFX9IURiTTsWQ1RhFgGqes,2251
24
+ mpflash/db/micropython_boards.zip,sha256=cc4m7VSskj__rhabw3j5OZCiz1yEi6yCx7JGFn1QB0k,16647
25
+ mpflash/db/models.py,sha256=Q4yjZPcNRIGWevoACeGDS1i31QX6jq1q5TsyPjmdmz4,3448
26
+ mpflash/db/tools.py,sha256=6SEGfshNob4yRQ4h-Cj_xcWMRY28sbA8CWauNXV_uMI,814
27
+ mpflash/download/__init__.py,sha256=zidXvsSFCfR-BZCZ6TiB7uEucEuUqXnZhKSfTs60lzU,7930
28
+ mpflash/download/from_web.py,sha256=PVJDaFfYLJGXlPva5fExh4Yg2H7j3idyJEcfOiVVJBs,7608
29
+ mpflash/download/fwinfo.py,sha256=gpa92PkysT1B7mxPAFJ-b_6y03QCNgHKm-J6T_RFNMI,1852
30
+ mpflash/download/jid.py,sha256=ToRImbHdtvJ7AtZDH3aQURxBDci-0RvRtj5uCt8tHlI,2213
31
+ mpflash/downloaded.py,sha256=RLz52l7uSvNW5HGMicTAj8aWLxnXYTsQbfcwCbjb_oo,4042
32
+ mpflash/errors.py,sha256=IAidY3qkZsXy6Pm1rdmVFmGyg81ywHhse3itaPctA2w,247
33
+ mpflash/flash/__init__.py,sha256=jif7-ifsXMabidjNdqUQyl1CwD5_USjCAZFhU5W-Aw8,2992
34
+ mpflash/flash/esp.py,sha256=4977E1hDqJ4-EIkLzwrUtgZuc0ZTD7NvP1PQZgZ2DoU,3227
35
+ mpflash/flash/stm32.py,sha256=dqp9BZ4Vr-6GlQcF12TSmRf-5TXkov9qvCpMgeUJc7Y,574
36
+ mpflash/flash/stm32_dfu.py,sha256=W-3JsRQyf3DduoIRXDmGZ35RogqtjQgcJnk-GOtQoLE,3090
37
+ mpflash/flash/uf2/__init__.py,sha256=haL84hP2p1ZjKF6dXJJHAB_NTf7jT91MuZvmvg9SpIA,3617
38
+ mpflash/flash/uf2/boardid.py,sha256=U5wGM8VA3wEpUxQCMtuXpMZZomdVH8J_Zd5_GekUMuU,423
39
+ mpflash/flash/uf2/linux.py,sha256=uTgqyS7C7xfQ25RrTcSUkt-m2u2Ks_o7bPLzIecPoC8,4355
40
+ mpflash/flash/uf2/macos.py,sha256=JTaIpqnR_0k4oSEvzs9amhmK-PMxUJyZLnZ_wZwxa-0,1228
41
+ mpflash/flash/uf2/uf2disk.py,sha256=4_P2l-kedM7VSliA2u706LQLxvu3xWSod1-lj-xjZis,298
42
+ mpflash/flash/uf2/windows.py,sha256=S---sVjVrC00ZcnpOewtJIBfSCj2cr7FGQwEm_ZEDnY,1334
43
+ mpflash/flash/worklist.py,sha256=ZqbgYChXFGEVLVlGKeS9eJJDToxBYqjrfWE2NIa7Cck,5622
44
+ mpflash/list.py,sha256=NNhKpRh3ARZMdq56GLJgJ67GeuUf9SxjTzFhQjDsi9A,4008
45
+ mpflash/logger.py,sha256=nHeH_Z9M5c1b0ECunNmxz_mCfl9b7v5suaSDDqAdS2E,1078
46
+ mpflash/mpboard_id/__init__.py,sha256=Z6gDDWTCSKPp2fsuaUz80zgrklBR9XDlSLF9y_evR9A,391
47
+ mpflash/mpboard_id/alternate.py,sha256=ZhqfdA9sLJmyOfJ6WwK9wrzzUn6JQdkAreiL0q5XEQg,1913
48
+ mpflash/mpboard_id/board_id.py,sha256=dGbYnqaGHm6Z68P6aCq5bv95pyhi9KKhQleQXmlyO8Y,2046
49
+ mpflash/mpboard_id/board_info.json,sha256=A3ZIt38KvAy2NMB5srHorSBd3Q3wOZIXufWiIs3XLrs,1019745
50
+ mpflash/mpboard_id/board_info.zip,sha256=-2bnQGRsIQuJUfz-7_-GQ8pMWJ1evhCez6yfjhXocNw,23213
51
+ mpflash/mpboard_id/known.py,sha256=IZ3LDYZpQo7TmWa67FzmbUJIqWuxoD_QiZ4JT1A6344,3304
52
+ mpflash/mpboard_id/resolve.py,sha256=5KCZ0Tcg3FYZ3HK_zux5EguwoSC2E03kCpW2fh4rN2A,779
53
+ mpflash/mpremoteboard/__init__.py,sha256=kZ-MziZPwx6UOs_ybLYEYeUDndC1XyylMcpGTiEHpTk,12043
54
+ mpflash/mpremoteboard/mpy_fw_info.py,sha256=ZDEPJN9XJnoG_oeWcLNiLJAD5bkVX2yI_j4K7msUxWM,5196
55
+ mpflash/mpremoteboard/runner.py,sha256=auJuK7uBq_qdZOX9DgzRARyAsTyhT8c9ycP02VqhMf4,4943
56
+ mpflash/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
+ mpflash/vendor/board_database.py,sha256=Cb8fEhJaZ2siMkLPW5rPwV9yzBsTtKGOqWUd9TxNgFM,8763
58
+ mpflash/vendor/click_aliases.py,sha256=adLhqLxNpJEPjSCIRSTkR-QzSgavGFKT0cwRbjxpzRU,5395
59
+ mpflash/vendor/dfu.py,sha256=6rqGCBS8mTxxaLtkdzJ8O6nc74kFk8jrkmKvxw-x-u8,5693
60
+ mpflash/vendor/pico-universal-flash-nuke/LICENSE.txt,sha256=Zkc2iTNbib2NCMwtLjMEz0vFCPglgvaw6Mj7QiWldpQ,1484
61
+ mpflash/vendor/pico-universal-flash-nuke/universal_flash_nuke.uf2,sha256=QuPMppqHMVOt3vDVU0bikHRLsTiDRQYNUcGQ_OLRFGI,28160
62
+ mpflash/vendor/pydfu.py,sha256=1I8dwbacUH_-u2y6gYZYRKO_Iof8Eb3rZsVyQ1ETluI,20364
63
+ mpflash/vendor/readme.md,sha256=BQ7Uxf8joeYMjTUuSLLBG49ob6a9MgFPIEwuc72-Mfw,415
64
+ mpflash/versions.py,sha256=HuujLNdMKY_mQXyEqwXVHcU8nbuXeBiWP2TMA5JQhr4,4884
65
+ mpflash-1.25.0rc1.dist-info/entry_points.txt,sha256=Jk_visOhYOsZIcSP2Ms9hKqfKy1iorR-6dYltSoWCpY,52
66
+ mpflash-1.25.0rc1.dist-info/LICENSE,sha256=mWpNhsIxWzetYNnTpr4eb3HtgsxGIC8KcYWxXEcxQvE,1077
67
+ mpflash-1.25.0rc1.dist-info/METADATA,sha256=L7CGVRIBkloWrj0gm30DxyXLAtFUPE425HzvyjenePU,23938
68
+ mpflash-1.25.0rc1.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
69
+ mpflash-1.25.0rc1.dist-info/RECORD,,
mpflash/db/boards.py DELETED
@@ -1,63 +0,0 @@
1
-
2
- from __future__ import annotations
3
-
4
- import sqlite3
5
- from pathlib import Path
6
- from typing import List
7
-
8
- from mpflash.common import FWInfo
9
- from mpflash.config import config
10
- from mpflash.logger import log
11
-
12
-
13
- def find_board_id(
14
- db_path: Path | None = None, board_id: str = "", description: str = "", version: str = "%"
15
- ) -> List[str]:
16
- """Get a list of board IDs from the database based on the board ID or description"""
17
- db_path = db_path or config.db_path
18
- conn = sqlite3.connect(db_path)
19
- conn.row_factory = sqlite3.Row
20
- rows = []
21
- with conn:
22
- cursor = conn.cursor()
23
-
24
- query = """
25
- SELECT DISTINCT board_id FROM board_downloaded
26
- where board_id like ? and version like ?
27
- ORDER BY `version` ASC
28
- """
29
- cursor.execute(query, (board_id,version))
30
- rows = cursor.fetchall()
31
- if len(rows) == 0:
32
- cursor.execute(
33
- """
34
- SELECT DISTINCT description FROM board_downloaded
35
- where description like ? and version like ?
36
- ORDER BY `description` ASC
37
- """,
38
- (description,version),
39
- )
40
- rows = cursor.fetchall()
41
-
42
- return [row['board_id'] for row in rows]
43
-
44
-
45
- def find_board_info(
46
- db_path: Path | None = None, board_id: str = "", version: str = "%"
47
- ) -> List[sqlite3.Row]:
48
- """get a list of board rows from the database based on the board ID and version"""
49
- db_path = db_path or config.db_path
50
- conn = sqlite3.connect(db_path)
51
- conn.row_factory = sqlite3.Row
52
- rows = []
53
- with conn:
54
- cursor = conn.cursor()
55
- query = """
56
- SELECT * FROM board_downloaded
57
- where board_id like ? and version like ?
58
- ORDER BY board_id, version ASC
59
- """
60
- cursor.execute(query, (board_id,version,))
61
- rows = cursor.fetchall()
62
-
63
- return rows
mpflash/db/downloads.py DELETED
@@ -1,87 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import sqlite3
4
- from pathlib import Path
5
- from typing import List
6
-
7
- from mpflash.common import FWInfo
8
- from mpflash.config import config
9
- from mpflash.logger import log
10
-
11
-
12
- def upsert_download(conn: sqlite3.Connection, board: FWInfo):
13
- """
14
- Adds a row to the downloaded firmware table in the database.
15
- - downloads.board_id <-- FWInfo.variant
16
- - downloads.source <-- FWInfo.firmware
17
-
18
- Args:
19
- conn : The database connection to use.
20
- board : The firmware information to add to the database.
21
-
22
- """
23
- with conn:
24
- conn.execute(
25
- """
26
- INSERT INTO downloads
27
- (port, board, filename, source, board_id, version, build, ext, family, custom, description)
28
- VALUES
29
- (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
30
- ON CONFLICT(filename) DO UPDATE SET
31
- port=excluded.port,
32
- board=excluded.board,
33
- source=excluded.source,
34
- board_id=excluded.board_id,
35
- version=excluded.version,
36
- build=excluded.build,
37
- ext=excluded.ext,
38
- family=excluded.family,
39
- custom=excluded.custom,
40
- description=excluded.description
41
- """,
42
- (
43
- board.port,
44
- board.board,
45
- board.filename,
46
- board.firmware,
47
- board.variant,
48
- board.version,
49
- board.build,
50
- board.ext,
51
- board.family,
52
- board.custom,
53
- board.description,
54
- ),
55
- )
56
- conn.commit()
57
-
58
- def downloaded(db_path: Path | None = None) -> List[FWInfo]:
59
- """Load a list of locally downloaded firmwares from the database"""
60
- db_path = db_path or config.db_path
61
- with sqlite3.connect(db_path) as conn:
62
- firmwares: List[FWInfo] = []
63
- try:
64
- conn.row_factory = sqlite3.Row
65
- cursor = conn.cursor()
66
- cursor.execute("SELECT * FROM downloads")
67
- rows = cursor.fetchall()
68
- for row in rows:
69
- fw_info = FWInfo.from_dict(
70
- {
71
- "filename": row["filename"],
72
- "version": row["version"],
73
- "board": row["board"],
74
- "variant": row["board_id"],
75
- "port": row["port"],
76
- "firmware": row["source"],
77
- "build": row["build"],
78
- "preview": 1 if int(row["build"]) > 0 else 0,
79
- }
80
- )
81
- firmwares.append(fw_info)
82
- except sqlite3.Error as e:
83
- log.error(f"Database error: {e}")
84
-
85
- # sort by filename
86
- firmwares.sort(key=lambda x: x.filename)
87
- return firmwares