mpflash 0.8.7__py3-none-any.whl → 0.9.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.
mpflash/cli_flash.py CHANGED
@@ -103,7 +103,7 @@ from .worklist import (WorkList, full_auto_worklist, manual_worklist,
103
103
  )
104
104
  @click.option(
105
105
  "--bootloader",
106
- "-b",
106
+ "-bl",
107
107
  "bootloader",
108
108
  type=click.Choice([e.value for e in BootloaderMethod]),
109
109
  default="mpy",
mpflash/config.py CHANGED
@@ -4,18 +4,15 @@ import os
4
4
  from pathlib import Path
5
5
  from typing import List
6
6
 
7
- import pkg_resources
8
7
  import platformdirs
8
+ from importlib.metadata import version
9
9
 
10
10
  from mpflash.logger import log
11
11
 
12
12
 
13
13
  def get_version():
14
14
  name = __package__ or "mpflash"
15
- try:
16
- return pkg_resources.get_distribution(name).version
17
- except pkg_resources.DistributionNotFound:
18
- return "Package not found"
15
+ return version(name)
19
16
 
20
17
 
21
18
  class MPtoolConfig:
@@ -32,16 +29,15 @@ class MPtoolConfig:
32
29
  @property
33
30
  def interactive(self):
34
31
  # No interactions in CI
35
- if os.getenv('GITHUB_ACTIONS') == 'true':
32
+ if os.getenv("GITHUB_ACTIONS") == "true":
36
33
  log.warning("Disabling interactive mode in CI")
37
34
  return False
38
35
  return self._interactive
39
-
36
+
40
37
  @interactive.setter
41
- def interactive(self, value:bool):
38
+ def interactive(self, value: bool):
42
39
  self._interactive = value
43
40
 
44
41
 
45
-
46
42
  config = MPtoolConfig()
47
43
  __version__ = get_version()
mpflash/downloaded.py CHANGED
@@ -4,7 +4,7 @@ from typing import Dict, List, Optional
4
4
  import jsonlines
5
5
  from loguru import logger as log
6
6
 
7
- from mpflash.common import FWInfo
7
+ from mpflash.common import PORT_FWTYPES, FWInfo
8
8
  from mpflash.vendor.versions import clean_version
9
9
 
10
10
  from .config import config
@@ -109,7 +109,7 @@ def filter_downloaded_fwlist(
109
109
  log.trace(f"Filtering firmware for {version} : {len(fw_list)} found.")
110
110
  # filter by port
111
111
  if port:
112
- fw_list = [fw for fw in fw_list if fw.port == port]
112
+ fw_list = [fw for fw in fw_list if fw.port == port and Path(fw.firmware).suffix in PORT_FWTYPES[port]]
113
113
  log.trace(f"Filtering firmware for {port} : {len(fw_list)} found.")
114
114
 
115
115
  if board_id:
@@ -120,6 +120,7 @@ def filter_downloaded_fwlist(
120
120
  # the firmware variant should match exactly the board_id
121
121
  fw_list = [fw for fw in fw_list if fw.variant == board_id]
122
122
  log.trace(f"Filtering firmware for {board_id} : {len(fw_list)} found.")
123
+
123
124
  if selector and port in selector:
124
125
  fw_list = [fw for fw in fw_list if fw.filename.endswith(selector[port])]
125
126
  return fw_list
mpflash/flash.py CHANGED
@@ -30,20 +30,23 @@ def flash_list(
30
30
  continue
31
31
  log.info(f"Updating {mcu.board} on {mcu.serialport} to {fw_info.version}")
32
32
  updated = None
33
- # try:
34
- if mcu.port in UF2_PORTS and fw_file.suffix == ".uf2":
35
- if not enter_bootloader(mcu, bootloader):
36
- continue
37
- updated = flash_uf2(mcu, fw_file=fw_file, erase=erase)
38
- elif mcu.port in ["stm32"]:
39
- if not enter_bootloader(mcu, bootloader):
40
- continue
41
- updated = flash_stm32(mcu, fw_file, erase=erase)
42
- elif mcu.port in ["esp32", "esp8266"]:
43
- # bootloader is handled by esptool for esp32/esp8266
44
- updated = flash_esp(mcu, fw_file=fw_file, erase=erase)
45
- else:
46
- log.error(f"Don't (yet) know how to flash {mcu.port}-{mcu.board} on {mcu.serialport}")
33
+ try:
34
+ if mcu.port in UF2_PORTS and fw_file.suffix == ".uf2":
35
+ if not enter_bootloader(mcu, bootloader):
36
+ continue
37
+ updated = flash_uf2(mcu, fw_file=fw_file, erase=erase)
38
+ elif mcu.port in ["stm32"]:
39
+ if not enter_bootloader(mcu, bootloader):
40
+ continue
41
+ updated = flash_stm32(mcu, fw_file, erase=erase)
42
+ elif mcu.port in ["esp32", "esp8266"]:
43
+ # bootloader is handled by esptool for esp32/esp8266
44
+ updated = flash_esp(mcu, fw_file=fw_file, erase=erase)
45
+ else:
46
+ log.error(f"Don't (yet) know how to flash {mcu.port}-{mcu.board} on {mcu.serialport}")
47
+ except Exception as e:
48
+ log.error(f"Failed to flash {mcu.board} on {mcu.serialport}")
49
+ log.exception(e)
47
50
 
48
51
  if updated:
49
52
  flashed.append(updated)
mpflash/flash_stm32.py CHANGED
@@ -1,4 +1,4 @@
1
- """Flash STM32 boards using either STM32CubeProgrammer CLI or dfu-util"""
1
+ """Flash STM32 boards using pydfu"""
2
2
 
3
3
  from pathlib import Path
4
4
 
@@ -11,14 +11,8 @@ from mpflash.mpremoteboard import MPRemoteBoard
11
11
 
12
12
  def flash_stm32(mcu: MPRemoteBoard, fw_file: Path, *, erase: bool, stm32_dfu: bool = True):
13
13
  # sourcery skip: lift-return-into-if
14
- log.info("Using dfu-util")
15
14
  dfu_init()
16
- updated = flash_stm32_dfu(mcu, fw_file=fw_file, erase=erase)
17
- # if stm32_dfu:
18
- # else:
19
- # log.info("Using STM32CubeProgrammer CLI")
20
- # updated = flash_stm32_cubecli(mcu, fw_file=fw_file, erase=erase)
21
-
22
- mcu.wait_for_restart()
23
- log.success(f"Flashed {mcu.version} to {mcu.board}")
15
+ if updated := flash_stm32_dfu(mcu, fw_file=fw_file, erase=erase):
16
+ mcu.wait_for_restart()
17
+ log.success(f"Flashed {mcu.version} to {mcu.board}")
24
18
  return updated
@@ -39,6 +39,7 @@ def dfu_init():
39
39
  log.error("pydfu not found")
40
40
  return None
41
41
  if platform.system() == "Windows":
42
+ log.debug("Initializing libusb backend on Windows...")
42
43
  init_libusb_windows()
43
44
 
44
45
 
@@ -59,6 +60,8 @@ def flash_stm32_dfu(
59
60
  Returns:
60
61
  Optional[MPRemoteBoard]: The flashed remote board if successful, None otherwise.
61
62
  """
63
+ log.info("Using pydfu to flash STM32 boards")
64
+
62
65
  if not pydfu:
63
66
  log.error("pydfu not found, please install it with 'pip install pydfu' if supported")
64
67
  return None
mpflash/flash_uf2.py CHANGED
@@ -12,6 +12,8 @@ from loguru import logger as log
12
12
  from rich.progress import track
13
13
 
14
14
  from mpflash.mpremoteboard import MPRemoteBoard
15
+ import tenacity
16
+ from tenacity import stop_after_attempt, wait_fixed
15
17
 
16
18
  from .common import PORT_FWTYPES
17
19
  from .flash_uf2_boardid import get_board_id
@@ -37,31 +39,51 @@ def flash_uf2(mcu: MPRemoteBoard, fw_file: Path, erase: bool) -> Optional[MPRemo
37
39
  log.error(f"UF2 not supported on {mcu.board} on {mcu.serialport}")
38
40
  return None
39
41
  if erase:
40
- log.info("Erasing not yet implemented for UF2 flashing.")
42
+ destination = waitfor_uf2()
41
43
 
44
+ if not destination or not destination.exists() or not (destination / "INFO_UF2.TXT").exists():
45
+ log.error("Board is not in bootloader mode")
46
+ return None
47
+
48
+ log.info("Board is in bootloader mode")
49
+ board_id = get_board_id(destination) # type: ignore
50
+ log.info(f"Board ID: {board_id}")
51
+ try:
52
+ cp_firmware_to_uf2(fw_file, destination)
53
+ log.success("Done copying, resetting the board and wait for it to restart")
54
+ except tenacity.RetryError:
55
+ log.error("Failed to copy the firmware file to the board.")
56
+ return None
57
+
58
+ if sys.platform in ["linux"]:
59
+ dismount_uf2_linux()
60
+
61
+ mcu.wait_for_restart()
62
+ # time.sleep(1) # 5 secs to short on linux
63
+ return mcu
64
+
65
+
66
+ def waitfor_uf2():
67
+ """
68
+ Wait for the UF2 drive to mount
69
+ """
42
70
  if sys.platform == "linux":
43
- destination = wait_for_UF2_linux()
71
+ return wait_for_UF2_linux()
44
72
  elif sys.platform == "win32":
45
- destination = wait_for_UF2_windows()
73
+ return wait_for_UF2_windows()
46
74
  elif sys.platform == "darwin":
47
75
  log.warning(f"OS {sys.platform} not tested/supported")
48
- destination = wait_for_UF2_macos()
76
+ return wait_for_UF2_macos()
49
77
  else:
50
78
  log.warning(f"OS {sys.platform} not tested/supported")
51
79
  return None
52
80
 
53
- if not destination or not destination.exists() or not (destination / "INFO_UF2.TXT").exists():
54
- log.error("Board is not in bootloader mode")
55
- return None
56
81
 
57
- log.info("Board is in bootloader mode")
58
- board_id = get_board_id(destination) # type: ignore
59
- log.info(f"Board ID: {board_id}")
82
+ @tenacity.retry(stop=stop_after_attempt(3), wait=wait_fixed(1), reraise=False)
83
+ def cp_firmware_to_uf2(fw_file, destination):
84
+ """
85
+ Copy the firmware file to the destination,
86
+ Retry 3 times with 1s delay
87
+ """
60
88
  log.info(f"Copying {fw_file} to {destination}.")
61
89
  shutil.copy(fw_file, destination)
62
- log.success("Done copying, resetting the board and wait for it to restart")
63
- if sys.platform in ["linux"]:
64
- dismount_uf2_linux()
65
- for _ in track(range(5 + 2), description="Waiting for the board to restart", transient=True, refresh_per_second=2):
66
- time.sleep(1) # 5 secs to short on linux
67
- return mcu
@@ -42,7 +42,10 @@ 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 disk.get("children")[0]["type"] == "part" and disk.get("children")[0]["fstype"] == "vfat":
45
+ if (
46
+ disk.get("children")[0]["type"] == "part"
47
+ and disk.get("children")[0]["fstype"] == "vfat"
48
+ ):
46
49
  uf2_part = disk.get("children")[0]
47
50
  # print( json.dumps(uf2_part, indent=4))
48
51
  uf2 = UF2Disk()
@@ -70,7 +73,7 @@ def pmount(disk: UF2Disk):
70
73
  log.debug(f"Mounted {disk.label} at {disk.mountpoint}")
71
74
  glb_dismount_me.append(disk)
72
75
  else:
73
- log.debug(f"\n{disk.label} already mounted at {disk.mountpoint}")
76
+ log.trace(f"\n{disk.label} already mounted at {disk.mountpoint}")
74
77
 
75
78
 
76
79
  def pumount(disk: UF2Disk):
@@ -101,9 +104,12 @@ def wait_for_UF2_linux(s_max: int = 10):
101
104
  uf2_drives = []
102
105
  # while not destination and wait > 0:
103
106
  for _ in track(
104
- range(s_max), description="Waiting for mcu to mount as a drive", transient=True, refresh_per_second=2
107
+ range(s_max),
108
+ description="Waiting for mcu to mount as a drive",
109
+ transient=True,
110
+ refresh_per_second=2,
111
+ total=s_max,
105
112
  ):
106
- # log.info(f"Waiting for mcu to mount as a drive : {wait} seconds left")
107
113
  uf2_drives += list(get_uf2_drives())
108
114
  for drive in get_uf2_drives():
109
115
  pmount(drive)
@@ -10,14 +10,17 @@ from typing import Optional
10
10
  from rich.progress import track
11
11
 
12
12
 
13
-
14
13
  def wait_for_UF2_macos(s_max: int = 10) -> Optional[Path]:
15
14
  """Wait for the MCU to mount as a drive"""
16
15
  if s_max < 1:
17
16
  s_max = 10
18
17
  destination = None
19
18
  for _ in track(
20
- range(s_max), description="Waiting for mcu to mount as a drive", transient=True, refresh_per_second=2
19
+ range(s_max),
20
+ description="Waiting for mcu to mount as a drive",
21
+ transient=True,
22
+ refresh_per_second=2,
23
+ total=s_max,
21
24
  ):
22
25
  # log.info(f"Waiting for mcu to mount as a drive : {n} seconds left")
23
26
  vol_mounts = Path("/Volumes").iterdir()
@@ -11,14 +11,18 @@ import psutil
11
11
  from rich.progress import track
12
12
 
13
13
 
14
-
15
-
16
14
  def wait_for_UF2_windows(s_max: int = 10) -> Optional[Path]:
17
15
  """Wait for the MCU to mount as a drive"""
18
16
  if s_max < 1:
19
17
  s_max = 10
20
18
  destination = None
21
- for _ in track(range(s_max), description="Waiting for mcu to mount as a drive", transient=True,refresh_per_second=2):
19
+ for _ in track(
20
+ range(s_max),
21
+ description="Waiting for mcu to mount as a drive",
22
+ transient=True,
23
+ refresh_per_second=2,
24
+ total=s_max,
25
+ ):
22
26
  # log.info(f"Waiting for mcu to mount as a drive : {n} seconds left")
23
27
  drives = [drive.device for drive in psutil.disk_partitions()]
24
28
  for drive in drives:
@@ -91,7 +91,9 @@ class MPRemoteBoard:
91
91
 
92
92
  if sys.platform == "win32":
93
93
  # Windows sort of comports by number - but fallback to device name
94
- return sorted(output, key=lambda x: int(x.split()[0][3:]) if x.split()[0][3:].isdigit() else x)
94
+ return sorted(
95
+ output, key=lambda x: int(x.split()[0][3:]) if x.split()[0][3:].isdigit() else x
96
+ )
95
97
  # sort by device name
96
98
  return sorted(output)
97
99
 
@@ -127,7 +129,9 @@ class MPRemoteBoard:
127
129
  self.description = descr = info["board"]
128
130
  pos = descr.rfind(" with")
129
131
  short_descr = descr[:pos].strip() if pos != -1 else ""
130
- if board_name := find_board_id_by_description(descr, short_descr, version=self.version):
132
+ if board_name := find_board_id_by_description(
133
+ descr, short_descr, version=self.version
134
+ ):
131
135
  self.board = board_name
132
136
  else:
133
137
  self.board = "UNKNOWN_BOARD"
@@ -211,7 +215,8 @@ class MPRemoteBoard:
211
215
  transient=True,
212
216
  get_time=lambda: time.time(),
213
217
  show_speed=False,
214
- refresh_per_second=1,
218
+ refresh_per_second=2,
219
+ total=timeout,
215
220
  ):
216
221
  time.sleep(1)
217
222
  try:
mpflash/worklist.py CHANGED
@@ -3,7 +3,7 @@ from typing import Dict, List, Optional, Tuple
3
3
 
4
4
  from loguru import logger as log
5
5
 
6
- from mpflash.common import FWInfo, filtered_comports
6
+ from mpflash.common import FWInfo, filtered_comports, PORT_FWTYPES
7
7
  from mpflash.errors import MPFlashError
8
8
 
9
9
  from .downloaded import find_downloaded_firmware
@@ -54,8 +54,9 @@ def auto_update(
54
54
  if not board_firmwares:
55
55
  log.error(f"No {target_version} firmware found for {mcu.board} on {mcu.serialport}.")
56
56
  continue
57
+
57
58
  if len(board_firmwares) > 1:
58
- log.debug(f"Multiple {target_version} firmwares found for {mcu.board} on {mcu.serialport}.")
59
+ log.warning(f"Multiple {target_version} firmwares found for {mcu.board} on {mcu.serialport}.")
59
60
 
60
61
  # just use the last firmware
61
62
  fw_info = board_firmwares[-1]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mpflash
3
- Version: 0.8.7
3
+ Version: 0.9.0
4
4
  Summary: Flash and download tool for MicroPython firmwares
5
5
  Home-page: https://github.com/Josverl/micropython-stubber/blob/main/src/mpflash/README.md
6
6
  License: MIT
@@ -6,26 +6,26 @@ mpflash/bootloader/manual.py,sha256=tebIE2YBYvsWx2YmAcUcWnTnSjCqR1AwkXKVHJvnQkA,
6
6
  mpflash/bootloader/micropython.py,sha256=of9OuCchiGoczXPi6i0NT9LZHB9FgvigtZxWWvAcb2Q,399
7
7
  mpflash/bootloader/touch1200.py,sha256=D9yB1n2bSR-nyQDdQXJtCsNknSfHhI6hRziBqOv_HJI,1466
8
8
  mpflash/cli_download.py,sha256=qKZzHmuHazw5fhj_EGDu4DsqYCan41BK99nk1YWELFE,3527
9
- mpflash/cli_flash.py,sha256=9udC74150-T96duaJzBUyzmxVANJBFCcVzLIpvfaDgk,7135
9
+ mpflash/cli_flash.py,sha256=IQfloZM1UK4VO4bo-8OxQkwH-RTGUFs7IWb-m4gFJJg,7136
10
10
  mpflash/cli_group.py,sha256=s180-nyUVNEwA5bPlkIum4mZPEW0Udf6oBAElnrjsvQ,2236
11
11
  mpflash/cli_list.py,sha256=AvYq5_Z7l0Z4rkbr23TwFNzstuZsQgopFpdcrTLwUvs,1965
12
12
  mpflash/cli_main.py,sha256=nFe30fOZZoz4zl3VkLUNoGv478etVtEEN-ccBmok9Tk,1093
13
13
  mpflash/common.py,sha256=ZfJR8dKKUy4VDZUgnDTILzuaem2o1Ix2haLxHQ47Z0o,5765
14
- mpflash/config.py,sha256=PsP-VzZkFOYcxyI_FiNyvlRyTOeHteO8n4oMQnCHm_8,1119
14
+ mpflash/config.py,sha256=7-IL4R9oHeSh0jO-hppw8pDv990nEI31dwBzZFD50eY,1007
15
15
  mpflash/connected.py,sha256=vzQ6heV7w5Mnu76nR2dr9FiQ7Ja1x1Q_k0TGgdV1lT8,2955
16
16
  mpflash/download.py,sha256=EL17R88QO4TaiX-80GjjlEd6CNZ0vDOcWPuwewZ0_zs,13875
17
- mpflash/downloaded.py,sha256=j662_mCvGqiLnSQv6RuKxuPQ2KTp7t8GOfRMXzKHh0A,4741
17
+ mpflash/downloaded.py,sha256=n2iSVv3pS6rZmUr5ry8tOh-jSCZJdI-g_QJG8N5R1As,4815
18
18
  mpflash/errors.py,sha256=6lUhVtECY3syV2bBGKzegGH4pPKXhevvhYQZd74sy6o,238
19
- mpflash/flash.py,sha256=C9lrtJBQnkVojJ-W6vnkR16S6zhPEwdRR7GEbYbnd1E,1875
19
+ mpflash/flash.py,sha256=aC1z4Jq8b8a8O6rCTX1gdGcO5yM1vGoWlZGIWgKuHro,2059
20
20
  mpflash/flash_esp.py,sha256=j-VdSAKzNQZRVVO7oM9NcRAJWPDHsUianOien8rnYE8,2252
21
- mpflash/flash_stm32.py,sha256=x80yyLSe29YuPMZ0KyykPWUr0_DiuVxDVttMM-0M3LQ,799
21
+ mpflash/flash_stm32.py,sha256=JNY1bL-VNlnaQ6AhY9drKj8EgwpGwty0WAH1JD-Ecfs,584
22
22
  mpflash/flash_stm32_cube.py,sha256=TnLNqmJcdwRXWj_t0W4o-NmwBjd3z94qpjuyz77oP9o,3859
23
- mpflash/flash_stm32_dfu.py,sha256=oag6eTnhmztKqskmEm7MAjXW_tS854ALvZqc4C2RXgY,2871
24
- mpflash/flash_uf2.py,sha256=VxUruch2pz8JgIbrOylA6gBCyx9C3Z4hoPMPaRQNN4g,2396
23
+ mpflash/flash_stm32_dfu.py,sha256=GUJTU6bmxu4m9cK_wQKRCXPKSIf7F8BAxKMSDs59TwQ,2985
24
+ mpflash/flash_uf2.py,sha256=f9CwUaBwnmgO9q7I5-Psbd0cStxyeiu0XDcu_OHlmVc,2796
25
25
  mpflash/flash_uf2_boardid.py,sha256=2s4K3QiKWK5HKFKWYsDV3hI8alfWSxEOMeurER3eZtM,408
26
- mpflash/flash_uf2_linux.py,sha256=Aj9qTEvZvJK-RBccvTBHMRwydMl29D6ynuBHHJXdfa4,3932
27
- mpflash/flash_uf2_macos.py,sha256=4O-7S96vxnjRB2R3IwwA8ZsD-L_IPh0Mmb-949vi9bQ,953
28
- mpflash/flash_uf2_windows.py,sha256=2K7R2uhfsdgFFmWAqFATQCljPQmBW56lsbDsHyk27J0,991
26
+ mpflash/flash_uf2_linux.py,sha256=I6KYbLrnn6lFvzoG-LFETak86VHuMG3XKpdrjCGH2co,3945
27
+ mpflash/flash_uf2_macos.py,sha256=HqQ2HjXlTYzCC5DzjNaoCOR4QKKi5UzjqJcfZVJLaKM,998
28
+ mpflash/flash_uf2_windows.py,sha256=Pg2siQENEqLddM7KKl9PdXtP7HzBsPICxo8uVCgn57E,1050
29
29
  mpflash/list.py,sha256=pSV9WJozObPSnW-oYs2JPdmh2PtCPJUNgvrozclpnU4,2874
30
30
  mpflash/logger.py,sha256=BAVrSXMGZLfSDRFbtVBtvb7Rl0sTJxooCgBS5t-6bXo,1057
31
31
  mpflash/mpboard_id/__init__.py,sha256=yeSWAP1YJWYWB2i8KZlBK1l8loJRcDo-xdymuCv92nU,3723
@@ -34,7 +34,7 @@ mpflash/mpboard_id/board.py,sha256=yQ8IDHQS09AelvTvmPhpmsL4oX3L7IXGqHorkxDOkoE,1
34
34
  mpflash/mpboard_id/board_id.py,sha256=G5s-kMKAD-LGUAuU5eYnq25-MGIQPyB-zJojjcGawa4,2878
35
35
  mpflash/mpboard_id/board_info.zip,sha256=F6YowS96DAqjten4ySe4MXgZwPtE-saZOUfY5OQkqKk,19759
36
36
  mpflash/mpboard_id/store.py,sha256=lQQgHSxcaM_ZURcfZNSUv3-ZJjUKMC_xEOOSdpzVvBU,1493
37
- mpflash/mpremoteboard/__init__.py,sha256=b4XMG8YU5exQK3cFQy2EPsnycvP63YpgbeMdW64MXZ4,7462
37
+ mpflash/mpremoteboard/__init__.py,sha256=j-Cex6TlihDp125gjGB01S_zE9nIq4mdRfamWjnOJoA,7549
38
38
  mpflash/mpremoteboard/mpy_fw_info.py,sha256=BTupe4rZDTs3UHRqvs429XqWHCchSpwa05yACOiOt5U,4413
39
39
  mpflash/mpremoteboard/runner.py,sha256=YUmo5Y0aOgMaww8CXSdNdgXD-wRKncILuMZ0OB_2qRU,4646
40
40
  mpflash/uf2disk.py,sha256=dQ8_U6e3qkFOyfXZDpWAsvEBIlMr-ZzLkzTDD8SADqM,286
@@ -44,9 +44,9 @@ mpflash/vendor/dfu.py,sha256=jGsiD3lbSV1Ar9qJubhoY_hy-L8FI-K55aow8vgwoYQ,5590
44
44
  mpflash/vendor/pydfu.py,sha256=1ObubGsPFrQ7T9M3JRlIPNIG2xx8uYffaEe0Y6bdf_g,19937
45
45
  mpflash/vendor/readme.md,sha256=ZVg7kuUYyXcWcrWkaSJ0CunwebCqu2SiS2sqDadwrT8,84
46
46
  mpflash/vendor/versions.py,sha256=osv5yFyg47_BZ85k3LRrzjyPu6T4psx56rgBN3YXMyM,3885
47
- mpflash/worklist.py,sha256=WtVcofHXeJEZZ3sucGh9vi2CeY8brpRKbhz6N3hqmgo,5792
48
- mpflash-0.8.7.dist-info/LICENSE,sha256=xHwgxGNkI0R2iN4KNfbPbQSzRomWyRz7bJnR1O2mln8,1057
49
- mpflash-0.8.7.dist-info/METADATA,sha256=wofCYFdkciI_M9LsY8fZ6RBQtaui69sAFuy6D03cLvA,15275
50
- mpflash-0.8.7.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
51
- mpflash-0.8.7.dist-info/entry_points.txt,sha256=Jk_visOhYOsZIcSP2Ms9hKqfKy1iorR-6dYltSoWCpY,52
52
- mpflash-0.8.7.dist-info/RECORD,,
47
+ mpflash/worklist.py,sha256=j64PVJXm8jhLzPUQt3rnJXCbT1JEczTax46mRWID9bM,5809
48
+ mpflash-0.9.0.dist-info/LICENSE,sha256=xHwgxGNkI0R2iN4KNfbPbQSzRomWyRz7bJnR1O2mln8,1057
49
+ mpflash-0.9.0.dist-info/METADATA,sha256=B5R5UZfNdyGhHZJZboAlHOOmxzwHW4PmTbzmI9Xh0TY,15275
50
+ mpflash-0.9.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
51
+ mpflash-0.9.0.dist-info/entry_points.txt,sha256=Jk_visOhYOsZIcSP2Ms9hKqfKy1iorR-6dYltSoWCpY,52
52
+ mpflash-0.9.0.dist-info/RECORD,,