bec-widgets 0.59.1__py3-none-any.whl → 0.61.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,18 @@
1
1
  # pylint: disable=missing-module-docstring
2
2
  from __future__ import annotations
3
3
 
4
+ import argparse
5
+ import importlib
4
6
  import inspect
7
+ import os
5
8
  import sys
9
+ from typing import Literal
6
10
 
7
11
  import black
12
+ import isort
13
+ from qtpy.QtWidgets import QGraphicsWidget, QWidget
14
+
15
+ from bec_widgets.utils import BECConnector
8
16
 
9
17
  if sys.version_info >= (3, 11):
10
18
  from typing import get_overloads
@@ -14,30 +22,52 @@ else:
14
22
  "If you want to use the real function 'typing.get_overloads()', please use Python 3.11 or later."
15
23
  )
16
24
 
17
- def get_overloads(obj):
18
- # Dummy function for Python versions before 3.11
25
+ def get_overloads(_obj):
26
+ """
27
+ Dummy function for Python versions before 3.11.
28
+ """
19
29
  return []
20
30
 
21
31
 
22
32
  class ClientGenerator:
23
33
  def __init__(self):
24
34
  self.header = """# This file was automatically generated by generate_cli.py\n
25
- from bec_widgets.cli.client_utils import rpc_call, RPCBase, BECGuiClientMixin
26
- from typing import Literal, Optional, overload"""
35
+ import enum
36
+ from typing import Literal, Optional, overload
37
+
38
+ from bec_widgets.cli.client_utils import RPCBase, rpc_call, BECGuiClientMixin
39
+
40
+ # pylint: skip-file"""
27
41
 
28
42
  self.content = ""
29
43
 
30
- def generate_client(self, published_classes: list):
44
+ def generate_client(
45
+ self, published_classes: dict[Literal["connector_classes", "top_level_classes"], list[type]]
46
+ ):
31
47
  """
32
48
  Generate the client for the published classes.
33
49
 
34
50
  Args:
35
- published_classes(list): The list of published classes (e.g. [BECWaveform1D, BECFigure]).
51
+ published_classes(dict): A dictionary with keys "connector_classes" and "top_level_classes" and values as lists of classes.
36
52
  """
37
- for cls in published_classes:
53
+ self.write_client_enum(published_classes["top_level_classes"])
54
+ for cls in published_classes["connector_classes"]:
38
55
  self.content += "\n\n"
39
56
  self.generate_content_for_class(cls)
40
57
 
58
+ def write_client_enum(self, published_classes: list[type]):
59
+ """
60
+ Write the client enum to the content.
61
+ """
62
+ self.content += """
63
+ class Widgets(str, enum.Enum):
64
+ \"\"\"
65
+ Enum for the available widgets.
66
+ \"\"\"
67
+ """
68
+ for cls in published_classes:
69
+ self.content += f'{cls.__name__} = "{cls.__name__}"\n '
70
+
41
71
  def generate_content_for_class(self, cls):
42
72
  """
43
73
  Generate the content for the class.
@@ -47,11 +77,6 @@ from typing import Literal, Optional, overload"""
47
77
  """
48
78
 
49
79
  class_name = cls.__name__
50
- module = cls.__module__
51
-
52
- # Generate the header
53
- # self.header += f"""
54
- # from {module} import {class_name}"""
55
80
 
56
81
  # Generate the content
57
82
  if cls.__name__ == "BECDockArea":
@@ -101,41 +126,85 @@ class {class_name}(RPCBase):"""
101
126
  except black.NothingChanged:
102
127
  formatted_content = full_content
103
128
 
129
+ isort.Config(
130
+ profile="black",
131
+ line_length=100,
132
+ multi_line_output=3,
133
+ include_trailing_comma=True,
134
+ known_first_party=["bec_widgets"],
135
+ )
136
+ formatted_content = isort.code(formatted_content)
137
+
104
138
  with open(file_name, "w", encoding="utf-8") as file:
105
139
  file.write(formatted_content)
106
140
 
141
+ @staticmethod
142
+ def get_rpc_classes(
143
+ repo_name: str,
144
+ ) -> dict[Literal["connector_classes", "top_level_classes"], list[type]]:
145
+ """
146
+ Get all RPC-enabled classes in the specified repository.
147
+
148
+ Args:
149
+ repo_name(str): The name of the repository.
150
+
151
+ Returns:
152
+ dict: A dictionary with keys "connector_classes" and "top_level_classes" and values as lists of classes.
153
+ """
154
+ connector_classes = []
155
+ top_level_classes = []
156
+ anchor_module = importlib.import_module(f"{repo_name}.widgets")
157
+ directory = os.path.dirname(anchor_module.__file__)
158
+ for root, _, files in sorted(os.walk(directory)):
159
+ for file in files:
160
+ if not file.endswith(".py") or file.startswith("__"):
161
+ continue
162
+
163
+ path = os.path.join(root, file)
164
+ subs = os.path.dirname(os.path.relpath(path, directory)).split("/")
165
+ if len(subs) == 1 and not subs[0]:
166
+ module_name = file.split(".")[0]
167
+ else:
168
+ module_name = ".".join(subs + [file.split(".")[0]])
169
+
170
+ module = importlib.import_module(f"{repo_name}.widgets.{module_name}")
171
+
172
+ for name in dir(module):
173
+ obj = getattr(module, name)
174
+ if not hasattr(obj, "__module__") or obj.__module__ != module.__name__:
175
+ continue
176
+ if isinstance(obj, type) and issubclass(obj, BECConnector):
177
+ connector_classes.append(obj)
178
+ if len(subs) == 1 and (
179
+ issubclass(obj, QWidget) or issubclass(obj, QGraphicsWidget)
180
+ ):
181
+ top_level_classes.append(obj)
182
+
183
+ return {"connector_classes": connector_classes, "top_level_classes": top_level_classes}
184
+
185
+
186
+ def main():
187
+ """
188
+ Main entry point for the script, controlled by command line arguments.
189
+ """
190
+
191
+ parser = argparse.ArgumentParser(description="Auto-generate the client for RPC widgets")
192
+ parser.add_argument("--core", action="store_true", help="Whether to generate the core client")
193
+
194
+ args = parser.parse_args()
195
+
196
+ if args.core:
197
+ current_path = os.path.dirname(__file__)
198
+ client_path = os.path.join(current_path, "client.py")
199
+
200
+ rpc_classes = ClientGenerator.get_rpc_classes("bec_widgets")
201
+ rpc_classes["connector_classes"].sort(key=lambda x: x.__name__)
202
+
203
+ generator = ClientGenerator()
204
+ generator.generate_client(rpc_classes)
205
+ generator.write(client_path)
206
+
107
207
 
108
208
  if __name__ == "__main__": # pragma: no cover
109
- import os
110
-
111
- from bec_widgets.utils import BECConnector
112
- from bec_widgets.widgets import BECDock, BECDockArea, BECFigure, SpiralProgressBar
113
- from bec_widgets.widgets.figure.plots.image.image import BECImageShow
114
- from bec_widgets.widgets.figure.plots.image.image_item import BECImageItem
115
- from bec_widgets.widgets.figure.plots.motor_map.motor_map import BECMotorMap
116
- from bec_widgets.widgets.figure.plots.plot_base import BECPlotBase
117
- from bec_widgets.widgets.figure.plots.waveform.waveform import BECWaveform
118
- from bec_widgets.widgets.figure.plots.waveform.waveform_curve import BECCurve
119
- from bec_widgets.widgets.spiral_progress_bar.ring import Ring
120
- from bec_widgets.widgets.website.website import WebsiteWidget
121
-
122
- current_path = os.path.dirname(__file__)
123
- client_path = os.path.join(current_path, "client.py")
124
- clss = [
125
- BECPlotBase,
126
- BECWaveform,
127
- BECFigure,
128
- BECCurve,
129
- BECImageShow,
130
- BECConnector,
131
- BECImageItem,
132
- BECMotorMap,
133
- BECDock,
134
- BECDockArea,
135
- SpiralProgressBar,
136
- Ring,
137
- WebsiteWidget,
138
- ]
139
- generator = ClientGenerator()
140
- generator.generate_client(clss)
141
- generator.write(client_path)
209
+ sys.argv = ["generate_cli.py", "--core"]
210
+ main()
@@ -23,6 +23,7 @@ class ConnectionConfig(BaseModel):
23
23
  model_config: dict = {"validate_assignment": True}
24
24
 
25
25
  @field_validator("gui_id")
26
+ @classmethod
26
27
  def generate_gui_id(cls, v, values):
27
28
  """Generate a GUI ID if none is provided."""
28
29
  if v is None:
@@ -1,3 +1,4 @@
1
+ from .buttons import StopButton
1
2
  from .dock import BECDock, BECDockArea
2
3
  from .figure import BECFigure, FigureConfig
3
4
  from .scan_control import ScanControl
@@ -0,0 +1 @@
1
+ from .stop_button.stop_button import StopButton
File without changes
@@ -0,0 +1,32 @@
1
+ from qtpy.QtWidgets import QPushButton
2
+
3
+ from bec_widgets.utils import BECConnector
4
+
5
+
6
+ class StopButton(BECConnector, QPushButton):
7
+ """A button that stops the current scan."""
8
+
9
+ def __init__(self, parent=None, client=None, config=None, gui_id=None):
10
+ super().__init__(client=client, config=config, gui_id=gui_id)
11
+ QPushButton.__init__(self, parent=parent)
12
+
13
+ self.get_bec_shortcuts()
14
+ self.setText("Stop")
15
+ self.setStyleSheet("background-color: #cc181e; color: white")
16
+ self.clicked.connect(self.stop_scan)
17
+
18
+ def stop_scan(self):
19
+ """Stop the scan."""
20
+ self.queue.request_scan_abortion()
21
+ self.queue.request_queue_reset()
22
+
23
+
24
+ if __name__ == "__main__": # pragma: no cover
25
+ import sys
26
+
27
+ from qtpy.QtWidgets import QApplication
28
+
29
+ app = QApplication(sys.argv)
30
+ widget = StopButton()
31
+ widget.show()
32
+ sys.exit(app.exec_())
@@ -63,8 +63,6 @@ class BECDock(BECConnector, Dock):
63
63
  super().__init__(client=client, config=config, gui_id=gui_id)
64
64
  Dock.__init__(self, name=name, **kwargs)
65
65
 
66
- self.parent_dock_area = parent_dock_area
67
-
68
66
  # Layout Manager
69
67
  self.layout_manager = GridLayoutManager(self.layout)
70
68
 
@@ -73,8 +71,8 @@ class BECDock(BECConnector, Dock):
73
71
  old_area = source.area
74
72
  self.setOrientation("horizontal", force=True)
75
73
  super().dropEvent(event)
76
- if old_area in self.parent_dock_area.tempAreas and old_area != self.parent_dock_area:
77
- self.parent_dock_area.removeTempArea(old_area)
74
+ if old_area in self.orig_area.tempAreas and old_area != self.orig_area:
75
+ self.orig_area.removeTempArea(old_area)
78
76
 
79
77
  def float(self):
80
78
  """
@@ -129,7 +127,7 @@ class BECDock(BECConnector, Dock):
129
127
  Args:
130
128
  title(str): The title of the dock.
131
129
  """
132
- self.parent_dock_area.docks[title] = self.parent_dock_area.docks.pop(self.name())
130
+ self.orig_area.docks[title] = self.orig_area.docks.pop(self.name())
133
131
  self.setTitle(title)
134
132
  self._name = title
135
133
 
@@ -206,7 +204,7 @@ class BECDock(BECConnector, Dock):
206
204
  """
207
205
  Attach the dock to the parent dock area.
208
206
  """
209
- self.parent_dock_area.removeTempArea(self.area)
207
+ self.orig_area.removeTempArea(self.area)
210
208
 
211
209
  def detach(self):
212
210
  """
@@ -231,7 +229,7 @@ class BECDock(BECConnector, Dock):
231
229
  Remove the dock from the parent dock area.
232
230
  """
233
231
  # self.cleanup()
234
- self.parent_dock_area.remove_dock(self.name())
232
+ self.orig_area.remove_dock(self.name())
235
233
 
236
234
  def cleanup(self):
237
235
  """
@@ -53,7 +53,6 @@ class BECWaveform(BECPlotBase):
53
53
  "set_y_lim",
54
54
  "set_grid",
55
55
  "lock_aspect_ratio",
56
- "plot",
57
56
  "remove",
58
57
  ]
59
58
  scan_signal_update = pyqtSignal()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.59.1
3
+ Version: 0.61.0
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
@@ -9,9 +9,11 @@ Classifier: Development Status :: 3 - Alpha
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Topic :: Scientific/Engineering
11
11
  Requires-Python: >=3.10
12
+ Requires-Dist: bec-ipython-client
12
13
  Requires-Dist: bec-lib
13
14
  Requires-Dist: black
14
15
  Requires-Dist: h5py
16
+ Requires-Dist: isort
15
17
  Requires-Dist: jedi
16
18
  Requires-Dist: pydantic
17
19
  Requires-Dist: pyqtdarktheme
@@ -22,7 +24,6 @@ Requires-Dist: zmq
22
24
  Provides-Extra: dev
23
25
  Requires-Dist: coverage; extra == 'dev'
24
26
  Requires-Dist: fakeredis; extra == 'dev'
25
- Requires-Dist: isort; extra == 'dev'
26
27
  Requires-Dist: pytest; extra == 'dev'
27
28
  Requires-Dist: pytest-qt; extra == 'dev'
28
29
  Requires-Dist: pytest-random-order; extra == 'dev'
@@ -1,12 +1,12 @@
1
1
  .gitignore,sha256=cMQ1MLmnoR88aMCCJwUyfoTnufzl4-ckmHtlFUqHcT4,3253
2
- .gitlab-ci.yml,sha256=WnkyBGO4oXDYAiNbLJn-XDSGVFS6hsDIehgZoy-uykw,8328
2
+ .gitlab-ci.yml,sha256=3PU2LONUl10zIOD4UCPQgA6vVBtniabww1MQkTMce7I,7995
3
3
  .pylintrc,sha256=OstrgmEyP0smNFBKoIN5_26-UmNZgMHnbjvAWX0UrLs,18535
4
4
  .readthedocs.yaml,sha256=aSOc277LqXcsTI6lgvm_JY80lMlr69GbPKgivua2cS0,603
5
- CHANGELOG.md,sha256=ctlX8vTc17QnJS2s0JJx-kKcLa4u_bLWxJYNi9W4jWo,6869
5
+ CHANGELOG.md,sha256=M5IR-g_0B-sq_qGAYP4A8BReh6U9HcGKxeAmMGGjPHs,6792
6
6
  LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
7
- PKG-INFO,sha256=sE4lIC595MOa6CLfcmAXnqV5-NxV08z9zVXJVvhgxCM,1284
7
+ PKG-INFO,sha256=nwiL8DuDWzYjWMcR_JGIZL2uTa8UFyC-NfJHBKxSpEI,1302
8
8
  README.md,sha256=y4jB6wvArS7N8_iTbKWnSM_oRAqLA2GqgzUR-FMh5sU,2645
9
- pyproject.toml,sha256=LnLH2kK3DoWUIuiYT5LMgPOflQZx-URLFkw_18FxgPU,1868
9
+ pyproject.toml,sha256=itvsOSpNTbXMXrClzMA00l9i7ATGsAqrSifK5IB2u5I,2115
10
10
  .git_hooks/pre-commit,sha256=n3RofIZHJl8zfJJIUomcMyYGFi_rwq4CC19z0snz3FI,286
11
11
  .gitlab/issue_templates/bug_report_template.md,sha256=gAuyEwl7XlnebBrkiJ9AqffSNOywmr8vygUFWKTuQeI,386
12
12
  .gitlab/issue_templates/documentation_update_template.md,sha256=FHLdb3TS_D9aL4CYZCjyXSulbaW5mrN2CmwTaeLPbNw,860
@@ -15,11 +15,11 @@ pyproject.toml,sha256=LnLH2kK3DoWUIuiYT5LMgPOflQZx-URLFkw_18FxgPU,1868
15
15
  bec_widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  bec_widgets/assets/bec_widgets_icon.png,sha256=K8dgGwIjalDh9PRHUsSQBqgdX7a00nM3igZdc20pkYM,1747017
17
17
  bec_widgets/assets/terminal_icon.png,sha256=bJl7Tft4Fi2uxvuXI8o14uMHnI9eAWKSU2uftXCH9ws,3889
18
- bec_widgets/cli/__init__.py,sha256=tLD8HWgyURhMjYlKZ43pBu-qvGD1LI5o3n3rEieg-70,43
19
- bec_widgets/cli/auto_updates.py,sha256=0sd7HiqOMn1jCbgVG3-H1nmQgdOMRwSjx6FAvdtVf1k,4747
20
- bec_widgets/cli/client.py,sha256=2Dr7lNrjH2LIslELHO65CLFeW4PB6x0rBSOj1kDQj9E,56486
18
+ bec_widgets/cli/__init__.py,sha256=d0Q6Fn44e7wFfLabDOBxpcJ1DPKWlFunGYDUBmO-4hA,22
19
+ bec_widgets/cli/auto_updates.py,sha256=DyBV3HnjMSH-cvVkYNcDiYKVf0Xut4Qy2qGQqkW47Bw,4833
20
+ bec_widgets/cli/client.py,sha256=6mzmRe_pjuz-3CoBJZkxaa05VzAmPLi_cDJ3uljmw8Y,54363
21
21
  bec_widgets/cli/client_utils.py,sha256=7u8P9EYgLPJuAcHxnFiZi-gCZohO3vAn0W7dqsSrs4M,10660
22
- bec_widgets/cli/generate_cli.py,sha256=Q_8jQP9lZFX89EK42RokLgJjN65cJgG7hjat_5iEb6w,4520
22
+ bec_widgets/cli/generate_cli.py,sha256=DIaGz7nhwef3ebIaP4LtiUC3q7MoM1swJ_e0SgAO2jo,6901
23
23
  bec_widgets/cli/rpc_register.py,sha256=QxXUZu5XNg00Yf5O3UHWOXg3-f_pzKjjoZYMOa-MOJc,2216
24
24
  bec_widgets/cli/rpc_wigdet_handler.py,sha256=VRLujiICU_Gq0mO1Hr15YwjlxU7OcAzqeoM8QHqSubM,1032
25
25
  bec_widgets/cli/server.py,sha256=rsj31Vsx6ayThNe4PQelQFahGjYXFZjfrNyB2fnm6Ro,5737
@@ -31,7 +31,7 @@ bec_widgets/examples/motor_movement/__init__.py,sha256=LzPJkxLAxOsZCbXR-fRCPmeYo
31
31
  bec_widgets/examples/motor_movement/motor_control_compilations.py,sha256=8rpA7a2xVZTDMrx7YQIj3IJew78J1gcVMkHvloS0U_Q,9055
32
32
  bec_widgets/examples/motor_movement/motor_controller.ui,sha256=83XX6NGILwntoUIghvzWnMuGf80O8khK3SduVKTAEFM,29105
33
33
  bec_widgets/utils/__init__.py,sha256=B7OZ2ArjyFaGNh4XYIbk49agnYCz704ltuFSalLCjSA,481
34
- bec_widgets/utils/bec_connector.py,sha256=CLrf30dW-0iYiQo4cwH7qSfsog-1ypfKMjQxJJjKpmw,5340
34
+ bec_widgets/utils/bec_connector.py,sha256=RxHJNF7JjtY5pRbTMu2eQTiRXvoyJ53QuTYxHjZba38,5357
35
35
  bec_widgets/utils/bec_dispatcher.py,sha256=nLdcj2u4dy8-ZR03XioCzr7hBg9Wq4Kw58OU6sDorT4,5593
36
36
  bec_widgets/utils/bec_table.py,sha256=nA2b8ukSeUfquFMAxGrUVOqdrzMoDYD6O_4EYbOG2zk,717
37
37
  bec_widgets/utils/colors.py,sha256=GYSDe0ZxsJSwxvuy-yG2BH17qlf_Sjq8dhDcyp9IhBI,8532
@@ -46,9 +46,12 @@ bec_widgets/utils/ui_loader.py,sha256=5NktcP1r1HQub7K82fW_jkj8rT2cqJQdMvDxwToLY4
46
46
  bec_widgets/utils/validator_delegate.py,sha256=Emj1WF6W8Ke1ruBWUfmHdVJpmOSPezuOt4zvQTay_44,442
47
47
  bec_widgets/utils/widget_io.py,sha256=f36198CvT_EzWQ_cg2G-4tRRsaMdJ3yVqsZWKJCQEfA,10880
48
48
  bec_widgets/utils/yaml_dialog.py,sha256=cMVif-39SB9WjwGH5FWBJcFs4tnfFJFs5cacydRyhy0,1853
49
- bec_widgets/widgets/__init__.py,sha256=LKgIuY3CI-NHCa_bY9pThYhxLH0MHDo8iNEJDDVIVmw,172
49
+ bec_widgets/widgets/__init__.py,sha256=2GykeIg8_dqly6ZYny8HC7OGNpmafXXV3WN61vYGvzk,204
50
+ bec_widgets/widgets/buttons/__init__.py,sha256=74ucIRU6-anoqQ-zT7wbrysmxhg_3_04xGhN_kllNUI,48
51
+ bec_widgets/widgets/buttons/stop_button/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ bec_widgets/widgets/buttons/stop_button/stop_button.py,sha256=x4a7RvlMkHzOd05zKOGYkyTmBza7Me7jgOL9WIgA_c4,906
50
53
  bec_widgets/widgets/dock/__init__.py,sha256=B7foHt02gnhM7mFksa7GJVwT7n0j_JvYDCt6wc6XR5g,61
51
- bec_widgets/widgets/dock/dock.py,sha256=npSJijKdaPZk6T4LrWQ-Q8PfJMgIniqo1UYLahPowA0,7695
54
+ bec_widgets/widgets/dock/dock.py,sha256=WPanKj6nodVP6PiEFkRTCj5Lf0pUupmM7i-5qZA_ATY,7596
52
55
  bec_widgets/widgets/dock/dock_area.py,sha256=9c_tLzyBRllLfc4H5o9-4bvasWp5hWe1NWg4mupXVtU,7911
53
56
  bec_widgets/widgets/figure/__init__.py,sha256=3hGx_KOV7QHCYAV06aNuUgKq4QIYCjUTad-DrwkUaBM,44
54
57
  bec_widgets/widgets/figure/figure.py,sha256=O--r3dyeOPXndV2400wpE9lPdBezzd0ZUt7yA2u2n0A,31468
@@ -61,7 +64,7 @@ bec_widgets/widgets/figure/plots/image/image_processor.py,sha256=TOnHbdq9rK5--L5
61
64
  bec_widgets/widgets/figure/plots/motor_map/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
65
  bec_widgets/widgets/figure/plots/motor_map/motor_map.py,sha256=Ff2WoNHxO_A3ggsbSd_AVUP1JeOWMuJs-0GLskxn-94,15267
63
66
  bec_widgets/widgets/figure/plots/waveform/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
- bec_widgets/widgets/figure/plots/waveform/waveform.py,sha256=xJkBsl1FIWBWsGaC_7nTy44ztp4xaJX-uAYU0MmV7Oc,23506
67
+ bec_widgets/widgets/figure/plots/waveform/waveform.py,sha256=f9YpsNufcICvZyDgcVujzdszdsh0_9gzvnRbpwZroLA,23490
65
68
  bec_widgets/widgets/figure/plots/waveform/waveform_curve.py,sha256=lTyeCydzvrcdvQXc89jEjoor-Uvo54i197-_M4VtqX8,7970
66
69
  bec_widgets/widgets/jupyter_console/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
70
  bec_widgets/widgets/jupyter_console/jupyter_console.py,sha256=ioLYJL31RdBoAOGFSS8PVSnUhkWPWmLC3tiKp7CouO8,2251
@@ -118,6 +121,7 @@ docs/user/getting_started/installation.md,sha256=nBl2Hfvo6ua3-tVZn1B-UG0hCTlrFY6
118
121
  docs/user/getting_started/quick_start.md,sha256=VGU880GwamcIZcBE8tjxuqX2syE-71jqZedtskCoBbA,9405
119
122
  docs/user/widgets/BECFigure.png,sha256=8dQr4u0uk_y0VV-R1Jh9yTR3Vidd9HDEno_07R0swaE,1605920
120
123
  docs/user/widgets/bec_figure.md,sha256=BwcumbhZd6a2zKmoHTvwKr8kG8WxBx9lS_QwxNiBMpQ,5155
124
+ docs/user/widgets/buttons.md,sha256=SKxhLsu_gquNSG-zMAzVzz2d6bUwtZ9y259ILoMyCu0,1214
121
125
  docs/user/widgets/image_plot.gif,sha256=_mVFhMTXGqwDOcEtrBHMZj5Thn2sLhDAHEeL2XyHN-s,14098977
122
126
  docs/user/widgets/motor.gif,sha256=FtaWdRHx4UZaGJPpq8LNhMMgX4PFcAB6IZ93JCMEh_w,2280719
123
127
  docs/user/widgets/progress_bar.gif,sha256=5jh0Zw2BBGPuNxszV1DBLJCb4_6glIRX-U2ABjnsK2k,5263592
@@ -125,11 +129,11 @@ docs/user/widgets/scatter_2D.gif,sha256=yHpsuAUseMafJjI_J5BcOhmE3nu9VFn_Xm9XHzJa
125
129
  docs/user/widgets/spiral_progress_bar.md,sha256=QTgUDIl6XPuK_HwSfB6sNijZ4bss26biDg6B_mJ8Pxk,2208
126
130
  docs/user/widgets/w1D.gif,sha256=tuHbleJpl6bJFNNC2OdndF5LF7IyfvlkFCMGZajrQPs,622773
127
131
  docs/user/widgets/website.md,sha256=wfudAupdtHX-Sfritg0xMWXZLLczJ4XwMLNWvu6ww-w,705
128
- docs/user/widgets/widgets.md,sha256=05D8R97KU84vz64G_Rm8Uu8nXy098ZRkMhNG8-Lc8Ng,361
132
+ docs/user/widgets/widgets.md,sha256=EfrElcZVh9jHt_0kIXdDtc7z3ErYGqwmVMxC_AHSGU0,370
129
133
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
130
134
  tests/end-2-end/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
131
135
  tests/end-2-end/conftest.py,sha256=taLqiYVzOhJjMre5ypgQjB7wzSXP4soKANW3XfAjems,1773
132
- tests/end-2-end/test_bec_dock_rpc_e2e.py,sha256=G-YBfOhJCyV6g74mxXuhAPA9E_BPQ6EUT6xS278aq34,8865
136
+ tests/end-2-end/test_bec_dock_rpc_e2e.py,sha256=8iJz4lITspY7eHdSgy9YvGUGTu3fsSperoVGBvTGT0U,9067
133
137
  tests/end-2-end/test_bec_figure_rpc_e2e.py,sha256=zTbB_F4Fs-QG8KhMK24xfsrCQBgZUAguMk3KFdEdP2o,5095
134
138
  tests/end-2-end/test_rpc_register_e2e.py,sha256=3dfCnSvdcRO92pzHt9WlCTK0vzTKAvPtliEoEKrtuzQ,1604
135
139
  tests/unit_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -143,12 +147,13 @@ tests/unit_tests/test_bec_motor_map.py,sha256=AfD_9-x6VV3TPnkQgNfFYRndPHDsGx-a_Y
143
147
  tests/unit_tests/test_client_utils.py,sha256=eViJ1Tz-HX9TkMvQH6W8cO-c3_1I8bUc4_Yen6LOc0E,830
144
148
  tests/unit_tests/test_color_validation.py,sha256=csdvVKAohENZIRY-JQ97Hv-TShb1erj4oKMX7QRwo78,1883
145
149
  tests/unit_tests/test_crosshair.py,sha256=3OMAJ2ZaISYXMOtkXf1rPdy94vCr8njeLi6uHblBL9Q,5045
146
- tests/unit_tests/test_generate_cli_client.py,sha256=J7CFoO67txGu_u1Mwk32EejRX204FRuvmVg_yhAr1WM,2397
150
+ tests/unit_tests/test_generate_cli_client.py,sha256=GmCLpyRWx5aREb66Api9T-OUpYE1wKgI4hhjUepYrvg,3408
147
151
  tests/unit_tests/test_motor_control.py,sha256=NBekcGALo5mYkuyBJvBhvJkWiQDV82hI4GmsobRzjTI,20770
148
152
  tests/unit_tests/test_plot_base.py,sha256=bOdlgAxh9oKk5PwiQ_MSFmzr44uJ61Tlg242RCIhl5c,2610
149
153
  tests/unit_tests/test_rpc_register.py,sha256=hECjZEimd440mwRrO0rg7L3PKN7__3DgjmESN6wx3bo,1179
150
154
  tests/unit_tests/test_scan_control.py,sha256=7dtGpE0g4FqUhhQeCkyJl-9o7NH3DFZJgEaqDmBYbBc,7551
151
155
  tests/unit_tests/test_spiral_progress_bar.py,sha256=yak3N9-TmEM3lQZPSROL4cAx9mior__se1XADlMScks,12418
156
+ tests/unit_tests/test_stop_button.py,sha256=hOoWO0emkvd5bR_EExxCnKsiZgXKqf_uIGTwzWLxhDw,704
152
157
  tests/unit_tests/test_waveform1d.py,sha256=j9-CCE0BkFVI3Gnv8pjV1gc9HwA5PYG0_ox1oZ60F6w,15272
153
158
  tests/unit_tests/test_website_widget.py,sha256=fBADIJJBAHU4Ro7u95kdemFVNv196UOcuO9oLHuHt8A,761
154
159
  tests/unit_tests/test_widget_io.py,sha256=FeL3ZYSBQnRt6jxj8VGYw1cmcicRQyHKleahw7XIyR0,3475
@@ -158,7 +163,8 @@ tests/unit_tests/test_configs/config_device_no_entry.yaml,sha256=hdvue9KLc_kfNzG
158
163
  tests/unit_tests/test_configs/config_scan.yaml,sha256=vo484BbWOjA_e-h6bTjSV9k7QaQHrlAvx-z8wtY-P4E,1915
159
164
  tests/unit_tests/test_msgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
160
165
  tests/unit_tests/test_msgs/available_scans_message.py,sha256=m_z97hIrjHXXMa2Ex-UvsPmTxOYXfjxyJaGkIY6StTY,46532
161
- bec_widgets-0.59.1.dist-info/METADATA,sha256=sE4lIC595MOa6CLfcmAXnqV5-NxV08z9zVXJVvhgxCM,1284
162
- bec_widgets-0.59.1.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
163
- bec_widgets-0.59.1.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
164
- bec_widgets-0.59.1.dist-info/RECORD,,
166
+ bec_widgets-0.61.0.dist-info/METADATA,sha256=nwiL8DuDWzYjWMcR_JGIZL2uTa8UFyC-NfJHBKxSpEI,1302
167
+ bec_widgets-0.61.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
168
+ bec_widgets-0.61.0.dist-info/entry_points.txt,sha256=80s2YKCNziN2ROUYbpDRyEmiejMf_dshmiYCdN7qNsU,70
169
+ bec_widgets-0.61.0.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
170
+ bec_widgets-0.61.0.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ bw-generate-cli = bec_widgets.cli.generate_cli:main
@@ -0,0 +1,38 @@
1
+ (user.widgets.buttons)=
2
+
3
+ # Buttons Widgets
4
+
5
+ This section consolidates various custom buttons used within the BEC GUIs, facilitating the integration of these
6
+ controls into different layouts.
7
+
8
+ ## Stop Button
9
+
10
+ **Purpose:**
11
+
12
+ The `Stop Button` provides a user interface control to immediately halt the execution of the current operation in the
13
+ BEC Client. It is designed for easy integration into any BEC GUI layout.
14
+
15
+ **Key Features:**
16
+
17
+ - **Immediate Termination:** Halts the execution of the current script or process.
18
+ - **Queue Management:** Clears any pending operations in the scan queue, ensuring the system is ready for new tasks.
19
+
20
+ **Code example:**
21
+
22
+ Integrating the `StopButton` into a BEC GUI layout is straightforward. The following example demonstrates how to embed
23
+ a `StopButton` within a GUI layout:
24
+
25
+ ```python
26
+ from qtpy.QtWidgets import QWidget, QVBoxLayout
27
+ from bec_widgets.widgets import StopButton
28
+
29
+
30
+ class MyGui(QWidget):
31
+ def __init__(self):
32
+ super().__init__()
33
+ self.setLayout(QVBoxLayout(self)) # Initialize the layout for the widget
34
+
35
+ # Create and add the StopButton to the layout
36
+ self.stop_button = StopButton()
37
+ self.layout().addWidget(self.stop_button)
38
+ ```
@@ -11,6 +11,7 @@ hidden: false
11
11
  bec_figure/
12
12
  spiral_progress_bar/
13
13
  website/
14
+ buttons/
14
15
  ```
15
16
 
16
17
 
pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bec_widgets"
7
- version = "0.59.1"
7
+ version = "0.61.0"
8
8
  description = "BEC Widgets"
9
9
  requires-python = ">=3.10"
10
10
  classifiers = [
@@ -19,10 +19,12 @@ dependencies = [
19
19
  "qtpy",
20
20
  "pyqtgraph",
21
21
  "bec_lib",
22
+ "bec_ipython_client", # needed for jupyter widget
22
23
  "zmq",
23
24
  "h5py",
24
25
  "pyqtdarktheme",
25
- "black",
26
+ "black", # needed for bw-generate-cli
27
+ "isort", # needed for bw-generate-cli
26
28
  ]
27
29
 
28
30
 
@@ -34,7 +36,6 @@ dev = [
34
36
  "pytest-xvfb",
35
37
  "coverage",
36
38
  "pytest-qt",
37
- "isort",
38
39
  "fakeredis",
39
40
  ]
40
41
  pyqt5 = ["PyQt5>=5.9", "PyQtWebEngine>=5.9"]
@@ -45,6 +46,9 @@ pyside6 = ["PySide6>=6.7"]
45
46
  "Bug Tracker" = "https://gitlab.psi.ch/bec/bec_widgets/issues"
46
47
  Homepage = "https://gitlab.psi.ch/bec/bec_widgets"
47
48
 
49
+ [project.scripts]
50
+ bw-generate-cli = "bec_widgets.cli.generate_cli:main"
51
+
48
52
  [tool.hatch.build.targets.wheel]
49
53
  include = ["*"]
50
54
 
@@ -57,6 +61,7 @@ profile = "black"
57
61
  line_length = 100
58
62
  multi_line_output = 3
59
63
  include_trailing_comma = true
64
+ known_first_party = ["bec_widgets"]
60
65
 
61
66
  [tool.semantic_release]
62
67
  build_command = "python -m build"
@@ -253,8 +253,14 @@ def test_auto_update(bec_client_lib, rpc_server_dock):
253
253
  plt_data = widgets[0].get_all_data()
254
254
 
255
255
  # check plotted data
256
- assert plt_data["bpm4i-bpm4i"]["x"] == last_scan_data["samx"]["samx"].val
257
- assert plt_data["bpm4i-bpm4i"]["y"] == last_scan_data["bpm4i"]["bpm4i"].val
256
+ assert (
257
+ plt_data[f"Scan {status.scan.scan_number} - bpm4i"]["x"]
258
+ == last_scan_data["samx"]["samx"].val
259
+ )
260
+ assert (
261
+ plt_data[f"Scan {status.scan.scan_number} - bpm4i"]["y"]
262
+ == last_scan_data["bpm4i"]["bpm4i"].val
263
+ )
258
264
 
259
265
  status = scans.grid_scan(
260
266
  dev.samx, -10, 10, 5, dev.samy, -5, 5, 5, exp_time=0.05, relative=False
@@ -268,5 +274,11 @@ def test_auto_update(bec_client_lib, rpc_server_dock):
268
274
  last_scan_data = queue.scan_storage.storage[-1].data
269
275
 
270
276
  # check plotted data
271
- assert plt_data[f"Scan {status.scan.scan_number}"]["x"] == last_scan_data["samx"]["samx"].val
272
- assert plt_data[f"Scan {status.scan.scan_number}"]["y"] == last_scan_data["samy"]["samy"].val
277
+ assert (
278
+ plt_data[f"Scan {status.scan.scan_number} - {dock.selected_device}"]["x"]
279
+ == last_scan_data["samx"]["samx"].val
280
+ )
281
+ assert (
282
+ plt_data[f"Scan {status.scan.scan_number} - {dock.selected_device}"]["y"]
283
+ == last_scan_data["samy"]["samy"].val
284
+ )