Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Error message pop-up #111

Merged
merged 8 commits into from
Oct 25, 2024
4 changes: 2 additions & 2 deletions src/badger/actions/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ..core import run_routine as run
from ..routine import Routine
from ..settings import init_settings
from ..errors import BadgerRunTerminatedError
from ..errors import BadgerRunTerminated


def run_n_archive(routine: Routine, yes=False, save=False, verbose=2,
Expand All @@ -34,7 +34,7 @@ def handler(*args):
print('') # start a new line
if flush_prompt: # erase the last prompt
sys.stdout.write('\033[F')
raise BadgerRunTerminatedError
raise BadgerRunTerminated
storage['paused'] = True

signal.signal(signal.SIGINT, handler)
Expand Down
6 changes: 3 additions & 3 deletions src/badger/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from pandas import concat, DataFrame

from badger.errors import BadgerRunTerminatedError
from badger.errors import BadgerRunTerminated
from badger.logger import _get_default_logger
from badger.logger.event import Events
from badger.routine import Routine
Expand All @@ -14,7 +14,7 @@ def check_run_status(active_callback):
while True:
status = active_callback()
if status == 2:
raise BadgerRunTerminatedError
raise BadgerRunTerminated
elif status == 1:
time.sleep(0)
continue
Expand Down Expand Up @@ -143,7 +143,7 @@ def run_routine(
while True:
status = active_callback()
if status == 2:
raise BadgerRunTerminatedError
raise BadgerRunTerminated
elif status == 1:
time.sleep(0)
continue
Expand Down
15 changes: 8 additions & 7 deletions src/badger/core_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import multiprocessing as mp

from badger.db import load_routine
from badger.errors import BadgerRunTerminatedError
from badger.errors import BadgerRunTerminated, BadgerError
from badger.logger import _get_default_logger
from badger.logger.event import Events
from badger.routine import Routine
Expand Down Expand Up @@ -165,7 +165,7 @@ def run_routine_subprocess(
while True:
if stop_process.is_set():
evaluate_queue[0].close()
raise BadgerRunTerminatedError
raise BadgerRunTerminated
elif not pause_process.is_set():
pause_process.wait()

Expand All @@ -176,12 +176,12 @@ def run_routine_subprocess(
if idx == 0:
max_eval = tc_config["max_eval"]
if len(routine.data) >= max_eval:
raise BadgerRunTerminatedError
raise BadgerRunTerminated
elif idx == 1:
max_time = tc_config["max_time"]
dt = time.time() - start_time
if dt >= max_time:
raise BadgerRunTerminatedError
raise BadgerRunTerminated

# TODO give user a message that a solution is being worked on.

Expand All @@ -195,7 +195,7 @@ def run_routine_subprocess(
# External triggers
if stop_process.is_set():
evaluate_queue[0].close()
raise BadgerRunTerminatedError
raise BadgerRunTerminated
elif not pause_process.is_set():
pause_process.wait()

Expand All @@ -220,10 +220,11 @@ def run_routine_subprocess(
combined_results = result

dump_state(dump_file, routine.generator, combined_results)
except BadgerRunTerminatedError:
except BadgerRunTerminated:
opt_logger.update(Events.OPTIMIZATION_END, solution_meta)
evaluate_queue[0].close()
except Exception as e:
opt_logger.update(Events.OPTIMIZATION_END, solution_meta)
evaluate_queue[0].close()
raise e
raise BadgerError(f"An error occurred: {str(e)}")

84 changes: 62 additions & 22 deletions src/badger/errors.py
Original file line number Diff line number Diff line change
@@ -1,62 +1,102 @@
class BadgerConfigError(Exception):
pass
from PyQt5.QtWidgets import QMessageBox
import traceback
import sys
from PyQt5.QtWidgets import QApplication

class BadgerError(Exception):
def __init__(self, message="", detailed_text=None):
if QApplication.instance() is None:
self.app = QApplication([])
else:
self.app = QApplication.instance()

if detailed_text is None:
detailed_text = self.capture_traceback_or_stack()

super().__init__(message)
self.detailed_text = detailed_text
self.show_message_box()

def show_message_box(self):
"""
Method to create and display a popup window with the error message.
"""
from badger.gui.default.windows.expandable_message_box import ExpandableMessageBox

class VariableRangeError(Exception):
pass
error_message = str(self)
dialog = ExpandableMessageBox(text=error_message, detailedText=self.detailed_text)
dialog.setIcon(QMessageBox.Critical)
dialog.exec_()

def capture_traceback_or_stack(self):
"""
Captures the current traceback if an exception is active, otherwise captures the call stack.
"""
exc_type, exc_value, exc_traceback = sys.exc_info()
if exc_traceback:
return ''.join(traceback.format_exception(exc_type, exc_value, exc_traceback))
else:
return ''.join(traceback.format_stack())

class BadgerNotImplementedError(Exception):
pass


class BadgerRunTerminatedError(Exception):
class BadgerConfigError(BadgerError):
pass

def __init__(self, message="Optimization run has been terminated!"):
super().__init__(message)

class VariableRangeError(BadgerError):
pass


class BadgerDBError(Exception):
class BadgerNotImplementedError(BadgerError):
pass


class BadgerEnvVarError(Exception):
class BadgerDBError(BadgerError):
pass


class BadgerEnvObsError(Exception):
class BadgerEnvVarError(BadgerError):
pass


class BadgerNoInterfaceError(Exception):
class BadgerEnvObsError(BadgerError):
pass


def __init__(self, message="Must provide an interface!"):
super().__init__(message)
class BadgerNoInterfaceError(BadgerError):
def __init__(self, detailed_text=None):
super().__init__(message="Must provide an interface!", detailed_text=detailed_text)


class BadgerInterfaceChannelError(Exception):
class BadgerInterfaceChannelError(BadgerError):
pass


class BadgerInvalidPluginError(Exception):
class BadgerInvalidPluginError(BadgerError):
pass


class BadgerPluginNotFoundError(Exception):
class BadgerPluginNotFoundError(BadgerError):
pass


class BadgerInvalidDocsError(Exception):
class BadgerInvalidDocsError(BadgerError):
pass


class BadgerLogbookError(Exception):
class BadgerLogbookError(BadgerError):
pass


class BadgerLoadConfigError(Exception):
class BadgerLoadConfigError(BadgerError):
pass


class BadgerRoutineError(Exception):
class BadgerRoutineError(BadgerError):
pass


class BadgerRunTerminated(Exception):
def __init__(self, message="Optimization run has been terminated!"):
super().__init__(message)
4 changes: 2 additions & 2 deletions src/badger/gui/default/components/routine_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import torch # for converting dtype str to torch object
from PyQt5.QtCore import pyqtSignal, QObject, QTimer
from ....core import run_routine, Routine
from ....errors import BadgerRunTerminatedError
from ....errors import BadgerRunTerminated
from ....tests.utils import get_current_vars
from ....routine import calculate_variable_bounds, calculate_initial_points
from ....settings import init_settings
Expand Down Expand Up @@ -175,7 +175,7 @@ def run(self) -> None:

self.routine.initial_points = init_points

except BadgerRunTerminatedError as e:
except BadgerRunTerminated as e:
self.signals.finished.emit()
self.signals.info.emit(str(e))
except Exception as e:
Expand Down
4 changes: 4 additions & 0 deletions src/badger/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
import shutil
import pytest

@pytest.fixture(autouse=True)
def suppress_popups(mocker):
mocker.patch('badger.gui.default.windows.expandable_message_box.ExpandableMessageBox.exec_', return_value=None)


@pytest.fixture(scope='module', autouse=True)
def config_test_settings(mock_plugin_root, mock_db_root,
Expand Down
6 changes: 3 additions & 3 deletions src/badger/tests/test_core.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import pytest
import pandas as pd
from badger.errors import BadgerRunTerminatedError
from badger.errors import BadgerRunTerminated


class TestCore:
Expand Down Expand Up @@ -82,7 +82,7 @@ def test_run_routine(self) -> None:

self.count = 0

with pytest.raises(BadgerRunTerminatedError):
with pytest.raises(BadgerRunTerminated):
run_routine(
routine,
self.mock_active_callback,
Expand Down Expand Up @@ -133,7 +133,7 @@ def test_run_turbo(self) -> None:

self.count = 0

with pytest.raises(BadgerRunTerminatedError):
with pytest.raises(BadgerRunTerminated):
run_routine(
routine,
self.mock_active_callback,
Expand Down
2 changes: 0 additions & 2 deletions src/badger/tests/test_routine_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QApplication


def test_routine_page_init(qtbot):
from badger.gui.default.components.routine_page import BadgerRoutinePage

window = BadgerRoutinePage()

qtbot.addWidget(window)


def test_routine_generation(qtbot):
from badger.errors import BadgerRoutineError
from badger.utils import get_badger_version, get_xopt_version
Expand Down