benchlab-pytools 3.3.0__tar.gz → 3.3.1__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 (224) hide show
  1. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/CHANGELOG.md +18 -0
  2. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/PKG-INFO +22 -11
  3. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/README.md +16 -0
  4. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/__init__.py +1 -1
  5. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/flash/README.md +20 -4
  6. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/flash/flash_manager.py +16 -7
  7. benchlab_pytools-3.3.1/benchlab/flash/requirements.txt +11 -0
  8. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/flash/test_flash_manager.py +16 -5
  9. benchlab_pytools-3.3.1/benchlab/link/requirements.txt +3 -0
  10. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/main.py +24 -8
  11. benchlab_pytools-3.3.1/benchlab/mqtt/requirements.txt +3 -0
  12. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/tools.py +3 -1
  13. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/pyproject.toml +19 -7
  14. benchlab_pytools-3.3.0/benchlab/flash/requirements.txt +0 -7
  15. benchlab_pytools-3.3.0/benchlab/mqtt/requirements.txt +0 -3
  16. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/.flake8 +0 -0
  17. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/.gitignore +0 -0
  18. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/CONTRIBUTING.md +0 -0
  19. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/LICENSE +0 -0
  20. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/__main__.py +0 -0
  21. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/bootstrap.py +0 -0
  22. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/README.md +0 -0
  23. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/__init__.py +0 -0
  24. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/config_client.py +0 -0
  25. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/config_manager.py +0 -0
  26. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/config_tool.py +0 -0
  27. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/diff.py +0 -0
  28. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/examples/complete_config.json +0 -0
  29. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/examples/rgb_lighting.json +0 -0
  30. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/examples/simple_fan.json +0 -0
  31. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/http_dto.py +0 -0
  32. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/schema.py +0 -0
  33. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/test_config_client.py +0 -0
  34. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/test_config_manager.py +0 -0
  35. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/test_diff.py +0 -0
  36. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/test_http_config_client.py +0 -0
  37. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/config/test_http_dto.py +0 -0
  38. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/core/README.md +0 -0
  39. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/core/__init__.py +0 -0
  40. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/core/config.py +0 -0
  41. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/core/datasource.py +0 -0
  42. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/core/datasource_manager.py +0 -0
  43. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/core/device_registry.py +0 -0
  44. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/core/discovery.py +0 -0
  45. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/core/infrastructure.py +0 -0
  46. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/core/process_manager.py +0 -0
  47. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/core/retry.py +0 -0
  48. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/core/shared_serial.py +0 -0
  49. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/core/statistics.py +0 -0
  50. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/csv_log/README.md +0 -0
  51. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/csv_log/__init__.py +0 -0
  52. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/csv_log/csv_logger_enhanced.py +0 -0
  53. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/csv_log/message_batcher.py +0 -0
  54. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/csv_log/requirements.txt +0 -0
  55. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/csv_log/smart_retry.py +0 -0
  56. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/flash/__init__.py +0 -0
  57. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/flash/dfu.py +0 -0
  58. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/flash/flash_tool.py +0 -0
  59. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/flash/image.py +0 -0
  60. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/flash/test_dfu.py +0 -0
  61. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/flash/test_flash_tool.py +0 -0
  62. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/flash/test_image.py +0 -0
  63. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/graph/README.md +0 -0
  64. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/graph/__init__.py +0 -0
  65. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/graph/app.py +0 -0
  66. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/graph/requirements.txt +0 -0
  67. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/graph/runner.py +0 -0
  68. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/graph/test_graph.py +0 -0
  69. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/graph/ui.py +0 -0
  70. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/hwinfo/README.md +0 -0
  71. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/hwinfo/__init__.py +0 -0
  72. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/hwinfo/hwinfo_export.py +0 -0
  73. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/hwinfo/requirements.txt +0 -0
  74. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/hwinfo/test_hwinfo_export.py +0 -0
  75. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/launcher.py +0 -0
  76. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/link/.env.EXAMPLE +0 -0
  77. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/link/README.md +0 -0
  78. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/link/__init__.py +0 -0
  79. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/link/link_main.py +0 -0
  80. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/link/test_link_main.py +0 -0
  81. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/menu.py +0 -0
  82. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/menu_classic.py +0 -0
  83. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/mqtt/README.md +0 -0
  84. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/mqtt/__init__.py +0 -0
  85. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/mqtt/mqtt.config_template +0 -0
  86. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/mqtt/mqtt_publisher.py +0 -0
  87. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/mqtt/test_mqtt_publisher.py +0 -0
  88. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/prefs.py +0 -0
  89. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/requirements.txt +0 -0
  90. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/restapi/.env.example +0 -0
  91. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/restapi/__init__.py +0 -0
  92. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/restapi/favicon.ico +0 -0
  93. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/restapi/readme.md +0 -0
  94. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/restapi/requirements.txt +0 -0
  95. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/restapi/telemetry_api.py +0 -0
  96. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/restapi/test_read_recovery.py +0 -0
  97. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/restapi/test_server.py +0 -0
  98. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/sources.py +0 -0
  99. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/tui/README.md +0 -0
  100. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/tui/__init__.py +0 -0
  101. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/tui/config.py +0 -0
  102. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/tui/requirements.txt +0 -0
  103. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/tui/test_tui_core.py +0 -0
  104. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/tui/test_tui_main.py +0 -0
  105. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/tui/tui_core.py +0 -0
  106. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/tui/tui_main.py +0 -0
  107. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/README.md +0 -0
  108. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/NOTICE.md +0 -0
  109. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/README.md +0 -0
  110. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/Running_from_source_on_linux.md +0 -0
  111. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/__init__.py +0 -0
  112. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/assets/vu1_hello_world.png +0 -0
  113. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/community_applications.md +0 -0
  114. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/config.yaml +0 -0
  115. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/database.py +0 -0
  116. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/dial_driver.py +0 -0
  117. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/dials/Comms_Hub_Gauge.py +0 -0
  118. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/dials/Comms_Hub_Server.py +0 -0
  119. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/dials/__init__.py +0 -0
  120. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/dials/base_logger.py +0 -0
  121. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/installer/inc/icon.ico +0 -0
  122. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/installer/install.nsi +0 -0
  123. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/make_version.py +0 -0
  124. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/pylintrc +0 -0
  125. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/requirements.txt +0 -0
  126. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/serial_driver.py +0 -0
  127. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/server.py +0 -0
  128. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/server_config.py +0 -0
  129. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/server_dial_handler.py +0 -0
  130. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/vu_notifications.py +0 -0
  131. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/android-chrome-192x192.png +0 -0
  132. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/android-chrome-512x512.png +0 -0
  133. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/apple-touch-icon.png +0 -0
  134. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/demo.css +0 -0
  135. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/demo.min.css +0 -0
  136. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/demo.rtl.css +0 -0
  137. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/demo.rtl.min.css +0 -0
  138. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.css +0 -0
  139. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.min.css +0 -0
  140. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.rtl.css +0 -0
  141. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.rtl.min.css +0 -0
  142. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.css +0 -0
  143. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.min.css +0 -0
  144. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.rtl.css +0 -0
  145. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.rtl.min.css +0 -0
  146. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-social.css +0 -0
  147. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-social.min.css +0 -0
  148. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-social.rtl.css +0 -0
  149. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-social.rtl.min.css +0 -0
  150. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.css +0 -0
  151. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.min.css +0 -0
  152. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.rtl.css +0 -0
  153. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.rtl.min.css +0 -0
  154. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler.css +0 -0
  155. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler.min.css +0 -0
  156. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler.rtl.css +0 -0
  157. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/tabler.rtl.min.css +0 -0
  158. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/css/theme.min.css +0 -0
  159. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/img/header.png +0 -0
  160. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/img/logo.png +0 -0
  161. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/dark-theme.js +0 -0
  162. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/dark-theme.min.js +0 -0
  163. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/demo.js +0 -0
  164. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/demo.min.js +0 -0
  165. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/jquery.min.js +0 -0
  166. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/tabler.esm.js +0 -0
  167. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/tabler.esm.min.js +0 -0
  168. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/tabler.js +0 -0
  169. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/tabler.min.js +0 -0
  170. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/vu1_api.js +0 -0
  171. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_api_key_settings.js +0 -0
  172. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_api_keys.js +0 -0
  173. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_dial.js +0 -0
  174. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_home.js +0 -0
  175. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_root.js +0 -0
  176. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/favicon-16x16.png +0 -0
  177. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/favicon-32x32.png +0 -0
  178. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/favicon.ico +0 -0
  179. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/favicon.png +0 -0
  180. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/index.html +0 -0
  181. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/views/api_keys.html +0 -0
  182. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/views/dial.html +0 -0
  183. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/views/footer.html +0 -0
  184. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/views/header.html +0 -0
  185. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/views/key_settings.html +0 -0
  186. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/VU-Server/www/views/start.html +0 -0
  187. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/__init__.py +0 -0
  188. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/assets/Barlow-Bold.ttf +0 -0
  189. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/assets/bl_dial_144x200.png +0 -0
  190. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/assets/bl_logo_144x200.png +0 -0
  191. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/devices.py +0 -0
  192. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/requirements.txt +0 -0
  193. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/sensors.py +0 -0
  194. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/test_devices.py +0 -0
  195. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/test_vu_server_config.py +0 -0
  196. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/test_vu_server_manager.py +0 -0
  197. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/test_vu_tui.py +0 -0
  198. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/vu_dial.config_template +0 -0
  199. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/vu_logo_gen.py +0 -0
  200. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/vu_server.config_template +0 -0
  201. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/vu_server_config.py +0 -0
  202. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/vu_server_manager.py +0 -0
  203. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/vu_tui.py +0 -0
  204. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/vu/vu_updater.py +0 -0
  205. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/README.md +0 -0
  206. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/__init__.py +0 -0
  207. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/assets/Inter-Bold.ttf +0 -0
  208. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/assets/Inter.ttf +0 -0
  209. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/assets/benchlab.png +0 -0
  210. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/benchlab_fleet.py +0 -0
  211. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/benchlab_graph.py +0 -0
  212. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/benchlab_overview.py +0 -0
  213. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/benchlab_telemetry.py +0 -0
  214. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/benchlab_ui.py +0 -0
  215. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/benchlab_utils.py +0 -0
  216. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/requirements.txt +0 -0
  217. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/test_wigidash.py +0 -0
  218. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/wigidash_device.py +0 -0
  219. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/wigidash_manager.py +0 -0
  220. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/wigidash_session.py +0 -0
  221. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/wigidash_usb.py +0 -0
  222. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab/wigidash/wigidash_widget.py +0 -0
  223. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/benchlab.py +0 -0
  224. {benchlab_pytools-3.3.0 → benchlab_pytools-3.3.1}/pytest.ini +0 -0
@@ -4,6 +4,23 @@ All notable changes to BENCHLAB PyTools are documented here. Format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning follows
5
5
  [SemVer](https://semver.org/).
6
6
 
7
+ ## [3.3.1] - 2026-10-17
8
+
9
+ ### Fixed
10
+ - Packaging: `benchlab-pytools[flash]` was missing `pydantic` and
11
+ `requests` (`flash_manager` imports `config_manager` -> `config.schema`
12
+ -> `pydantic`; `--source service_http` needs `requests`), so a clean
13
+ `[flash]`-only install crashed with `ModuleNotFoundError` on first use.
14
+ The launcher also reported `ModuleNotFoundError` as "Flash tool module
15
+ not available in this build" regardless of cause; it now prints the
16
+ real missing module and the install command. (#90)
17
+ - `check_bootloader_supported()` only gated BENCHLAB1 firmware against
18
+ the CMD_BOOTLOADER version floor; a BENCHLAB2 unit on firmware below
19
+ `0x05` (which predates CMD_BOOTLOADER on BL2, per the firmware repo's
20
+ protocol contract freeze history) passed the check and then hit a 5s
21
+ timeout in `enter_dfu_mode()` instead of being told up front to use a
22
+ physical BOOT0/jumper bootloader entry. (#94)
23
+
7
24
  ## [3.3.0] - 2026-10-01
8
25
 
9
26
  ### Added
@@ -193,6 +210,7 @@ export, MQTT publisher, VU dials, WigiDash, and config import/export tools,
193
210
  sharing a common data-source layer (direct serial, FastAPI, MQTT, named
194
211
  pipe, service HTTP, service WebSocket).
195
212
 
213
+ [3.3.1]: https://github.com/BenchLab-io/benchlab-pytools/compare/v3.3.0...v3.3.1
196
214
  [3.3.0]: https://github.com/BenchLab-io/benchlab-pytools/compare/v3.2.1...v3.3.0
197
215
  [3.2.1]: https://github.com/BenchLab-io/benchlab-pytools/compare/v3.2.0...v3.2.1
198
216
  [3.2.0]: https://github.com/BenchLab-io/benchlab-pytools/compare/v3.1.0...v3.2.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: benchlab-pytools
3
- Version: 3.3.0
3
+ Version: 3.3.1
4
4
  Summary: Python control suite for BENCHLAB telemetry devices
5
5
  Project-URL: Homepage, https://benchlab.io/
6
6
  Project-URL: Repository, https://github.com/BenchLab-io/benchlab-pytools
@@ -24,13 +24,14 @@ Classifier: Topic :: System :: Monitoring
24
24
  Requires-Python: >=3.10
25
25
  Requires-Dist: benchlab-pycore>=0.8.0
26
26
  Requires-Dist: packaging<26.0,>=23.0
27
+ Requires-Dist: pydantic>=2.0.0
27
28
  Requires-Dist: python-dotenv<2.0,>=1.2.2
28
29
  Requires-Dist: pywin32>=306; platform_system == 'Windows'
30
+ Requires-Dist: requests>=2.33.1
29
31
  Requires-Dist: textual<9.0,>=0.60
30
32
  Requires-Dist: windows-curses>=2.4.1; platform_system == 'Windows'
31
33
  Provides-Extra: all
32
34
  Requires-Dist: amqtt<0.13.0,>=0.12.0; extra == 'all'
33
- Requires-Dist: benchlab-pycore>=0.8.0; extra == 'all'
34
35
  Requires-Dist: blessed>=1.20.0; extra == 'all'
35
36
  Requires-Dist: dearpygui>=2.1.1; extra == 'all'
36
37
  Requires-Dist: fastapi==0.111.1; extra == 'all'
@@ -42,25 +43,20 @@ Requires-Dist: numpy>=2.2.0; extra == 'all'
42
43
  Requires-Dist: paho-mqtt<3.0,>=2.0; extra == 'all'
43
44
  Requires-Dist: pillow>=10.0.0; extra == 'all'
44
45
  Requires-Dist: pillow>=11.3.0; extra == 'all'
45
- Requires-Dist: pydantic>=2.0.0; extra == 'all'
46
46
  Requires-Dist: pyelftools>=0.31; extra == 'all'
47
47
  Requires-Dist: pyserial>=3.5; extra == 'all'
48
48
  Requires-Dist: python-dotenv==1.2.2; extra == 'all'
49
49
  Requires-Dist: pyusb>=1.3.1; extra == 'all'
50
50
  Requires-Dist: pyyaml<7.0,>=6.0; extra == 'all'
51
51
  Requires-Dist: pyyaml>=6.0; extra == 'all'
52
- Requires-Dist: requests>=2.31.0; extra == 'all'
53
- Requires-Dist: requests>=2.33.1; extra == 'all'
54
52
  Requires-Dist: ruamel-yaml; extra == 'all'
55
53
  Requires-Dist: tornado; extra == 'all'
56
54
  Requires-Dist: tqdm>=4.66; extra == 'all'
57
55
  Requires-Dist: uvicorn[standard]==0.24.0; extra == 'all'
58
56
  Requires-Dist: websockets<16.0,>=13.0; extra == 'all'
59
57
  Provides-Extra: csv-log
60
- Requires-Dist: benchlab-pycore>=0.8.0; extra == 'csv-log'
61
58
  Requires-Dist: pyserial>=3.5; extra == 'csv-log'
62
59
  Provides-Extra: flash
63
- Requires-Dist: benchlab-pycore>=0.8.0; extra == 'flash'
64
60
  Requires-Dist: intelhex>=2.3.0; extra == 'flash'
65
61
  Requires-Dist: libusb-package>=1.0.26.1; (sys_platform == 'win32') and extra == 'flash'
66
62
  Requires-Dist: pyelftools>=0.31; extra == 'flash'
@@ -72,29 +68,28 @@ Requires-Dist: dearpygui>=2.1.1; extra == 'graph'
72
68
  Requires-Dist: pyserial>=3.5; extra == 'graph'
73
69
  Provides-Extra: hwinfo
74
70
  Requires-Dist: pyserial>=3.5; extra == 'hwinfo'
71
+ Provides-Extra: link
72
+ Requires-Dist: paho-mqtt<3.0,>=2.0; extra == 'link'
73
+ Requires-Dist: pyserial>=3.5; extra == 'link'
75
74
  Provides-Extra: mqtt
76
75
  Requires-Dist: amqtt<0.13.0,>=0.12.0; extra == 'mqtt'
77
76
  Requires-Dist: paho-mqtt<3.0,>=2.0; extra == 'mqtt'
78
77
  Requires-Dist: pyyaml<7.0,>=6.0; extra == 'mqtt'
79
78
  Provides-Extra: restapi
80
79
  Requires-Dist: fastapi==0.111.1; extra == 'restapi'
81
- Requires-Dist: pydantic>=2.0.0; extra == 'restapi'
82
80
  Requires-Dist: pyserial>=3.5; extra == 'restapi'
83
81
  Requires-Dist: python-dotenv==1.2.2; extra == 'restapi'
84
82
  Requires-Dist: uvicorn[standard]==0.24.0; extra == 'restapi'
85
83
  Provides-Extra: service-ws
86
84
  Requires-Dist: websockets<16.0,>=13.0; extra == 'service-ws'
87
85
  Provides-Extra: tui
88
- Requires-Dist: pydantic>=2.0.0; extra == 'tui'
89
86
  Requires-Dist: pyserial>=3.5; extra == 'tui'
90
- Requires-Dist: requests>=2.33.1; extra == 'tui'
91
87
  Provides-Extra: vu
92
88
  Requires-Dist: blessed>=1.20.0; extra == 'vu'
93
89
  Requires-Dist: numpy; extra == 'vu'
94
90
  Requires-Dist: pillow>=10.0.0; extra == 'vu'
95
91
  Requires-Dist: pyserial>=3.5; extra == 'vu'
96
92
  Requires-Dist: pyyaml>=6.0; extra == 'vu'
97
- Requires-Dist: requests>=2.31.0; extra == 'vu'
98
93
  Requires-Dist: ruamel-yaml; extra == 'vu'
99
94
  Requires-Dist: tornado; extra == 'vu'
100
95
  Provides-Extra: wigidash
@@ -191,6 +186,22 @@ python -m benchlab -config ... # Device configuration import/export
191
186
  python -m benchlab -flash ... # Firmware flash tool (STM32 ROM DFU)
192
187
  ```
193
188
 
189
+ The flash tool needs its extra: `pip install "benchlab-pytools[flash]"`. It takes a firmware
190
+ image with `--file` and does not download one; releases live in
191
+ [BENCHLAB-FW](https://github.com/BenchLab-io/BENCHLAB-FW/releases). Start with `--list` to see what
192
+ is connected, and `--verify-only` to check an image against a device without erasing or writing:
193
+
194
+ ```bash
195
+ python -m benchlab -flash --list
196
+ python -m benchlab -flash --file benchlab2-fw07-v0.7.2.bin --verify-only
197
+ ```
198
+
199
+ **On Windows, flashing needs a one-time driver step.** In DFU mode the board enumerates as
200
+ ST's ROM bootloader (VID `0483`, PID `DF11`), which does not bind to a driver libusb can use,
201
+ so the tool cannot see a device that is plugged in and sitting in its bootloader. Bind WinUSB
202
+ to it with [Zadig](https://zadig.akeo.ie/) first -- see
203
+ [Windows: USB driver setup](benchlab/flash/README.md#windows-usb-driver-setup-zadig).
204
+
194
205
  Running with no flags is equivalent to launching the interactive menu.
195
206
 
196
207
  ### Data Sources
@@ -83,6 +83,22 @@ python -m benchlab -config ... # Device configuration import/export
83
83
  python -m benchlab -flash ... # Firmware flash tool (STM32 ROM DFU)
84
84
  ```
85
85
 
86
+ The flash tool needs its extra: `pip install "benchlab-pytools[flash]"`. It takes a firmware
87
+ image with `--file` and does not download one; releases live in
88
+ [BENCHLAB-FW](https://github.com/BenchLab-io/BENCHLAB-FW/releases). Start with `--list` to see what
89
+ is connected, and `--verify-only` to check an image against a device without erasing or writing:
90
+
91
+ ```bash
92
+ python -m benchlab -flash --list
93
+ python -m benchlab -flash --file benchlab2-fw07-v0.7.2.bin --verify-only
94
+ ```
95
+
96
+ **On Windows, flashing needs a one-time driver step.** In DFU mode the board enumerates as
97
+ ST's ROM bootloader (VID `0483`, PID `DF11`), which does not bind to a driver libusb can use,
98
+ so the tool cannot see a device that is plugged in and sitting in its bootloader. Bind WinUSB
99
+ to it with [Zadig](https://zadig.akeo.ie/) first -- see
100
+ [Windows: USB driver setup](benchlab/flash/README.md#windows-usb-driver-setup-zadig).
101
+
86
102
  Running with no flags is equivalent to launching the interactive menu.
87
103
 
88
104
  ### Data Sources
@@ -2,4 +2,4 @@
2
2
  BENCHLAB Telemetry Package
3
3
  """
4
4
 
5
- __version__ = "3.3.0"
5
+ __version__ = "3.3.1"
@@ -178,10 +178,26 @@ WinUSB (or libusbK) driver to it using
178
178
 
179
179
  1. Start the flash operation so the device enters DFU mode (or put it into
180
180
  DFU mode and let it stay there briefly).
181
- 2. Open Zadig, enable "List All Devices", find the device (it should show
182
- up as an STM32 BOOTLOADER or similar, VID/PID `0483`/`DF11`).
183
- 3. Select the WinUSB driver and click "Install Driver" / "Replace Driver".
184
- 4. Re-run the flash command.
181
+ 2. Open Zadig **as Administrator** and find the device -- it should show up
182
+ as `STM32 BOOTLOADER`. A driverless device is listed by default; only
183
+ enable "List All Devices" if it does not appear.
184
+ 3. **Check the USB ID reads `0483 DF11`** before continuing, so the driver
185
+ cannot go onto the wrong device.
186
+ 4. Select the WinUSB driver and click "Install Driver" / "Replace Driver".
187
+ This takes around 30 seconds and the window may appear frozen.
188
+ 5. Re-run the flash command.
189
+
190
+ To confirm the bind before re-running, on Windows:
191
+
192
+ ```powershell
193
+ Get-PnpDevice | Where-Object { $_.InstanceId -like '*VID_0483&PID_DF11*' } |
194
+ Select-Object Status, FriendlyName, Service
195
+ ```
196
+
197
+ `Service : WinUSB` with `Status : OK` means libusb can now see it. An
198
+ unbound device instead reports `Status : Error` and
199
+ `ConfigManagerErrorCode : 28` ("no driver installed"), which is the
200
+ underlying cause of the timeout above.
185
201
 
186
202
  This is a one-time setup per machine/USB port combination. This is a
187
203
  Windows driver-binding limitation, independent of this tool being pure
@@ -32,6 +32,11 @@ logger = logging.getLogger("benchlab.flash.manager")
32
32
  # ignore the opcode).
33
33
  MIN_BOOTLOADER_FW_VERSION = 0x04
34
34
 
35
+ # Same opcode, same commit (c722244), but BL2's frozen protocol contracts
36
+ # show it landed between the fw04 and fw05 freezes -- benchlab2-fw03.json/
37
+ # benchlab2-fw04.json have no BOOTLOADER entry, benchlab2-fw05.json does.
38
+ MIN_BOOTLOADER_FW_VERSION_BL2 = 0x05
39
+
35
40
  _KNOWN_PRODUCT_IDS = (BENCHLAB_ORIGINAL_PRODUCT_ID, BENCHLAB_BL2_PRODUCT_ID)
36
41
  _BENCHLAB_VENDOR_ID = 0xEE
37
42
 
@@ -155,16 +160,20 @@ class FlashManager:
155
160
 
156
161
  def check_bootloader_supported(
157
162
  self, device_info: dict, product_id: int) -> None:
158
- if (product_id == BENCHLAB_ORIGINAL_PRODUCT_ID
159
- and device_info.get("FwVersion", 0)
160
- < MIN_BOOTLOADER_FW_VERSION):
163
+ if product_id == BENCHLAB_ORIGINAL_PRODUCT_ID:
164
+ min_fw = MIN_BOOTLOADER_FW_VERSION
165
+ elif product_id == BENCHLAB_BL2_PRODUCT_ID:
166
+ min_fw = MIN_BOOTLOADER_FW_VERSION_BL2
167
+ else:
168
+ return
169
+
170
+ if device_info.get("FwVersion", 0) < min_fw:
161
171
  raise UnsupportedFirmwareError(
162
172
  "This device's firmware "
163
173
  f"(0x{device_info.get('FwVersion', 0):02X}) predates "
164
- f"CMD_BOOTLOADER support (requires "
165
- f"0x{MIN_BOOTLOADER_FW_VERSION:02X}+). It cannot be put "
166
- "into DFU mode via software -- use a physical BOOT0/jumper "
167
- "bootloader entry instead.")
174
+ f"CMD_BOOTLOADER support (requires 0x{min_fw:02X}+). It "
175
+ "cannot be put into DFU mode via software -- use a "
176
+ "physical BOOT0/jumper bootloader entry instead.")
168
177
 
169
178
  def enter_dfu_mode(
170
179
  self, identifier: str, port: Optional[str] = None,
@@ -0,0 +1,11 @@
1
+ pyserial>=3.5
2
+ pyusb>=1.3.1
3
+ intelhex>=2.3.0
4
+ pyelftools>=0.31
5
+ tqdm>=4.66
6
+ benchlab-pycore>=0.8.0
7
+ libusb-package>=1.0.26.1; sys_platform == 'win32'
8
+ # flash_manager -> config_manager -> config.schema (see #90)
9
+ pydantic>=2.0.0
10
+ # needed by --source service_http (see #90)
11
+ requests>=2.33.1
@@ -108,11 +108,22 @@ def test_check_bootloader_supported_bl1_version_gate(
108
108
  info, BENCHLAB_ORIGINAL_PRODUCT_ID)
109
109
 
110
110
 
111
- def test_check_bootloader_supported_bl2_not_version_gated(manager):
112
- # BL2's CMD_BOOTLOADER gating isn't modeled here (all shipped BL2
113
- # firmware postdates it) -- should never raise regardless of fw value.
114
- info = _device_info(product_id=BENCHLAB_BL2_PRODUCT_ID, fw=0x01)
115
- manager.check_bootloader_supported(info, BENCHLAB_BL2_PRODUCT_ID)
111
+ @pytest.mark.parametrize("fw,should_raise", [
112
+ (0x03, True),
113
+ (0x04, True),
114
+ (0x05, False),
115
+ (0x07, False),
116
+ ])
117
+ def test_check_bootloader_supported_bl2_version_gate(
118
+ manager, fw, should_raise):
119
+ info = _device_info(product_id=BENCHLAB_BL2_PRODUCT_ID, fw=fw)
120
+ if should_raise:
121
+ with pytest.raises(UnsupportedFirmwareError):
122
+ manager.check_bootloader_supported(
123
+ info, BENCHLAB_BL2_PRODUCT_ID)
124
+ else:
125
+ manager.check_bootloader_supported(
126
+ info, BENCHLAB_BL2_PRODUCT_ID)
116
127
 
117
128
 
118
129
  # -- enter_dfu_mode / wait_for_dfu_device ----------------------------------
@@ -0,0 +1,3 @@
1
+ # benchlab/link/requirements.txt
2
+ paho-mqtt>=2.0,<3.0
3
+ pyserial>=3.5
@@ -402,34 +402,50 @@ def launch_mode() -> None:
402
402
  try:
403
403
  sys.argv.remove('-config')
404
404
  from benchlab.config.config_tool import main as config_main
405
+ except ModuleNotFoundError as exc:
406
+ # A missing transitive dependency is not a missing build: name the
407
+ # real cause. There is no install hint because config's only
408
+ # third-party import (pydantic) is a core dependency, so a miss
409
+ # here means a broken install rather than a missing extra (#90,
410
+ # #92).
411
+ print(f"Config tool unavailable: {exc}")
412
+ else:
405
413
  sys.exit(config_main())
406
- except ModuleNotFoundError:
407
- print("Config tool module not available in this build.")
408
414
 
409
415
  elif args.flash:
410
416
  # Flash tool handles its own argument parsing
411
417
  try:
412
418
  sys.argv.remove('-flash')
413
419
  from benchlab.flash.flash_tool import main as flash_main
420
+ except ModuleNotFoundError as exc:
421
+ # A missing transitive dependency is not a missing build: name
422
+ # it, and point at the extra that supplies it (see #90).
423
+ print(f"Flash tool unavailable: {exc}")
424
+ print('Install it with: pip install "benchlab-pytools[flash]"')
425
+ else:
414
426
  sys.exit(flash_main())
415
- except ModuleNotFoundError:
416
- print("Flash tool module not available in this build.")
417
427
 
418
428
  elif args.fastapi:
419
429
  try:
420
430
  from benchlab.restapi.telemetry_api import run_server
431
+ except ModuleNotFoundError as exc:
432
+ # Same reasoning as -flash: a missing dependency is not a missing
433
+ # build, so report which module is absent (see #90).
434
+ print(f"FastAPI / Uvicorn unavailable: {exc}")
435
+ print('Install it with: pip install "benchlab-pytools[restapi]"')
436
+ else:
421
437
  run_server()
422
- except ModuleNotFoundError:
423
- print("FastAPI / Uvicorn not available in this build.")
424
438
 
425
439
  elif args.mqtt:
426
440
  try:
427
441
  from benchlab.mqtt.mqtt_publisher import run_mqtt_mode
442
+ except ModuleNotFoundError as exc:
443
+ print(f"MQTT module unavailable: {exc}")
444
+ print('Install it with: pip install "benchlab-pytools[mqtt]"')
445
+ else:
428
446
  broker = args.mqtt if args.mqtt else "localhost"
429
447
  os.environ.setdefault("MQTT_BROKER", broker)
430
448
  run_mqtt_mode(broker)
431
- except ModuleNotFoundError:
432
- print("MQTT module not available in this build.")
433
449
 
434
450
  elif args.link:
435
451
  _export_link_env(args)
@@ -0,0 +1,3 @@
1
+ paho-mqtt>=2.0,<3.0
2
+ amqtt>=0.12.0,<0.13.0
3
+ pyyaml>=6.0,<7.0
@@ -25,7 +25,9 @@ CONSUMER_TOOLS = {
25
25
  "flag": "-config",
26
26
  "module": "benchlab.config.config_tool",
27
27
  "function": "main",
28
- "requirements": "requirements.txt",
28
+ # No requirements file: config's only third-party import is pydantic,
29
+ # which is a core dependency, so there is nothing tool-specific to
30
+ # install (see #92).
29
31
  "supported_sources": ["direct", "named_pipe"],
30
32
  },
31
33
  "flash": {
@@ -27,31 +27,41 @@ classifiers = [
27
27
  "Topic :: System :: Monitoring",
28
28
  ]
29
29
 
30
+ # Boundary rule (see #92): anything imported by code that ships in every install
31
+ # -- the launcher, benchlab/core and benchlab/config -- lives here, not in an
32
+ # extra. Extras below may only list what a tool's own modules need on top of this.
30
33
  dependencies = [
31
34
  "packaging>=23.0,<26.0",
32
35
  "python-dotenv>=1.2.2,<2.0",
33
36
  "textual>=0.60,<9.0",
34
37
  "benchlab-pycore>=0.8.0",
38
+ # Import-time dependency of benchlab/config/schema.py, reached by -config,
39
+ # -flash and the REST API (the #90 chain). -config has no extra of its own,
40
+ # so pydantic cannot live in one.
41
+ "pydantic>=2.0.0",
42
+ # Lazily imported by benchlab/core/datasource.py for the service_http source,
43
+ # which every tool with service_http in supported_sources can select.
44
+ "requests>=2.33.1",
35
45
  "windows-curses>=2.4.1; platform_system=='Windows'",
36
46
  "pywin32>=306; platform_system=='Windows'",
37
47
  ]
38
48
 
49
+ # Extras list only what a tool's own modules import beyond the core dependencies
50
+ # above. pydantic, requests and benchlab-pycore are core now, so they are not
51
+ # repeated per extra; pyserial stays explicit because those modules import it
52
+ # directly rather than through benchlab-pycore.
39
53
  [project.optional-dependencies]
40
54
  tui = [
41
55
  "pyserial>=3.5",
42
- "pydantic>=2.0.0",
43
- "requests>=2.33.1",
44
56
  ]
45
57
  csv_log = [
46
58
  "pyserial>=3.5",
47
- "benchlab-pycore>=0.8.0",
48
59
  ]
49
60
  restapi = [
50
61
  "fastapi==0.111.1",
51
62
  "uvicorn[standard]==0.24.0",
52
63
  "pyserial>=3.5",
53
64
  "python-dotenv==1.2.2",
54
- "pydantic>=2.0.0",
55
65
  ]
56
66
  mqtt = [
57
67
  "paho-mqtt>=2.0,<3.0",
@@ -69,7 +79,6 @@ hwinfo = [
69
79
  "pyserial>=3.5",
70
80
  ]
71
81
  vu = [
72
- "requests>=2.31.0",
73
82
  "PyYAML>=6.0",
74
83
  "blessed>=1.20.0",
75
84
  "Pillow>=10.0.0",
@@ -86,17 +95,20 @@ wigidash = [
86
95
  "pyserial>=3.5",
87
96
  "libusb-package>=1.0.26.1; sys_platform == 'win32'",
88
97
  ]
98
+ link = [
99
+ "paho-mqtt>=2.0,<3.0",
100
+ "pyserial>=3.5",
101
+ ]
89
102
  flash = [
90
103
  "pyserial>=3.5",
91
104
  "pyusb>=1.3.1",
92
105
  "intelhex>=2.3.0",
93
106
  "pyelftools>=0.31",
94
107
  "tqdm>=4.66",
95
- "benchlab-pycore>=0.8.0",
96
108
  "libusb-package>=1.0.26.1; sys_platform == 'win32'",
97
109
  ]
98
110
  all = [
99
- "benchlab-pytools[tui,csv_log,restapi,mqtt,service_ws,graph,hwinfo,vu,wigidash,flash]",
111
+ "benchlab-pytools[tui,csv_log,restapi,mqtt,service_ws,graph,hwinfo,vu,wigidash,flash,link]",
100
112
  ]
101
113
 
102
114
  [project.urls]
@@ -1,7 +0,0 @@
1
- pyserial>=3.5
2
- pyusb>=1.3.1
3
- intelhex>=2.3.0
4
- pyelftools>=0.31
5
- tqdm>=4.66
6
- benchlab-pycore>=0.8.0
7
- libusb-package>=1.0.26.1; sys_platform == 'win32'
@@ -1,3 +0,0 @@
1
- paho-mqtt>=1.6.1
2
- amqtt>=0.12.0,<0.13.0
3
- pyyaml>=6.0,<7.0