From 01c6e092b9cd46ae056c43e8c6576f7a570cce80 Mon Sep 17 00:00:00 2001 From: wakonig_k Date: Sat, 13 Dec 2025 19:41:23 +0100 Subject: [PATCH] fix(scan queue): adjustments for changes to the pydantic model of the scan queue --- .../scan_progressbar/scan_progressbar.py | 17 +- .../widgets/services/bec_queue/bec_queue.py | 24 +- tests/unit_tests/test_scan_progress_bar.py | 209 ++++++++---------- 3 files changed, 127 insertions(+), 123 deletions(-) diff --git a/bec_widgets/widgets/progress/scan_progressbar/scan_progressbar.py b/bec_widgets/widgets/progress/scan_progressbar/scan_progressbar.py index 401936e5..2ebce2c8 100644 --- a/bec_widgets/widgets/progress/scan_progressbar/scan_progressbar.py +++ b/bec_widgets/widgets/progress/scan_progressbar/scan_progressbar.py @@ -6,6 +6,7 @@ import time from typing import Literal import numpy as np +from bec_lib import messages from bec_lib.endpoints import MessageEndpoints from bec_lib.logger import bec_logger from qtpy.QtCore import QObject, QTimer, Signal @@ -264,22 +265,28 @@ class ScanProgressBar(BECWidget, QWidget): """ if not "queue" in msg_content: return - primary_queue_info = msg_content["queue"].get("primary", {}).get("info", []) + if "primary" not in msg_content["queue"]: + return + if (primary_queue := msg_content.get("queue").get("primary")) is None: + return + if not isinstance(primary_queue, messages.ScanQueueStatus): + return + primary_queue_info = primary_queue.info if len(primary_queue_info) == 0: return scan_info = primary_queue_info[0] if scan_info is None: return - if scan_info.get("status").lower() == "running" and self.task is None: + if scan_info.status.lower() == "running" and self.task is None: self.task = ProgressTask(parent=self) self.progress_started.emit() - active_request_block = scan_info.get("active_request_block", {}) + active_request_block = scan_info.active_request_block if active_request_block is None: return - self.scan_number = active_request_block.get("scan_number") - report_instructions = active_request_block.get("report_instructions", []) + self.scan_number = active_request_block.scan_number + report_instructions = active_request_block.report_instructions if not report_instructions: return diff --git a/bec_widgets/widgets/services/bec_queue/bec_queue.py b/bec_widgets/widgets/services/bec_queue/bec_queue.py index 1530afda..473ed3ef 100644 --- a/bec_widgets/widgets/services/bec_queue/bec_queue.py +++ b/bec_widgets/widgets/services/bec_queue/bec_queue.py @@ -1,5 +1,6 @@ from __future__ import annotations +from bec_lib import messages from bec_lib.endpoints import MessageEndpoints from bec_qthemes import material_icon from qtpy.QtCore import Property, Qt, Signal, Slot @@ -145,7 +146,16 @@ class BECQueue(BECWidget, CompactPopupWidget): _metadata (dict): The metadata. """ # only show the primary queue for now - queue_info = content.get("queue", {}).get("primary", {}).get("info", []) + queues = content.get("queue", {}) + if not queues: + self.reset_content() + return + primary_queue: messages.ScanQueueStatus | None = queues.get("primary") + if not primary_queue: + self.reset_content() + return + queue_info = primary_queue.info + self.table.setRowCount(len(queue_info)) self.table.clearContents() @@ -154,19 +164,19 @@ class BECQueue(BECWidget, CompactPopupWidget): return for index, item in enumerate(queue_info): - blocks = item.get("request_blocks", []) + blocks = item.request_blocks scan_types = [] scan_numbers = [] scan_ids = [] - status = item.get("status", "") + status = item.status for request_block in blocks: - scan_type = request_block.get("content", {}).get("scan_type", "") + scan_type = request_block.msg.scan_type if scan_type: scan_types.append(scan_type) - scan_number = request_block.get("scan_number", "") + scan_number = request_block.scan_number if scan_number: scan_numbers.append(str(scan_number)) - scan_id = request_block.get("scan_id", "") + scan_id = request_block.scan_id if scan_id: scan_ids.append(scan_id) if scan_types: @@ -178,7 +188,7 @@ class BECQueue(BECWidget, CompactPopupWidget): self.set_row(index, scan_numbers, scan_types, status, scan_ids) busy = ( False - if all(item.get("status") in ("STOPPED", "COMPLETED", "IDLE") for item in queue_info) + if all(item.status in ("STOPPED", "COMPLETED", "IDLE") for item in queue_info) else True ) self.set_global_state("warning" if busy else "default") diff --git a/tests/unit_tests/test_scan_progress_bar.py b/tests/unit_tests/test_scan_progress_bar.py index a531d4f2..3a5b4b56 100644 --- a/tests/unit_tests/test_scan_progress_bar.py +++ b/tests/unit_tests/test_scan_progress_bar.py @@ -25,6 +25,30 @@ def scan_progressbar(qtbot, mocked_client): yield widget +@pytest.fixture +def scan_message(): + return messages.ScanQueueMessage( + metadata={ + "file_suffix": None, + "file_directory": None, + "user_metadata": {"sample_name": ""}, + "RID": "94949c6e-d5f2-4f01-837e-a5d36257dd5d", + }, + scan_type="line_scan", + parameter={ + "args": {"samx": [-10.0, 10.0]}, + "kwargs": { + "steps": 20, + "relative": False, + "exp_time": 0.1, + "burst_at_each_point": 1, + "system_config": {"file_suffix": None, "file_directory": None}, + }, + }, + queue="primary", + ) + + def test_progress_task_basic(): """percentage, remaining, and formatted time helpers behave as expected.""" task = ProgressTask(parent=None, value=50, max_value=100, done=False) @@ -167,7 +191,9 @@ def test_progressbar_queue_update(scan_progressbar): """ Test that an empty queue update does not change the progress source. """ - msg = messages.ScanQueueStatusMessage(queue={"primary": {"info": [], "status": "RUNNING"}}) + msg = messages.ScanQueueStatusMessage( + queue={"primary": messages.ScanQueueStatus(info=[], status="RUNNING")} + ) with mock.patch.object(scan_progressbar, "set_progress_source") as mock_set_source: scan_progressbar.on_queue_update( msg.content, msg.metadata, _override_slot_params={"verify_sender": False} @@ -175,50 +201,37 @@ def test_progressbar_queue_update(scan_progressbar): mock_set_source.assert_not_called() -def test_progressbar_queue_update_with_scan(scan_progressbar): +def test_progressbar_queue_update_with_scan(scan_progressbar, scan_message): """ Test that a queue update with a scan changes the progress source to SCAN_PROGRESS. """ + request_block = messages.RequestBlock( + msg=scan_message, + RID="some-rid", + scan_motors=["samx"], + readout_priority={"monitored": ["samx"]}, + is_scan=True, + scan_number=1, + scan_id="e3f50794-852c-4bb1-965e-41c585ab0aa9", + report_instructions=[{"scan_progress": 20}], + ) msg = messages.ScanQueueStatusMessage( metadata={}, queue={ - "primary": { - "info": [ - { - "queue_id": "40831e2c-fbd1-4432-8072-ad168a7ad964", - "scan_id": ["e3f50794-852c-4bb1-965e-41c585ab0aa9"], - "status": "RUNNING", - "active_request_block": { - "msg": messages.ScanQueueMessage( - metadata={ - "file_suffix": None, - "file_directory": None, - "user_metadata": {"sample_name": ""}, - "RID": "94949c6e-d5f2-4f01-837e-a5d36257dd5d", - }, - scan_type="line_scan", - parameter={ - "args": {"samx": [-10.0, 10.0]}, - "kwargs": { - "steps": 20, - "relative": False, - "exp_time": 0.1, - "burst_at_each_point": 1, - "system_config": { - "file_suffix": None, - "file_directory": None, - }, - }, - }, - queue="primary", - ), - "scan_number": 1, - "report_instructions": [{"scan_progress": 20}], - }, - } + "primary": messages.ScanQueueStatus( + info=[ + messages.QueueInfoEntry( + queue_id="40831e2c-fbd1-4432-8072-ad168a7ad964", + scan_id=["e3f50794-852c-4bb1-965e-41c585ab0aa9"], + status="RUNNING", + active_request_block=request_block, + is_scan=[True], + request_blocks=[request_block], + scan_number=[1], + ) ], - "status": "RUNNING", - } + status="RUNNING", + ) }, ) @@ -229,50 +242,37 @@ def test_progressbar_queue_update_with_scan(scan_progressbar): mock_set_source.assert_called_once_with(ProgressSource.SCAN_PROGRESS) -def test_progressbar_queue_update_with_device(scan_progressbar): +def test_progressbar_queue_update_with_device(scan_progressbar, scan_message): """ Test that a queue update with a device changes the progress source to DEVICE_PROGRESS. """ + request_block = messages.RequestBlock( + msg=scan_message, + RID="some-rid", + scan_motors=["samx"], + readout_priority={"monitored": ["samx"]}, + is_scan=True, + scan_number=1, + scan_id="e3f50794-852c-4bb1-965e-41c585ab0aa9", + report_instructions=[{"device_progress": ["samx"]}], + ) msg = messages.ScanQueueStatusMessage( metadata={}, queue={ - "primary": { - "info": [ - { - "queue_id": "40831e2c-fbd1-4432-8072-ad168a7ad964", - "scan_id": ["e3f50794-852c-4bb1-965e-41c585ab0aa9"], - "status": "RUNNING", - "active_request_block": { - "msg": messages.ScanQueueMessage( - metadata={ - "file_suffix": None, - "file_directory": None, - "user_metadata": {"sample_name": ""}, - "RID": "94949c6e-d5f2-4f01-837e-a5d36257dd5d", - }, - scan_type="line_scan", - parameter={ - "args": {"samx": [-10.0, 10.0]}, - "kwargs": { - "steps": 20, - "relative": False, - "exp_time": 0.1, - "burst_at_each_point": 1, - "system_config": { - "file_suffix": None, - "file_directory": None, - }, - }, - }, - queue="primary", - ), - "scan_number": 1, - "report_instructions": [{"device_progress": ["samx"]}], - }, - } + "primary": messages.ScanQueueStatus( + info=[ + messages.QueueInfoEntry( + queue_id="40831e2c-fbd1-4432-8072-ad168a7ad964", + scan_id=["e3f50794-852c-4bb1-965e-41c585ab0aa9"], + status="RUNNING", + active_request_block=request_block, + is_scan=[True], + request_blocks=[request_block], + scan_number=[1], + ) ], - "status": "RUNNING", - } + status="RUNNING", + ) }, ) @@ -283,49 +283,36 @@ def test_progressbar_queue_update_with_device(scan_progressbar): mock_set_source.assert_called_once_with(ProgressSource.DEVICE_PROGRESS, device="samx") -def test_progressbar_queue_update_with_no_scan_or_device(scan_progressbar): +def test_progressbar_queue_update_with_no_scan_or_device(scan_progressbar, scan_message): """ Test that a queue update with neither scan nor device does not change the progress source. """ + request_block = messages.RequestBlock( + msg=scan_message, + RID="some-rid", + scan_motors=["samx"], + readout_priority={"monitored": ["samx"]}, + is_scan=True, + scan_number=1, + scan_id="e3f50794-852c-4bb1-965e-41c585ab0aa9", + ) msg = messages.ScanQueueStatusMessage( metadata={}, queue={ - "primary": { - "info": [ - { - "queue_id": "40831e2c-fbd1-4432-8072-ad168a7ad964", - "scan_id": ["e3f50794-852c-4bb1-965e-41c585ab0aa9"], - "status": "RUNNING", - "active_request_block": { - "msg": messages.ScanQueueMessage( - metadata={ - "file_suffix": None, - "file_directory": None, - "user_metadata": {"sample_name": ""}, - "RID": "94949c6e-d5f2-4f01-837e-a5d36257dd5d", - }, - scan_type="line_scan", - parameter={ - "args": {"samx": [-10.0, 10.0]}, - "kwargs": { - "steps": 20, - "relative": False, - "exp_time": 0.1, - "burst_at_each_point": 1, - "system_config": { - "file_suffix": None, - "file_directory": None, - }, - }, - }, - queue="primary", - ), - "scan_number": 1, - }, - } + "primary": messages.ScanQueueStatus( + info=[ + messages.QueueInfoEntry( + queue_id="40831e2c-fbd1-4432-8072-ad168a7ad964", + scan_id=["e3f50794-852c-4bb1-965e-41c585ab0aa9"], + status="RUNNING", + active_request_block=request_block, + is_scan=[True], + request_blocks=[request_block], + scan_number=[1], + ) ], - "status": "RUNNING", - } + status="RUNNING", + ) }, )