bec-widgets 0.62.0__tar.gz → 0.63.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 (169) hide show
  1. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/CHANGELOG.md +35 -28
  2. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/PKG-INFO +1 -1
  3. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/cli/client.py +43 -0
  4. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/cli/client_utils.py +38 -71
  5. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/cli/rpc_wigdet_handler.py +2 -0
  6. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/examples/jupyter_console/jupyter_console_window.py +5 -6
  7. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/bec_dispatcher.py +1 -5
  8. bec_widgets-0.63.1/bec_widgets/widgets/text_box/text_box.py +127 -0
  9. bec_widgets-0.63.1/docs/user/widgets/text_box.md +33 -0
  10. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/widgets/widgets.md +1 -0
  11. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/pyproject.toml +1 -1
  12. bec_widgets-0.63.1/tests/unit_tests/test_msgs/__init__.py +0 -0
  13. bec_widgets-0.63.1/tests/unit_tests/test_text_box_widget.py +55 -0
  14. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/.git_hooks/pre-commit +0 -0
  15. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/.gitignore +0 -0
  16. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/.gitlab/issue_templates/bug_report_template.md +0 -0
  17. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/.gitlab/issue_templates/documentation_update_template.md +0 -0
  18. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/.gitlab/issue_templates/feature_request_template.md +0 -0
  19. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/.gitlab/merge_request_templates/default.md +0 -0
  20. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/.gitlab-ci.yml +0 -0
  21. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/.pylintrc +0 -0
  22. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/.readthedocs.yaml +0 -0
  23. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/LICENSE +0 -0
  24. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/README.md +0 -0
  25. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/__init__.py +0 -0
  26. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/assets/bec_widgets_icon.png +0 -0
  27. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/assets/terminal_icon.png +0 -0
  28. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/cli/__init__.py +0 -0
  29. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/cli/auto_updates.py +0 -0
  30. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/cli/generate_cli.py +0 -0
  31. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/cli/rpc_register.py +0 -0
  32. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/cli/server.py +0 -0
  33. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/examples/__init__.py +0 -0
  34. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/examples/jupyter_console/__init__.py +0 -0
  35. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/examples/jupyter_console/jupyter_console_window.ui +0 -0
  36. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/examples/motor_movement/__init__.py +0 -0
  37. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/examples/motor_movement/motor_control_compilations.py +0 -0
  38. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/examples/motor_movement/motor_controller.ui +0 -0
  39. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/__init__.py +0 -0
  40. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/bec_connector.py +0 -0
  41. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/bec_table.py +0 -0
  42. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/colors.py +0 -0
  43. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/container_utils.py +0 -0
  44. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/crosshair.py +0 -0
  45. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/entry_validator.py +0 -0
  46. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/layout_manager.py +0 -0
  47. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/plugin_utils.py +0 -0
  48. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/rpc_decorator.py +0 -0
  49. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/thread_checker.py +0 -0
  50. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/ui_loader.py +0 -0
  51. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/validator_delegate.py +0 -0
  52. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/widget_io.py +0 -0
  53. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/utils/yaml_dialog.py +0 -0
  54. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/__init__.py +0 -0
  55. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/buttons/__init__.py +0 -0
  56. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/buttons/stop_button/__init__.py +0 -0
  57. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/buttons/stop_button/stop_button.py +0 -0
  58. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/dock/__init__.py +0 -0
  59. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/dock/dock.py +0 -0
  60. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/dock/dock_area.py +0 -0
  61. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/figure/__init__.py +0 -0
  62. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/figure/figure.py +0 -0
  63. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/figure/plots/__init__.py +0 -0
  64. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/figure/plots/image/__init__.py +0 -0
  65. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/figure/plots/image/image.py +0 -0
  66. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/figure/plots/image/image_item.py +0 -0
  67. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/figure/plots/image/image_processor.py +0 -0
  68. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/figure/plots/motor_map/__init__.py +0 -0
  69. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/figure/plots/motor_map/motor_map.py +0 -0
  70. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/figure/plots/plot_base.py +0 -0
  71. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/figure/plots/waveform/__init__.py +0 -0
  72. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/figure/plots/waveform/waveform.py +0 -0
  73. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/figure/plots/waveform/waveform_curve.py +0 -0
  74. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/jupyter_console/__init__.py +0 -0
  75. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/jupyter_console/jupyter_console.py +0 -0
  76. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/__init__.py +0 -0
  77. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/motor_control.py +0 -0
  78. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/motor_table/__init__.py +0 -0
  79. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/motor_table/motor_table.py +0 -0
  80. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/motor_table/motor_table.ui +0 -0
  81. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/movement_absolute/__init__.py +0 -0
  82. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/movement_absolute/movement_absolute.py +0 -0
  83. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/movement_absolute/movement_absolute.ui +0 -0
  84. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/movement_relative/__init__.py +0 -0
  85. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/movement_relative/movement_relative.py +0 -0
  86. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/movement_relative/movement_relative.ui +0 -0
  87. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/selection/__init__.py +0 -0
  88. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/selection/selection.py +0 -0
  89. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/motor_control/selection/selection.ui +0 -0
  90. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/scan_control/__init__.py +0 -0
  91. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/scan_control/scan_control.py +0 -0
  92. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/spiral_progress_bar/__init__.py +0 -0
  93. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/spiral_progress_bar/ring.py +0 -0
  94. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/spiral_progress_bar/spiral_progress_bar.py +0 -0
  95. {bec_widgets-0.62.0/bec_widgets/widgets/website → bec_widgets-0.63.1/bec_widgets/widgets/text_box}/__init__.py +0 -0
  96. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/toolbar/__init__.py +0 -0
  97. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/toolbar/toolbar.py +0 -0
  98. {bec_widgets-0.62.0/tests → bec_widgets-0.63.1/bec_widgets/widgets/website}/__init__.py +0 -0
  99. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/bec_widgets/widgets/website/website.py +0 -0
  100. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/Makefile +0 -0
  101. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/_static/custom.css +0 -0
  102. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/_templates/custom-class-template.rst +0 -0
  103. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/_templates/custom-module-template.rst +0 -0
  104. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/api_reference/api_reference.md +0 -0
  105. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/assets/apps_48dp.svg +0 -0
  106. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/assets/display_settings_48dp.svg +0 -0
  107. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/assets/index_api.svg +0 -0
  108. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/assets/index_contribute.svg +0 -0
  109. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/assets/index_getting_started.svg +0 -0
  110. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/assets/index_user_guide.svg +0 -0
  111. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/assets/rocket_launch_48dp.svg +0 -0
  112. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/conf.py +0 -0
  113. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/developer/developer.md +0 -0
  114. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/index.md +0 -0
  115. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/introduction/introduction.md +0 -0
  116. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/make.bat +0 -0
  117. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/requirements.txt +0 -0
  118. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/api_reference/api_reference.md +0 -0
  119. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/applications/applications.md +0 -0
  120. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/customisation.md +0 -0
  121. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/getting_started/BECDockArea.png +0 -0
  122. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/getting_started/auto_updates.md +0 -0
  123. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/getting_started/getting_started.md +0 -0
  124. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/getting_started/gui_complex_gui.gif +0 -0
  125. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/getting_started/installation.md +0 -0
  126. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/getting_started/quick_start.md +0 -0
  127. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/user.md +0 -0
  128. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/widgets/BECFigure.png +0 -0
  129. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/widgets/bec_figure.md +0 -0
  130. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/widgets/buttons.md +0 -0
  131. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/widgets/image_plot.gif +0 -0
  132. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/widgets/motor.gif +0 -0
  133. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/widgets/progress_bar.gif +0 -0
  134. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/widgets/scatter_2D.gif +0 -0
  135. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/widgets/spiral_progress_bar.md +0 -0
  136. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/widgets/w1D.gif +0 -0
  137. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/docs/user/widgets/website.md +0 -0
  138. {bec_widgets-0.62.0/tests/end-2-end → bec_widgets-0.63.1/tests}/__init__.py +0 -0
  139. {bec_widgets-0.62.0/tests/unit_tests → bec_widgets-0.63.1/tests/end-2-end}/__init__.py +0 -0
  140. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/end-2-end/conftest.py +0 -0
  141. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/end-2-end/test_bec_dock_rpc_e2e.py +0 -0
  142. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/end-2-end/test_bec_figure_rpc_e2e.py +0 -0
  143. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/end-2-end/test_rpc_register_e2e.py +0 -0
  144. {bec_widgets-0.62.0/tests/unit_tests/test_msgs → bec_widgets-0.63.1/tests/unit_tests}/__init__.py +0 -0
  145. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/client_mocks.py +0 -0
  146. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/conftest.py +0 -0
  147. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_bec_connector.py +0 -0
  148. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_bec_dispatcher.py +0 -0
  149. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_bec_dock.py +0 -0
  150. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_bec_figure.py +0 -0
  151. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_bec_motor_map.py +0 -0
  152. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_client_utils.py +0 -0
  153. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_color_validation.py +0 -0
  154. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_configs/config_device.yaml +0 -0
  155. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_configs/config_device_no_entry.yaml +0 -0
  156. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_configs/config_scan.yaml +0 -0
  157. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_crosshair.py +0 -0
  158. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_generate_cli_client.py +0 -0
  159. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_motor_control.py +0 -0
  160. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_msgs/available_scans_message.py +0 -0
  161. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_plot_base.py +0 -0
  162. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_rpc_register.py +0 -0
  163. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_scan_control.py +0 -0
  164. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_spiral_progress_bar.py +0 -0
  165. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_stop_button.py +0 -0
  166. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_waveform1d.py +0 -0
  167. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_website_widget.py +0 -0
  168. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_widget_io.py +0 -0
  169. {bec_widgets-0.62.0 → bec_widgets-0.63.1}/tests/unit_tests/test_yaml_dialog.py +0 -0
@@ -2,6 +2,41 @@
2
2
 
3
3
 
4
4
 
5
+ ## v0.63.1 (2024-06-13)
6
+
7
+ ### Fix
8
+
9
+ * fix: just terminate the remote process in close() instead of communicating
10
+
11
+ The proper finalization sequence will be executed by the remote process
12
+ on SIGTERM ([`9263f8e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/9263f8ef5c17ae7a007a1a564baf787b39061756))
13
+
14
+
15
+ ## v0.63.0 (2024-06-13)
16
+
17
+ ### Documentation
18
+
19
+ * docs: add documentation ([`bc709c4`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/bc709c4184c985d4e721f9ea7d1b3dad5e9153a7))
20
+
21
+ ### Feature
22
+
23
+ * feat: add textbox widget ([`d9d4e3c`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/d9d4e3c9bf73ab2a5629c2867b50fc91e69489ec))
24
+
25
+ ### Refactor
26
+
27
+ * refactor: add pydantic config, add change_theme ([`6b8432f`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/6b8432f5b20a71175a3537b5f6832b76e3b67d73))
28
+
29
+ ### Test
30
+
31
+ * test: add test for text box ([`b49462a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/b49462abeb186e56bac79d2ef0b0add1ef28a1a5))
32
+
33
+ ### Unknown
34
+
35
+ * Revert "feat: implement non-polling, interruptible waiting of gui instruction response with timeout"
36
+
37
+ This reverts commit abc6caa2d0b6141dfbe1f3d025f78ae14deddcb3 ([`fe04dd8`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/fe04dd80e59a0e74f7fdea603e0642707ecc7c2a))
38
+
39
+
5
40
  ## v0.62.0 (2024-06-12)
6
41
 
7
42
  ### Feature
@@ -135,31 +170,3 @@
135
170
 
136
171
 
137
172
  ## v0.57.6 (2024-06-06)
138
-
139
- ### Fix
140
-
141
- * fix(bar): docstrings extended ([`edb1775`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/edb1775967c3ff0723d0edad2b764f1ffc832b7c))
142
-
143
-
144
- ## v0.57.5 (2024-06-06)
145
-
146
- ### Documentation
147
-
148
- * docs(figure): docs adjusted to be compatible with new signature ([`c037b87`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/c037b87675af91b26e8c7c60e76622d4ed4cf5d5))
149
-
150
- ### Fix
151
-
152
- * fix(waveform): added .plot method with the same signature as BECFigure.plot ([`8479caf`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8479caf53a7325788ca264e5bd9aee01f1d4c5a0))
153
-
154
- * fix(plot_base): .plot removed from plot_base.py, because there is no use case for it ([`82e2c89`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/82e2c898d2e26f786b2d481f85c647472675e75b))
155
-
156
- ### Refactor
157
-
158
- * refactor(figure): logic for .add_image and .image consolidated; logic for .add_plot and .plot consolidated ([`52bc322`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/52bc322b2b8d3ef92ff3480e61bddaf32464f976))
159
-
160
-
161
- ## v0.57.4 (2024-06-06)
162
-
163
- ### Fix
164
-
165
- * fix(docks): set_title do update dock internal _name now ([`15cbc21`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/15cbc21e5bb3cf85f5822d44a2b3665b5aa2f346))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.62.0
3
+ Version: 0.63.1
4
4
  Summary: BEC Widgets
5
5
  Project-URL: Bug Tracker, https://gitlab.psi.ch/bec/bec_widgets/issues
6
6
  Project-URL: Homepage, https://gitlab.psi.ch/bec/bec_widgets
@@ -17,6 +17,7 @@ class Widgets(str, enum.Enum):
17
17
  BECDockArea = "BECDockArea"
18
18
  BECFigure = "BECFigure"
19
19
  SpiralProgressBar = "SpiralProgressBar"
20
+ TextBox = "TextBox"
20
21
  WebsiteWidget = "WebsiteWidget"
21
22
 
22
23
 
@@ -1897,6 +1898,48 @@ class SpiralProgressBar(RPCBase):
1897
1898
  """
1898
1899
 
1899
1900
 
1901
+ class StopButton(RPCBase):
1902
+ @property
1903
+ @rpc_call
1904
+ def config_dict(self) -> "dict":
1905
+ """
1906
+ Get the configuration of the widget.
1907
+
1908
+ Returns:
1909
+ dict: The configuration of the widget.
1910
+ """
1911
+
1912
+ @rpc_call
1913
+ def get_all_rpc(self) -> "dict":
1914
+ """
1915
+ Get all registered RPC objects.
1916
+ """
1917
+
1918
+
1919
+ class TextBox(RPCBase):
1920
+ @rpc_call
1921
+ def set_color(self, background_color: str, font_color: str) -> None:
1922
+ """
1923
+ Set the background color of the Widget.
1924
+
1925
+ Args:
1926
+ background_color (str): The color to set the background in HEX.
1927
+ font_color (str): The color to set the font in HEX.
1928
+ """
1929
+
1930
+ @rpc_call
1931
+ def set_text(self, text: str) -> None:
1932
+ """
1933
+ Set the text of the Widget
1934
+ """
1935
+
1936
+ @rpc_call
1937
+ def set_font_size(self, size: int) -> None:
1938
+ """
1939
+ Set the font size of the text in the Widget.
1940
+ """
1941
+
1942
+
1900
1943
  class WebsiteWidget(RPCBase):
1901
1944
  @rpc_call
1902
1945
  def set_url(self, url: str) -> None:
@@ -14,7 +14,7 @@ from typing import TYPE_CHECKING
14
14
 
15
15
  from bec_lib.endpoints import MessageEndpoints
16
16
  from bec_lib.utils.import_utils import isinstance_based_on_class_name, lazy_import, lazy_import_from
17
- from qtpy.QtCore import QEventLoop, QSocketNotifier, QTimer
17
+ from qtpy.QtCore import QCoreApplication
18
18
 
19
19
  import bec_widgets.cli.client as client
20
20
  from bec_widgets.cli.auto_updates import AutoUpdates
@@ -24,8 +24,6 @@ if TYPE_CHECKING:
24
24
 
25
25
  from bec_widgets.cli.client import BECDockArea, BECFigure
26
26
 
27
- from bec_lib.serialization import MsgpackSerialization
28
-
29
27
  messages = lazy_import("bec_lib.messages")
30
28
  # from bec_lib.connector import MessageObject
31
29
  MessageObject = lazy_import_from("bec_lib.connector", ("MessageObject",))
@@ -176,16 +174,11 @@ class BECGuiClientMixin:
176
174
  """
177
175
  Close the figure.
178
176
  """
179
- if self._process is None:
180
- return
181
- if self.gui_is_alive():
182
- self._run_rpc("close", (), wait_for_rpc_response=True)
183
- else:
184
- self._run_rpc("close", (), wait_for_rpc_response=False)
185
- self._process.terminate()
186
- self._process_output_processing_thread.join()
187
- self._process = None
188
177
  self._client.shutdown()
178
+ if self._process:
179
+ self._process.terminate()
180
+ self._process_output_processing_thread.join()
181
+ self._process = None
189
182
 
190
183
  def print_log(self) -> None:
191
184
  """
@@ -207,48 +200,6 @@ class RPCResponseTimeoutError(Exception):
207
200
  )
208
201
 
209
202
 
210
- class QtRedisMessageWaiter:
211
- def __init__(self, redis_connector, message_to_wait):
212
- self.ev_loop = QEventLoop()
213
- self.response = None
214
- self.connector = redis_connector
215
- self.message_to_wait = message_to_wait
216
- self.pubsub = redis_connector._redis_conn.pubsub()
217
- self.pubsub.subscribe(self.message_to_wait.endpoint)
218
- fd = self.pubsub.connection._sock.fileno()
219
- self.notifier = QSocketNotifier(fd, QSocketNotifier.Read)
220
- self.notifier.activated.connect(self._pubsub_readable)
221
-
222
- def _msg_received(self, msg_obj):
223
- self.response = msg_obj.value
224
- self.ev_loop.quit()
225
-
226
- def wait(self, timeout=1):
227
- timer = QTimer()
228
- timer.singleShot(timeout * 1000, self.ev_loop.quit)
229
- self.ev_loop.exec_()
230
- timer.stop()
231
- self.notifier.setEnabled(False)
232
- self.pubsub.close()
233
- return self.response
234
-
235
- def _pubsub_readable(self, fd):
236
- while True:
237
- msg = self.pubsub.get_message()
238
- if msg:
239
- if msg["type"] == "subscribe":
240
- # get_message buffers, so we may already have the answer
241
- # let's check...
242
- continue
243
- else:
244
- break
245
- else:
246
- return
247
- channel = msg["channel"].decode()
248
- msg = MessageObject(topic=channel, value=MsgpackSerialization.loads(msg["data"]))
249
- self.connector._execute_callback(self._msg_received, msg, {})
250
-
251
-
252
203
  class RPCBase:
253
204
  def __init__(self, gui_id: str = None, config: dict = None, parent=None) -> None:
254
205
  self._client = BECDispatcher().client
@@ -275,7 +226,7 @@ class RPCBase:
275
226
  parent = parent._parent
276
227
  return parent
277
228
 
278
- def _run_rpc(self, method, *args, wait_for_rpc_response=True, timeout=3, **kwargs):
229
+ def _run_rpc(self, method, *args, wait_for_rpc_response=True, **kwargs):
279
230
  """
280
231
  Run the RPC call.
281
232
 
@@ -297,24 +248,16 @@ class RPCBase:
297
248
 
298
249
  # pylint: disable=protected-access
299
250
  receiver = self._root._gui_id
300
- if wait_for_rpc_response:
301
- redis_msg = QtRedisMessageWaiter(
302
- self._client.connector, MessageEndpoints.gui_instruction_response(request_id)
303
- )
304
-
305
251
  self._client.connector.set_and_publish(MessageEndpoints.gui_instructions(receiver), rpc_msg)
306
252
 
307
- if wait_for_rpc_response:
308
- response = redis_msg.wait(timeout)
309
-
310
- if response is None:
311
- raise RPCResponseTimeoutError(request_id, timeout)
312
-
313
- # get class name
314
- if not response.accepted:
315
- raise ValueError(response.message["error"])
316
- msg_result = response.message.get("result")
317
- return self._create_widget_from_msg_result(msg_result)
253
+ if not wait_for_rpc_response:
254
+ return None
255
+ response = self._wait_for_response(request_id)
256
+ # get class name
257
+ if not response.content["accepted"]:
258
+ raise ValueError(response.content["message"]["error"])
259
+ msg_result = response.content["message"].get("result")
260
+ return self._create_widget_from_msg_result(msg_result)
318
261
 
319
262
  def _create_widget_from_msg_result(self, msg_result):
320
263
  if msg_result is None:
@@ -337,6 +280,30 @@ class RPCBase:
337
280
  return cls(parent=self, **msg_result)
338
281
  return msg_result
339
282
 
283
+ def _wait_for_response(self, request_id: str, timeout: int = 5):
284
+ """
285
+ Wait for the response from the server.
286
+
287
+ Args:
288
+ request_id(str): The request ID.
289
+ timeout(int): The timeout in seconds.
290
+
291
+ Returns:
292
+ The response from the server.
293
+ """
294
+ start_time = time.time()
295
+ response = None
296
+
297
+ while response is None and self.gui_is_alive() and (time.time() - start_time) < timeout:
298
+ response = self._client.connector.get(
299
+ MessageEndpoints.gui_instruction_response(request_id)
300
+ )
301
+ QCoreApplication.processEvents() # keep UI responsive (and execute signals/slots)
302
+ if response is None and (time.time() - start_time) >= timeout:
303
+ raise RPCResponseTimeoutError(request_id, timeout)
304
+
305
+ return response
306
+
340
307
  def gui_is_alive(self):
341
308
  """
342
309
  Check if the GUI is alive.
@@ -1,6 +1,7 @@
1
1
  from bec_widgets.utils import BECConnector
2
2
  from bec_widgets.widgets.figure import BECFigure
3
3
  from bec_widgets.widgets.spiral_progress_bar.spiral_progress_bar import SpiralProgressBar
4
+ from bec_widgets.widgets.text_box.text_box import TextBox
4
5
  from bec_widgets.widgets.website.website import WebsiteWidget
5
6
 
6
7
 
@@ -11,6 +12,7 @@ class RPCWidgetHandler:
11
12
  "BECFigure": BECFigure,
12
13
  "SpiralProgressBar": SpiralProgressBar,
13
14
  "Website": WebsiteWidget,
15
+ "TextBox": TextBox,
14
16
  }
15
17
 
16
18
  @staticmethod
@@ -136,18 +136,17 @@ if __name__ == "__main__": # pragma: no cover
136
136
 
137
137
  module_path = os.path.dirname(bec_widgets.__file__)
138
138
 
139
+ bec_dispatcher = BECDispatcher()
140
+ client = bec_dispatcher.client
141
+ client.start()
142
+
139
143
  app = QApplication(sys.argv)
140
144
  app.setApplicationName("Jupyter Console")
141
145
  app.setApplicationDisplayName("Jupyter Console")
142
- qdarktheme.setup_theme("auto")
146
+ # qdarktheme.setup_theme("auto")
143
147
  icon = QIcon()
144
148
  icon.addFile(os.path.join(module_path, "assets", "terminal_icon.png"), size=QSize(48, 48))
145
149
  app.setWindowIcon(icon)
146
-
147
- bec_dispatcher = BECDispatcher()
148
- client = bec_dispatcher.client
149
- client.start()
150
-
151
150
  win = JupyterConsoleWindow()
152
151
  win.show()
153
152
 
@@ -9,7 +9,7 @@ import redis
9
9
  from bec_lib.client import BECClient
10
10
  from bec_lib.redis_connector import MessageObject, RedisConnector
11
11
  from bec_lib.service_config import ServiceConfig
12
- from qtpy.QtCore import QCoreApplication, QObject
12
+ from qtpy.QtCore import QObject
13
13
  from qtpy.QtCore import Signal as pyqtSignal
14
14
 
15
15
  if TYPE_CHECKING:
@@ -71,7 +71,6 @@ class BECDispatcher:
71
71
 
72
72
  _instance = None
73
73
  _initialized = False
74
- qapp = None
75
74
 
76
75
  def __new__(cls, client=None, config: str = None, *args, **kwargs):
77
76
  if cls._instance is None:
@@ -83,9 +82,6 @@ class BECDispatcher:
83
82
  if self._initialized:
84
83
  return
85
84
 
86
- if not QCoreApplication.instance():
87
- BECDispatcher.qapp = QCoreApplication([])
88
-
89
85
  self._slots = collections.defaultdict(set)
90
86
  self.client = client
91
87
 
@@ -0,0 +1,127 @@
1
+ import re
2
+
3
+ from pydantic import Field, field_validator
4
+ from qtpy.QtWidgets import QTextEdit
5
+
6
+ from bec_widgets.utils.bec_connector import BECConnector, ConnectionConfig
7
+ from bec_widgets.utils.colors import Colors
8
+
9
+
10
+ class TextBoxConfig(ConnectionConfig):
11
+
12
+ theme: str = Field("dark", description="The theme of the figure widget.")
13
+ font_color: str = Field("#FFF", description="The font color of the text")
14
+ background_color: str = Field("#000", description="The background color of the widget.")
15
+ font_size: int = Field(16, description="The font size of the text in the widget.")
16
+ text: str = Field("", description="The text to display in the widget.")
17
+
18
+ @classmethod
19
+ @field_validator("theme")
20
+ def validate_theme(cls, v):
21
+ """Validate the theme of the figure widget."""
22
+ if v not in ["dark", "light"]:
23
+ raise ValueError("Theme must be either 'dark' or 'light'")
24
+ return v
25
+
26
+ _validate_font_color = field_validator("font_color")(Colors.validate_color)
27
+ _validate_background_color = field_validator("background_color")(Colors.validate_color)
28
+
29
+
30
+ class TextBox(BECConnector, QTextEdit):
31
+
32
+ USER_ACCESS = ["set_color", "set_text", "set_font_size"]
33
+
34
+ def __init__(self, text: str = "", parent=None, client=None, config=None, gui_id=None):
35
+ if config is None:
36
+ config = TextBoxConfig(widget_class=self.__class__.__name__)
37
+ else:
38
+ if isinstance(config, dict):
39
+ config = TextBoxConfig(**config)
40
+ self.config = config
41
+ super().__init__(client=client, config=config, gui_id=gui_id)
42
+ QTextEdit.__init__(self, parent=parent)
43
+
44
+ self.config = config
45
+ self.setReadOnly(True)
46
+ self.setGeometry(self.rect())
47
+ self.set_color(self.config.background_color, self.config.font_color)
48
+ if not text:
49
+ text = "<h1>Welcome to the BEC Widget TextBox</h1><p>A widget that allows user to display text in plain and HTML format.</p><p>This is an example of displaying HTML text.</p>"
50
+ self.set_text(text)
51
+
52
+ def change_theme(self) -> None:
53
+ """
54
+ Change the theme of the figure widget.
55
+ """
56
+ if self.config.theme == "dark":
57
+ theme = "light"
58
+ font_color = "#000"
59
+ background_color = "#FFF"
60
+ else:
61
+ theme = "dark"
62
+ font_color = "#FFF"
63
+ background_color = "#000"
64
+ self.config.theme = theme
65
+ self.set_color(background_color, font_color)
66
+
67
+ def set_color(self, background_color: str, font_color: str) -> None:
68
+ """Set the background color of the widget.
69
+
70
+ Args:
71
+ background_color (str): The color to set the background in HEX.
72
+ font_color (str): The color to set the font in HEX.
73
+
74
+ """
75
+ self.config.background_color = background_color
76
+ self.config.font_color = font_color
77
+ self._update_stylesheet()
78
+
79
+ def set_font_size(self, size: int) -> None:
80
+ """Set the font size of the text in the widget.
81
+
82
+ Args:
83
+ size (int): The font size to set.
84
+ """
85
+ self.config.font_size = size
86
+ self._update_stylesheet()
87
+
88
+ def _update_stylesheet(self):
89
+ """Update the stylesheet of the widget."""
90
+ self.setStyleSheet(
91
+ f"background-color: {self.config.background_color}; color: {self.config.font_color}; font-size: {self.config.font_size}px"
92
+ )
93
+
94
+ def set_text(self, text: str) -> None:
95
+ """Set the text of the widget.
96
+
97
+ Args:
98
+ text (str): The text to set.
99
+ """
100
+ if self.is_html(text):
101
+ self.setHtml(text)
102
+ else:
103
+ self.setPlainText(text)
104
+ self.config.text = text
105
+
106
+ def is_html(self, text: str) -> bool:
107
+ """Check if the text contains HTML tags.
108
+
109
+ Args:
110
+ text (str): The text to check.
111
+
112
+ Returns:
113
+ bool: True if the text contains HTML tags, False otherwise.
114
+ """
115
+ return bool(re.search(r"<[a-zA-Z/][^>]*>", text))
116
+
117
+
118
+ if __name__ == "__main__":
119
+ import sys
120
+
121
+ from qtpy.QtWidgets import QApplication
122
+
123
+ app = QApplication(sys.argv)
124
+
125
+ widget = TextBox()
126
+ widget.show()
127
+ sys.exit(app.exec())
@@ -0,0 +1,33 @@
1
+ (user.widgets.text_box)=
2
+ # [Text Box Widget](/api_reference/_autosummary/bec_widgets.cli.client.TextBoxWidget)
3
+ **Purpose:**
4
+
5
+ The Text Box Widget is a widget that allows you to display text within the BEC GUI. The widget can be used to display plain text or HTML text.
6
+
7
+ **Key Features:**
8
+
9
+ - set the text to display.
10
+ - automatically detects if the text is plain text or HTML text.
11
+ - set background color and font color.
12
+
13
+ **Code example:**
14
+
15
+ The following code snipped demonstrates how to create a `TextBox` widget using BEC Widgets within BEC.
16
+ ```python
17
+ text_box = gui.add_dock().add_widget("TextBox")
18
+ # set the text to display
19
+ text_box.set_text("Hello, World!")
20
+ # set the background color and font color
21
+ text_box.set_color(backgroud_color="#FFF", font_color="#000")
22
+ # set the text to display as HTML
23
+ text_box.set_text("<h1>Welcome to BEC Widgets</h1><p>This is an example of displaying <strong>HTML</strong> text.</p>")
24
+ ```
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
@@ -12,6 +12,7 @@ bec_figure/
12
12
  spiral_progress_bar/
13
13
  website/
14
14
  buttons/
15
+ text_box/
15
16
  ```
16
17
 
17
18
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bec_widgets"
7
- version = "0.62.0"
7
+ version = "0.63.1"
8
8
  description = "BEC Widgets"
9
9
  requires-python = ">=3.10"
10
10
  classifiers = [
@@ -0,0 +1,55 @@
1
+ import re
2
+ from unittest import mock
3
+
4
+ import pytest
5
+
6
+ from bec_widgets.widgets.text_box.text_box import TextBox
7
+
8
+ from .client_mocks import mocked_client
9
+
10
+
11
+ @pytest.fixture
12
+ def text_box_widget(qtbot, mocked_client):
13
+ widget = TextBox(client=mocked_client)
14
+ qtbot.addWidget(widget)
15
+ qtbot.waitExposed(widget)
16
+ yield widget
17
+ widget.close()
18
+
19
+
20
+ def test_textbox_widget(text_box_widget):
21
+ """Test the TextBox widget."""
22
+ text = "Hello World!"
23
+ text_box_widget.set_text(text)
24
+ assert text_box_widget.toPlainText() == text
25
+
26
+ text_box_widget.set_color("#FFDDC1", "#123456")
27
+ text_box_widget.set_font_size(20)
28
+ assert (
29
+ text_box_widget.styleSheet() == "background-color: #FFDDC1; color: #123456; font-size: 20px"
30
+ )
31
+ text_box_widget.set_color("white", "blue")
32
+ text_box_widget.set_font_size(14)
33
+ assert text_box_widget.styleSheet() == "background-color: white; color: blue; font-size: 14px"
34
+ text = "<h1>Welcome to PyQt6</h1><p>This is an example of displaying <strong>HTML</strong> text.</p>"
35
+ with mock.patch.object(text_box_widget, "setHtml") as mocked_set_html:
36
+ text_box_widget.set_text(text)
37
+ assert mocked_set_html.call_count == 1
38
+ assert mocked_set_html.call_args == mock.call(text)
39
+
40
+
41
+ def test_textbox_change_theme(text_box_widget):
42
+ """Test change theme functionaility"""
43
+ # Default is dark theme
44
+ text_box_widget.change_theme()
45
+ assert text_box_widget.config.theme == "light"
46
+ assert (
47
+ text_box_widget.styleSheet()
48
+ == f"background-color: #FFF; color: #000; font-size: {text_box_widget.config.font_size}px"
49
+ )
50
+ text_box_widget.change_theme()
51
+ assert text_box_widget.config.theme == "dark"
52
+ assert (
53
+ text_box_widget.styleSheet()
54
+ == f"background-color: #000; color: #FFF; font-size: {text_box_widget.config.font_size}px"
55
+ )
File without changes
File without changes
File without changes
File without changes