bec-widgets 0.59.0__py3-none-any.whl → 0.60.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:
@@ -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()
@@ -68,7 +68,7 @@ class BECCurve(BECConnector, pg.PlotDataItem):
68
68
  "set",
69
69
  "set_data",
70
70
  "set_color",
71
- "set_colormap_z",
71
+ "set_color_map_z",
72
72
  "set_symbol",
73
73
  "set_symbol_color",
74
74
  "set_symbol_size",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.59.0
3
+ Version: 0.60.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=P6Luyx0Hu_SvqXdhNIIKok5kgPW9EsyOaRw1YrrOKZA,7013
5
+ CHANGELOG.md,sha256=ZN4q7ZllSvFOCrwCteZ0uSJr8Vc-QC8kRNdGvSjpZ8I,7022
6
6
  LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
7
- PKG-INFO,sha256=MAL6cE2vhCDQphF93IQ6n5C3MuUPlzhRXuW7H6Vw9O8,1284
7
+ PKG-INFO,sha256=yKloOHaV8JrHipEfMkYVLZIxQU0ZvqeqXjK5kCd_2-g,1302
8
8
  README.md,sha256=y4jB6wvArS7N8_iTbKWnSM_oRAqLA2GqgzUR-FMh5sU,2645
9
- pyproject.toml,sha256=Zi9BiQNDd0VqI7KspQh6m-7MlaULYx5lucZQuqYjXDc,1868
9
+ pyproject.toml,sha256=lGx8dV1vE3NBrjHIHggomwMZw4LX26QN-CKc5N2-CFE,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=Zi9BiQNDd0VqI7KspQh6m-7MlaULYx5lucZQuqYjXDc,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
18
+ bec_widgets/cli/__init__.py,sha256=d0Q6Fn44e7wFfLabDOBxpcJ1DPKWlFunGYDUBmO-4hA,22
19
19
  bec_widgets/cli/auto_updates.py,sha256=0sd7HiqOMn1jCbgVG3-H1nmQgdOMRwSjx6FAvdtVf1k,4747
20
- bec_widgets/cli/client.py,sha256=JBvlAr8YsNg-txbyeGSsJdovh02ePgtbt2L4JREk7rs,56378
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
@@ -48,7 +48,7 @@ bec_widgets/utils/widget_io.py,sha256=f36198CvT_EzWQ_cg2G-4tRRsaMdJ3yVqsZWKJCQEf
48
48
  bec_widgets/utils/yaml_dialog.py,sha256=cMVif-39SB9WjwGH5FWBJcFs4tnfFJFs5cacydRyhy0,1853
49
49
  bec_widgets/widgets/__init__.py,sha256=LKgIuY3CI-NHCa_bY9pThYhxLH0MHDo8iNEJDDVIVmw,172
50
50
  bec_widgets/widgets/dock/__init__.py,sha256=B7foHt02gnhM7mFksa7GJVwT7n0j_JvYDCt6wc6XR5g,61
51
- bec_widgets/widgets/dock/dock.py,sha256=npSJijKdaPZk6T4LrWQ-Q8PfJMgIniqo1UYLahPowA0,7695
51
+ bec_widgets/widgets/dock/dock.py,sha256=WPanKj6nodVP6PiEFkRTCj5Lf0pUupmM7i-5qZA_ATY,7596
52
52
  bec_widgets/widgets/dock/dock_area.py,sha256=9c_tLzyBRllLfc4H5o9-4bvasWp5hWe1NWg4mupXVtU,7911
53
53
  bec_widgets/widgets/figure/__init__.py,sha256=3hGx_KOV7QHCYAV06aNuUgKq4QIYCjUTad-DrwkUaBM,44
54
54
  bec_widgets/widgets/figure/figure.py,sha256=O--r3dyeOPXndV2400wpE9lPdBezzd0ZUt7yA2u2n0A,31468
@@ -61,8 +61,8 @@ bec_widgets/widgets/figure/plots/image/image_processor.py,sha256=TOnHbdq9rK5--L5
61
61
  bec_widgets/widgets/figure/plots/motor_map/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
62
  bec_widgets/widgets/figure/plots/motor_map/motor_map.py,sha256=Ff2WoNHxO_A3ggsbSd_AVUP1JeOWMuJs-0GLskxn-94,15267
63
63
  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
65
- bec_widgets/widgets/figure/plots/waveform/waveform_curve.py,sha256=gFXt6v4P-kHterXUqkZx0eofWlYHxo32I8Kh0zYDLik,7969
64
+ bec_widgets/widgets/figure/plots/waveform/waveform.py,sha256=f9YpsNufcICvZyDgcVujzdszdsh0_9gzvnRbpwZroLA,23490
65
+ bec_widgets/widgets/figure/plots/waveform/waveform_curve.py,sha256=lTyeCydzvrcdvQXc89jEjoor-Uvo54i197-_M4VtqX8,7970
66
66
  bec_widgets/widgets/jupyter_console/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
67
  bec_widgets/widgets/jupyter_console/jupyter_console.py,sha256=ioLYJL31RdBoAOGFSS8PVSnUhkWPWmLC3tiKp7CouO8,2251
68
68
  bec_widgets/widgets/motor_control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -143,7 +143,7 @@ tests/unit_tests/test_bec_motor_map.py,sha256=AfD_9-x6VV3TPnkQgNfFYRndPHDsGx-a_Y
143
143
  tests/unit_tests/test_client_utils.py,sha256=eViJ1Tz-HX9TkMvQH6W8cO-c3_1I8bUc4_Yen6LOc0E,830
144
144
  tests/unit_tests/test_color_validation.py,sha256=csdvVKAohENZIRY-JQ97Hv-TShb1erj4oKMX7QRwo78,1883
145
145
  tests/unit_tests/test_crosshair.py,sha256=3OMAJ2ZaISYXMOtkXf1rPdy94vCr8njeLi6uHblBL9Q,5045
146
- tests/unit_tests/test_generate_cli_client.py,sha256=J7CFoO67txGu_u1Mwk32EejRX204FRuvmVg_yhAr1WM,2397
146
+ tests/unit_tests/test_generate_cli_client.py,sha256=GmCLpyRWx5aREb66Api9T-OUpYE1wKgI4hhjUepYrvg,3408
147
147
  tests/unit_tests/test_motor_control.py,sha256=NBekcGALo5mYkuyBJvBhvJkWiQDV82hI4GmsobRzjTI,20770
148
148
  tests/unit_tests/test_plot_base.py,sha256=bOdlgAxh9oKk5PwiQ_MSFmzr44uJ61Tlg242RCIhl5c,2610
149
149
  tests/unit_tests/test_rpc_register.py,sha256=hECjZEimd440mwRrO0rg7L3PKN7__3DgjmESN6wx3bo,1179
@@ -158,7 +158,8 @@ tests/unit_tests/test_configs/config_device_no_entry.yaml,sha256=hdvue9KLc_kfNzG
158
158
  tests/unit_tests/test_configs/config_scan.yaml,sha256=vo484BbWOjA_e-h6bTjSV9k7QaQHrlAvx-z8wtY-P4E,1915
159
159
  tests/unit_tests/test_msgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
160
160
  tests/unit_tests/test_msgs/available_scans_message.py,sha256=m_z97hIrjHXXMa2Ex-UvsPmTxOYXfjxyJaGkIY6StTY,46532
161
- bec_widgets-0.59.0.dist-info/METADATA,sha256=MAL6cE2vhCDQphF93IQ6n5C3MuUPlzhRXuW7H6Vw9O8,1284
162
- bec_widgets-0.59.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
163
- bec_widgets-0.59.0.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
164
- bec_widgets-0.59.0.dist-info/RECORD,,
161
+ bec_widgets-0.60.0.dist-info/METADATA,sha256=yKloOHaV8JrHipEfMkYVLZIxQU0ZvqeqXjK5kCd_2-g,1302
162
+ bec_widgets-0.60.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
163
+ bec_widgets-0.60.0.dist-info/entry_points.txt,sha256=80s2YKCNziN2ROUYbpDRyEmiejMf_dshmiYCdN7qNsU,70
164
+ bec_widgets-0.60.0.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
165
+ bec_widgets-0.60.0.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ bw-generate-cli = bec_widgets.cli.generate_cli:main
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.0"
7
+ version = "0.60.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"
@@ -1,10 +1,12 @@
1
1
  from textwrap import dedent
2
2
 
3
3
  import black
4
- import pytest
4
+ import isort
5
5
 
6
6
  from bec_widgets.cli.generate_cli import ClientGenerator
7
7
 
8
+ # pylint: disable=missing-function-docstring
9
+
8
10
 
9
11
  # Mock classes to test the generator
10
12
  class MockBECWaveform1D:
@@ -24,25 +26,39 @@ class MockBECFigure:
24
26
 
25
27
  def add_plot(self, plot_id: str):
26
28
  """Add a plot to the figure."""
27
- pass
28
29
 
29
30
  def remove_plot(self, plot_id: str):
30
31
  """Remove a plot from the figure."""
31
- pass
32
32
 
33
33
 
34
34
  def test_client_generator_with_black_formatting():
35
35
  generator = ClientGenerator()
36
- generator.generate_client([MockBECWaveform1D, MockBECFigure])
36
+ rpc_classes = {
37
+ "connector_classes": [MockBECWaveform1D, MockBECFigure],
38
+ "top_level_classes": [MockBECFigure],
39
+ }
40
+ generator.generate_client(rpc_classes)
37
41
 
38
42
  # Format the expected output with black to ensure it matches the generator output
39
43
  expected_output = dedent(
40
44
  '''\
41
45
  # This file was automatically generated by generate_cli.py
42
46
 
43
- from bec_widgets.cli.client_utils import rpc_call, RPCBase, BECGuiClientMixin
47
+ import enum
44
48
  from typing import Literal, Optional, overload
45
49
 
50
+ from bec_widgets.cli.client_utils import BECGuiClientMixin, RPCBase, rpc_call
51
+
52
+ # pylint: skip-file
53
+
54
+ class Widgets(str, enum.Enum):
55
+ """
56
+ Enum for the available widgets.
57
+ """
58
+
59
+ MockBECFigure = "MockBECFigure"
60
+
61
+
46
62
  class MockBECWaveform1D(RPCBase):
47
63
  @rpc_call
48
64
  def set_frequency(self, frequency: float) -> list:
@@ -78,4 +94,20 @@ def test_client_generator_with_black_formatting():
78
94
  generator.header + "\n" + generator.content, mode=black.FileMode(line_length=100)
79
95
  )
80
96
 
97
+ generated_output_formatted = isort.code(generated_output_formatted)
98
+
81
99
  assert expected_output_formatted == generated_output_formatted
100
+
101
+
102
+ def test_client_generator_classes():
103
+ generator = ClientGenerator()
104
+ out = generator.get_rpc_classes("bec_widgets")
105
+ assert list(out.keys()) == ["connector_classes", "top_level_classes"]
106
+ connector_cls_names = [cls.__name__ for cls in out["connector_classes"]]
107
+ top_level_cls_names = [cls.__name__ for cls in out["top_level_classes"]]
108
+
109
+ assert "BECFigure" in connector_cls_names
110
+ assert "BECWaveform" in connector_cls_names
111
+ assert "BECDockArea" in top_level_cls_names
112
+ assert "BECFigure" in top_level_cls_names
113
+ assert "BECWaveform" not in top_level_cls_names