Skip to content
Merged

dev #606

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 44 additions & 15 deletions speedwagon/frontend/qtwidgets/dialog/dialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
ALREADY_STOPPED_MESSAGE = "Already stopped"
DEFAULT_WINDOW_FLAGS = QtCore.Qt.WindowType(0)

module_logger = logging.getLogger(__name__)


def about_dialog_box(parent: QtWidgets.QWidget) -> None:
"""Launch the about speedwagon dialog box."""
Expand Down Expand Up @@ -249,7 +251,12 @@

def __init__(self, context: "WorkflowProgress"):
super().__init__(context)
self.context.write_to_console("Stopping")
try:
self.context.attach_logger(module_logger)
module_logger.info("Stopping")
self.context.flush()
finally:
self.context.detach_logger(module_logger)
self.context.banner.setText("Stopping")

cancel_button: QtWidgets.QPushButton = self.context.button_box.button(
Expand Down Expand Up @@ -288,7 +295,11 @@
close_button: QtWidgets.QPushButton = self.context.button_box.button(
QtWidgets.QDialogButtonBox.StandardButton.Close
)
self.context.write_to_console("Successfully aborted")
try:
self.context.attach_logger(module_logger)
module_logger.info("Successfully aborted")
finally:
self.context.detach_logger(module_logger)
self.context.banner.setText("Aborted")
close_button.clicked.connect(self.context.accept) # type: ignore

Expand Down Expand Up @@ -346,6 +357,9 @@
progress_bar: QtWidgets.QProgressBar
console: QtWidgets.QTextBrowser

_WRITE_HTML_BLOCK_TO_CONSOLE_WARN_MSG = \
"Don't use write_html_block_to_console directly"

def __init__(
self, parent: typing.Optional[QtWidgets.QWidget] = None
) -> None:
Expand All @@ -370,7 +384,7 @@
self.banner: QtWidgets.QLabel
# =====================================================================
self._log_handler = logging_helpers.QtSignalLogHandler(self)
self._parent_logger: typing.Optional[logging.Logger] = None
self._log_handler.setLevel(logging.INFO)

self._console_data = QtGui.QTextDocument(parent=self)

Expand All @@ -380,30 +394,38 @@

self.cursor.movePosition(self.cursor.MoveOperation.End)

def flush(self) -> None:
self._log_handler.flush()

def write_html_block_to_console(self, html: str) -> None:
warnings.warn(
self._WRITE_HTML_BLOCK_TO_CONSOLE_WARN_MSG,
DeprecationWarning,
stacklevel=2
)
self.cursor.beginEditBlock()
self.cursor.insertHtml(html.strip())
self.cursor.endEditBlock()

def flush(self) -> None:
self._log_handler.flush()
def _write_html_block_to_console(self, html: str) -> None:
self.cursor.beginEditBlock()
self.cursor.insertHtml(html.strip())
self.cursor.endEditBlock()

def attach_logger(self, logger: logging.Logger) -> None:
self._parent_logger = logger
self._log_handler.signals.messageSent.connect( # type: ignore
self.write_html_block_to_console
self._write_html_block_to_console
)
formatter = logging_helpers.ConsoleFormatter()
self._log_handler.setFormatter(formatter)
self._parent_logger.addHandler(self._log_handler)
logger.addHandler(self._log_handler)

def remove_log_handles(self) -> None:
if self._parent_logger is not None:
self._log_handler.flush()
self._parent_logger.removeHandler(self._log_handler)
self._parent_logger = None
def detach_logger(self, logger: logging.Logger) -> None:
logger.removeHandler(self._log_handler)
self._log_handler.flush()

def get_console_content(self) -> str:
self._log_handler.flush()
return self._console_data.toPlainText()


Expand Down Expand Up @@ -444,8 +466,6 @@

# =====================================================================

self.finished.connect(self.remove_log_handles) # type: ignore

def clean_local_console(self) -> None:
# CRITICAL: Running self.console.clear() seems to cause A SEGFAULT when
# shutting down!!!
Expand Down Expand Up @@ -497,7 +517,16 @@
def set_current_progress(self, value: int) -> None:
self.progress_bar.setValue(value)

def set_log_level(self, level: int) -> None:
self._log_handler.setLevel(level)

def write_to_console(self, text: str, level: int = logging.INFO) -> None:
warnings.warn(

Check warning on line 524 in speedwagon/frontend/qtwidgets/dialog/dialogs.py

View check run for this annotation

Jenkins - UIUCLibrary / Test Coverage

Not covered line

Line 524 is not covered by tests
"write_to_console is deprecated. "
"Use attach_logger and write to that instead.",
DeprecationWarning,
stacklevel=2
)
cursor = QtGui.QTextCursor(self._console_data)
cursor.movePosition(cursor.MoveOperation.End)
cursor.beginEditBlock()
Expand Down
30 changes: 24 additions & 6 deletions speedwagon/frontend/qtwidgets/gui_startup.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ def do_work(self) -> None:
),
workflow_loader_strategy=self._internal.workflow_loader_strategy,
request_more_info_strategy=self.request_more_info_strategy,
log_level=logging.DEBUG,
)


Expand Down Expand Up @@ -745,7 +746,7 @@ def __init__(
sys.argv
)
self._internal_values = StartQtThreaded.InternalValues(
logger=logging.getLogger(),
logger=logging.getLogger(__name__),
log_data=io.StringIO(),
request_window=user_interaction.QtRequestMoreInfo(self.windows),
)
Expand Down Expand Up @@ -1080,6 +1081,10 @@ def _rejected() -> None:
)

dialog_box.attach_logger(self._internal_values.logger)
callbacks.signals.finished.connect(
lambda: dialog_box.detach_logger(self._internal_values.logger)
)

job_manager.request_more_info = (
lambda workflow, options, pretask_results, wait_condition=None: (
open_request_more_info_dialog_box(
Expand All @@ -1104,7 +1109,12 @@ def _rejected() -> None:
liaison=speedwagon.runner_strategies.JobManagerLiaison(
callbacks=speedwagon.runner.JobRunnerCallbacks(
update_progress=callbacks.update_progress,
log=callbacks.log,
log=lambda text, level=logging.INFO: (
self._internal_values.logger.log(
level=level,
msg=text,
)
),
status=callbacks.status,
finished=callbacks.finished,
error=callbacks.error,
Expand Down Expand Up @@ -1368,7 +1378,7 @@ def __init__(
] = None
self.options: typing.Optional[SettingsData] = None
self.workflow: typing.Optional[AbsWorkflow] = None
self.logger = logger or logging.getLogger()
self.logger = logger or logging.getLogger(__name__)

def load_json_string(self, data: str) -> None:
"""Load json data containing options and workflow info.
Expand Down Expand Up @@ -1471,17 +1481,25 @@ def _run_workflow(
)
)
dialog_box.attach_logger(self.logger)
dialog_box.set_log_level(logging.DEBUG)
self.logger.setLevel(logging.DEBUG)
callbacks_to_dialog_box.signals.finished.connect(
lambda: dialog_box.detach_logger(self.logger)
)

job_manager.workflow_loader_strategy = self.load_workflow_strategy

liaison = speedwagon.runner_strategies.JobManagerLiaison(
callbacks=speedwagon.runner.JobRunnerCallbacks(
update_progress=callbacks_to_dialog_box.update_progress,
log=callbacks_to_dialog_box.log,
log=lambda text, level=logging.INFO: self.logger.log(
level=level, msg=text
),
status=callbacks_to_dialog_box.status,
finished=callbacks_to_dialog_box.finished,
error=callbacks_to_dialog_box.error,
cancelling_complete=callbacks_to_dialog_box.cancelling_complete
cancelling_complete=(
callbacks_to_dialog_box.cancelling_complete
),
),
events=threaded_events,
)
Expand Down
32 changes: 27 additions & 5 deletions speedwagon/frontend/qtwidgets/runners.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

USER_ABORTED_MESSAGE = "User Aborted"

module_logger = logging.getLogger(__name__)


class TaskFailed(Exception):
"""Task has failed."""
Expand Down Expand Up @@ -53,11 +55,13 @@
finished = QtCore.Signal(speedwagon.runner.JobSuccess)

def __init__(
self, parent: qtwidgets.dialog.dialogs.WorkflowProgress
self, parent: qtwidgets.dialog.dialogs.WorkflowProgress,
) -> None:
"""Create a new workprogress callback object."""
super().__init__(parent)
self._active = True
self.dialog_box = parent
self.dialog_box.destroyed.connect(self._on_parent_destroyed)
# self.cancel_requested.connect(self.dialog_box.cancel_requested)
self.status_changed.connect(self.set_banner_text)
self.progress_changed.connect(self.dialog_box.set_current_progress)
Expand All @@ -69,7 +73,11 @@
self.started.connect(self.dialog_box.show)

self.status_changed.connect(self.dialog_box.flush)
self.message.connect(self.dialog_box.write_to_console)
self.message.connect(self._write_to_console)

def _on_parent_destroyed(self):
# so dialog_box is not written to by mistake after it's deleted
self._active = False

Check warning on line 80 in speedwagon/frontend/qtwidgets/runners.py

View check run for this annotation

Jenkins - UIUCLibrary / MyPy Coverage

Not covered lines

Lines 78-80 are not covered by tests

def log(self, text: str, level: int) -> None:
"""Log a message."""
Expand All @@ -82,7 +90,8 @@

def set_status(self, text: str) -> None:
"""Set the status of the job."""
self.status_changed.emit(text)
if self._active:
self.status_changed.emit(text)

def _error_message(
self,
Expand All @@ -91,8 +100,8 @@
traceback: Optional[str] = None,
) -> None:
if message is not None:
self.dialog_box.write_to_console(message)
self.dialog_box.write_to_console(str(exc), level=logging.ERROR)
self._write_to_console(message)
self._write_to_console(str(exc), level=logging.ERROR)
error = QtWidgets.QMessageBox()
error.setWindowTitle("Workflow Failed")
error.setIcon(QtWidgets.QMessageBox.Icon.Critical)
Expand All @@ -102,6 +111,19 @@
error.exec()
self.dialog_box.failed()

def _write_to_console(
self,
text: str,
level: int = logging.INFO
) -> None:
if not self._active:
return

Check warning on line 120 in speedwagon/frontend/qtwidgets/runners.py

View check run for this annotation

Jenkins - UIUCLibrary / Test Coverage

Not covered line

Line 120 is not covered by tests
try:
self.dialog_box.attach_logger(module_logger)
module_logger.log(level, text)
finally:
self.dialog_box.detach_logger(module_logger)

@QtCore.Slot(object)
def _finished(self, results: speedwagon.runner.JobSuccess) -> None:
if results in [
Expand Down
Loading
Loading