micropython-stubber 1.20.1__tar.gz → 1.20.2__tar.gz

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 (168) hide show
  1. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/PKG-INFO +3 -3
  2. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/pyproject.toml +4 -1
  3. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/readme.md +2 -2
  4. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/README.md +16 -5
  5. micropython_stubber-1.20.2/src/mpflash/mpflash/add_firmware.py +98 -0
  6. micropython_stubber-1.20.2/src/mpflash/mpflash/ask_input.py +226 -0
  7. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/cli_download.py +42 -25
  8. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/cli_flash.py +70 -32
  9. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/cli_group.py +14 -12
  10. micropython_stubber-1.20.2/src/mpflash/mpflash/cli_list.py +77 -0
  11. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/cli_main.py +17 -6
  12. micropython_stubber-1.20.2/src/mpflash/mpflash/common.py +151 -0
  13. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/config.py +2 -0
  14. micropython_stubber-1.20.2/src/mpflash/mpflash/connected.py +74 -0
  15. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/download.py +56 -42
  16. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/downloaded.py +9 -9
  17. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/flash.py +2 -2
  18. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/flash_esp.py +2 -2
  19. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/flash_uf2.py +16 -8
  20. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/flash_uf2_linux.py +5 -16
  21. micropython_stubber-1.20.2/src/mpflash/mpflash/flash_uf2_macos.py +78 -0
  22. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/flash_uf2_windows.py +1 -1
  23. micropython_stubber-1.20.2/src/mpflash/mpflash/list.py +89 -0
  24. micropython_stubber-1.20.2/src/mpflash/mpflash/mpboard_id/__init__.py +89 -0
  25. micropython_stubber-1.20.2/src/mpflash/mpflash/mpboard_id/add_boards.py +255 -0
  26. micropython_stubber-1.20.2/src/mpflash/mpflash/mpboard_id/board.py +37 -0
  27. micropython_stubber-1.20.2/src/mpflash/mpflash/mpboard_id/board_id.py +70 -0
  28. micropython_stubber-1.20.2/src/mpflash/mpflash/mpboard_id/board_info.zip +0 -0
  29. micropython_stubber-1.20.2/src/mpflash/mpflash/mpboard_id/store.py +42 -0
  30. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/mpremoteboard/__init__.py +18 -6
  31. micropython_stubber-1.20.2/src/mpflash/mpflash/uf2disk.py +12 -0
  32. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/vendor/dfu.py +1 -0
  33. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/vendor/versions.py +7 -3
  34. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/worklist.py +71 -48
  35. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/poetry.lock +164 -138
  36. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/pyproject.toml +18 -15
  37. micropython_stubber-1.20.2/src/stubber/__init__.py +3 -0
  38. micropython_stubber-1.20.2/src/stubber/basicgit.py +288 -0
  39. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/board/createstubs.py +4 -3
  40. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/board/createstubs_db.py +5 -7
  41. micropython_stubber-1.20.2/src/stubber/board/createstubs_db_min.py +332 -0
  42. micropython_stubber-1.20.2/src/stubber/board/createstubs_db_mpy.mpy +0 -0
  43. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/board/createstubs_mem.py +6 -7
  44. micropython_stubber-1.20.2/src/stubber/board/createstubs_mem_min.py +307 -0
  45. micropython_stubber-1.20.2/src/stubber/board/createstubs_mem_mpy.mpy +0 -0
  46. micropython_stubber-1.20.2/src/stubber/board/createstubs_min.py +295 -0
  47. micropython_stubber-1.20.2/src/stubber/board/createstubs_mpy.mpy +0 -0
  48. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/board/modulelist.txt +1 -0
  49. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/get_core_cmd.py +7 -6
  50. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/get_docstubs_cmd.py +8 -3
  51. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/get_frozen_cmd.py +5 -2
  52. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/publish.py +18 -7
  53. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/utils/makeversionhdr.py +3 -2
  54. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/utils/versions.py +2 -1
  55. micropython_stubber-1.20.1/src/mpflash/mpflash/ask_input.py +0 -249
  56. micropython_stubber-1.20.1/src/mpflash/mpflash/cli_list.py +0 -41
  57. micropython_stubber-1.20.1/src/mpflash/mpflash/common.py +0 -38
  58. micropython_stubber-1.20.1/src/mpflash/mpflash/list.py +0 -89
  59. micropython_stubber-1.20.1/src/mpflash/mpflash/mpboard_id/__init__.py +0 -96
  60. micropython_stubber-1.20.1/src/mpflash/mpflash/mpboard_id/board_id.py +0 -66
  61. micropython_stubber-1.20.1/src/mpflash/mpflash/mpboard_id/board_info.csv +0 -2213
  62. micropython_stubber-1.20.1/src/mpflash/mpflash/mpboard_id/board_info.json +0 -19910
  63. micropython_stubber-1.20.1/src/stubber/__init__.py +0 -3
  64. micropython_stubber-1.20.1/src/stubber/board/createstubs_db_min.py +0 -828
  65. micropython_stubber-1.20.1/src/stubber/board/createstubs_db_mpy.mpy +0 -0
  66. micropython_stubber-1.20.1/src/stubber/board/createstubs_mem_min.py +0 -768
  67. micropython_stubber-1.20.1/src/stubber/board/createstubs_mem_mpy.mpy +0 -0
  68. micropython_stubber-1.20.1/src/stubber/board/createstubs_min.py +0 -977
  69. micropython_stubber-1.20.1/src/stubber/board/createstubs_mpy.mpy +0 -0
  70. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/LICENSE +0 -0
  71. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/libusb_flash.ipynb +0 -0
  72. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/__init__.py +0 -0
  73. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/errors.py +0 -0
  74. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/flash_stm32.py +0 -0
  75. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/flash_stm32_cube.py +0 -0
  76. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/flash_stm32_dfu.py +0 -0
  77. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/flash_uf2_boardid.py +0 -0
  78. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/logger.py +0 -0
  79. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/mpremoteboard/mpy_fw_info.py +0 -0
  80. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/mpremoteboard/runner.py +0 -0
  81. {micropython_stubber-1.20.1/src/stubber → micropython_stubber-1.20.2/src/mpflash/mpflash/vendor}/basicgit.py +0 -0
  82. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/vendor/pydfu.py +0 -0
  83. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/mpflash/vendor/readme.md +0 -0
  84. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/mpflash/stm32_udev_rules.md +0 -0
  85. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/board/board_info.csv +0 -0
  86. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/board/boot.py +0 -0
  87. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/board/createstubs_lvgl.py +0 -0
  88. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/board/createstubs_lvgl_min.py +0 -0
  89. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/board/createstubs_lvgl_mpy.mpy +0 -0
  90. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/board/fw_info.py +0 -0
  91. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/board/info.py +0 -0
  92. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/board/main.py +0 -0
  93. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/board/pyrightconfig.json +0 -0
  94. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/bulk/mcu_stubber.py +0 -0
  95. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/codemod/__init__.py +0 -0
  96. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/codemod/_partials/__init__.py +0 -0
  97. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/codemod/_partials/db_main.py +0 -0
  98. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/codemod/_partials/lvgl_main.py +0 -0
  99. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/codemod/_partials/modules_reader.py +0 -0
  100. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/codemod/add_comment.py +0 -0
  101. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/codemod/add_method.py +0 -0
  102. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/codemod/board.py +0 -0
  103. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/codemod/enrich.py +0 -0
  104. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/codemod/merge_docstub.py +0 -0
  105. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/codemod/modify_list.py +0 -0
  106. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/codemod/utils.py +0 -0
  107. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/__init__.py +0 -0
  108. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/build_cmd.py +0 -0
  109. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/cli.py +0 -0
  110. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/clone_cmd.py +0 -0
  111. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/config_cmd.py +0 -0
  112. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/enrich_folder_cmd.py +0 -0
  113. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/get_mcu_cmd.py +0 -0
  114. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/merge_cmd.py +0 -0
  115. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/publish_cmd.py +0 -0
  116. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/stub_cmd.py +0 -0
  117. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/switch_cmd.py +0 -0
  118. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/commands/variants_cmd.py +0 -0
  119. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/cst_transformer.py +0 -0
  120. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/data/board_info.csv +0 -0
  121. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/data/board_info.json +0 -0
  122. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/data/micropython_tags.csv +0 -0
  123. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/data/requirements-core-micropython.txt +0 -0
  124. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/data/requirements-core-pycopy.txt +0 -0
  125. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/downloader.py +0 -0
  126. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/freeze/__init__.py +0 -0
  127. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/freeze/common.py +0 -0
  128. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/freeze/freeze_folder.py +0 -0
  129. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/freeze/freeze_manifest_2.py +0 -0
  130. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/freeze/get_frozen.py +0 -0
  131. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/get_cpython.py +0 -0
  132. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/get_lobo.py +0 -0
  133. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/minify.py +0 -0
  134. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/__init__.py +0 -0
  135. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/bump.py +0 -0
  136. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/candidates.py +0 -0
  137. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/database.py +0 -0
  138. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/defaults.py +0 -0
  139. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/enums.py +0 -0
  140. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/helpers.py +0 -0
  141. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/merge_docstubs.py +0 -0
  142. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/missing_class_methods.py +0 -0
  143. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/package.py +0 -0
  144. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/pathnames.py +0 -0
  145. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/pypi.py +0 -0
  146. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/publish/stubpackage.py +0 -0
  147. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/rst/__init__.py +0 -0
  148. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/rst/classsort.py +0 -0
  149. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/rst/lookup.py +0 -0
  150. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/rst/output_dict.py +0 -0
  151. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/rst/reader.py +0 -0
  152. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/rst/report_return.py +0 -0
  153. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/rst/rst_utils.py +0 -0
  154. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/stubber.py +0 -0
  155. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/stubs_from_docs.py +0 -0
  156. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/tools/__init__.py +0 -0
  157. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/tools/manifestfile.py +0 -0
  158. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/tools/readme.md +0 -0
  159. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/update_fallback.py +0 -0
  160. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/update_module_list.py +0 -0
  161. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/utils/__init__.py +0 -0
  162. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/utils/config.py +0 -0
  163. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/utils/manifest.py +0 -0
  164. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/utils/post.py +0 -0
  165. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/utils/repos.py +0 -0
  166. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/utils/stubmaker.py +0 -0
  167. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/utils/typed_config_toml.py +0 -0
  168. {micropython_stubber-1.20.1 → micropython_stubber-1.20.2}/src/stubber/variants.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: micropython-stubber
3
- Version: 1.20.1
3
+ Version: 1.20.2
4
4
  Summary: Tooling to create and maintain stubs for MicroPython
5
5
  Home-page: https://github.com/Josverl/micropython-stubber#readme
6
6
  License: MIT
@@ -129,8 +129,8 @@ cd my_stub_folder
129
129
  mkdir all-stubs
130
130
 
131
131
  # clone the micropython repo's and switch to a specific version
132
- stubber clone
133
- stubber switch --version v1.18
132
+ stubber clone --add-stubs
133
+ stubber switch v1.22.2
134
134
 
135
135
  # get the document stubs for the current version ( v1.18 )
136
136
  stubber get-docstubs
@@ -8,7 +8,7 @@ repo-path = "./repos"
8
8
 
9
9
  [tool.poetry]
10
10
  name = "micropython-stubber"
11
- version = "1.20.1"
11
+ version = "1.20.2"
12
12
  description = "Tooling to create and maintain stubs for MicroPython"
13
13
  authors = ["Jos Verlinde <jos_verlinde@hotmail.com>"]
14
14
  license = "MIT"
@@ -97,6 +97,7 @@ pytest-mock = "^3.10.0"
97
97
  mock = "^4.0.3"
98
98
  distro = "^1.8.0"
99
99
  fasteners = "^0.19"
100
+ jsons = "^1.6.3"
100
101
 
101
102
  [tool.poetry.group.dev]
102
103
  optional = true
@@ -141,6 +142,7 @@ exclude = [
141
142
 
142
143
  "**/all-stubs",
143
144
  "src/stubber/board/stubs",
145
+ "**/.venv"
144
146
  ]
145
147
  ignore = [
146
148
  "tests/mocks",
@@ -164,6 +166,7 @@ reportInvalidStringEscapeSequence = "information"
164
166
  reportUnboundVariable = "information"
165
167
  ReportSelfClsParameterName = "information"
166
168
  reportOptionalSubscript = "information"
169
+ reportCallInDefaultInitializer = "error"
167
170
  # Section 3 - reduce noise
168
171
  reportMissingTypeStubs = "none"
169
172
  reportOptionalMemberAccess = "none" # "read" is not a known member of "None" - occurs often in frozen code
@@ -79,8 +79,8 @@ cd my_stub_folder
79
79
  mkdir all-stubs
80
80
 
81
81
  # clone the micropython repo's and switch to a specific version
82
- stubber clone
83
- stubber switch --version v1.18
82
+ stubber clone --add-stubs
83
+ stubber switch v1.22.2
84
84
 
85
85
  # get the document stubs for the current version ( v1.18 )
86
86
  stubber get-docstubs
@@ -1,12 +1,24 @@
1
1
  # MPFLASH
2
+ [![pypi version](https://badgen.net/pypi/v/mpflash)](https://pypi.org/project/mpflash/)
3
+ [![python versions](https://badgen.net/pypi/python/mpflash)](https://badgen.net/pypi/python/mpflash)
4
+ [![Downloads](https://static.pepy.tech/badge/mpflash)](https://pepy.tech/project/mpflash)
5
+
2
6
 
3
7
  `mpflash` is a command-line tool for working with MicroPython firmware. It provides features to help you flash and update Micropython on one or more .
4
8
 
5
- This tool was initially created to be used in a CI/CD pipeline to automate the process of downloading and flashing MicroPython firmware to multiple boards, but it has been extend with a TUI to me be used for manual downloadig, flashing and development.
9
+ This tool was initially created to be used in a CI/CD pipeline to automate the process of downloading and flashing MicroPython firmware to multiple boards, but it has been extend with a TUI to be used for manual downloadig, flashing and development.
6
10
 
7
- `mpflash` has been tested on Windows x64, Linux X64, but not (yet) macOS.
8
- Tested ports: `rp2`, `samd`, `esp32`, `esp32s3`, `esp32c3`, `esp8266` and `stm32`
11
+ `mpflash` has been tested on:
12
+ - OS: Windows x64, Linux X64, but not (yet) macOS.
13
+ - Micropython (hardware) ports:
14
+ - `rp2`, using `.uf2`, using filecopy (macos not tested yet)
15
+ - `samd`, using ` .uf2`, using filecopy (macos not tested yet)
16
+ - `esp32`, using `.bin`, using esptool,
17
+ - `esp8266`, using `.bin`, using esptool
18
+ - `stm32`, using ` .dfu`, using pydfu
9
19
 
20
+ Not yet implemented: `nrf`, `cc3200`, `mimxrt`
21
+
10
22
  ## Features
11
23
  1. List the connected boards including their firmware details, in a tabular or json format
12
24
  2. Download MicroPython firmware for versions, and matching a specified board or matches your current attached board.
@@ -34,8 +46,7 @@ On Windows this will not be an issue, but on Linux you can use udev rules to gi
34
46
  ## Detailed usage
35
47
  You can list the connected boards using the following command:
36
48
  ```bash
37
- $ mpflash list
38
- D:\MyPython\micropython-stubber> mpflash list
49
+ $> mpflash list
39
50
  Connected boards
40
51
  ┏━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━┓
41
52
  ┃ Serial ┃Family ┃Port ┃Board ┃CPU ┃Version ┃build ┃
@@ -0,0 +1,98 @@
1
+ import shutil
2
+ from pathlib import Path
3
+ from typing import Union
4
+
5
+ import jsonlines
6
+ import requests
7
+ from loguru import logger as log
8
+
9
+ # re-use logic from mpremote
10
+ from mpremote.mip import _rewrite_url as rewrite_url # type: ignore
11
+
12
+ from mpflash.common import FWInfo
13
+ from mpflash.config import config
14
+ from mpflash.vendor.versions import get_preview_mp_version, get_stable_mp_version
15
+
16
+
17
+ def add_firmware(
18
+ source: Union[Path, str],
19
+ new_fw: FWInfo,
20
+ *,
21
+ force: bool = False,
22
+ custom: bool = False,
23
+ description: str = "",
24
+ ) -> bool:
25
+ """Add a firmware to the firmware folder.
26
+
27
+ stored in the port folder, with the same filename as the source.
28
+
29
+ """
30
+ # Check minimal info needed
31
+ if not new_fw.port or not new_fw.board:
32
+ log.error("Port and board are required")
33
+ return False
34
+ if not isinstance(source, Path) and not source.startswith("http"):
35
+ log.error(f"Invalid source {source}")
36
+ return False
37
+
38
+ # use sensible defaults
39
+ source_2 = Path(source)
40
+ new_fw.ext = new_fw.ext or source_2.suffix
41
+ new_fw.variant = new_fw.variant or new_fw.board
42
+ new_fw.custom = new_fw.custom or custom
43
+ new_fw.description = new_fw.description or description
44
+ if not new_fw.version:
45
+ # TODO: Get version from filename
46
+ # or use the last preview version
47
+ new_fw.version = get_preview_mp_version() if new_fw.preview else get_stable_mp_version()
48
+
49
+ config.firmware_folder.mkdir(exist_ok=True)
50
+
51
+ fw_filename = config.firmware_folder / new_fw.port / source_2.name
52
+
53
+ new_fw.filename = str(fw_filename.relative_to(config.firmware_folder))
54
+ new_fw.firmware = source.as_uri() if isinstance(source, Path) else source
55
+
56
+ if not copy_firmware(source, fw_filename, force):
57
+ log.error(f"Failed to copy {source} to {fw_filename}")
58
+ return False
59
+ # add to inventory
60
+ with jsonlines.open(config.firmware_folder / "firmware.jsonl", "a") as writer:
61
+ log.info(f"Adding {new_fw.port} {new_fw.board}")
62
+ log.info(f" to {fw_filename}")
63
+
64
+ writer.write(new_fw.to_dict())
65
+ return True
66
+
67
+
68
+ def copy_firmware(source: Union[Path, str], fw_filename: Path, force: bool = False):
69
+ """Add a firmware to the firmware folder.
70
+ stored in the port folder, with the same filename as the source.
71
+ """
72
+ if fw_filename.exists() and not force:
73
+ log.error(f" {fw_filename} already exists. Use --force to overwrite")
74
+ return False
75
+ fw_filename.parent.mkdir(exist_ok=True)
76
+ if isinstance(source, Path):
77
+ if not source.exists():
78
+ log.error(f"File {source} does not exist")
79
+ return False
80
+ # file copy
81
+ log.debug(f"Copy {source} to {fw_filename}")
82
+ shutil.copy(source, fw_filename)
83
+ return True
84
+ # handle github urls
85
+ url = rewrite_url(source)
86
+ if str(source).startswith("http://") or str(source).startswith("https://"):
87
+ log.debug(f"Download {url} to {fw_filename}")
88
+ response = requests.get(url)
89
+
90
+ if response.status_code == 200:
91
+ with open(fw_filename, "wb") as file:
92
+ file.write(response.content)
93
+ log.info("File downloaded and saved successfully.")
94
+ return True
95
+ else:
96
+ print("Failed to download the file.")
97
+ return False
98
+ return False
@@ -0,0 +1,226 @@
1
+ """
2
+ Interactive input for mpflash.
3
+
4
+ Note: The prompts can use "{version}" and "{action}" to insert the version and action in the prompt without needing an f-string.
5
+ The values are provided from the answers dictionary.
6
+ """
7
+
8
+ from typing import List, Sequence, Tuple, Union
9
+
10
+ from loguru import logger as log
11
+
12
+ from .common import DownloadParams, FlashParams, ParamType
13
+ from .config import config
14
+ from .mpboard_id import get_known_boards_for_port, get_known_ports, known_stored_boards
15
+ from .mpremoteboard import MPRemoteBoard
16
+ from .vendor.versions import micropython_versions
17
+
18
+
19
+ def ask_missing_params(
20
+ params: ParamType,
21
+ ) -> ParamType:
22
+ """
23
+ Asks the user for parameters that have not been supplied on the commandline and returns the updated params.
24
+
25
+ Args:
26
+ params (ParamType): The parameters to be updated.
27
+
28
+ Returns:
29
+ ParamType: The updated parameters.
30
+ """
31
+ import inquirer
32
+
33
+ log.trace(f"ask_missing_params: {params}")
34
+
35
+ # if action flash, single input
36
+ # if action download, multiple input
37
+ multi_select = isinstance(params, DownloadParams)
38
+ action = "download" if isinstance(params, DownloadParams) else "flash"
39
+ if not config.interactive:
40
+ # no interactivity allowed
41
+ return params
42
+
43
+ questions = []
44
+ answers: dict[str, Union[str, List]] = {"action": action}
45
+ if not multi_select:
46
+ if not params.serial or "?" in params.serial:
47
+ questions.append(ask_serialport(multi_select=False, bluetooth=False))
48
+ else:
49
+ answers["serial"] = params.serial
50
+
51
+ if params.versions == [] or "?" in params.versions:
52
+ questions.append(ask_mp_version(multi_select=multi_select, action=action))
53
+ else:
54
+ # versions is used to show only the boards for the selected versions
55
+ answers["versions"] = params.versions # type: ignore
56
+
57
+ if not params.boards or "?" in params.boards:
58
+ questions.extend(ask_port_board(multi_select=multi_select, action=action))
59
+ if questions:
60
+ answers = inquirer.prompt(questions, answers=answers) # type: ignore
61
+ if not answers:
62
+ # input cancelled by user
63
+ return [] # type: ignore
64
+ log.trace(f"answers: {answers}")
65
+ if isinstance(params, FlashParams) and "serial" in answers:
66
+ if isinstance(answers["serial"], str):
67
+ answers["serial"] = [answers["serial"]]
68
+ params.serial = [s.split()[0] for s in answers["serial"]] # split to remove the description
69
+ if "port" in answers:
70
+ params.ports = [p for p in params.ports if p != "?"] # remove the "?" if present
71
+ params.ports.extend(answers["port"])
72
+ if "boards" in answers:
73
+ params.boards = [b for b in params.boards if b != "?"] # remove the "?" if present
74
+ params.boards.extend(answers["boards"] if isinstance(answers["boards"], list) else [answers["boards"]])
75
+ if "versions" in answers:
76
+ params.versions = [v for v in params.versions if v != "?"] # remove the "?" if present
77
+ # make sure it is a list
78
+ if isinstance(answers["versions"], (list, tuple)):
79
+ params.versions.extend(answers["versions"])
80
+ else:
81
+ params.versions.append(answers["versions"])
82
+ # remove duplicates
83
+ params.ports = list(set(params.ports))
84
+ params.boards = list(set(params.boards))
85
+ params.versions = list(set(params.versions))
86
+ log.trace(f"ask_missing_params returns: {params}")
87
+
88
+ return params
89
+
90
+
91
+ def filter_matching_boards(answers: dict) -> Sequence[Tuple[str, str]]:
92
+ """
93
+ Filters the known boards based on the selected versions and returns the filtered boards.
94
+
95
+ Args:
96
+ answers (dict): The user's answers.
97
+
98
+ Returns:
99
+ Sequence[Tuple[str, str]]: The filtered boards.
100
+ """
101
+ versions = None
102
+ # if version is not asked ; then need to get the version from the inputs
103
+ if "versions" in answers:
104
+ versions = list(answers["versions"])
105
+ if "stable" in versions:
106
+ versions.remove("stable")
107
+ versions.append(micropython_versions()[-2]) # latest stable
108
+ elif "preview" in versions:
109
+ versions.remove("preview")
110
+ versions.extend((micropython_versions()[-1], micropython_versions()[-2])) # latest preview and stable
111
+
112
+ some_boards = known_stored_boards(answers["port"], versions) # or known_mp_boards(answers["port"])
113
+
114
+ if some_boards:
115
+ # Create a dictionary where the keys are the second elements of the tuples
116
+ # This will automatically remove duplicates because dictionaries cannot have duplicate keys
117
+ unique_dict = {item[1]: item for item in some_boards}
118
+ # Get the values of the dictionary, which are the unique items from the original list
119
+ some_boards = list(unique_dict.values())
120
+ else:
121
+ some_boards = [(f"No {answers['port']} boards found for version(s) {versions}", "")]
122
+ return some_boards
123
+
124
+
125
+ def ask_port_board(*, multi_select: bool, action: str):
126
+ """
127
+ Asks the user for the port and board selection.
128
+
129
+ Args:
130
+ questions (list): The list of questions to be asked.
131
+ action (str): The action to be performed.
132
+
133
+ Returns:
134
+ None
135
+ """
136
+ # import only when needed to reduce load time
137
+ import inquirer
138
+
139
+ # if action flash, single input
140
+ # if action download, multiple input
141
+ inquirer_ux = inquirer.Checkbox if multi_select else inquirer.List
142
+ return [
143
+ inquirer.List(
144
+ "port",
145
+ message="Which port do you want to {action} " + "to {serial} ?" if action == "flash" else "?",
146
+ choices=get_known_ports(),
147
+ # autocomplete=True,
148
+ ),
149
+ inquirer_ux(
150
+ "boards",
151
+ message=(
152
+ "Which {port} board firmware do you want to {action} " + "to {serial} ?" if action == "flash" else "?"
153
+ ),
154
+ choices=filter_matching_boards,
155
+ validate=lambda _, x: True if x else "Please select at least one board", # type: ignore
156
+ ),
157
+ ]
158
+
159
+
160
+ def ask_mp_version(multi_select: bool, action: str):
161
+ """
162
+ Asks the user for the version selection.
163
+
164
+ Args:
165
+ questions (list): The list of questions to be asked.
166
+ action (str): The action to be performed.
167
+
168
+ Returns:
169
+
170
+ """
171
+ # import only when needed to reduce load time
172
+ import inquirer
173
+ import inquirer.errors
174
+
175
+ input_ux = inquirer.Checkbox if multi_select else inquirer.List
176
+
177
+ mp_versions: List[str] = micropython_versions()
178
+ mp_versions.reverse() # newest first
179
+
180
+ # remove the versions for which there are no known boards in the board_info.json
181
+ # todo: this may be a little slow
182
+ mp_versions = [v for v in mp_versions if "preview" in v or get_known_boards_for_port("stm32", [v])]
183
+
184
+ def at_least_one_validation(answers, current) -> bool:
185
+ if not current:
186
+ raise inquirer.errors.ValidationError("", reason="Please select at least one version")
187
+ if isinstance(current, list) and not any(current):
188
+ raise inquirer.errors.ValidationError("", reason="Please select at least one version")
189
+ return True
190
+
191
+ message = "Which version(s) do you want to {action} " + ("to {serial} ?" if action == "flash" else "?")
192
+ q = input_ux(
193
+ # inquirer.List(
194
+ "versions",
195
+ message=message,
196
+ # Hints would be nice , but needs a hint for each and every option
197
+ # hints=["Use space to select multiple options"],
198
+ choices=mp_versions,
199
+ autocomplete=True,
200
+ validate=at_least_one_validation, # type: ignore
201
+ )
202
+ return q
203
+
204
+
205
+ def ask_serialport(*, multi_select: bool = False, bluetooth: bool = False):
206
+ """
207
+ Asks the user for the serial port selection.
208
+
209
+ Args:
210
+ questions (list): The list of questions to be asked.
211
+ action (str): The action to be performed.
212
+
213
+ Returns:
214
+ None
215
+ """
216
+ # import only when needed to reduce load time
217
+ import inquirer
218
+
219
+ comports = MPRemoteBoard.connected_boards(bluetooth=bluetooth, description=True)
220
+ return inquirer.List(
221
+ "serial",
222
+ message="Which serial port do you want to {action} ?",
223
+ choices=comports,
224
+ other=True,
225
+ validate=lambda _, x: True if x else "Please select or enter a serial port", # type: ignore
226
+ )
@@ -1,18 +1,18 @@
1
1
  """CLI to Download MicroPython firmware for specific ports, boards and versions."""
2
2
 
3
3
  from pathlib import Path
4
- from typing import List, Tuple
5
4
 
6
5
  import rich_click as click
7
6
  from loguru import logger as log
8
7
 
8
+ from mpflash.connected import connected_ports_boards
9
9
  from mpflash.errors import MPFlashError
10
- from mpflash.mpboard_id import find_stored_board
10
+ from mpflash.mpboard_id import find_known_board
11
11
  from mpflash.vendor.versions import clean_version
12
12
 
13
- from .ask_input import DownloadParams, ask_missing_params
13
+ from .ask_input import ask_missing_params
14
14
  from .cli_group import cli
15
- from .cli_list import list_mcus
15
+ from .common import DownloadParams
16
16
  from .config import config
17
17
  from .download import download
18
18
 
@@ -50,6 +50,28 @@ from .download import download
50
50
  help="The board(s) to download the firmware for.",
51
51
  metavar="BOARD_ID or ?",
52
52
  )
53
+ @click.option(
54
+ "--serial",
55
+ "--serial-port",
56
+ "-s",
57
+ "serial",
58
+ default=["*"],
59
+ show_default=True,
60
+ multiple=True,
61
+ help="Which serial port(s) to flash",
62
+ metavar="SERIALPORT",
63
+ )
64
+ @click.option(
65
+ "--ignore",
66
+ "-i",
67
+ is_eager=True,
68
+ help="Serial port(s) to ignore. Defaults to MPFLASH_IGNORE.",
69
+ multiple=True,
70
+ default=[],
71
+ envvar="MPFLASH_IGNORE",
72
+ show_default=True,
73
+ metavar="SERIALPORT",
74
+ )
53
75
  @click.option(
54
76
  "--clean/--no-clean",
55
77
  default=True,
@@ -67,14 +89,25 @@ def cli_download(**kwargs) -> int:
67
89
  params = DownloadParams(**kwargs)
68
90
  params.versions = list(params.versions)
69
91
  params.boards = list(params.boards)
92
+ params.serial = list(params.serial)
93
+ params.ignore = list(params.ignore)
94
+
95
+ # all_boards: List[MPRemoteBoard] = []
70
96
  if params.boards:
71
- pass
72
- # TODO Clean board - same as in cli_flash.py
97
+ if not params.ports:
98
+ # no ports specified - resolve ports from specified boards by resolving board IDs
99
+ for board in params.boards:
100
+ if board != "?":
101
+ try:
102
+ board_ = find_known_board(board)
103
+ params.ports.append(board_.port)
104
+ except MPFlashError as e:
105
+ log.error(f"{e}")
73
106
  else:
74
- # no boards specified - detect connected boards
75
- params.ports, params.boards = connected_ports_boards()
107
+ # no boards specified - detect connected ports and boards
108
+ params.ports, params.boards, _ = connected_ports_boards(include=params.serial, ignore=params.ignore)
76
109
 
77
- params = ask_missing_params(params, action="download")
110
+ params = ask_missing_params(params)
78
111
  if not params: # Cancelled by user
79
112
  return 2
80
113
  params.versions = [clean_version(v, drop_v=True) for v in params.versions]
@@ -93,19 +126,3 @@ def cli_download(**kwargs) -> int:
93
126
  except MPFlashError as e:
94
127
  log.error(f"{e}")
95
128
  return 1
96
-
97
-
98
- def connected_ports_boards() -> Tuple[List[str], List[str]]:
99
- """
100
- Returns a tuple containing lists of unique ports and boards from the connected MCUs.
101
- Boards that are physically connected, but give no tangible response are ignored.
102
-
103
- Returns:
104
- A tuple containing two lists:
105
- - A list of unique ports where MCUs are connected.
106
- - A list of unique board names of the connected MCUs.
107
- """
108
- mpr_boards = [b for b in list_mcus() if b.connected]
109
- ports = list({b.port for b in mpr_boards})
110
- boards = list({b.board for b in mpr_boards})
111
- return ports, boards