bec-widgets 0.57.1__py3-none-any.whl → 0.57.2__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 CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
 
4
4
 
5
+ ## v0.57.2 (2024-06-06)
6
+
7
+ ### Fix
8
+
9
+ * fix(test/e2e): autoupdate e2e rewritten ([`e1af5ca`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e1af5ca60f0616835f9f41d84412f29dc298c644))
10
+
11
+ * fix(test/e2e): spiral_progress_bar e2e tests rewritten to use config_dict ([`7fb31fc`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/7fb31fc4d762ff4ca839971b3092a084186f81b8))
12
+
13
+ * fix(test/e2e): dockarea and dock e2e tests changed to check asserts against config_dict ([`5c6ba65`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/5c6ba65469863ea1e6fc5abdc742650e20eba9b9))
14
+
15
+ * fix: rpc_server_dock fixture now spawns the server process ([`cd9fc46`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/cd9fc46ff8a947242c8c28adcd73d7de60b11c44))
16
+
17
+ * fix: accept scalars or numpy arrays of 1 element ([`2a88e17`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/2a88e17b23436c55d25b7d3449e4af3a7689661c))
18
+
19
+ ### Refactor
20
+
21
+ * refactor: move _get_output and _start_plot_process at the module level ([`69f4371`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/69f4371007c66aee6b7521a6803054025adf8c92))
22
+
23
+
5
24
  ## v0.57.1 (2024-06-06)
6
25
 
7
26
  ### Documentation
@@ -146,30 +165,3 @@
146
165
 
147
166
 
148
167
  ## v0.53.0 (2024-05-09)
149
-
150
- ### Ci
151
-
152
- * ci: use formatter config of toml file ([`5cc816d`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/5cc816d0af73e20c648e044a027c589704ab1625))
153
-
154
- ### Documentation
155
-
156
- * docs: update install instructions ([`57ee735`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/57ee735e5c2436d45a285507cdc939daa20e8e8f))
157
-
158
- ### Feature
159
-
160
- * feat: moved to pyproject.toml; closes #162 ([`c86ce30`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/c86ce302a964d71ee631f0817609ab5aa0e3ab0f))
161
-
162
- ### Fix
163
-
164
- * fix: fixed semver job and upgraded to v9 ([`32e1a9d`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/32e1a9d8472eb1c25d30697d407a8ffecd04e75d))
165
-
166
- ### Refactor
167
-
168
- * refactor: applied formatter ([`4117fd7`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/4117fd7b5b2090ff4fb7ad9e0d92cc87cd13ed5f))
169
-
170
-
171
- ## v0.52.1 (2024-05-08)
172
-
173
- ### Fix
174
-
175
- * fix(docstrings): docstrings formating fixed for sphinx to properly format readdocs ([`7f2f7cd`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/7f2f7cd07a14876617cd83cedde8c281fdc52c3a))
PKG-INFO CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.57.1
3
+ Version: 0.57.2
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
@@ -27,6 +27,7 @@ Requires-Dist: pytest; extra == 'dev'
27
27
  Requires-Dist: pytest-qt; extra == 'dev'
28
28
  Requires-Dist: pytest-random-order; extra == 'dev'
29
29
  Requires-Dist: pytest-timeout; extra == 'dev'
30
+ Requires-Dist: pytest-xvfb; extra == 'dev'
30
31
  Provides-Extra: pyqt5
31
32
  Requires-Dist: pyqt5>=5.9; extra == 'pyqt5'
32
33
  Provides-Extra: pyqt6
bec_widgets/cli/client.py CHANGED
@@ -1651,6 +1651,16 @@ class BECDockArea(RPCBase, BECGuiClientMixin):
1651
1651
  Get all registered RPC objects.
1652
1652
  """
1653
1653
 
1654
+ @property
1655
+ @rpc_call
1656
+ def temp_areas(self) -> "list":
1657
+ """
1658
+ Get the temporary areas in the dock area.
1659
+
1660
+ Returns:
1661
+ list: The temporary areas in the dock area.
1662
+ """
1663
+
1654
1664
 
1655
1665
  class SpiralProgressBar(RPCBase):
1656
1666
  @rpc_call
@@ -61,10 +61,54 @@ def rpc_call(func):
61
61
  return wrapper
62
62
 
63
63
 
64
+ def _get_output(process) -> None:
65
+ try:
66
+ os.set_blocking(process.stdout.fileno(), False)
67
+ os.set_blocking(process.stderr.fileno(), False)
68
+ while process.poll() is None:
69
+ readylist, _, _ = select.select([process.stdout, process.stderr], [], [], 1)
70
+ if process.stdout in readylist:
71
+ output = process.stdout.read(1024)
72
+ if output:
73
+ print(output, end="")
74
+ if process.stderr in readylist:
75
+ error_output = process.stderr.read(1024)
76
+ if error_output:
77
+ print(error_output, end="", file=sys.stderr)
78
+ except Exception as e:
79
+ print(f"Error reading process output: {str(e)}")
80
+
81
+
82
+ def _start_plot_process(gui_id, gui_class, config) -> None:
83
+ """
84
+ Start the plot in a new process.
85
+ """
86
+ # pylint: disable=subprocess-run-check
87
+ monitor_module = importlib.import_module("bec_widgets.cli.server")
88
+ monitor_path = monitor_module.__file__
89
+
90
+ command = [
91
+ sys.executable,
92
+ "-u",
93
+ monitor_path,
94
+ "--id",
95
+ gui_id,
96
+ "--config",
97
+ config,
98
+ "--gui_class",
99
+ gui_class.__name__,
100
+ ]
101
+ process = subprocess.Popen(command, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
102
+ process_output_processing_thread = threading.Thread(target=_get_output, args=(process,))
103
+ process_output_processing_thread.start()
104
+ return process, process_output_processing_thread
105
+
106
+
64
107
  class BECGuiClientMixin:
65
108
  def __init__(self, **kwargs) -> None:
66
109
  super().__init__(**kwargs)
67
110
  self._process = None
111
+ self._process_output_processing_thread = None
68
112
  self.auto_updates = self._get_update_script()
69
113
  self._target_endpoint = MessageEndpoints.scan_status()
70
114
  self._selected_device = None
@@ -118,7 +162,10 @@ class BECGuiClientMixin:
118
162
  Show the figure.
119
163
  """
120
164
  if self._process is None or self._process.poll() is not None:
121
- self._start_plot_process()
165
+ self._start_update_script()
166
+ self._process, self._process_output_processing_thread = _start_plot_process(
167
+ self._gui_id, self.__class__, self._client._service_config.redis
168
+ )
122
169
  while not self.gui_is_alive():
123
170
  print("Waiting for GUI to start...")
124
171
  time.sleep(1)
@@ -138,34 +185,6 @@ class BECGuiClientMixin:
138
185
  self._process = None
139
186
  self._client.shutdown()
140
187
 
141
- def _start_plot_process(self) -> None:
142
- """
143
- Start the plot in a new process.
144
- """
145
- self._start_update_script()
146
- # pylint: disable=subprocess-run-check
147
- config = self._client._service_config.redis
148
- monitor_module = importlib.import_module("bec_widgets.cli.server")
149
- monitor_path = monitor_module.__file__
150
- gui_class = self.__class__.__name__
151
-
152
- command = [
153
- sys.executable,
154
- "-u",
155
- monitor_path,
156
- "--id",
157
- self._gui_id,
158
- "--config",
159
- config,
160
- "--gui_class",
161
- gui_class,
162
- ]
163
- self._process = subprocess.Popen(
164
- command, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
165
- )
166
- self._process_output_processing_thread = threading.Thread(target=self._get_output)
167
- self._process_output_processing_thread.start()
168
-
169
188
  def print_log(self) -> None:
170
189
  """
171
190
  Print the log of the plot process.
@@ -176,26 +195,6 @@ class BECGuiClientMixin:
176
195
  # Flush list
177
196
  self.stderr_output.clear()
178
197
 
179
- def _get_output(self) -> str:
180
- try:
181
- os.set_blocking(self._process.stdout.fileno(), False)
182
- os.set_blocking(self._process.stderr.fileno(), False)
183
- while self._process.poll() is None:
184
- readylist, _, _ = select.select(
185
- [self._process.stdout, self._process.stderr], [], [], 1
186
- )
187
- if self._process.stdout in readylist:
188
- output = self._process.stdout.read(1024)
189
- if output:
190
- print(output, end="")
191
- if self._process.stderr in readylist:
192
- error_output = self._process.stderr.read(1024)
193
- if error_output:
194
- print(error_output, end="", file=sys.stderr)
195
- self.stderr_output.append(error_output)
196
- except Exception as e:
197
- print(f"Error reading process output: {str(e)}")
198
-
199
198
 
200
199
  class RPCResponseTimeoutError(Exception):
201
200
  """Exception raised when an RPC response is not received within the expected time."""
@@ -33,6 +33,7 @@ class BECDockArea(BECConnector, DockArea):
33
33
  "detach_dock",
34
34
  "attach_all",
35
35
  "get_all_rpc",
36
+ "temp_areas",
36
37
  ]
37
38
 
38
39
  def __init__(
@@ -70,9 +71,22 @@ class BECDockArea(BECConnector, DockArea):
70
71
 
71
72
  @panels.setter
72
73
  def panels(self, value: dict):
73
-
74
74
  self.docks = WeakValueDictionary(value)
75
75
 
76
+ @property
77
+ def temp_areas(self) -> list:
78
+ """
79
+ Get the temporary areas in the dock area.
80
+
81
+ Returns:
82
+ list: The temporary areas in the dock area.
83
+ """
84
+ return list(map(str, self.tempAreas))
85
+
86
+ @temp_areas.setter
87
+ def temp_areas(self, value: list):
88
+ self.tempAreas = list(map(str, value))
89
+
76
90
  def restore_state(
77
91
  self, state: dict = None, missing: Literal["ignore", "error"] = "ignore", extra="bottom"
78
92
  ):
@@ -107,6 +121,7 @@ class BECDockArea(BECConnector, DockArea):
107
121
  name(str): The name of the dock to remove.
108
122
  """
109
123
  dock = self.docks.pop(name, None)
124
+ self.config.docks.pop(name, None)
110
125
  if dock:
111
126
  dock.close()
112
127
  if len(self.docks) <= 1:
@@ -190,7 +205,7 @@ class BECDockArea(BECConnector, DockArea):
190
205
  BECDock: The undocked dock.
191
206
  """
192
207
  dock = self.docks[dock_name]
193
- self.floatDock(dock)
208
+ dock.detach()
194
209
  return dock
195
210
 
196
211
  def attach_all(self):
@@ -317,7 +317,7 @@ class BECMotorMap(BECPlotBase):
317
317
  Returns:
318
318
  float: Motor initial position.
319
319
  """
320
- init_position = round(self.dev[name].read()[entry]["value"], precision)
320
+ init_position = round(float(self.dev[name].read()[entry]["value"]), precision)
321
321
  return init_position
322
322
 
323
323
  def _validate_signal_entries(
@@ -403,7 +403,7 @@ class BECMotorMap(BECPlotBase):
403
403
  # Update plot title
404
404
  precision = self.config.precision
405
405
  self.set_title(
406
- f"Motor position: ({round(current_x,precision)}, {round(current_y,precision)})"
406
+ f"Motor position: ({round(float(current_x),precision)}, {round(float(current_y),precision)})"
407
407
  )
408
408
 
409
409
  @pyqtSlot(dict)
@@ -577,7 +577,6 @@ class BECWaveform(BECPlotBase):
577
577
  Returns:
578
578
  dict | pd.DataFrame: Data of all curves in the specified format.
579
579
  """
580
-
581
580
  data = {}
582
581
  try:
583
582
  import pandas as pd
@@ -115,7 +115,8 @@ class Ring(BECConnector):
115
115
 
116
116
  def set_value(self, value: int | float):
117
117
  self.config.value = round(
118
- max(self.config.min_value, min(self.config.max_value, value)), self.config.precision
118
+ float(max(self.config.min_value, min(self.config.max_value, value))),
119
+ self.config.precision,
119
120
  )
120
121
 
121
122
  def set_color(self, color: str | tuple):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.57.1
3
+ Version: 0.57.2
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
@@ -27,6 +27,7 @@ Requires-Dist: pytest; extra == 'dev'
27
27
  Requires-Dist: pytest-qt; extra == 'dev'
28
28
  Requires-Dist: pytest-random-order; extra == 'dev'
29
29
  Requires-Dist: pytest-timeout; extra == 'dev'
30
+ Requires-Dist: pytest-xvfb; extra == 'dev'
30
31
  Provides-Extra: pyqt5
31
32
  Requires-Dist: pyqt5>=5.9; extra == 'pyqt5'
32
33
  Provides-Extra: pyqt6
@@ -2,11 +2,11 @@
2
2
  .gitlab-ci.yml,sha256=RF2JeGh8tG09DyAOwEu991IZy3C8Vm6lI8O_4Dr9B9Q,12239
3
3
  .pylintrc,sha256=OstrgmEyP0smNFBKoIN5_26-UmNZgMHnbjvAWX0UrLs,18535
4
4
  .readthedocs.yaml,sha256=aSOc277LqXcsTI6lgvm_JY80lMlr69GbPKgivua2cS0,603
5
- CHANGELOG.md,sha256=zxHMzEXHUbEgqxmsrAtt2A-iiShgClvqzI5lZKRqoX4,6824
5
+ CHANGELOG.md,sha256=pG4sxxA4UKrOCZsHzC7nzYA5A7dwla6lFKnMujn04rQ,6889
6
6
  LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
7
- PKG-INFO,sha256=3KI7EdkH96oYBSsLvSfLCot3XuI2m8AgiRHo3zXUrRo,1135
7
+ PKG-INFO,sha256=VKjVy_MzeMyq50c2kmwfQ9hoe6abecAZIR6nSJcwVck,1178
8
8
  README.md,sha256=y4jB6wvArS7N8_iTbKWnSM_oRAqLA2GqgzUR-FMh5sU,2645
9
- pyproject.toml,sha256=-9xY8HWFrm3iGS29r-3dRMXdM-LJecifdKwnmvYoWPU,1803
9
+ pyproject.toml,sha256=mYnyN3JxG1ULTqPhRsHj5xvuD0wUNtZydA6gaSddQSE,1822
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
@@ -17,8 +17,8 @@ bec_widgets/assets/bec_widgets_icon.png,sha256=K8dgGwIjalDh9PRHUsSQBqgdX7a00nM3i
17
17
  bec_widgets/assets/terminal_icon.png,sha256=bJl7Tft4Fi2uxvuXI8o14uMHnI9eAWKSU2uftXCH9ws,3889
18
18
  bec_widgets/cli/__init__.py,sha256=tLD8HWgyURhMjYlKZ43pBu-qvGD1LI5o3n3rEieg-70,43
19
19
  bec_widgets/cli/auto_updates.py,sha256=8x4_SrD8Hh1RbrUWXLfisw6X5v8Mij2DiTfjvn9dkUw,4692
20
- bec_widgets/cli/client.py,sha256=_39klWIob_MdCJ8mxjXhJ_1z56qVCoyeMH0Ji2uEiik,52876
21
- bec_widgets/cli/client_utils.py,sha256=gxa9TpYCWa0a7jsrMaWv_FQOnfeqP-xht8PYbhcEgys,10802
20
+ bec_widgets/cli/client.py,sha256=DaBkuNB38XhOdNuAmd7UPaEy4kEWCgOdWWfMsPBsWAI,53089
21
+ bec_widgets/cli/client_utils.py,sha256=7u8P9EYgLPJuAcHxnFiZi-gCZohO3vAn0W7dqsSrs4M,10660
22
22
  bec_widgets/cli/generate_cli.py,sha256=tBt-F4Xccg9Pj2zuDEGHd0Ho1fKLfCf3PuSa8KmelQk,4431
23
23
  bec_widgets/cli/rpc_register.py,sha256=QxXUZu5XNg00Yf5O3UHWOXg3-f_pzKjjoZYMOa-MOJc,2216
24
24
  bec_widgets/cli/rpc_wigdet_handler.py,sha256=OXHoiDFJPzbQ5RO0bzIX5aUXeMMlJTwAiTmB0_7Chj4,913
@@ -49,7 +49,7 @@ bec_widgets/utils/yaml_dialog.py,sha256=cMVif-39SB9WjwGH5FWBJcFs4tnfFJFs5cacydRy
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
51
  bec_widgets/widgets/dock/dock.py,sha256=kdX0ZbuUdx6XETZ1NUgzBWlee_Q7JcN3fXpARDAlre8,8955
52
- bec_widgets/widgets/dock/dock_area.py,sha256=MtuT6_LYCPQ0TnKBtO4_4ReA9L8tZZrroUjkzEQspdk,7322
52
+ bec_widgets/widgets/dock/dock_area.py,sha256=Yj01iI5Lzh-Rf6D9Z4m48JItVHC-1954MJHfjYimEE8,7731
53
53
  bec_widgets/widgets/figure/__init__.py,sha256=3hGx_KOV7QHCYAV06aNuUgKq4QIYCjUTad-DrwkUaBM,44
54
54
  bec_widgets/widgets/figure/figure.py,sha256=OzeKZme89JnzMcKT1sACnyw951EtRoSUALl58upY6b4,29762
55
55
  bec_widgets/widgets/figure/plots/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -59,9 +59,9 @@ bec_widgets/widgets/figure/plots/image/image.py,sha256=fdANm_lMzmKeddwCq3Arc1p48
59
59
  bec_widgets/widgets/figure/plots/image/image_item.py,sha256=1oytCY2IIgRbtS3GRrp9JV02KOif78O2-iaK0qYuHFU,9058
60
60
  bec_widgets/widgets/figure/plots/image/image_processor.py,sha256=59JwHMEBjLo72fmrAB7W1PFBT2oBe16heBaZfYM6MAk,4368
61
61
  bec_widgets/widgets/figure/plots/motor_map/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
- bec_widgets/widgets/figure/plots/motor_map/motor_map.py,sha256=HKRbt8sD8fmzpYcEWD8-nYs1Mv7pLup1BfRAEVmKN3A,15246
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=k6Lh08V00N9gATppaLgaSaij4Husf8sYU_HXTvF3oB4,21664
64
+ bec_widgets/widgets/figure/plots/waveform/waveform.py,sha256=U0d4Qdsej9AlHrAf7krgE4AFWEkK_Y-IAGjH-Tv9bT0,21663
65
65
  bec_widgets/widgets/figure/plots/waveform/waveform_curve.py,sha256=9q7nJfyH8y9rWw_AIOd6tk7cbckoAGNLHv2oHEKCCyo,7229
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
@@ -82,7 +82,7 @@ bec_widgets/widgets/motor_control/selection/selection.ui,sha256=vXXpvNWuL6xyHhW7
82
82
  bec_widgets/widgets/scan_control/__init__.py,sha256=IOfHl15vxb_uC6KN62-PeUzbBha_vQyqkkXbJ2HU674,38
83
83
  bec_widgets/widgets/scan_control/scan_control.py,sha256=B5n2U2iVtTCY3Tx93JyBqzGCDCmWhWwAOhbPelLI-bs,17168
84
84
  bec_widgets/widgets/spiral_progress_bar/__init__.py,sha256=4efbtcqCToMIw5bkQrTzy2TzuBCXvlhuUPh1bYC_Yzg,51
85
- bec_widgets/widgets/spiral_progress_bar/ring.py,sha256=_wUIZOZ_UZaI3U9-s-VS5v-yv5NBPB991WoXunNr1jI,7077
85
+ bec_widgets/widgets/spiral_progress_bar/ring.py,sha256=WlS3L3mSxFQNtc8T_XEPM7IoVeXYnM2SE5ImjvX6kJU,7097
86
86
  bec_widgets/widgets/spiral_progress_bar/spiral_progress_bar.py,sha256=AjQsZDEqPlTn0kE4xkYKOj2ae5vJ9gW-k3yz1Y32vsY,22543
87
87
  bec_widgets/widgets/toolbar/__init__.py,sha256=d-TP4_cr_VbpwreMM4ePnfZ5YXsEPQ45ibEf75nuGoE,36
88
88
  bec_widgets/widgets/toolbar/toolbar.py,sha256=e0zCD_0q7K4NVhrzD8001Qvfxt-VhqHTgofchS9NgCM,5125
@@ -122,10 +122,10 @@ docs/user/widgets/w1D.gif,sha256=tuHbleJpl6bJFNNC2OdndF5LF7IyfvlkFCMGZajrQPs,622
122
122
  docs/user/widgets/widgets.md,sha256=NFdqTlLTHXueErLzvw4wHwTUrzRSEuRelb1fiT4PySg,352
123
123
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
124
124
  tests/end-2-end/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
125
- tests/end-2-end/conftest.py,sha256=b5Yebbj8C1-IcXq23XGbOnXF0kOZD_Po46Z-p4cBwfs,1346
126
- tests/end-2-end/test_bec_dock_rpc_e2e.py,sha256=5W1uczZV6AqzjY6rHMR8GJDQuGpImtz-BGqq_cdqjbE,9823
127
- tests/end-2-end/test_bec_figure_rpc_e2e.py,sha256=X8lQLx2NsB6-nU61IhVtAw1-pJ4A2qFgx5PxOWC0V7Q,5527
128
- tests/end-2-end/test_rpc_register_e2e.py,sha256=M7sSq3us2yQIW5tAIFOFfBULatZTQNLdt0frh1bINts,1595
125
+ tests/end-2-end/conftest.py,sha256=taLqiYVzOhJjMre5ypgQjB7wzSXP4soKANW3XfAjems,1773
126
+ tests/end-2-end/test_bec_dock_rpc_e2e.py,sha256=G-YBfOhJCyV6g74mxXuhAPA9E_BPQ6EUT6xS278aq34,8865
127
+ tests/end-2-end/test_bec_figure_rpc_e2e.py,sha256=yIbGoDJRN22XVmNASCSh51MdcCMSan1d1qNW1QIXiVk,5082
128
+ tests/end-2-end/test_rpc_register_e2e.py,sha256=yUt0-UzWZX1keyHO-dyK0zIevtTgBWLP47_zpcvBywI,1583
129
129
  tests/unit_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
130
130
  tests/unit_tests/client_mocks.py,sha256=ErrklY7446jXE2_XGKebs_a-2Pqif5ECOPvxVAKRZXY,4170
131
131
  tests/unit_tests/conftest.py,sha256=KrnktXPWmZhnKNue-xGWOLD1XGEvdz9Vf7V2eO3XQ3A,596
@@ -150,7 +150,7 @@ tests/unit_tests/test_configs/config_device_no_entry.yaml,sha256=hdvue9KLc_kfNzG
150
150
  tests/unit_tests/test_configs/config_scan.yaml,sha256=vo484BbWOjA_e-h6bTjSV9k7QaQHrlAvx-z8wtY-P4E,1915
151
151
  tests/unit_tests/test_msgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
152
152
  tests/unit_tests/test_msgs/available_scans_message.py,sha256=m_z97hIrjHXXMa2Ex-UvsPmTxOYXfjxyJaGkIY6StTY,46532
153
- bec_widgets-0.57.1.dist-info/METADATA,sha256=3KI7EdkH96oYBSsLvSfLCot3XuI2m8AgiRHo3zXUrRo,1135
154
- bec_widgets-0.57.1.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
155
- bec_widgets-0.57.1.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
156
- bec_widgets-0.57.1.dist-info/RECORD,,
153
+ bec_widgets-0.57.2.dist-info/METADATA,sha256=VKjVy_MzeMyq50c2kmwfQ9hoe6abecAZIR6nSJcwVck,1178
154
+ bec_widgets-0.57.2.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
155
+ bec_widgets-0.57.2.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
156
+ bec_widgets-0.57.2.dist-info/RECORD,,
pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bec_widgets"
7
- version = "0.57.1"
7
+ version = "0.57.2"
8
8
  description = "BEC Widgets"
9
9
  requires-python = ">=3.10"
10
10
  classifiers = [
@@ -31,6 +31,7 @@ dev = [
31
31
  "pytest",
32
32
  "pytest-random-order",
33
33
  "pytest-timeout",
34
+ "pytest-xvfb",
34
35
  "coverage",
35
36
  "pytest-qt",
36
37
  "isort",
@@ -1,40 +1,55 @@
1
+ import random
2
+ import time
3
+ from contextlib import contextmanager
4
+
1
5
  import pytest
6
+ from bec_lib.endpoints import MessageEndpoints
2
7
 
8
+ from bec_widgets.cli.client_utils import _start_plot_process
3
9
  from bec_widgets.cli.rpc_register import RPCRegister
4
- from bec_widgets.cli.server import BECWidgetsCLIServer
5
10
  from bec_widgets.utils import BECDispatcher
6
11
  from bec_widgets.widgets import BECDockArea, BECFigure
7
12
 
8
13
 
14
+ # make threads check in autouse, **will be executed at the end**; better than
15
+ # having it in fixtures for each test, since it prevents from needing to
16
+ # 'manually' shutdown bec_client_lib (for example) to make it happy, whereas
17
+ # whereas in fact bec_client_lib makes its on cleanup
9
18
  @pytest.fixture(autouse=True)
10
- def rpc_register():
11
- yield RPCRegister()
12
- RPCRegister.reset_singleton()
19
+ def threads_check_fixture(threads_check):
20
+ return
21
+
22
+
23
+ @pytest.fixture
24
+ def gui_id():
25
+ return f"figure_{random.randint(0,100)}" # make a new gui id each time, to ensure no 'gui is alive' zombie key can perturbate
26
+
27
+
28
+ @contextmanager
29
+ def plot_server(gui_id, klass, client_lib):
30
+ dispatcher = BECDispatcher(client=client_lib) # Has to init singleton with fixture client
31
+ process, output_thread = _start_plot_process(
32
+ gui_id, klass, client_lib._client._service_config.redis
33
+ )
34
+ try:
35
+ while client_lib._client.connector.get(MessageEndpoints.gui_heartbeat(gui_id)) is None:
36
+ time.sleep(0.3)
37
+ yield gui_id
38
+ finally:
39
+ process.terminate()
40
+ process.wait()
41
+ output_thread.join()
42
+ dispatcher.disconnect_all()
43
+ dispatcher.reset_singleton()
13
44
 
14
45
 
15
46
  @pytest.fixture
16
- def rpc_server_figure(qtbot, bec_client_lib, threads_check):
17
- dispatcher = BECDispatcher(client=bec_client_lib) # Has to init singleton with fixture client
18
- server = BECWidgetsCLIServer(gui_id="figure", gui_class=BECFigure)
19
- qtbot.addWidget(server.gui)
20
- qtbot.waitExposed(server.gui)
21
- qtbot.wait(1000) # 1s long to wait until gui is ready
22
- yield server
23
- dispatcher.disconnect_all()
24
- server.client.shutdown()
25
- server.shutdown()
26
- dispatcher.reset_singleton()
47
+ def rpc_server_figure(gui_id, bec_client_lib):
48
+ with plot_server(gui_id, BECFigure, bec_client_lib) as server:
49
+ yield server
27
50
 
28
51
 
29
52
  @pytest.fixture
30
- def rpc_server_dock(qtbot, bec_client_lib, threads_check):
31
- dispatcher = BECDispatcher(client=bec_client_lib) # Has to init singleton with fixture client
32
- server = BECWidgetsCLIServer(gui_id="figure", gui_class=BECDockArea)
33
- qtbot.addWidget(server.gui)
34
- qtbot.waitExposed(server.gui)
35
- qtbot.wait(1000) # 1s long to wait until gui is ready
36
- yield server
37
- dispatcher.disconnect_all()
38
- server.client.shutdown()
39
- server.shutdown()
40
- dispatcher.reset_singleton()
53
+ def rpc_server_dock(gui_id, bec_client_lib):
54
+ with plot_server(gui_id, BECDockArea, bec_client_lib) as server:
55
+ yield server
@@ -1,3 +1,5 @@
1
+ import time
2
+
1
3
  import numpy as np
2
4
  import pytest
3
5
  from bec_lib.client import BECClient
@@ -8,24 +10,10 @@ from bec_widgets.cli.client import BECDockArea, BECFigure, BECImageShow, BECMoto
8
10
  from bec_widgets.utils import Colors
9
11
 
10
12
 
11
- @pytest.fixture(name="bec_client")
12
- def cli_bec_client(rpc_server_dock):
13
- """
14
- Fixture to create a BECClient instance that is independent of the GUI.
15
- """
16
- # pylint: disable=protected-access
17
- cli_client = BECClient(forced=True, config=rpc_server_dock.client._service_config)
18
- cli_client.start()
19
- yield cli_client
20
- cli_client.shutdown()
21
-
22
-
23
- def test_rpc_add_dock_with_figure_e2e(rpc_server_dock, qtbot):
24
- dock = BECDockArea(rpc_server_dock.gui_id)
25
- dock_server = rpc_server_dock.gui
26
-
13
+ def test_rpc_add_dock_with_figure_e2e(bec_client_lib, rpc_server_dock):
27
14
  # BEC client shortcuts
28
- client = rpc_server_dock.client
15
+ dock = BECDockArea(rpc_server_dock)
16
+ client = bec_client_lib
29
17
  dev = client.device_manager.devices
30
18
  scans = client.scans
31
19
  queue = client.queue
@@ -35,17 +23,18 @@ def test_rpc_add_dock_with_figure_e2e(rpc_server_dock, qtbot):
35
23
  d1 = dock.add_dock("dock_1")
36
24
  d2 = dock.add_dock("dock_2")
37
25
 
38
- assert len(dock_server.docks) == 3
39
-
26
+ dock_config = dock.config_dict
27
+ assert len(dock_config["docks"]) == 3
40
28
  # Add 3 figures with some widgets
41
29
  fig0 = d0.add_widget("BECFigure")
42
30
  fig1 = d1.add_widget("BECFigure")
43
31
  fig2 = d2.add_widget("BECFigure")
44
32
 
45
- assert len(dock_server.docks) == 3
46
- assert len(dock_server.docks["dock_0"].widgets) == 1
47
- assert len(dock_server.docks["dock_1"].widgets) == 1
48
- assert len(dock_server.docks["dock_2"].widgets) == 1
33
+ dock_config = dock.config_dict
34
+ assert len(dock_config["docks"]) == 3
35
+ assert len(dock_config["docks"]["dock_0"]["widgets"]) == 1
36
+ assert len(dock_config["docks"]["dock_1"]["widgets"]) == 1
37
+ assert len(dock_config["docks"]["dock_2"]["widgets"]) == 1
49
38
 
50
39
  assert fig1.__class__.__name__ == "BECFigure"
51
40
  assert fig1.__class__ == BECFigure
@@ -98,7 +87,7 @@ def test_rpc_add_dock_with_figure_e2e(rpc_server_dock, qtbot):
98
87
 
99
88
  # wait for scan to finish
100
89
  while not status.status == "COMPLETED":
101
- qtbot.wait(200)
90
+ time.sleep(0.2)
102
91
 
103
92
  # plot
104
93
  plt_last_scan_data = queue.scan_storage.storage[-1].data
@@ -110,7 +99,7 @@ def test_rpc_add_dock_with_figure_e2e(rpc_server_dock, qtbot):
110
99
  last_image_device = client.connector.get_last(MessageEndpoints.device_monitor("eiger"))[
111
100
  "data"
112
101
  ].data
113
- qtbot.wait(500)
102
+ time.sleep(0.5)
114
103
  last_image_plot = im.images[0].get_data()
115
104
  np.testing.assert_equal(last_image_device, last_image_plot)
116
105
 
@@ -129,40 +118,41 @@ def test_rpc_add_dock_with_figure_e2e(rpc_server_dock, qtbot):
129
118
  )
130
119
 
131
120
 
132
- def test_dock_manipulations_e2e(rpc_server_dock, qtbot):
133
- dock = BECDockArea(rpc_server_dock.gui_id)
134
- dock_server = rpc_server_dock.gui
121
+ def test_dock_manipulations_e2e(rpc_server_dock):
122
+ dock = BECDockArea(rpc_server_dock)
135
123
 
136
124
  d0 = dock.add_dock("dock_0")
137
125
  d1 = dock.add_dock("dock_1")
138
126
  d2 = dock.add_dock("dock_2")
139
- assert len(dock_server.docks) == 3
127
+ dock_config = dock.config_dict
128
+ assert len(dock_config["docks"]) == 3
140
129
 
141
130
  d0.detach()
142
131
  dock.detach_dock("dock_2")
143
- assert len(dock_server.docks) == 3
144
- assert len(dock_server.tempAreas) == 2
132
+ dock_config = dock.config_dict
133
+ assert len(dock_config["docks"]) == 3
134
+ assert len(dock.temp_areas) == 2
145
135
 
146
136
  d0.attach()
147
- assert len(dock_server.docks) == 3
148
- assert len(dock_server.tempAreas) == 1
137
+ dock_config = dock.config_dict
138
+ assert len(dock_config["docks"]) == 3
139
+ assert len(dock.temp_areas) == 1
149
140
 
150
141
  d2.remove()
151
- qtbot.wait(200)
142
+ dock_config = dock.config_dict
143
+ assert len(dock_config["docks"]) == 2
152
144
 
153
- assert len(dock_server.docks) == 2
154
- docks_list = list(dict(dock_server.docks).keys())
155
- assert ["dock_0", "dock_1"] == docks_list
145
+ assert ["dock_0", "dock_1"] == list(dock_config["docks"])
156
146
 
157
147
  dock.clear_all()
158
148
 
159
- assert len(dock_server.docks) == 0
160
- assert len(dock_server.tempAreas) == 0
149
+ dock_config = dock.config_dict
150
+ assert len(dock_config["docks"]) == 0
151
+ assert len(dock.temp_areas) == 0
161
152
 
162
153
 
163
154
  def test_spiral_bar(rpc_server_dock):
164
- dock = BECDockArea(rpc_server_dock.gui_id)
165
- dock_server = rpc_server_dock.gui
155
+ dock = BECDockArea(rpc_server_dock)
166
156
 
167
157
  d0 = dock.add_dock(name="dock_0")
168
158
 
@@ -173,49 +163,46 @@ def test_spiral_bar(rpc_server_dock):
173
163
  bar.set_colors_from_map("viridis")
174
164
  bar.set_value([10, 20, 30, 40, 50])
175
165
 
176
- bar_server = dock_server.docks["dock_0"].widgets[0]
166
+ bar_config = bar.config_dict
177
167
 
178
- expected_colors = Colors.golden_angle_color("viridis", 5, "RGB")
179
- bar_colors = [ring.color.getRgb() for ring in bar_server.rings]
180
- bar_values = [ring.config.value for ring in bar_server.rings]
168
+ expected_colors = [list(color) for color in Colors.golden_angle_color("viridis", 5, "RGB")]
169
+ bar_colors = [ring.config_dict["color"] for ring in bar.rings]
170
+ bar_values = [ring.config_dict["value"] for ring in bar.rings]
171
+ assert bar_config["num_bars"] == 5
181
172
  assert bar_values == [10, 20, 30, 40, 50]
182
173
  assert bar_colors == expected_colors
183
174
 
184
175
 
185
- def test_spiral_bar_scan_update(rpc_server_dock, qtbot):
186
- dock = BECDockArea(rpc_server_dock.gui_id)
187
- dock_server = rpc_server_dock.gui
176
+ def test_spiral_bar_scan_update(bec_client_lib, rpc_server_dock):
177
+ dock = BECDockArea(rpc_server_dock)
188
178
 
189
179
  d0 = dock.add_dock("dock_0")
190
180
 
191
- d0.add_widget("SpiralProgressBar")
181
+ bar = d0.add_widget("SpiralProgressBar")
192
182
 
193
- client = rpc_server_dock.client
183
+ client = bec_client_lib
194
184
  dev = client.device_manager.devices
185
+ dev.samx.tolerance.set(0)
186
+ dev.samy.tolerance.set(0)
195
187
  scans = client.scans
196
188
 
197
189
  status = scans.line_scan(dev.samx, -5, 5, steps=10, exp_time=0.05, relative=False)
190
+ status.wait()
198
191
 
199
- while not status.status == "COMPLETED":
200
- qtbot.wait(200)
201
-
202
- qtbot.wait(200)
203
- bar_server = dock_server.docks["dock_0"].widgets[0]
204
- assert bar_server.config.num_bars == 1
205
- np.testing.assert_allclose(bar_server.rings[0].config.value, 10, atol=0.1)
206
- np.testing.assert_allclose(bar_server.rings[0].config.min_value, 0, atol=0.1)
207
- np.testing.assert_allclose(bar_server.rings[0].config.max_value, 10, atol=0.1)
192
+ bar_config = bar.config_dict
193
+ assert bar_config["num_bars"] == 1
194
+ assert bar_config["rings"][0]["value"] == 10
195
+ assert bar_config["rings"][0]["min_value"] == 0
196
+ assert bar_config["rings"][0]["max_value"] == 10
208
197
 
209
198
  status = scans.grid_scan(dev.samx, -5, 5, 4, dev.samy, -10, 10, 4, relative=True, exp_time=0.1)
199
+ status.wait()
210
200
 
211
- while not status.status == "COMPLETED":
212
- qtbot.wait(200)
213
-
214
- qtbot.wait(200)
215
- assert bar_server.config.num_bars == 1
216
- np.testing.assert_allclose(bar_server.rings[0].config.value, 16, atol=0.1)
217
- np.testing.assert_allclose(bar_server.rings[0].config.min_value, 0, atol=0.1)
218
- np.testing.assert_allclose(bar_server.rings[0].config.max_value, 16, atol=0.1)
201
+ bar_config = bar.config_dict
202
+ assert bar_config["num_bars"] == 1
203
+ assert bar_config["rings"][0]["value"] == 16
204
+ assert bar_config["rings"][0]["min_value"] == 0
205
+ assert bar_config["rings"][0]["max_value"] == 16
219
206
 
220
207
  init_samx = dev.samx.read()["samx"]["value"]
221
208
  init_samy = dev.samy.read()["samy"]["value"]
@@ -226,23 +213,20 @@ def test_spiral_bar_scan_update(rpc_server_dock, qtbot):
226
213
  dev.samy.velocity.put(5)
227
214
 
228
215
  status = scans.umv(dev.samx, 5, dev.samy, 10, relative=True)
216
+ status.wait()
229
217
 
230
- while not status.status == "COMPLETED":
231
- qtbot.wait(200)
232
-
233
- qtbot.wait(200)
234
- assert bar_server.config.num_bars == 2
235
- np.testing.assert_allclose(bar_server.rings[0].config.value, final_samx, atol=0.1)
236
- np.testing.assert_allclose(bar_server.rings[1].config.value, final_samy, atol=0.1)
237
- np.testing.assert_allclose(bar_server.rings[0].config.min_value, init_samx, atol=0.1)
238
- np.testing.assert_allclose(bar_server.rings[1].config.min_value, init_samy, atol=0.1)
239
- np.testing.assert_allclose(bar_server.rings[0].config.max_value, final_samx, atol=0.1)
240
- np.testing.assert_allclose(bar_server.rings[1].config.max_value, final_samy, atol=0.1)
218
+ bar_config = bar.config_dict
219
+ assert bar_config["num_bars"] == 2
220
+ assert bar_config["rings"][0]["value"] == final_samx
221
+ assert bar_config["rings"][1]["value"] == final_samy
222
+ assert bar_config["rings"][0]["min_value"] == init_samx
223
+ assert bar_config["rings"][0]["max_value"] == final_samx
224
+ assert bar_config["rings"][1]["min_value"] == init_samy
225
+ assert bar_config["rings"][1]["max_value"] == final_samy
241
226
 
242
227
 
243
- def test_auto_update(rpc_server_dock, bec_client, qtbot):
244
- dock = BECDockArea(rpc_server_dock.gui_id)
245
- dock._client = bec_client
228
+ def test_auto_update(bec_client_lib, rpc_server_dock):
229
+ dock = BECDockArea(rpc_server_dock)
246
230
 
247
231
  AutoUpdates.enabled = True
248
232
  AutoUpdates.create_default_dock = True
@@ -253,16 +237,13 @@ def test_auto_update(rpc_server_dock, bec_client, qtbot):
253
237
  # we need to start the update script manually; normally this is done when the GUI is started
254
238
  dock._start_update_script()
255
239
 
256
- client = bec_client
240
+ client = bec_client_lib
257
241
  dev = client.device_manager.devices
258
242
  scans = client.scans
259
243
  queue = client.queue
260
244
 
261
245
  status = scans.line_scan(dev.samx, -5, 5, steps=10, exp_time=0.05, relative=False)
262
-
263
- # wait for scan to finish
264
- while not status.status == "COMPLETED":
265
- qtbot.wait(200)
246
+ status.wait()
266
247
 
267
248
  last_scan_data = queue.scan_storage.storage[-1].data
268
249
 
@@ -278,10 +259,7 @@ def test_auto_update(rpc_server_dock, bec_client, qtbot):
278
259
  status = scans.grid_scan(
279
260
  dev.samx, -10, 10, 5, dev.samy, -5, 5, 5, exp_time=0.05, relative=False
280
261
  )
281
-
282
- # wait for scan to finish
283
- while not status.status == "COMPLETED":
284
- qtbot.wait(200)
262
+ status.wait()
285
263
 
286
264
  plt = dock.auto_updates.get_default_figure()
287
265
  widgets = plt.widget_list
@@ -5,9 +5,8 @@ from bec_lib.endpoints import MessageEndpoints
5
5
  from bec_widgets.cli.client import BECFigure, BECImageShow, BECMotorMap, BECWaveform
6
6
 
7
7
 
8
- def test_rpc_waveform1d_custom_curve(rpc_server_figure, qtbot):
9
- fig = BECFigure(rpc_server_figure.gui_id)
10
- fig_server = rpc_server_figure.gui
8
+ def test_rpc_waveform1d_custom_curve(rpc_server_figure):
9
+ fig = BECFigure(rpc_server_figure)
11
10
 
12
11
  ax = fig.add_plot()
13
12
  curve = ax.add_curve_custom([1, 2, 3], [1, 2, 3])
@@ -15,13 +14,12 @@ def test_rpc_waveform1d_custom_curve(rpc_server_figure, qtbot):
15
14
  curve = ax.curves[0]
16
15
  curve.set_color("blue")
17
16
 
18
- assert len(fig_server.widgets) == 1
19
- assert len(fig_server.widgets[ax.rpc_id].curves) == 1
17
+ assert len(fig.widgets) == 1
18
+ assert len(fig.widgets[ax.rpc_id].curves) == 1
20
19
 
21
20
 
22
21
  def test_rpc_plotting_shortcuts_init_configs(rpc_server_figure, qtbot):
23
- fig = BECFigure(rpc_server_figure.gui_id)
24
- fig_server = rpc_server_figure.gui
22
+ fig = BECFigure(rpc_server_figure)
25
23
 
26
24
  plt = fig.plot(x_name="samx", y_name="bpm4i")
27
25
  im = fig.image("eiger")
@@ -29,7 +27,7 @@ def test_rpc_plotting_shortcuts_init_configs(rpc_server_figure, qtbot):
29
27
  plt_z = fig.add_plot("samx", "samy", "bpm4i")
30
28
 
31
29
  # Checking if classes are correctly initialised
32
- assert len(fig_server.widgets) == 4
30
+ assert len(fig.widgets) == 4
33
31
  assert plt.__class__.__name__ == "BECWaveform"
34
32
  assert plt.__class__ == BECWaveform
35
33
  assert im.__class__.__name__ == "BECImageShow"
@@ -75,24 +73,21 @@ def test_rpc_plotting_shortcuts_init_configs(rpc_server_figure, qtbot):
75
73
  }
76
74
 
77
75
 
78
- def test_rpc_waveform_scan(rpc_server_figure, qtbot):
79
- fig = BECFigure(rpc_server_figure.gui_id)
76
+ def test_rpc_waveform_scan(rpc_server_figure, bec_client_lib):
77
+ fig = BECFigure(rpc_server_figure)
80
78
 
81
79
  # add 3 different curves to track
82
80
  plt = fig.plot(x_name="samx", y_name="bpm4i")
83
81
  fig.plot(x_name="samx", y_name="bpm3a")
84
82
  fig.plot(x_name="samx", y_name="bpm4d")
85
83
 
86
- client = rpc_server_figure.client
84
+ client = bec_client_lib
87
85
  dev = client.device_manager.devices
88
86
  scans = client.scans
89
87
  queue = client.queue
90
88
 
91
89
  status = scans.line_scan(dev.samx, -5, 5, steps=10, exp_time=0.05, relative=False)
92
-
93
- # wait for scan to finish
94
- while not status.status == "COMPLETED":
95
- qtbot.wait(200)
90
+ status.wait()
96
91
 
97
92
  last_scan_data = queue.scan_storage.storage[-1].data
98
93
 
@@ -108,38 +103,33 @@ def test_rpc_waveform_scan(rpc_server_figure, qtbot):
108
103
  assert plt_data["bpm4d-bpm4d"]["y"] == last_scan_data["bpm4d"]["bpm4d"].val
109
104
 
110
105
 
111
- def test_rpc_image(rpc_server_figure, qtbot):
112
- fig = BECFigure(rpc_server_figure.gui_id)
106
+ def test_rpc_image(rpc_server_figure, bec_client_lib):
107
+ fig = BECFigure(rpc_server_figure)
113
108
 
114
109
  im = fig.image("eiger")
115
110
 
116
- client = rpc_server_figure.client
111
+ client = bec_client_lib
117
112
  dev = client.device_manager.devices
118
113
  scans = client.scans
119
114
 
120
115
  status = scans.line_scan(dev.samx, -5, 5, steps=10, exp_time=0.05, relative=False)
121
-
122
- # wait for scan to finish
123
- while not status.status == "COMPLETED":
124
- qtbot.wait(200)
116
+ status.wait()
125
117
 
126
118
  last_image_device = client.connector.get_last(MessageEndpoints.device_monitor("eiger"))[
127
119
  "data"
128
120
  ].data
129
- qtbot.wait(500)
130
121
  last_image_plot = im.images[0].get_data()
131
122
 
132
123
  # check plotted data
133
124
  np.testing.assert_equal(last_image_device, last_image_plot)
134
125
 
135
126
 
136
- def test_rpc_motor_map(rpc_server_figure, qtbot):
137
- fig = BECFigure(rpc_server_figure.gui_id)
138
- fig_server = rpc_server_figure.gui
127
+ def test_rpc_motor_map(rpc_server_figure, bec_client_lib):
128
+ fig = BECFigure(rpc_server_figure)
139
129
 
140
130
  motor_map = fig.motor_map("samx", "samy")
141
131
 
142
- client = rpc_server_figure.client
132
+ client = bec_client_lib
143
133
  dev = client.device_manager.devices
144
134
  scans = client.scans
145
135
 
@@ -147,10 +137,8 @@ def test_rpc_motor_map(rpc_server_figure, qtbot):
147
137
  initial_pos_y = dev.samy.read()["samy"]["value"]
148
138
 
149
139
  status = scans.mv(dev.samx, 1, dev.samy, 2, relative=True)
140
+ status.wait()
150
141
 
151
- # wait for scan to finish
152
- while not status.status == "COMPLETED":
153
- qtbot.wait(200)
154
142
  final_pos_x = dev.samx.read()["samx"]["value"]
155
143
  final_pos_y = dev.samy.read()["samy"]["value"]
156
144
 
@@ -3,40 +3,30 @@ import pytest
3
3
  from bec_widgets.cli.client import BECFigure, BECImageShow, BECMotorMap, BECWaveform
4
4
 
5
5
 
6
- def find_deepest_value(d: dict):
7
- """
8
- Recursively find the deepest value in a dictionary
9
- Args:
10
- d(dict): Dictionary to search
11
-
12
- Returns:
13
- The deepest value in the dictionary.
14
- """
15
- if isinstance(d, dict):
16
- if d:
17
- return find_deepest_value(next(iter(d.values())))
18
- return d
19
-
20
-
21
- def test_rpc_register_list_connections(rpc_server_figure, rpc_register, qtbot):
22
- fig = BECFigure(rpc_server_figure.gui_id)
23
- fig_server = rpc_server_figure.gui
6
+ def test_rpc_register_list_connections(rpc_server_figure):
7
+ fig = BECFigure(rpc_server_figure)
24
8
 
25
9
  plt = fig.plot(x_name="samx", y_name="bpm4i")
26
10
  im = fig.image("eiger")
27
11
  motor_map = fig.motor_map("samx", "samy")
28
12
  plt_z = fig.add_plot("samx", "samy", "bpm4i")
29
13
 
30
- all_connections = rpc_register.list_all_connections()
14
+ # keep only class names from objects, since objects on server and client are different
15
+ # so the best we can do is to compare types (rpc register is unit-tested elsewhere)
16
+ all_connections = {obj_id: type(obj).__name__ for obj_id, obj in fig.get_all_rpc().items()}
31
17
 
32
- # Construct dict of all rpc items manually
33
- all_subwidgets_expected = dict(fig_server.widgets)
34
- curve_1D = find_deepest_value(fig_server.widgets[plt.rpc_id]._curves_data)
35
- curve_2D = find_deepest_value(fig_server.widgets[plt_z.rpc_id]._curves_data)
36
- curves_expected = {curve_1D.rpc_id: curve_1D, curve_2D.rpc_id: curve_2D}
37
- fig_expected = {fig.rpc_id: fig_server}
18
+ all_subwidgets_expected = {wid: type(widget).__name__ for wid, widget in fig.widgets.items()}
19
+ curve_1D = fig.widgets[plt.rpc_id]
20
+ curve_2D = fig.widgets[plt_z.rpc_id]
21
+ curves_expected = {
22
+ curve_1D.rpc_id: type(curve_1D).__name__,
23
+ curve_2D.rpc_id: type(curve_2D).__name__,
24
+ }
25
+ curves_expected.update({curve._gui_id: type(curve).__name__ for curve in curve_1D.curves})
26
+ curves_expected.update({curve._gui_id: type(curve).__name__ for curve in curve_2D.curves})
27
+ fig_expected = {fig.rpc_id: type(fig).__name__}
38
28
  image_item_expected = {
39
- fig_server.widgets[im.rpc_id].images[0].rpc_id: fig_server.widgets[im.rpc_id].images[0]
29
+ fig.widgets[im.rpc_id].images[0].rpc_id: type(fig.widgets[im.rpc_id].images[0]).__name__
40
30
  }
41
31
 
42
32
  all_connections_expected = {