benchlab-pytools 3.4.0__tar.gz → 3.5.0__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 (222) hide show
  1. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/CHANGELOG.md +21 -0
  2. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/PKG-INFO +2 -2
  3. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/__init__.py +1 -1
  4. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/core/datasource_manager.py +15 -2
  5. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/core/discovery.py +4 -2
  6. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/main.py +33 -0
  7. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/mqtt/mqtt_publisher.py +3 -0
  8. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/restapi/telemetry_api.py +1 -0
  9. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/tui/config.py +2 -1
  10. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/tui/test_tui_core.py +7 -4
  11. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/tui/tui_core.py +36 -20
  12. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/pyproject.toml +1 -1
  13. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/.flake8 +0 -0
  14. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/.gitignore +0 -0
  15. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/CONTRIBUTING.md +0 -0
  16. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/LICENSE +0 -0
  17. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/README.md +0 -0
  18. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/__main__.py +0 -0
  19. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/bootstrap.py +0 -0
  20. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/README.md +0 -0
  21. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/__init__.py +0 -0
  22. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/config_client.py +0 -0
  23. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/config_manager.py +0 -0
  24. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/config_tool.py +0 -0
  25. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/diff.py +0 -0
  26. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/examples/complete_config.json +0 -0
  27. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/examples/rgb_lighting.json +0 -0
  28. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/examples/simple_fan.json +0 -0
  29. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/http_dto.py +0 -0
  30. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/schema.py +0 -0
  31. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/test_config_client.py +0 -0
  32. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/test_config_manager.py +0 -0
  33. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/test_diff.py +0 -0
  34. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/test_http_config_client.py +0 -0
  35. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/config/test_http_dto.py +0 -0
  36. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/core/README.md +0 -0
  37. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/core/__init__.py +0 -0
  38. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/core/config.py +0 -0
  39. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/core/datasource.py +0 -0
  40. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/core/device_registry.py +0 -0
  41. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/core/infrastructure.py +0 -0
  42. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/core/process_manager.py +0 -0
  43. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/core/retry.py +0 -0
  44. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/core/shared_serial.py +0 -0
  45. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/core/statistics.py +0 -0
  46. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/csv_log/README.md +0 -0
  47. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/csv_log/__init__.py +0 -0
  48. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/csv_log/csv_logger_enhanced.py +0 -0
  49. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/csv_log/message_batcher.py +0 -0
  50. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/csv_log/requirements.txt +0 -0
  51. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/csv_log/smart_retry.py +0 -0
  52. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/flash/README.md +0 -0
  53. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/flash/__init__.py +0 -0
  54. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/flash/dfu.py +0 -0
  55. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/flash/flash_manager.py +0 -0
  56. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/flash/flash_tool.py +0 -0
  57. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/flash/image.py +0 -0
  58. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/flash/requirements.txt +0 -0
  59. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/flash/test_dfu.py +0 -0
  60. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/flash/test_flash_manager.py +0 -0
  61. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/flash/test_flash_tool.py +0 -0
  62. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/flash/test_image.py +0 -0
  63. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/graph/README.md +0 -0
  64. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/graph/__init__.py +0 -0
  65. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/graph/app.py +0 -0
  66. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/graph/requirements.txt +0 -0
  67. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/graph/runner.py +0 -0
  68. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/graph/test_graph.py +0 -0
  69. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/graph/ui.py +0 -0
  70. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/hwinfo/README.md +0 -0
  71. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/hwinfo/__init__.py +0 -0
  72. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/hwinfo/hwinfo_export.py +0 -0
  73. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/hwinfo/requirements.txt +0 -0
  74. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/hwinfo/test_hwinfo_export.py +0 -0
  75. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/launcher.py +0 -0
  76. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/link/.env.EXAMPLE +0 -0
  77. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/link/README.md +0 -0
  78. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/link/__init__.py +0 -0
  79. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/link/link_main.py +0 -0
  80. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/link/requirements.txt +0 -0
  81. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/link/test_link_main.py +0 -0
  82. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/menu.py +0 -0
  83. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/menu_classic.py +0 -0
  84. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/mqtt/README.md +0 -0
  85. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/mqtt/__init__.py +0 -0
  86. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/mqtt/mqtt.config_template +0 -0
  87. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/mqtt/requirements.txt +0 -0
  88. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/mqtt/test_mqtt_publisher.py +0 -0
  89. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/prefs.py +0 -0
  90. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/requirements.txt +0 -0
  91. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/restapi/.env.example +0 -0
  92. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/restapi/__init__.py +0 -0
  93. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/restapi/favicon.ico +0 -0
  94. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/restapi/readme.md +0 -0
  95. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/restapi/requirements.txt +0 -0
  96. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/restapi/test_read_recovery.py +0 -0
  97. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/restapi/test_server.py +0 -0
  98. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/sources.py +0 -0
  99. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/tools.py +0 -0
  100. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/tui/README.md +0 -0
  101. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/tui/__init__.py +0 -0
  102. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/tui/requirements.txt +0 -0
  103. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/tui/test_tui_main.py +0 -0
  104. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/tui/tui_main.py +0 -0
  105. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/README.md +0 -0
  106. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/NOTICE.md +0 -0
  107. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/README.md +0 -0
  108. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/Running_from_source_on_linux.md +0 -0
  109. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/__init__.py +0 -0
  110. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/assets/vu1_hello_world.png +0 -0
  111. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/community_applications.md +0 -0
  112. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/config.yaml +0 -0
  113. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/database.py +0 -0
  114. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/dial_driver.py +0 -0
  115. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/dials/Comms_Hub_Gauge.py +0 -0
  116. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/dials/Comms_Hub_Server.py +0 -0
  117. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/dials/__init__.py +0 -0
  118. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/dials/base_logger.py +0 -0
  119. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/installer/inc/icon.ico +0 -0
  120. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/installer/install.nsi +0 -0
  121. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/make_version.py +0 -0
  122. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/pylintrc +0 -0
  123. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/requirements.txt +0 -0
  124. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/serial_driver.py +0 -0
  125. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/server.py +0 -0
  126. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/server_config.py +0 -0
  127. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/server_dial_handler.py +0 -0
  128. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/vu_notifications.py +0 -0
  129. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/android-chrome-192x192.png +0 -0
  130. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/android-chrome-512x512.png +0 -0
  131. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/apple-touch-icon.png +0 -0
  132. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/demo.css +0 -0
  133. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/demo.min.css +0 -0
  134. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/demo.rtl.css +0 -0
  135. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/demo.rtl.min.css +0 -0
  136. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.css +0 -0
  137. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.min.css +0 -0
  138. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.rtl.css +0 -0
  139. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-flags.rtl.min.css +0 -0
  140. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.css +0 -0
  141. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.min.css +0 -0
  142. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.rtl.css +0 -0
  143. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-payments.rtl.min.css +0 -0
  144. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-social.css +0 -0
  145. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-social.min.css +0 -0
  146. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-social.rtl.css +0 -0
  147. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-social.rtl.min.css +0 -0
  148. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.css +0 -0
  149. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.min.css +0 -0
  150. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.rtl.css +0 -0
  151. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler-vendors.rtl.min.css +0 -0
  152. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler.css +0 -0
  153. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler.min.css +0 -0
  154. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler.rtl.css +0 -0
  155. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/tabler.rtl.min.css +0 -0
  156. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/css/theme.min.css +0 -0
  157. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/img/header.png +0 -0
  158. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/img/logo.png +0 -0
  159. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/dark-theme.js +0 -0
  160. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/dark-theme.min.js +0 -0
  161. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/demo.js +0 -0
  162. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/demo.min.js +0 -0
  163. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/jquery.min.js +0 -0
  164. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/tabler.esm.js +0 -0
  165. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/tabler.esm.min.js +0 -0
  166. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/tabler.js +0 -0
  167. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/tabler.min.js +0 -0
  168. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/vu1_api.js +0 -0
  169. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_api_key_settings.js +0 -0
  170. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_api_keys.js +0 -0
  171. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_dial.js +0 -0
  172. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_home.js +0 -0
  173. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/assets/js/vu1_gui_root.js +0 -0
  174. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/favicon-16x16.png +0 -0
  175. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/favicon-32x32.png +0 -0
  176. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/favicon.ico +0 -0
  177. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/favicon.png +0 -0
  178. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/index.html +0 -0
  179. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/views/api_keys.html +0 -0
  180. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/views/dial.html +0 -0
  181. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/views/footer.html +0 -0
  182. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/views/header.html +0 -0
  183. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/views/key_settings.html +0 -0
  184. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/VU-Server/www/views/start.html +0 -0
  185. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/__init__.py +0 -0
  186. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/assets/Barlow-Bold.ttf +0 -0
  187. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/assets/bl_dial_144x200.png +0 -0
  188. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/assets/bl_logo_144x200.png +0 -0
  189. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/devices.py +0 -0
  190. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/requirements.txt +0 -0
  191. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/sensors.py +0 -0
  192. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/test_devices.py +0 -0
  193. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/test_vu_server_config.py +0 -0
  194. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/test_vu_server_manager.py +0 -0
  195. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/test_vu_tui.py +0 -0
  196. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/vu_dial.config_template +0 -0
  197. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/vu_logo_gen.py +0 -0
  198. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/vu_server.config_template +0 -0
  199. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/vu_server_config.py +0 -0
  200. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/vu_server_manager.py +0 -0
  201. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/vu_tui.py +0 -0
  202. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/vu/vu_updater.py +0 -0
  203. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/README.md +0 -0
  204. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/__init__.py +0 -0
  205. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/assets/Inter-Bold.ttf +0 -0
  206. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/assets/Inter.ttf +0 -0
  207. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/assets/benchlab.png +0 -0
  208. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/benchlab_fleet.py +0 -0
  209. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/benchlab_graph.py +0 -0
  210. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/benchlab_overview.py +0 -0
  211. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/benchlab_telemetry.py +0 -0
  212. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/benchlab_ui.py +0 -0
  213. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/benchlab_utils.py +0 -0
  214. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/requirements.txt +0 -0
  215. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/test_wigidash.py +0 -0
  216. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/wigidash_device.py +0 -0
  217. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/wigidash_manager.py +0 -0
  218. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/wigidash_session.py +0 -0
  219. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/wigidash_usb.py +0 -0
  220. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab/wigidash/wigidash_widget.py +0 -0
  221. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/benchlab.py +0 -0
  222. {benchlab_pytools-3.4.0 → benchlab_pytools-3.5.0}/pytest.ini +0 -0
@@ -4,6 +4,27 @@ 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.5.0] - 2026-11-04
8
+
9
+ ### Added
10
+ - BL1 (ORIGINAL, fw07+) fault status is now supported, matching BL2:
11
+ the TUI is variant-aware and decodes faults with the correct enum
12
+ for each device instead of always assuming BL2's (which previously
13
+ meant BL1 faults were silently never shown). (#100)
14
+ - `PatchVersion` is now surfaced end-to-end (TUI Device tab, discovery,
15
+ FastAPI `/devices`, MQTT publisher), including a fix for a
16
+ worker-loop bug that dropped it on every periodic device-list
17
+ refresh. (#100)
18
+ - A startup check now verifies the installed `benchlab-pycore` version
19
+ and fails with a clear message instead of an `ImportError` traceback
20
+ when it's missing or too old. (#100)
21
+
22
+ ### Changed
23
+ - Raised the `benchlab-pycore` floor to `>=0.9.1` after finding and
24
+ reporting a `read_device()` short-read bug in 0.9.0
25
+ (benchlab-pycore#22), fixed upstream in 0.9.1 (benchlab-pycore#23).
26
+ (#100)
27
+
7
28
  ## [3.4.0] - 2026-10-22
8
29
 
9
30
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: benchlab-pytools
3
- Version: 3.4.0
3
+ Version: 3.5.0
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
@@ -22,7 +22,7 @@ Classifier: Programming Language :: Python :: 3.13
22
22
  Classifier: Topic :: System :: Hardware
23
23
  Classifier: Topic :: System :: Monitoring
24
24
  Requires-Python: >=3.10
25
- Requires-Dist: benchlab-pycore>=0.8.0
25
+ Requires-Dist: benchlab-pycore>=0.9.1
26
26
  Requires-Dist: packaging<26.0,>=23.0
27
27
  Requires-Dist: pydantic>=2.0.0
28
28
  Requires-Dist: python-dotenv<2.0,>=1.2.2
@@ -2,4 +2,4 @@
2
2
  BENCHLAB Telemetry Package
3
3
  """
4
4
 
5
- __version__ = "3.4.0"
5
+ __version__ = "3.5.0"
@@ -372,7 +372,11 @@ class DataSourceManager:
372
372
  time.sleep(2.0)
373
373
  continue
374
374
 
375
- # Update device list periodically
375
+ # Update device list periodically. list_devices() only
376
+ # returns a summary shape; merge in get_device_info()'s
377
+ # fuller dict (as connect() does) so fields it alone
378
+ # provides -- e.g. PatchVersion -- don't get dropped on
379
+ # every refresh.
376
380
  try:
377
381
  devices = self._datasource.list_devices()
378
382
  with self._lock:
@@ -380,7 +384,16 @@ class DataSourceManager:
380
384
  for device in devices:
381
385
  uid = device.get('uid')
382
386
  if uid:
383
- self._devices[uid] = device
387
+ device_entry = device.copy()
388
+ try:
389
+ full_info = (
390
+ self._datasource.get_device_info(
391
+ uid))
392
+ if full_info:
393
+ device_entry.update(full_info)
394
+ except Exception:
395
+ pass
396
+ self._devices[uid] = device_entry
384
397
  except Exception as e:
385
398
  logger.debug(f"Error updating device list: {e}")
386
399
 
@@ -68,13 +68,15 @@ def discover_devices() -> List[Dict[str, Any]]:
68
68
  ser.close()
69
69
  if uid:
70
70
  fw = info.get("FwVersion", "?")
71
+ patch = info.get("PatchVersion", 0xFF)
71
72
  product_id = info.get(
72
73
  "ProductId", BENCHLAB_ORIGINAL_PRODUCT_ID)
73
74
  variant = (
74
75
  "BL2" if product_id == BENCHLAB_BL2_PRODUCT_ID
75
76
  else "ORIGINAL")
76
- devices.append({"uid": uid, "port": port,
77
- "fw": fw, "variant": variant})
77
+ devices.append({
78
+ "uid": uid, "port": port, "fw": fw,
79
+ "PatchVersion": patch, "variant": variant})
78
80
  logger.info(
79
81
  "Discovered BenchLab device UID=%s on %s "
80
82
  "(FW=%s, Variant=%s)",
@@ -17,6 +17,9 @@ import logging
17
17
  import os
18
18
  import sys
19
19
  import traceback
20
+ from importlib.metadata import PackageNotFoundError, version
21
+
22
+ from packaging.version import Version
20
23
 
21
24
  from .tools import CONSUMER_TOOLS, LAUNCH_PROFILES # noqa: F401
22
25
  # CONSUMER_TOOLS re-exported for benchlab.main.CONSUMER_TOOLS consumers
@@ -25,6 +28,34 @@ from .launcher import launch_tools_concurrent
25
28
 
26
29
  logger = logging.getLogger("benchlab.launcher")
27
30
 
31
+ # Keep in sync with the "benchlab-pycore>=X.Y.Z" pin in pyproject.toml --
32
+ # this is pytools' own belt-and-suspenders check so a stale pycore install
33
+ # (e.g. an env pip never upgraded) fails with a clear message instead of an
34
+ # ImportError traceback deep in a tool module.
35
+ MIN_PYCORE_VERSION = "0.9.1"
36
+
37
+
38
+ def _check_pycore_version() -> None:
39
+ try:
40
+ installed = version("benchlab-pycore")
41
+ except PackageNotFoundError:
42
+ print(
43
+ "ERROR: benchlab-pycore is not installed.\n"
44
+ "Install it with: pip install "
45
+ f"\"benchlab-pycore>={MIN_PYCORE_VERSION}\"",
46
+ file=sys.stderr)
47
+ sys.exit(1)
48
+
49
+ if Version(installed) < Version(MIN_PYCORE_VERSION):
50
+ print(
51
+ f"ERROR: benchlab-pycore {installed} is installed, but "
52
+ f"pytools requires >={MIN_PYCORE_VERSION}.\n"
53
+ "Upgrade it with: pip install "
54
+ f"\"benchlab-pycore>={MIN_PYCORE_VERSION}\"",
55
+ file=sys.stderr)
56
+ sys.exit(1)
57
+
58
+
28
59
  try:
29
60
  from .menu import interactive_loop
30
61
  except ImportError as e:
@@ -511,6 +542,8 @@ def launch_mode() -> None:
511
542
 
512
543
  def main() -> None:
513
544
  """Entry point."""
545
+ if not ({"-h", "--help", "--version"} & set(sys.argv[1:])):
546
+ _check_pycore_version()
514
547
  launch_mode()
515
548
 
516
549
 
@@ -351,6 +351,7 @@ def device_thread(device, cfg, publish_interval=1):
351
351
  vendor_id = 0
352
352
  product_id = BENCHLAB_ORIGINAL_PRODUCT_ID
353
353
  fw_version = device.get("firmware")
354
+ patch_version = 0xFF
354
355
  try:
355
356
  dev_info = read_device(ser)
356
357
  if dev_info:
@@ -358,6 +359,7 @@ def device_thread(device, cfg, publish_interval=1):
358
359
  product_id = dev_info.get(
359
360
  'ProductId', BENCHLAB_ORIGINAL_PRODUCT_ID)
360
361
  fw_version = dev_info.get('FwVersion', fw_version)
362
+ patch_version = dev_info.get('PatchVersion', 0xFF)
361
363
  except Exception:
362
364
  pass
363
365
  variant = (
@@ -373,6 +375,7 @@ def device_thread(device, cfg, publish_interval=1):
373
375
  "VendorId": vendor_id,
374
376
  "ProductId": product_id,
375
377
  "FwVersion": fw_version,
378
+ "PatchVersion": patch_version,
376
379
  "variant": variant,
377
380
  }
378
381
  topic_info = f"{cfg['topic_prefix']}/{uid}/info"
@@ -606,6 +606,7 @@ def list_devices():
606
606
  "uid": uid,
607
607
  "port": info.get("port", "unknown"),
608
608
  "firmware": device_info.get("FwVersion", "?"),
609
+ "PatchVersion": device_info.get("PatchVersion", 0xFF),
609
610
  "variant": device_info.get("variant", "ORIGINAL"),
610
611
  "VendorId": device_info.get("VendorId", 0),
611
612
  "ProductId": device_info.get("ProductId", 0),
@@ -325,7 +325,8 @@ class Layout:
325
325
  }
326
326
 
327
327
  # Faults tab column positions — two-column grid (17 rows each) so all
328
- # 34 Fault enum members fit on one screen under MIN_TERMINAL_ROWS/COLS.
328
+ # 34 BL2 Fault enum members (or 16 for ORIGINAL fw07+) fit on one
329
+ # screen under MIN_TERMINAL_ROWS/COLS.
329
330
  FAULT_COLS = {
330
331
  'NAME': 2, # Fault name column (left grid column)
331
332
  'ACTIVE': 26, # Active status column (left grid column)
@@ -237,12 +237,15 @@ def test_faults_tab_handles_device_without_fault_data():
237
237
  def test_decode_faults_helper():
238
238
  from benchlab.tui.tui_core import _decode_faults
239
239
 
240
- assert _decode_faults(None) == []
241
- assert _decode_faults(0) == []
242
- assert _decode_faults(1 << 9) == ["OCP_CPU1"]
243
- decoded = _decode_faults((1 << 0) | (1 << 33))
240
+ assert _decode_faults(None, "BL2") == []
241
+ assert _decode_faults(0, "BL2") == []
242
+ assert _decode_faults(1 << 9, "BL2") == ["OCP_CPU1"]
243
+ decoded = _decode_faults((1 << 0) | (1 << 33), "BL2")
244
244
  assert set(decoded) == {"OTP_TCHIP", "CURRENT_IMBALANCE_HPWR2"}
245
245
 
246
+ decoded_original = _decode_faults((1 << 0) | (1 << 10), "ORIGINAL")
247
+ assert set(decoded_original) == {"OTP_TCHIP", "OCP_ATX12V"}
248
+
246
249
 
247
250
  def test_help_modal_renders_without_stomping_main_refresh():
248
251
  """Regression test: help modal must be composited, not overwritten
@@ -13,12 +13,21 @@ from typing import Dict, Any, List, Optional
13
13
 
14
14
  from .config import Config
15
15
  from benchlab.core.statistics import ChannelStats, StatsFormatter
16
- from benchlab_pycore.core import Fault
16
+ from benchlab_pycore.core import Fault, FaultBL2
17
17
 
18
18
  logger = logging.getLogger("benchlab.tui.tui_core")
19
19
 
20
20
 
21
- def _decode_faults(bitmask: Optional[float]) -> List[str]:
21
+ def _fault_enum(variant: str):
22
+ """Return the Fault enum for the given device variant.
23
+
24
+ BL2 has its own 34-member enum (FaultBL2); ORIGINAL (fw07+) uses the
25
+ 16-member Fault enum.
26
+ """
27
+ return FaultBL2 if variant == 'BL2' else Fault
28
+
29
+
30
+ def _decode_faults(bitmask: Optional[float], variant: str) -> List[str]:
22
31
  """Decode a FaultStatus/FaultLog bitmask into a list of Fault names.
23
32
 
24
33
  Returns an empty list for None/0/falsy bitmasks (no faults set).
@@ -26,7 +35,7 @@ def _decode_faults(bitmask: Optional[float]) -> List[str]:
26
35
  if not bitmask:
27
36
  return []
28
37
  bitmask = int(bitmask)
29
- return [f.name for f in Fault if bitmask & (1 << f.value)]
38
+ return [f.name for f in _fault_enum(variant) if bitmask & (1 << f.value)]
30
39
 
31
40
 
32
41
  class TUICore:
@@ -602,6 +611,10 @@ class TUICore:
602
611
  product_id = device_info.get('ProductId', 0)
603
612
  product_str = _hex_str(product_id)
604
613
  fw_str = _hex_str(device_info.get('FwVersion', 0))
614
+ patch = device_info.get('PatchVersion')
615
+ patch_str = (
616
+ "N/A" if patch is None or int(patch) == 0xFF
617
+ else str(int(patch)))
605
618
 
606
619
  variant = device_info.get('variant')
607
620
  if variant is None:
@@ -616,14 +629,15 @@ class TUICore:
616
629
  self.stdscr.addstr(12, 4, f"{'Product ID':<22} {product_str}")
617
630
  self.stdscr.addstr(13, 4, f"{'Device UID':<22} {uid or 'N/A'}")
618
631
  self.stdscr.addstr(14, 4, f"{'Firmware Version':<22} {fw_str}")
632
+ self.stdscr.addstr(15, 4, f"{'Firmware Patch':<22} {patch_str}")
619
633
 
620
- # Quick-glance active-fault warning (BL2 fw05+ only; nothing is
621
- # drawn for ORIGINAL devices or pre-fw05 BL2, where FaultStatus
622
- # is simply absent from sensor_data). Full per-fault detail,
623
- # including latched history, lives on the Faults tab.
634
+ # Quick-glance active-fault warning (BL2 fw05+ / ORIGINAL fw07+
635
+ # only; nothing is drawn where FaultStatus is simply absent from
636
+ # sensor_data). Full per-fault detail, including latched
637
+ # history, lives on the Faults tab.
624
638
  sd = snapshot.get('sensor_data') or {}
625
- if variant == 'BL2' and sd.get('FaultStatus') is not None:
626
- active_faults = _decode_faults(sd.get('FaultStatus'))
639
+ if sd.get('FaultStatus') is not None:
640
+ active_faults = _decode_faults(sd.get('FaultStatus'), variant)
627
641
  if active_faults:
628
642
  names = ", ".join(active_faults)
629
643
  msg = f"Active Faults: {names}"
@@ -632,7 +646,7 @@ class TUICore:
632
646
  msg = (f"{len(active_faults)} active "
633
647
  f"fault(s) — see Faults tab")
634
648
  self.stdscr.addstr(
635
- 16, 4, msg,
649
+ 17, 4, msg,
636
650
  curses.color_pair(Config.COLOR_PAIRS['error']))
637
651
 
638
652
  self._draw_section(18, 2, "TUI")
@@ -1249,13 +1263,9 @@ class TUICore:
1249
1263
  pass
1250
1264
 
1251
1265
  def _render_faults_tab(self, snapshot: Dict[str, Any]):
1252
- """Render Faults tab — all 34 BL2 Fault enum members, live/latched."""
1253
- self._draw_section(4, 2, "Fault Monitoring (BL2)")
1254
-
1255
- if not snapshot.get('connected'):
1256
- self._draw_disconnected("Fault")
1257
- return
1258
-
1266
+ """Render Faults tab — all Fault enum members for the connected
1267
+ device's variant (34 for BL2, 16 for ORIGINAL fw07+), live/latched.
1268
+ """
1259
1269
  sd = snapshot.get('sensor_data') or {}
1260
1270
  device_info = snapshot.get('device_info') or {}
1261
1271
  product_id = device_info.get('ProductId')
@@ -1263,12 +1273,18 @@ class TUICore:
1263
1273
  if variant is None:
1264
1274
  variant = 'BL2' if product_id == 0x11 else 'ORIGINAL'
1265
1275
 
1266
- if variant != 'BL2' or sd.get('FaultStatus') is None:
1276
+ self._draw_section(4, 2, f"Fault Monitoring ({variant})")
1277
+
1278
+ if not snapshot.get('connected'):
1279
+ self._draw_disconnected("Fault")
1280
+ return
1281
+
1282
+ if sd.get('FaultStatus') is None:
1267
1283
  try:
1268
1284
  self.stdscr.addstr(
1269
1285
  6, 4,
1270
1286
  "Fault data unavailable for this device "
1271
- "(BL2 firmware 05+ required).",
1287
+ "(BL2 firmware 05+ or ORIGINAL firmware 07+ required).",
1272
1288
  curses.color_pair(Config.COLOR_PAIRS['default']))
1273
1289
  except curses.error:
1274
1290
  pass
@@ -1292,7 +1308,7 @@ class TUICore:
1292
1308
  except curses.error:
1293
1309
  pass
1294
1310
 
1295
- faults = list(Fault)
1311
+ faults = list(_fault_enum(variant))
1296
1312
  for i, fault in enumerate(faults):
1297
1313
  col_idx = i // rows_per_col
1298
1314
  row = 6 + (i % rows_per_col)
@@ -34,7 +34,7 @@ dependencies = [
34
34
  "packaging>=23.0,<26.0",
35
35
  "python-dotenv>=1.2.2,<2.0",
36
36
  "textual>=0.60,<9.0",
37
- "benchlab-pycore>=0.8.0",
37
+ "benchlab-pycore>=0.9.1",
38
38
  # Import-time dependency of benchlab/config/schema.py, reached by -config,
39
39
  # -flash and the REST API (the #90 chain). -config has no extra of its own,
40
40
  # so pydantic cannot live in one.