bec-widgets 0.50.0__py3-none-any.whl → 0.50.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.
- bec_widgets/cli/client_utils.py +3 -2
- bec_widgets/cli/server.py +8 -5
- bec_widgets/utils/bec_dispatcher.py +20 -5
- {bec_widgets-0.50.0.dist-info → bec_widgets-0.50.2.dist-info}/METADATA +1 -1
- {bec_widgets-0.50.0.dist-info → bec_widgets-0.50.2.dist-info}/RECORD +9 -9
- tests/unit_tests/test_bec_dispatcher.py +83 -2
- {bec_widgets-0.50.0.dist-info → bec_widgets-0.50.2.dist-info}/LICENSE +0 -0
- {bec_widgets-0.50.0.dist-info → bec_widgets-0.50.2.dist-info}/WHEEL +0 -0
- {bec_widgets-0.50.0.dist-info → bec_widgets-0.50.2.dist-info}/top_level.txt +0 -0
bec_widgets/cli/client_utils.py
CHANGED
@@ -12,7 +12,7 @@ import uuid
|
|
12
12
|
from functools import wraps
|
13
13
|
from typing import TYPE_CHECKING
|
14
14
|
|
15
|
-
from bec_lib import MessageEndpoints, messages
|
15
|
+
from bec_lib import MessageEndpoints, ServiceConfig, messages
|
16
16
|
from bec_lib.connector import MessageObject
|
17
17
|
from bec_lib.device import DeviceBase
|
18
18
|
from qtpy.QtCore import QCoreApplication
|
@@ -136,10 +136,11 @@ class BECFigureClientMixin:
|
|
136
136
|
"""
|
137
137
|
self._start_update_script()
|
138
138
|
# pylint: disable=subprocess-run-check
|
139
|
+
config = self._client._service_config.redis
|
139
140
|
monitor_module = importlib.import_module("bec_widgets.cli.server")
|
140
141
|
monitor_path = monitor_module.__file__
|
141
142
|
|
142
|
-
command = [sys.executable, "-u", monitor_path, "--id", self._gui_id]
|
143
|
+
command = [sys.executable, "-u", monitor_path, "--id", self._gui_id, "--config", config]
|
143
144
|
self._process = subprocess.Popen(
|
144
145
|
command, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
145
146
|
)
|
bec_widgets/cli/server.py
CHANGED
@@ -15,8 +15,10 @@ from bec_widgets.widgets.plots import BECCurve, BECImageShow, BECWaveform
|
|
15
15
|
class BECWidgetsCLIServer:
|
16
16
|
WIDGETS = [BECWaveform, BECFigure, BECCurve, BECImageShow]
|
17
17
|
|
18
|
-
def __init__(
|
19
|
-
self
|
18
|
+
def __init__(
|
19
|
+
self, gui_id: str = None, dispatcher: BECDispatcher = None, client=None, config=None
|
20
|
+
) -> None:
|
21
|
+
self.dispatcher = BECDispatcher(config=config) if dispatcher is None else dispatcher
|
20
22
|
self.client = self.dispatcher.client if client is None else client
|
21
23
|
self.client.start()
|
22
24
|
self.gui_id = gui_id
|
@@ -32,7 +34,7 @@ class BECWidgetsCLIServer:
|
|
32
34
|
self._shutdown_event = False
|
33
35
|
self._heartbeat_timer = QTimer()
|
34
36
|
self._heartbeat_timer.timeout.connect(self.emit_heartbeat)
|
35
|
-
self._heartbeat_timer.start(
|
37
|
+
self._heartbeat_timer.start(200) # Emit heartbeat every 1 seconds
|
36
38
|
|
37
39
|
def on_rpc_update(self, msg: dict, metadata: dict):
|
38
40
|
request_id = metadata.get("request_id")
|
@@ -125,11 +127,12 @@ if __name__ == "__main__": # pragma: no cover
|
|
125
127
|
|
126
128
|
parser = argparse.ArgumentParser(description="BEC Widgets CLI Server")
|
127
129
|
parser.add_argument("--id", type=str, help="The id of the server")
|
130
|
+
parser.add_argument("--config", type=str, help="Config to connect to redis.")
|
128
131
|
|
129
132
|
args = parser.parse_args()
|
130
133
|
|
131
|
-
server = BECWidgetsCLIServer(gui_id=args.id)
|
132
|
-
# server = BECWidgetsCLIServer(gui_id="test")
|
134
|
+
server = BECWidgetsCLIServer(gui_id=args.id, config=args.config)
|
135
|
+
# server = BECWidgetsCLIServer(gui_id="test",config="awi-bec-dev-01:6379")
|
133
136
|
|
134
137
|
fig = server.fig
|
135
138
|
win.setCentralWidget(fig)
|
@@ -6,7 +6,7 @@ from collections.abc import Callable
|
|
6
6
|
from typing import TYPE_CHECKING, Union
|
7
7
|
|
8
8
|
import redis
|
9
|
-
from bec_lib import BECClient
|
9
|
+
from bec_lib import BECClient, ServiceConfig
|
10
10
|
from bec_lib.redis_connector import MessageObject, RedisConnector
|
11
11
|
from qtpy.QtCore import QObject
|
12
12
|
from qtpy.QtCore import Signal as pyqtSignal
|
@@ -71,13 +71,13 @@ class BECDispatcher:
|
|
71
71
|
_instance = None
|
72
72
|
_initialized = False
|
73
73
|
|
74
|
-
def __new__(cls, client=None, *args, **kwargs):
|
74
|
+
def __new__(cls, client=None, config: str = None, *args, **kwargs):
|
75
75
|
if cls._instance is None:
|
76
76
|
cls._instance = super(BECDispatcher, cls).__new__(cls)
|
77
77
|
cls._initialized = False
|
78
78
|
return cls._instance
|
79
79
|
|
80
|
-
def __init__(self, client=None):
|
80
|
+
def __init__(self, client=None, config: str = None):
|
81
81
|
if self._initialized:
|
82
82
|
return
|
83
83
|
|
@@ -85,7 +85,14 @@ class BECDispatcher:
|
|
85
85
|
self.client = client
|
86
86
|
|
87
87
|
if self.client is None:
|
88
|
-
|
88
|
+
if config is not None:
|
89
|
+
host, port = config.split(":")
|
90
|
+
redis_config = {"host": host, "port": port}
|
91
|
+
self.client = BECClient(
|
92
|
+
config=ServiceConfig(redis=redis_config), connector_cls=QtRedisConnector
|
93
|
+
) # , forced=True)
|
94
|
+
else:
|
95
|
+
self.client = BECClient(connector_cls=QtRedisConnector) # , forced=True)
|
89
96
|
else:
|
90
97
|
if self.client.started:
|
91
98
|
# have to reinitialize client to use proper connector
|
@@ -122,7 +129,15 @@ class BECDispatcher:
|
|
122
129
|
self._slots[slot].update(set(topics_str))
|
123
130
|
|
124
131
|
def disconnect_slot(self, slot: Callable, topics: Union[str, list]):
|
125
|
-
|
132
|
+
# find the right slot to disconnect from ;
|
133
|
+
# slot callbacks are wrapped in QtThreadSafeCallback objects,
|
134
|
+
# but the slot we receive here is the original callable
|
135
|
+
for connected_slot in self._slots:
|
136
|
+
if connected_slot.cb == slot:
|
137
|
+
break
|
138
|
+
else:
|
139
|
+
return
|
140
|
+
self.client.connector.unregister(topics, cb=connected_slot)
|
126
141
|
topics_str, _ = self.client.connector._convert_endpointinfo(topics)
|
127
142
|
self._slots[slot].difference_update(set(topics_str))
|
128
143
|
if not self._slots[slot]:
|
@@ -3,10 +3,10 @@ bec_widgets/cli/__init__.py,sha256=ULoNTVnv2UeSSjhFq3uCQJ-0JTJf9oU76l27aRiizL4,7
|
|
3
3
|
bec_widgets/cli/auto_updates.py,sha256=ptZeBKr13o9THc8oKLn93K_16i6G3pxzw8hZ4MUgjW4,3845
|
4
4
|
bec_widgets/cli/bec_widgets_icon.png,sha256=pRCGpoOtwyZl97fBV_CHcGppliErzd0qQkCXLxjbp-s,5760
|
5
5
|
bec_widgets/cli/client.py,sha256=AvkaEDKB8cZFm2WS5JWIusMXtcqErEeP2Ayk9l7iAp8,39163
|
6
|
-
bec_widgets/cli/client_utils.py,sha256=
|
6
|
+
bec_widgets/cli/client_utils.py,sha256=IzyVAcko47vC47_oT0fAi9M-8OrZ2qmUfMlOAvQGuhU,10205
|
7
7
|
bec_widgets/cli/generate_cli.py,sha256=JLqUlUgfz_f_4KHPRUAN-Xli-K7uNOc8-F-LkAC7Scw,4004
|
8
8
|
bec_widgets/cli/rpc_register.py,sha256=OZOWX0IKGXqDsnrUYi0Irl_zpPS4Q_JPCV9JQfN6YYw,2212
|
9
|
-
bec_widgets/cli/server.py,sha256=
|
9
|
+
bec_widgets/cli/server.py,sha256=UpbegcLn2nd9gPF2swNfPQGHVwG14ZjQBpZKCAjQT4E,4942
|
10
10
|
bec_widgets/examples/__init__.py,sha256=WWQ0cu7m8sA4Ehy-DWdTIqSISjaHsbxhsNmNrMnhDZU,202
|
11
11
|
bec_widgets/examples/eiger_plot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
12
|
bec_widgets/examples/eiger_plot/eiger_plot.py,sha256=Uxl2Usf8jEzaX7AT8zVqa1x8ZIEgI1HmazSlb-tRFWE,10359
|
@@ -30,7 +30,7 @@ bec_widgets/examples/stream_plot/stream_plot.py,sha256=vHii1p9JxSyGQ_VcCjnk9SHJ4
|
|
30
30
|
bec_widgets/simulations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
31
31
|
bec_widgets/utils/__init__.py,sha256=xytx86Yosjkta0PU4rHfoeO7FCPcimS15xjMPQUgIXc,403
|
32
32
|
bec_widgets/utils/bec_connector.py,sha256=U_quQy7p1ISEpTnvwKsnDw5rdCc3jEoATfPVez2K7eI,4867
|
33
|
-
bec_widgets/utils/bec_dispatcher.py,sha256=
|
33
|
+
bec_widgets/utils/bec_dispatcher.py,sha256=xJrsHJ-flLFGA-XCa6wCsMzMpRu1fAy9IcUuLh6igSo,5569
|
34
34
|
bec_widgets/utils/bec_table.py,sha256=Xy5qM343K8EvEpB4g_129b63yo1wdEvEY3wqxB_p_Iw,716
|
35
35
|
bec_widgets/utils/colors.py,sha256=JsLxzkxbw-I8GIuvnIKyiM83n0edhyMG2Fa4Ffm62ww,2392
|
36
36
|
bec_widgets/utils/container_utils.py,sha256=rL-ryupQ4-7Y8mKNup5aklXleOfXSd97uwXTa9UR90A,1492
|
@@ -78,7 +78,7 @@ tests/unit_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
|
|
78
78
|
tests/unit_tests/client_mocks.py,sha256=LNUgI9Ccv5Ol7_pmybIhoVqZZem1RPIsTDk7ZTARNls,4128
|
79
79
|
tests/unit_tests/conftest.py,sha256=KrnktXPWmZhnKNue-xGWOLD1XGEvdz9Vf7V2eO3XQ3A,596
|
80
80
|
tests/unit_tests/test_bec_connector.py,sha256=f2XXGGw3NoZLIUrDuZuEWwF_ttOYmmquCgUrV5XkIOY,1951
|
81
|
-
tests/unit_tests/test_bec_dispatcher.py,sha256=
|
81
|
+
tests/unit_tests/test_bec_dispatcher.py,sha256=WW-wlzSgZA_h2Qx5EMvXfMlb2i7RYbWj2Cz3S2EzsZQ,4178
|
82
82
|
tests/unit_tests/test_bec_figure.py,sha256=T4k-E1D3sjTTDTFZGdTFDQv0EYNQ_R-QbWOM7pQwFw4,7926
|
83
83
|
tests/unit_tests/test_bec_monitor.py,sha256=mN7gBY7oXY6j65zzihpy8r-FvwVoCQlie3F6SoVq0mo,7042
|
84
84
|
tests/unit_tests/test_bec_motor_map.py,sha256=IXSfitUGxOPqmngwVNPK5nwi2QDcXWjBkGNb0dBZDxQ,4611
|
@@ -99,8 +99,8 @@ tests/unit_tests/test_widget_io.py,sha256=FeL3ZYSBQnRt6jxj8VGYw1cmcicRQyHKleahw7
|
|
99
99
|
tests/unit_tests/test_yaml_dialog.py,sha256=HNrqferkdg02-9ieOhhI2mr2Qvt7GrYgXmQ061YCTbg,5794
|
100
100
|
tests/unit_tests/test_msgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
101
101
|
tests/unit_tests/test_msgs/available_scans_message.py,sha256=m_z97hIrjHXXMa2Ex-UvsPmTxOYXfjxyJaGkIY6StTY,46532
|
102
|
-
bec_widgets-0.50.
|
103
|
-
bec_widgets-0.50.
|
104
|
-
bec_widgets-0.50.
|
105
|
-
bec_widgets-0.50.
|
106
|
-
bec_widgets-0.50.
|
102
|
+
bec_widgets-0.50.2.dist-info/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
|
103
|
+
bec_widgets-0.50.2.dist-info/METADATA,sha256=1y0vUcfn4EHSqdP0RgJQ99mJRfVR1Qq7u16T95__1S4,3719
|
104
|
+
bec_widgets-0.50.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
105
|
+
bec_widgets-0.50.2.dist-info/top_level.txt,sha256=EXCwhJYmXmd1DjYYL3hrGsddX-97IwYSiIHrf27FFVk,18
|
106
|
+
bec_widgets-0.50.2.dist-info/RECORD,,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# pylint: disable = no-name-in-module,missing-class-docstring, missing-module-docstring
|
2
|
+
import threading
|
2
3
|
import time
|
3
4
|
from unittest import mock
|
4
5
|
|
@@ -13,8 +14,9 @@ from bec_widgets.utils.bec_dispatcher import QtRedisConnector
|
|
13
14
|
|
14
15
|
|
15
16
|
@pytest.fixture
|
16
|
-
def bec_dispatcher_w_connector(bec_dispatcher, topics_msg_list):
|
17
|
+
def bec_dispatcher_w_connector(bec_dispatcher, topics_msg_list, send_msg_event):
|
17
18
|
def pubsub_msg_generator():
|
19
|
+
send_msg_event.wait()
|
18
20
|
for topic, msg in topics_msg_list:
|
19
21
|
yield {"channel": topic.encode(), "pattern": None, "data": msg}
|
20
22
|
while True:
|
@@ -33,6 +35,11 @@ def bec_dispatcher_w_connector(bec_dispatcher, topics_msg_list):
|
|
33
35
|
dummy_msg = MsgpackSerialization.dumps(ScanMessage(point_id=0, scan_id="0", data={}))
|
34
36
|
|
35
37
|
|
38
|
+
@pytest.fixture
|
39
|
+
def send_msg_event():
|
40
|
+
return threading.Event()
|
41
|
+
|
42
|
+
|
36
43
|
@pytest.mark.parametrize(
|
37
44
|
"topics_msg_list",
|
38
45
|
[
|
@@ -43,7 +50,7 @@ dummy_msg = MsgpackSerialization.dumps(ScanMessage(point_id=0, scan_id="0", data
|
|
43
50
|
)
|
44
51
|
],
|
45
52
|
)
|
46
|
-
def test_dispatcher_disconnect_all(bec_dispatcher_w_connector, qtbot):
|
53
|
+
def test_dispatcher_disconnect_all(bec_dispatcher_w_connector, qtbot, send_msg_event):
|
47
54
|
bec_dispatcher = bec_dispatcher_w_connector
|
48
55
|
cb1 = mock.Mock(spec=[])
|
49
56
|
cb2 = mock.Mock(spec=[])
|
@@ -53,7 +60,81 @@ def test_dispatcher_disconnect_all(bec_dispatcher_w_connector, qtbot):
|
|
53
60
|
bec_dispatcher.connect_slot(cb2, "topic2")
|
54
61
|
bec_dispatcher.connect_slot(cb2, "topic3")
|
55
62
|
assert len(bec_dispatcher.client.connector._topics_cb) == 3
|
63
|
+
send_msg_event.set()
|
64
|
+
qtbot.wait(10)
|
65
|
+
assert cb1.call_count == 2
|
66
|
+
assert cb2.call_count == 2
|
56
67
|
|
57
68
|
bec_dispatcher.disconnect_all()
|
58
69
|
|
59
70
|
assert len(bec_dispatcher.client.connector._topics_cb) == 0
|
71
|
+
|
72
|
+
|
73
|
+
@pytest.mark.parametrize(
|
74
|
+
"topics_msg_list",
|
75
|
+
[
|
76
|
+
(
|
77
|
+
("topic1", dummy_msg),
|
78
|
+
("topic2", dummy_msg),
|
79
|
+
)
|
80
|
+
],
|
81
|
+
)
|
82
|
+
def test_dispatcher_disconnect_one(bec_dispatcher_w_connector, qtbot, send_msg_event):
|
83
|
+
# test for BEC issue #276
|
84
|
+
bec_dispatcher = bec_dispatcher_w_connector
|
85
|
+
cb1 = mock.Mock(spec=[])
|
86
|
+
cb2 = mock.Mock(spec=[])
|
87
|
+
|
88
|
+
bec_dispatcher.connect_slot(cb1, "topic1")
|
89
|
+
bec_dispatcher.connect_slot(cb2, "topic2")
|
90
|
+
assert len(bec_dispatcher.client.connector._topics_cb) == 2
|
91
|
+
bec_dispatcher.disconnect_slot(cb1, "topic1")
|
92
|
+
assert len(bec_dispatcher.client.connector._topics_cb) == 1
|
93
|
+
|
94
|
+
send_msg_event.set()
|
95
|
+
qtbot.wait(10)
|
96
|
+
assert cb1.call_count == 0
|
97
|
+
cb2.assert_called_once()
|
98
|
+
|
99
|
+
|
100
|
+
@pytest.mark.parametrize("topics_msg_list", [(("topic1", dummy_msg),)])
|
101
|
+
def test_dispatcher_2_cb_same_topic(bec_dispatcher_w_connector, qtbot, send_msg_event):
|
102
|
+
# test for BEC issue #276
|
103
|
+
bec_dispatcher = bec_dispatcher_w_connector
|
104
|
+
cb1 = mock.Mock(spec=[])
|
105
|
+
cb2 = mock.Mock(spec=[])
|
106
|
+
|
107
|
+
bec_dispatcher.connect_slot(cb1, "topic1")
|
108
|
+
bec_dispatcher.connect_slot(cb2, "topic1")
|
109
|
+
assert len(bec_dispatcher.client.connector._topics_cb) == 1
|
110
|
+
bec_dispatcher.disconnect_slot(cb1, "topic1")
|
111
|
+
|
112
|
+
send_msg_event.set()
|
113
|
+
qtbot.wait(10)
|
114
|
+
assert cb1.call_count == 0
|
115
|
+
cb2.assert_called_once()
|
116
|
+
|
117
|
+
|
118
|
+
@pytest.mark.parametrize(
|
119
|
+
"topics_msg_list",
|
120
|
+
[
|
121
|
+
(
|
122
|
+
("topic1", dummy_msg),
|
123
|
+
("topic2", dummy_msg),
|
124
|
+
)
|
125
|
+
],
|
126
|
+
)
|
127
|
+
def test_dispatcher_2_topic_same_cb(bec_dispatcher_w_connector, qtbot, send_msg_event):
|
128
|
+
# test for BEC issue #276
|
129
|
+
bec_dispatcher = bec_dispatcher_w_connector
|
130
|
+
cb1 = mock.Mock(spec=[])
|
131
|
+
|
132
|
+
bec_dispatcher.connect_slot(cb1, "topic1")
|
133
|
+
bec_dispatcher.connect_slot(cb1, "topic2")
|
134
|
+
assert len(bec_dispatcher.client.connector._topics_cb) == 2
|
135
|
+
bec_dispatcher.disconnect_slot(cb1, "topic1")
|
136
|
+
assert len(bec_dispatcher.client.connector._topics_cb) == 1
|
137
|
+
|
138
|
+
send_msg_event.set()
|
139
|
+
qtbot.wait(10)
|
140
|
+
cb1.assert_called_once()
|
File without changes
|
File without changes
|
File without changes
|