bec-widgets 0.75.0__py3-none-any.whl → 0.76.1__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.
- CHANGELOG.md +20 -16
- PKG-INFO +1 -1
- bec_widgets/cli/generate_cli.py +21 -0
- bec_widgets/utils/generate_designer_plugin.py +148 -0
- bec_widgets/utils/plugin_templates/plugin.template +54 -0
- bec_widgets/utils/plugin_templates/register.template +15 -0
- bec_widgets/widgets/ring_progress_bar/ring_progress_bar.py +1 -1
- bec_widgets/widgets/text_box/text_box.py +1 -1
- bec_widgets/widgets/website/website.py +1 -1
- {bec_widgets-0.75.0.dist-info → bec_widgets-0.76.1.dist-info}/METADATA +1 -1
- {bec_widgets-0.75.0.dist-info → bec_widgets-0.76.1.dist-info}/RECORD +16 -12
- pyproject.toml +1 -1
- tests/unit_tests/test_generate_plugin.py +155 -0
- {bec_widgets-0.75.0.dist-info → bec_widgets-0.76.1.dist-info}/WHEEL +0 -0
- {bec_widgets-0.75.0.dist-info → bec_widgets-0.76.1.dist-info}/entry_points.txt +0 -0
- {bec_widgets-0.75.0.dist-info → bec_widgets-0.76.1.dist-info}/licenses/LICENSE +0 -0
CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## v0.76.1 (2024-06-29)
|
4
|
+
|
5
|
+
### Fix
|
6
|
+
|
7
|
+
* fix(plugins): fixes and tests for auto-gen plugins ([`c42511d`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/c42511dd44cc13577e108a6cef3166376e594f54))
|
8
|
+
|
9
|
+
## v0.76.0 (2024-06-28)
|
10
|
+
|
11
|
+
### Feature
|
12
|
+
|
13
|
+
* feat(designer): added support for creating designer plugins automatically ([`c1dd0ee`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/c1dd0ee1906dba1f2e2ae9ce40a84d55c26a1cce))
|
14
|
+
|
15
|
+
### Fix
|
16
|
+
|
17
|
+
* fix: fixed qwidget inheritance for ring progress bar ([`0610d2f`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/0610d2f9f027f8659e7149f2dfbb316ff30e337d))
|
18
|
+
|
19
|
+
### Unknown
|
20
|
+
|
21
|
+
* fix:parent set as first kwarg TextBox and WebsiteWidget ([`a45c407`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a45c4075684b93bfdcee03e5a416b84f61d3bc6f))
|
22
|
+
|
3
23
|
## v0.75.0 (2024-06-26)
|
4
24
|
|
5
25
|
### Feature
|
@@ -110,10 +130,6 @@
|
|
110
130
|
|
111
131
|
## v0.71.0 (2024-06-23)
|
112
132
|
|
113
|
-
### Feature
|
114
|
-
|
115
|
-
* feat(scan_group_box): scan box for args and kwargs separated from ScanControlGUI code ([`d8cf441`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/d8cf44134c30063e586771f9068947fef7a306d1))
|
116
|
-
|
117
133
|
### Fix
|
118
134
|
|
119
135
|
* fix(cleanup): cleanup added to device_input widgets and scan_control ([`8badb6a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8badb6adc1d003dbf0b2b1a800c34821f3fc9aa3))
|
@@ -126,16 +142,6 @@
|
|
126
142
|
|
127
143
|
* fix(scan_control): only scans with defined gui_config are allowed ([`6dff187`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/6dff1879c4178df0f8ebfd35101acdebb028d572))
|
128
144
|
|
129
|
-
* fix(WidgetIO): find handlers within base classes ([`ca85638`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/ca856384f380dabf28d43f1cd48511af784c035b))
|
130
|
-
|
131
|
-
* fix(scan_control): adapted widget to scan BEC gui config ([`8b822e0`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8b822e0fa8e28f080b9a4bf81948a7280a4c07bf))
|
132
|
-
|
133
|
-
* fix(scan_control): scan_control.py combatible with the newest BEC versions, test disabled ([`67d398c`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/67d398caf74e08ab25a70cc5d85a5f0c2de8212d))
|
134
|
-
|
135
|
-
### Refactor
|
136
|
-
|
137
|
-
* refactor(device_line_edit): renamed default_device to default ([`4e2c9df`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/4e2c9df6a4979d935285fd7eba17fd7fd455a35c))
|
138
|
-
|
139
145
|
### Test
|
140
146
|
|
141
147
|
* test(scan_control): tests added ([`56e74a0`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/56e74a0e7da72d18e89bc30d1896dbf9ef97cd6b))
|
@@ -149,5 +155,3 @@
|
|
149
155
|
* fix(device_line_edit):SizePolicy fixed for 100 horizontal ([`21d20e0`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/21d20e0fc78e9a3853abe802733388cce119ce20))
|
150
156
|
|
151
157
|
* tests WIP ([`c09644b`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/c09644b29ddb291c91dc58bcd6ebf02ff45cab36))
|
152
|
-
|
153
|
-
## v0.70.0 (2024-06-21)
|
PKG-INFO
CHANGED
bec_widgets/cli/generate_cli.py
CHANGED
@@ -10,6 +10,7 @@ from typing import Literal
|
|
10
10
|
import black
|
11
11
|
import isort
|
12
12
|
|
13
|
+
from bec_widgets.utils.generate_designer_plugin import DesignerPluginGenerator
|
13
14
|
from bec_widgets.utils.plugin_utils import get_rpc_classes
|
14
15
|
|
15
16
|
if sys.version_info >= (3, 11):
|
@@ -161,6 +162,26 @@ def main():
|
|
161
162
|
generator.generate_client(rpc_classes)
|
162
163
|
generator.write(client_path)
|
163
164
|
|
165
|
+
for cls in rpc_classes["top_level_classes"]:
|
166
|
+
plugin = DesignerPluginGenerator(cls)
|
167
|
+
if not hasattr(plugin, "info"):
|
168
|
+
continue
|
169
|
+
|
170
|
+
# if the class directory already has a register, plugin and pyproject file, skip
|
171
|
+
if os.path.exists(
|
172
|
+
os.path.join(plugin.info.base_path, f"register_{plugin.info.plugin_name_snake}.py")
|
173
|
+
):
|
174
|
+
continue
|
175
|
+
if os.path.exists(
|
176
|
+
os.path.join(plugin.info.base_path, f"{plugin.info.plugin_name_snake}_plugin.py")
|
177
|
+
):
|
178
|
+
continue
|
179
|
+
if os.path.exists(
|
180
|
+
os.path.join(plugin.info.base_path, f"{plugin.info.plugin_name_snake}.pyproject")
|
181
|
+
):
|
182
|
+
continue
|
183
|
+
plugin.run()
|
184
|
+
|
164
185
|
|
165
186
|
if __name__ == "__main__": # pragma: no cover
|
166
187
|
sys.argv = ["generate_cli.py", "--core"]
|
@@ -0,0 +1,148 @@
|
|
1
|
+
import inspect
|
2
|
+
import os
|
3
|
+
import re
|
4
|
+
|
5
|
+
from qtpy.QtCore import QObject
|
6
|
+
|
7
|
+
EXCLUDED_PLUGINS = ["BECConnector", "BECDockArea", "BECDock"]
|
8
|
+
|
9
|
+
|
10
|
+
class DesignerPluginInfo:
|
11
|
+
def __init__(self, plugin_class):
|
12
|
+
self.plugin_class = plugin_class
|
13
|
+
self.plugin_name_pascal = plugin_class.__name__
|
14
|
+
self.plugin_name_snake = self.pascal_to_snake(self.plugin_name_pascal)
|
15
|
+
self.widget_import = f"from {plugin_class.__module__} import {self.plugin_name_pascal}"
|
16
|
+
plugin_module = (
|
17
|
+
".".join(plugin_class.__module__.split(".")[:-1]) + f".{self.plugin_name_snake}_plugin"
|
18
|
+
)
|
19
|
+
self.plugin_import = f"from {plugin_module} import {self.plugin_name_pascal}Plugin"
|
20
|
+
|
21
|
+
# first sentence / line of the docstring is used as tooltip
|
22
|
+
self.plugin_tooltip = (
|
23
|
+
plugin_class.__doc__.split("\n")[0].strip().replace('"', "'")
|
24
|
+
if plugin_class.__doc__
|
25
|
+
else self.plugin_name_pascal
|
26
|
+
)
|
27
|
+
|
28
|
+
self.base_path = os.path.dirname(inspect.getfile(plugin_class))
|
29
|
+
|
30
|
+
@staticmethod
|
31
|
+
def pascal_to_snake(name: str) -> str:
|
32
|
+
"""
|
33
|
+
Convert PascalCase to snake_case.
|
34
|
+
|
35
|
+
Args:
|
36
|
+
name (str): The name to be converted.
|
37
|
+
|
38
|
+
Returns:
|
39
|
+
str: The converted name.
|
40
|
+
"""
|
41
|
+
s1 = re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", name)
|
42
|
+
s2 = re.sub(r"([A-Z]+)([A-Z][a-z])", r"\1_\2", s1)
|
43
|
+
return s2.lower()
|
44
|
+
|
45
|
+
|
46
|
+
class DesignerPluginGenerator:
|
47
|
+
def __init__(self, widget: type):
|
48
|
+
self._excluded = False
|
49
|
+
self.widget = widget
|
50
|
+
self.info = DesignerPluginInfo(widget)
|
51
|
+
if widget.__name__ in EXCLUDED_PLUGINS:
|
52
|
+
|
53
|
+
self._excluded = True
|
54
|
+
return
|
55
|
+
|
56
|
+
self.templates = {}
|
57
|
+
self.template_path = os.path.join(
|
58
|
+
os.path.dirname(os.path.abspath(__file__)), "plugin_templates"
|
59
|
+
)
|
60
|
+
|
61
|
+
def run(self):
|
62
|
+
if self._excluded:
|
63
|
+
print(f"Plugin {self.widget.__name__} is excluded from generation.")
|
64
|
+
return
|
65
|
+
self._check_class_validity()
|
66
|
+
self._load_templates()
|
67
|
+
self._write_templates()
|
68
|
+
|
69
|
+
def _check_class_validity(self):
|
70
|
+
|
71
|
+
# Check if the widget is a QWidget subclass
|
72
|
+
if not issubclass(self.widget, QObject):
|
73
|
+
return
|
74
|
+
|
75
|
+
# Check if the widget class has parent as the first argument. This is a strict requirement of Qt!
|
76
|
+
signature = list(inspect.signature(self.widget.__init__).parameters.values())
|
77
|
+
if len(signature) == 1 or signature[1].name != "parent":
|
78
|
+
raise ValueError(
|
79
|
+
f"Widget class {self.widget.__name__} must have parent as the first argument."
|
80
|
+
)
|
81
|
+
|
82
|
+
base_cls = [val for val in self.widget.__bases__ if issubclass(val, QObject)]
|
83
|
+
if not base_cls:
|
84
|
+
raise ValueError(
|
85
|
+
f"Widget class {self.widget.__name__} must inherit from a QObject subclass."
|
86
|
+
)
|
87
|
+
|
88
|
+
# Check if the widget class calls the super constructor with parent argument
|
89
|
+
init_source = inspect.getsource(self.widget.__init__)
|
90
|
+
cls_init_found = (
|
91
|
+
bool(init_source.find(f"{base_cls[0].__name__}.__init__(self, parent=parent") > 0)
|
92
|
+
or bool(init_source.find(f"{base_cls[0].__name__}.__init__(self, parent)") > 0)
|
93
|
+
or bool(init_source.find(f"{base_cls[0].__name__}.__init__(self, parent,") > 0)
|
94
|
+
)
|
95
|
+
super_init_found = (
|
96
|
+
bool(
|
97
|
+
init_source.find(f"super({base_cls[0].__name__}, self).__init__(parent=parent") > 0
|
98
|
+
)
|
99
|
+
or bool(init_source.find(f"super({base_cls[0].__name__}, self).__init__(parent,") > 0)
|
100
|
+
or bool(init_source.find(f"super({base_cls[0].__name__}, self).__init__(parent)") > 0)
|
101
|
+
)
|
102
|
+
if issubclass(self.widget.__bases__[0], QObject) and not super_init_found:
|
103
|
+
super_init_found = (
|
104
|
+
bool(init_source.find("super().__init__(parent=parent") > 0)
|
105
|
+
or bool(init_source.find("super().__init__(parent,") > 0)
|
106
|
+
or bool(init_source.find("super().__init__(parent)") > 0)
|
107
|
+
)
|
108
|
+
|
109
|
+
if not cls_init_found and not super_init_found:
|
110
|
+
raise ValueError(
|
111
|
+
f"Widget class {self.widget.__name__} must call the super constructor with parent."
|
112
|
+
)
|
113
|
+
|
114
|
+
def _write_templates(self):
|
115
|
+
self._write_register()
|
116
|
+
self._write_plugin()
|
117
|
+
self._write_pyproject()
|
118
|
+
|
119
|
+
def _write_register(self):
|
120
|
+
file_path = os.path.join(self.info.base_path, f"register_{self.info.plugin_name_snake}.py")
|
121
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
122
|
+
f.write(self.templates["register"].format(**self.info.__dict__))
|
123
|
+
|
124
|
+
def _write_plugin(self):
|
125
|
+
file_path = os.path.join(self.info.base_path, f"{self.info.plugin_name_snake}_plugin.py")
|
126
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
127
|
+
f.write(self.templates["plugin"].format(**self.info.__dict__))
|
128
|
+
|
129
|
+
def _write_pyproject(self):
|
130
|
+
file_path = os.path.join(self.info.base_path, f"{self.info.plugin_name_snake}.pyproject")
|
131
|
+
out = {"files": [f"{self.info.plugin_class.__module__.split('.')[-1]}.py"]}
|
132
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
133
|
+
f.write(str(out))
|
134
|
+
|
135
|
+
def _load_templates(self):
|
136
|
+
for file in os.listdir(self.template_path):
|
137
|
+
if not file.endswith(".template"):
|
138
|
+
continue
|
139
|
+
with open(os.path.join(self.template_path, file), "r", encoding="utf-8") as f:
|
140
|
+
self.templates[file.split(".")[0]] = f.read()
|
141
|
+
|
142
|
+
|
143
|
+
if __name__ == "__main__": # pragma: no cover
|
144
|
+
# from bec_widgets.widgets.bec_queue.bec_queue import BECQueue
|
145
|
+
from bec_widgets.widgets.dock import BECDockArea
|
146
|
+
|
147
|
+
generator = DesignerPluginGenerator(BECDockArea)
|
148
|
+
generator.run()
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Copyright (C) 2022 The Qt Company Ltd.
|
2
|
+
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
3
|
+
|
4
|
+
from qtpy.QtDesigner import QDesignerCustomWidgetInterface
|
5
|
+
from qtpy.QtGui import QIcon
|
6
|
+
|
7
|
+
{widget_import}
|
8
|
+
|
9
|
+
DOM_XML = """
|
10
|
+
<ui language='c++'>
|
11
|
+
<widget class='{plugin_name_pascal}' name='{plugin_name_snake}'>
|
12
|
+
</widget>
|
13
|
+
</ui>
|
14
|
+
"""
|
15
|
+
|
16
|
+
|
17
|
+
class {plugin_name_pascal}Plugin(QDesignerCustomWidgetInterface): # pragma: no cover
|
18
|
+
def __init__(self):
|
19
|
+
super().__init__()
|
20
|
+
self._form_editor = None
|
21
|
+
|
22
|
+
def createWidget(self, parent):
|
23
|
+
t = {plugin_name_pascal}(parent)
|
24
|
+
return t
|
25
|
+
|
26
|
+
def domXml(self):
|
27
|
+
return DOM_XML
|
28
|
+
|
29
|
+
def group(self):
|
30
|
+
return ""
|
31
|
+
|
32
|
+
def icon(self):
|
33
|
+
return QIcon()
|
34
|
+
|
35
|
+
def includeFile(self):
|
36
|
+
return "{plugin_name_snake}"
|
37
|
+
|
38
|
+
def initialize(self, form_editor):
|
39
|
+
self._form_editor = form_editor
|
40
|
+
|
41
|
+
def isContainer(self):
|
42
|
+
return False
|
43
|
+
|
44
|
+
def isInitialized(self):
|
45
|
+
return self._form_editor is not None
|
46
|
+
|
47
|
+
def name(self):
|
48
|
+
return "{plugin_name_pascal}"
|
49
|
+
|
50
|
+
def toolTip(self):
|
51
|
+
return "{plugin_tooltip}"
|
52
|
+
|
53
|
+
def whatsThis(self):
|
54
|
+
return self.toolTip()
|
@@ -0,0 +1,15 @@
|
|
1
|
+
def main(): # pragma: no cover
|
2
|
+
from qtpy import PYSIDE6
|
3
|
+
|
4
|
+
if not PYSIDE6:
|
5
|
+
print("PYSIDE6 is not available in the environment. Cannot patch designer.")
|
6
|
+
return
|
7
|
+
from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
|
8
|
+
|
9
|
+
{plugin_import}
|
10
|
+
|
11
|
+
QPyDesignerCustomWidgetCollection.addCustomWidget({plugin_name_pascal}Plugin())
|
12
|
+
|
13
|
+
|
14
|
+
if __name__ == "__main__": # pragma: no cover
|
15
|
+
main()
|
@@ -104,7 +104,7 @@ class RingProgressBar(BECConnector, QWidget):
|
|
104
104
|
config = RingProgressBarConfig(**config, widget_class=self.__class__.__name__)
|
105
105
|
self.config = config
|
106
106
|
super().__init__(client=client, config=config, gui_id=gui_id)
|
107
|
-
QWidget.__init__(self, parent=
|
107
|
+
QWidget.__init__(self, parent=parent)
|
108
108
|
|
109
109
|
self.get_bec_shortcuts()
|
110
110
|
self.entry_validator = EntryValidator(self.dev)
|
@@ -31,7 +31,7 @@ class TextBox(BECConnector, QTextEdit):
|
|
31
31
|
|
32
32
|
USER_ACCESS = ["set_color", "set_text", "set_font_size"]
|
33
33
|
|
34
|
-
def __init__(self, text: str = "",
|
34
|
+
def __init__(self, parent=None, text: str = "", client=None, config=None, gui_id=None):
|
35
35
|
if config is None:
|
36
36
|
config = TextBoxConfig(widget_class=self.__class__.__name__)
|
37
37
|
else:
|
@@ -21,7 +21,7 @@ class WebsiteWidget(BECConnector, QWebEngineView):
|
|
21
21
|
|
22
22
|
USER_ACCESS = ["set_url", "get_url", "reload", "back", "forward"]
|
23
23
|
|
24
|
-
def __init__(self, url: str = None,
|
24
|
+
def __init__(self, parent=None, url: str = None, config=None, client=None, gui_id=None):
|
25
25
|
super().__init__(client=client, config=config, gui_id=gui_id)
|
26
26
|
QWebEngineView.__init__(self, parent=parent)
|
27
27
|
self.set_url(url)
|
@@ -2,11 +2,11 @@
|
|
2
2
|
.gitlab-ci.yml,sha256=RnYDz4zKXjlqltTryprlB1s5vLXxI2-seW-Vb70NNF0,8162
|
3
3
|
.pylintrc,sha256=OstrgmEyP0smNFBKoIN5_26-UmNZgMHnbjvAWX0UrLs,18535
|
4
4
|
.readthedocs.yaml,sha256=aSOc277LqXcsTI6lgvm_JY80lMlr69GbPKgivua2cS0,603
|
5
|
-
CHANGELOG.md,sha256=
|
5
|
+
CHANGELOG.md,sha256=ekeMC81fhBxY6irOaVb51CGYg1cb_im8AiO4lyZHckc,6690
|
6
6
|
LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
|
7
|
-
PKG-INFO,sha256
|
7
|
+
PKG-INFO,sha256=-U5bxfflX9Bl1WUPGgROel3NEW1D9GQROCFx6yvARMo,1407
|
8
8
|
README.md,sha256=y4jB6wvArS7N8_iTbKWnSM_oRAqLA2GqgzUR-FMh5sU,2645
|
9
|
-
pyproject.toml,sha256=
|
9
|
+
pyproject.toml,sha256=zhu2wjrXmnpH5r_LXscKMezya9iLtxDqoAWpmqWS8-M,2344
|
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
|
@@ -19,7 +19,7 @@ bec_widgets/cli/__init__.py,sha256=d0Q6Fn44e7wFfLabDOBxpcJ1DPKWlFunGYDUBmO-4hA,2
|
|
19
19
|
bec_widgets/cli/auto_updates.py,sha256=DyBV3HnjMSH-cvVkYNcDiYKVf0Xut4Qy2qGQqkW47Bw,4833
|
20
20
|
bec_widgets/cli/client.py,sha256=754vTVMVLkdpGa5wsH2wGP0fJW59wRubt6HOB8AG7_w,61582
|
21
21
|
bec_widgets/cli/client_utils.py,sha256=zq1gPW7t4n9Nsn4MLkdUeKwwl-9nUcf5UjuN8lZr9iY,12281
|
22
|
-
bec_widgets/cli/generate_cli.py,sha256=
|
22
|
+
bec_widgets/cli/generate_cli.py,sha256=FUMSm84ztE6UIIHs8U0Irof1i5LRu6CXW1sl-RF_UKA,5877
|
23
23
|
bec_widgets/cli/rpc_register.py,sha256=QxXUZu5XNg00Yf5O3UHWOXg3-f_pzKjjoZYMOa-MOJc,2216
|
24
24
|
bec_widgets/cli/rpc_wigdet_handler.py,sha256=1qQOGrM8rozaWLkoxAW8DTVLv_L_DZdZgUMDPy5MOek,1486
|
25
25
|
bec_widgets/cli/server.py,sha256=2EJvkQDzrDTsZjRPs7g2v_iPTspGqxzY34tRAnvjxjY,7281
|
@@ -46,6 +46,7 @@ bec_widgets/utils/colors.py,sha256=GYSDe0ZxsJSwxvuy-yG2BH17qlf_Sjq8dhDcyp9IhBI,8
|
|
46
46
|
bec_widgets/utils/container_utils.py,sha256=m3VUyAYmSWkEwApP9tBvKxPYVtc2kHw4toxIpMryJy4,1495
|
47
47
|
bec_widgets/utils/crosshair.py,sha256=SubY4FQCI6vUKsmMYGKHR7uYdGQJ6vhoYLuC1XlKS9I,9626
|
48
48
|
bec_widgets/utils/entry_validator.py,sha256=IqmtResXQtnmMvWVSl8IrnggqSzXLp4cSggn6WdSTpE,1298
|
49
|
+
bec_widgets/utils/generate_designer_plugin.py,sha256=T6DqL29sN4LcXLH8Hoa410UGnoRzjsZ-z0PRGTEzkRE,5809
|
49
50
|
bec_widgets/utils/layout_manager.py,sha256=H0nKsIMaPxRkof1MEXlSmW6w1dFxA6astaGzf4stI84,4727
|
50
51
|
bec_widgets/utils/plugin_utils.py,sha256=tmZkUNvVlldPjHDfL_TbaV2jjAECgPjGsvLMmmyZcfc,3342
|
51
52
|
bec_widgets/utils/rpc_decorator.py,sha256=pIvtqySQLnuS7l2Ti_UAe4WX7CRivZnsE5ZdKAihxh0,479
|
@@ -54,6 +55,8 @@ bec_widgets/utils/ui_loader.py,sha256=5NktcP1r1HQub7K82fW_jkj8rT2cqJQdMvDxwToLY4
|
|
54
55
|
bec_widgets/utils/validator_delegate.py,sha256=Emj1WF6W8Ke1ruBWUfmHdVJpmOSPezuOt4zvQTay_44,442
|
55
56
|
bec_widgets/utils/widget_io.py,sha256=U_02ESf9Ukz63B01AzYioNepSc6SX11nJhPPSDmL4IA,11318
|
56
57
|
bec_widgets/utils/yaml_dialog.py,sha256=cMVif-39SB9WjwGH5FWBJcFs4tnfFJFs5cacydRyhy0,1853
|
58
|
+
bec_widgets/utils/plugin_templates/plugin.template,sha256=JHkUvYegesW-xEhZuY4FQVGqyEMBRLaPY4JNI8Ni_vE,1182
|
59
|
+
bec_widgets/utils/plugin_templates/register.template,sha256=XyL3OZPT_FTArLAM8tHd5qMqv2ZuAbJAZLsNNnHcagU,417
|
57
60
|
bec_widgets/widgets/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
58
61
|
bec_widgets/widgets/bec_queue/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
59
62
|
bec_widgets/widgets/bec_queue/bec_queue.py,sha256=voIsj599a5t-u-H15tpSqjGBmy5ra6LsHpZnqEZFrI8,3551
|
@@ -114,18 +117,18 @@ bec_widgets/widgets/motor_control/selection/selection.py,sha256=WNHndvv4JvxeAMnD
|
|
114
117
|
bec_widgets/widgets/motor_control/selection/selection.ui,sha256=vXXpvNWuL6xyHhW7Lx1zmVFX-95Z5AXGlhKQD2HmM1A,1779
|
115
118
|
bec_widgets/widgets/ring_progress_bar/__init__.py,sha256=_uoJKnDM2YAeUBfwc5WLbIHSJj7zm_FAurSKP3WRaCw,47
|
116
119
|
bec_widgets/widgets/ring_progress_bar/ring.py,sha256=3XwvM5cymCxffOYEjaDTqfqpNLjEunHTyZCBxz0cvmc,11238
|
117
|
-
bec_widgets/widgets/ring_progress_bar/ring_progress_bar.py,sha256=
|
120
|
+
bec_widgets/widgets/ring_progress_bar/ring_progress_bar.py,sha256=9TzlR4mGWnV1dPBwdkwL-GVNzG30r3oy0secm7k-gKM,24070
|
118
121
|
bec_widgets/widgets/scan_control/__init__.py,sha256=IOfHl15vxb_uC6KN62-PeUzbBha_vQyqkkXbJ2HU674,38
|
119
122
|
bec_widgets/widgets/scan_control/scan_control.py,sha256=u2fjSUiSRYTkIq9WhdfQuQV6Sv3iWWcSfCraVGro1RQ,7686
|
120
123
|
bec_widgets/widgets/scan_control/scan_group_box.py,sha256=8XGpYcdKTEtiqOFbBxZ6xV07ZJ_tg9R-JDfsdTdqXSI,7400
|
121
124
|
bec_widgets/widgets/text_box/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
122
|
-
bec_widgets/widgets/text_box/text_box.py,sha256=
|
125
|
+
bec_widgets/widgets/text_box/text_box.py,sha256=dg2gpOqdBZNKD08mygb40twweFBiG-xsXz0GlIhfXV0,4240
|
123
126
|
bec_widgets/widgets/toolbar/__init__.py,sha256=d-TP4_cr_VbpwreMM4ePnfZ5YXsEPQ45ibEf75nuGoE,36
|
124
127
|
bec_widgets/widgets/toolbar/toolbar.py,sha256=e0zCD_0q7K4NVhrzD8001Qvfxt-VhqHTgofchS9NgCM,5125
|
125
128
|
bec_widgets/widgets/vscode/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
126
129
|
bec_widgets/widgets/vscode/vscode.py,sha256=ZyJJCJapYrGhqgudEt8JQn723DDqLdwjsXxXa5q3EkU,2544
|
127
130
|
bec_widgets/widgets/website/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
128
|
-
bec_widgets/widgets/website/website.py,sha256=
|
131
|
+
bec_widgets/widgets/website/website.py,sha256=iMOooGlZPQ5Y_T_7g4rJZXj-tKpbIupA1O6_WN27JuI,1722
|
129
132
|
docs/Makefile,sha256=i2WHuFlgfyAPEW4ssEP8NY4cOibDJrVjvzSEU8_Ggwc,634
|
130
133
|
docs/conf.py,sha256=HxLxupNGu0Smhwn57g1kFdjZzFuaWVREgRJKhT1zi2k,2464
|
131
134
|
docs/index.md,sha256=8ZCgaLIbJsYvt-jwi--QxsNwnK4-k3rejIeOOLclG40,1101
|
@@ -198,6 +201,7 @@ tests/unit_tests/test_crosshair.py,sha256=3OMAJ2ZaISYXMOtkXf1rPdy94vCr8njeLi6uHb
|
|
198
201
|
tests/unit_tests/test_device_input_base.py,sha256=DiwbNzFQ8o90ELhlT103roqLNEzJ09bvlpNrOmT4lfM,2423
|
199
202
|
tests/unit_tests/test_device_input_widgets.py,sha256=yQ67Xwn-T7NHAIT1XLA4DvcxQEIJYMUr9PfPnT6CAPI,5805
|
200
203
|
tests/unit_tests/test_generate_cli_client.py,sha256=adcMoXjWpFLVjpauCu0r31CMMibUY1LF1MMf8rO-6rw,2815
|
204
|
+
tests/unit_tests/test_generate_plugin.py,sha256=9603ucZChM-pYpHadzsR94U1Zec1KZT34WedX9qzgMo,4464
|
201
205
|
tests/unit_tests/test_motor_control.py,sha256=NBekcGALo5mYkuyBJvBhvJkWiQDV82hI4GmsobRzjTI,20770
|
202
206
|
tests/unit_tests/test_plot_base.py,sha256=Akr_JgglUCrtERtdtsMqWko_MLUYoAYRGzV2sum-YHo,3836
|
203
207
|
tests/unit_tests/test_plugin_utils.py,sha256=PonKNpu4fZaFmKbI2v0tZJjZrsTvBGSF96bPHvKJvrE,608
|
@@ -218,8 +222,8 @@ tests/unit_tests/test_configs/config_device_no_entry.yaml,sha256=hdvue9KLc_kfNzG
|
|
218
222
|
tests/unit_tests/test_configs/config_scan.yaml,sha256=vo484BbWOjA_e-h6bTjSV9k7QaQHrlAvx-z8wtY-P4E,1915
|
219
223
|
tests/unit_tests/test_msgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
220
224
|
tests/unit_tests/test_msgs/available_scans_message.py,sha256=m_z97hIrjHXXMa2Ex-UvsPmTxOYXfjxyJaGkIY6StTY,46532
|
221
|
-
bec_widgets-0.
|
222
|
-
bec_widgets-0.
|
223
|
-
bec_widgets-0.
|
224
|
-
bec_widgets-0.
|
225
|
-
bec_widgets-0.
|
225
|
+
bec_widgets-0.76.1.dist-info/METADATA,sha256=-U5bxfflX9Bl1WUPGgROel3NEW1D9GQROCFx6yvARMo,1407
|
226
|
+
bec_widgets-0.76.1.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
227
|
+
bec_widgets-0.76.1.dist-info/entry_points.txt,sha256=3otEkCdDB9LZJuBLzG4pFLK5Di0CVybN_12IsZrQ-58,166
|
228
|
+
bec_widgets-0.76.1.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
|
229
|
+
bec_widgets-0.76.1.dist-info/RECORD,,
|
pyproject.toml
CHANGED
@@ -0,0 +1,155 @@
|
|
1
|
+
import importlib
|
2
|
+
import inspect
|
3
|
+
import os
|
4
|
+
import sys
|
5
|
+
|
6
|
+
import pytest
|
7
|
+
|
8
|
+
from bec_widgets.utils.generate_designer_plugin import DesignerPluginGenerator
|
9
|
+
|
10
|
+
|
11
|
+
def load_plugin(dir_path, content, plugin_name="MyWidget"):
|
12
|
+
plugin_path = dir_path.mkdir("plugin").join("plugin.py")
|
13
|
+
plugin_path.write(content)
|
14
|
+
sys.path.append(str(dir_path))
|
15
|
+
plugin = importlib.import_module("plugin.plugin")
|
16
|
+
importlib.reload(plugin)
|
17
|
+
yield getattr(plugin, plugin_name)
|
18
|
+
sys.path.pop()
|
19
|
+
|
20
|
+
|
21
|
+
@pytest.fixture(
|
22
|
+
params=[
|
23
|
+
"""
|
24
|
+
from qtpy.QtWidgets import QWidget
|
25
|
+
class MyWidget(QWidget):
|
26
|
+
def __init__(self, parent=None):
|
27
|
+
QWidget.__init__(self, parent)
|
28
|
+
""",
|
29
|
+
"""
|
30
|
+
from qtpy.QtWidgets import QWidget
|
31
|
+
class MyWidget(QWidget):
|
32
|
+
def __init__(self, parent=None):
|
33
|
+
QWidget.__init__(self, parent=parent)
|
34
|
+
""",
|
35
|
+
"""
|
36
|
+
from qtpy.QtWidgets import QWidget
|
37
|
+
class MyWidget(QWidget):
|
38
|
+
def __init__(self, parent=None):
|
39
|
+
super().__init__(parent)
|
40
|
+
""",
|
41
|
+
"""
|
42
|
+
from qtpy.QtWidgets import QWidget
|
43
|
+
class MyWidget(QWidget):
|
44
|
+
def __init__(self, parent=None):
|
45
|
+
super().__init__(parent=parent)
|
46
|
+
""",
|
47
|
+
"""
|
48
|
+
from qtpy.QtWidgets import QWidget
|
49
|
+
class MyWidget(QWidget):
|
50
|
+
def __init__(self, parent=None):
|
51
|
+
super(QWidget, self).__init__(parent)"""
|
52
|
+
"""
|
53
|
+
from qtpy.QtWidgets import QWidget
|
54
|
+
class MyWidget(QWidget):
|
55
|
+
def __init__(self, parent=None):
|
56
|
+
super(QWidget, self).__init__(parent=parent)
|
57
|
+
""",
|
58
|
+
]
|
59
|
+
)
|
60
|
+
def plugin_with_correct_parent(tmpdir, request):
|
61
|
+
yield from load_plugin(tmpdir, request.param)
|
62
|
+
|
63
|
+
|
64
|
+
@pytest.fixture(
|
65
|
+
params=[
|
66
|
+
"""
|
67
|
+
from qtpy.QtWidgets import QWidget
|
68
|
+
class MyWidget(QWidget):
|
69
|
+
def __init__(self, parent=None):
|
70
|
+
QWidget.__init__(self)
|
71
|
+
""",
|
72
|
+
"""
|
73
|
+
from qtpy.QtWidgets import QWidget
|
74
|
+
class MyWidget(QWidget):
|
75
|
+
def __init__(self, parent=None):
|
76
|
+
super().__init__()
|
77
|
+
""",
|
78
|
+
"""
|
79
|
+
from qtpy.QtWidgets import QWidget
|
80
|
+
class MyWidget(QWidget):
|
81
|
+
def __init__(self, parent=None):
|
82
|
+
super(QWidget, self).__init__()
|
83
|
+
""",
|
84
|
+
]
|
85
|
+
)
|
86
|
+
def plugin_with_missing_parent(tmpdir, request):
|
87
|
+
yield from load_plugin(tmpdir, request.param)
|
88
|
+
|
89
|
+
|
90
|
+
def test_generate_plugin(plugin_with_correct_parent):
|
91
|
+
generator = DesignerPluginGenerator(plugin_with_correct_parent)
|
92
|
+
generator.run()
|
93
|
+
assert os.path.exists(f"{generator.info.base_path}/register_my_widget.py")
|
94
|
+
assert os.path.exists(f"{generator.info.base_path}/my_widget_plugin.py")
|
95
|
+
assert os.path.exists(f"{generator.info.base_path}/my_widget.pyproject")
|
96
|
+
|
97
|
+
|
98
|
+
def test_generate_plugin_with_missing_parent(plugin_with_missing_parent):
|
99
|
+
with pytest.raises(ValueError) as excinfo:
|
100
|
+
generator = DesignerPluginGenerator(plugin_with_missing_parent)
|
101
|
+
generator.run()
|
102
|
+
assert "Widget class MyWidget must call the super constructor with parent." in str(
|
103
|
+
excinfo.value
|
104
|
+
)
|
105
|
+
|
106
|
+
|
107
|
+
@pytest.fixture()
|
108
|
+
def plugin_with_excluded_widget(tmpdir):
|
109
|
+
content = """
|
110
|
+
from qtpy.QtWidgets import QWidget
|
111
|
+
class BECDock(QWidget):
|
112
|
+
def __init__(self, parent=None):
|
113
|
+
QWidget.__init__(self, parent)
|
114
|
+
"""
|
115
|
+
yield from load_plugin(tmpdir, content, plugin_name="BECDock")
|
116
|
+
|
117
|
+
|
118
|
+
def test_generate_plugin_with_excluded_widget(plugin_with_excluded_widget, capsys):
|
119
|
+
generator = DesignerPluginGenerator(plugin_with_excluded_widget)
|
120
|
+
generator.run()
|
121
|
+
captured = capsys.readouterr()
|
122
|
+
|
123
|
+
assert "Plugin BECDock is excluded from generation." in captured.out
|
124
|
+
assert not os.path.exists(f"{generator.info.base_path}/register_bec_dock.py")
|
125
|
+
assert not os.path.exists(f"{generator.info.base_path}/bec_dock_plugin.py")
|
126
|
+
assert not os.path.exists(f"{generator.info.base_path}/bec_dock.pyproject")
|
127
|
+
|
128
|
+
|
129
|
+
@pytest.fixture(
|
130
|
+
params=[
|
131
|
+
"""
|
132
|
+
from qtpy.QtWidgets import QWidget
|
133
|
+
class MyWidget(QWidget):
|
134
|
+
def __init__(self):
|
135
|
+
QWidget.__init__(self)
|
136
|
+
""",
|
137
|
+
"""
|
138
|
+
from qtpy.QtWidgets import QWidget
|
139
|
+
class MyWidget(QWidget):
|
140
|
+
def __init__(self, config, parent=None):
|
141
|
+
super().__init__()
|
142
|
+
""",
|
143
|
+
]
|
144
|
+
)
|
145
|
+
def plugin_with_no_parent_as_first_arg(tmpdir, request):
|
146
|
+
yield from load_plugin(tmpdir, request.param)
|
147
|
+
|
148
|
+
|
149
|
+
def test_generate_plugin_raises_exception_when_first_argument_is_not_parent(
|
150
|
+
plugin_with_no_parent_as_first_arg,
|
151
|
+
):
|
152
|
+
with pytest.raises(ValueError) as excinfo:
|
153
|
+
generator = DesignerPluginGenerator(plugin_with_no_parent_as_first_arg)
|
154
|
+
generator.run()
|
155
|
+
assert "Widget class MyWidget must have parent as the first argument." in str(excinfo.value)
|
File without changes
|
File without changes
|
File without changes
|