From 1d7b423bb307b6aae3879987776310c14380895d Mon Sep 17 00:00:00 2001 From: David Perl Date: Mon, 7 Apr 2025 13:51:04 +0200 Subject: [PATCH] fix: warning in logpanel - chain a signal to the child BecLogsQueue rather than passing the signal instance in --- .../widgets/utility/logpanel/logpanel.py | 30 +++++++++---------- tests/unit_tests/test_logpanel.py | 4 ++- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/bec_widgets/widgets/utility/logpanel/logpanel.py b/bec_widgets/widgets/utility/logpanel/logpanel.py index 116da1c1..84d03f7d 100644 --- a/bec_widgets/widgets/utility/logpanel/logpanel.py +++ b/bec_widgets/widgets/utility/logpanel/logpanel.py @@ -8,13 +8,14 @@ import re from collections import deque from functools import partial, reduce from re import Pattern -from typing import TYPE_CHECKING, Literal +from typing import Literal from bec_lib.client import BECClient from bec_lib.connector import ConnectorBase from bec_lib.endpoints import MessageEndpoints from bec_lib.logger import LogLevel, bec_logger from bec_lib.messages import LogMessage, StatusMessage +from PySide6.QtCore import QObject from qtpy.QtCore import QDateTime, Qt, Signal # type: ignore from qtpy.QtGui import QFont from qtpy.QtWidgets import ( @@ -51,9 +52,6 @@ from bec_widgets.widgets.utility.logpanel._util import ( simple_color_format, ) -if TYPE_CHECKING: - from PySide6.QtCore import SignalInstance - logger = bec_logger.logger MODULE_PATH = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) @@ -68,20 +66,22 @@ DEFAULT_LOG_COLORS = { } -class BecLogsQueue: +class BecLogsQueue(QObject): """Manages getting logs from BEC Redis and formatting them for display""" + new_message = Signal() + def __init__( self, + parent: QObject | None, conn: ConnectorBase, - new_message_signal: SignalInstance, maxlen: int = 1000, line_formatter: LineFormatter = noop_format, ) -> None: + super().__init__(parent=parent) self._timestamp_start: QDateTime | None = None self._timestamp_end: QDateTime | None = None self._conn = conn - self._new_message_signal: SignalInstance | None = new_message_signal self._max_length = maxlen self._data: deque[LogMessage] = deque([], self._max_length) self._display_queue: deque[str] = deque([], self._max_length) @@ -91,9 +91,9 @@ class BecLogsQueue: self._set_formatter_and_update_filter(line_formatter) self._conn.register([MessageEndpoints.log()], None, self._process_incoming_log_msg) - def disconnect(self): + def unsub_and_disconnect(self): self._conn.unregister([MessageEndpoints.log()], None, self._process_incoming_log_msg) - self._new_message_signal.disconnect() + self.new_message.disconnect() def _process_incoming_log_msg(self, msg: dict): try: @@ -101,10 +101,9 @@ class BecLogsQueue: self._data.append(_msg) if self.filter is None or self.filter(_msg): self._display_queue.append(self._line_formatter(_msg)) - if self._new_message_signal: - self._new_message_signal.emit() - except Exception: - pass + self.new_message.emit() + except Exception as e: + logger.warning(f"Error in LogPanel incoming message callback: {e}") def _set_formatter_and_update_filter(self, line_formatter: LineFormatter = noop_format): self._line_formatter: LineFormatter = line_formatter @@ -396,10 +395,11 @@ class LogPanel(TextBox): self._update_colors() self._service_status = service_status or BECServiceStatusMixin(self, client=self.client) # type: ignore self._log_manager = BecLogsQueue( + parent, self.client.connector, # type: ignore - new_message_signal=self._new_messages, line_formatter=partial(simple_color_format, colors=self._colors), ) + self._log_manager.new_message.connect(self._new_messages) self.toolbar = LogPanelToolbar(parent=parent) self.toolbar_area = QScrollArea() @@ -513,7 +513,7 @@ class LogPanel(TextBox): def cleanup(self): self._service_status.cleanup() - self._log_manager.disconnect() + self._log_manager.unsub_and_disconnect() super().cleanup() diff --git a/tests/unit_tests/test_logpanel.py b/tests/unit_tests/test_logpanel.py index 52516e4f..caafc787 100644 --- a/tests/unit_tests/test_logpanel.py +++ b/tests/unit_tests/test_logpanel.py @@ -62,6 +62,7 @@ def log_panel(qtbot, mocked_client: MagicMock): qtbot.addWidget(widget) qtbot.waitExposed(widget) yield widget + widget.cleanup() def test_log_panel_init(log_panel: LogPanel): @@ -89,6 +90,7 @@ def test_logpanel_output(qtbot, log_panel: LogPanel): assert log_panel.plain_text == TEST_COMBINED_PLAINTEXT def display_queue_empty(): + print(log_panel._log_manager._display_queue) return len(log_panel._log_manager._display_queue) == 0 next_text = "datetime | error | test log message" @@ -102,7 +104,7 @@ def test_logpanel_output(qtbot, log_panel: LogPanel): } ) - qtbot.waitUntil(display_queue_empty) + qtbot.waitUntil(display_queue_empty, timeout=5000) assert log_panel.plain_text == TEST_COMBINED_PLAINTEXT + next_text + "\n"