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.
- .gitlab-ci.yml +25 -23
- CHANGELOG.md +54 -51
- PKG-INFO +3 -2
- bec_widgets/cli/__init__.py +1 -1
- bec_widgets/cli/auto_updates.py +5 -3
- bec_widgets/cli/client.py +562 -639
- bec_widgets/cli/generate_cli.py +114 -45
- bec_widgets/utils/bec_connector.py +1 -0
- bec_widgets/widgets/__init__.py +1 -0
- bec_widgets/widgets/buttons/__init__.py +1 -0
- bec_widgets/widgets/buttons/stop_button/__init__.py +0 -0
- bec_widgets/widgets/buttons/stop_button/stop_button.py +32 -0
- bec_widgets/widgets/dock/dock.py +5 -7
- bec_widgets/widgets/figure/plots/waveform/waveform.py +0 -1
- {bec_widgets-0.59.1.dist-info → bec_widgets-0.61.0.dist-info}/METADATA +3 -2
- {bec_widgets-0.59.1.dist-info → bec_widgets-0.61.0.dist-info}/RECORD +25 -19
- bec_widgets-0.61.0.dist-info/entry_points.txt +2 -0
- docs/user/widgets/buttons.md +38 -0
- docs/user/widgets/widgets.md +1 -0
- pyproject.toml +8 -3
- tests/end-2-end/test_bec_dock_rpc_e2e.py +16 -4
- tests/unit_tests/test_generate_cli_client.py +37 -5
- tests/unit_tests/test_stop_button.py +25 -0
- {bec_widgets-0.59.1.dist-info → bec_widgets-0.61.0.dist-info}/WHEEL +0 -0
- {bec_widgets-0.59.1.dist-info → bec_widgets-0.61.0.dist-info}/licenses/LICENSE +0 -0
bec_widgets/cli/generate_cli.py
CHANGED
@@ -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(
|
18
|
-
|
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
|
-
|
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(
|
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(
|
51
|
+
published_classes(dict): A dictionary with keys "connector_classes" and "top_level_classes" and values as lists of classes.
|
36
52
|
"""
|
37
|
-
|
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
|
-
|
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()
|
bec_widgets/widgets/__init__.py
CHANGED
@@ -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_())
|
bec_widgets/widgets/dock/dock.py
CHANGED
@@ -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.
|
77
|
-
self.
|
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.
|
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.
|
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.
|
232
|
+
self.orig_area.remove_dock(self.name())
|
235
233
|
|
236
234
|
def cleanup(self):
|
237
235
|
"""
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: bec_widgets
|
3
|
-
Version: 0.
|
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=
|
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=
|
5
|
+
CHANGELOG.md,sha256=M5IR-g_0B-sq_qGAYP4A8BReh6U9HcGKxeAmMGGjPHs,6792
|
6
6
|
LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
|
7
|
-
PKG-INFO,sha256=
|
7
|
+
PKG-INFO,sha256=nwiL8DuDWzYjWMcR_JGIZL2uTa8UFyC-NfJHBKxSpEI,1302
|
8
8
|
README.md,sha256=y4jB6wvArS7N8_iTbKWnSM_oRAqLA2GqgzUR-FMh5sU,2645
|
9
|
-
pyproject.toml,sha256=
|
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=
|
19
|
-
bec_widgets/cli/auto_updates.py,sha256=
|
20
|
-
bec_widgets/cli/client.py,sha256=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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.
|
162
|
-
bec_widgets-0.
|
163
|
-
bec_widgets-0.
|
164
|
-
bec_widgets-0.
|
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,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
|
+
```
|
docs/user/widgets/widgets.md
CHANGED
pyproject.toml
CHANGED
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "bec_widgets"
|
7
|
-
version = "0.
|
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
|
257
|
-
|
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
|
272
|
-
|
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
|
+
)
|