From a2076352088ff169359374f4d367766025f3288b Mon Sep 17 00:00:00 2001
From: Pekka T Savolainen
Date: Fri, 11 Oct 2024 18:36:16 +0300
Subject: [PATCH] Update Add/Update SpineOpt Wizard
- Required SpineOpt version is now 0.8.3
- Introduce new option to Troubleshooting section, which shows the instructions to Install or Update SpineOpt manually
- Remove Reset Registry button and show the instructions how to reset the registry manually
- Add Copy log button to Total Failure page
- Update links
Re Issue #2973
---
spinetoolbox/config.py | 2 +-
spinetoolbox/ui_main.py | 12 +-
.../widgets/add_up_spine_opt_wizard.py | 238 ++++++++++--------
spinetoolbox/widgets/install_julia_wizard.py | 7 +-
tests/widgets/test_AddUpSpineOptWizard.py | 52 ++--
5 files changed, 176 insertions(+), 135 deletions(-)
diff --git a/spinetoolbox/config.py b/spinetoolbox/config.py
index e3882ee35..9b556add4 100644
--- a/spinetoolbox/config.py
+++ b/spinetoolbox/config.py
@@ -18,7 +18,7 @@
LATEST_PROJECT_VERSION = 13
# For the Add/Update SpineOpt wizard
-REQUIRED_SPINE_OPT_VERSION = "0.6.9"
+REQUIRED_SPINE_OPT_VERSION = "0.8.3"
# Invalid characters for directory names
# NOTE: "." is actually valid in a directory name but this is
diff --git a/spinetoolbox/ui_main.py b/spinetoolbox/ui_main.py
index 16a0afd6b..dfbcec7dd 100644
--- a/spinetoolbox/ui_main.py
+++ b/spinetoolbox/ui_main.py
@@ -128,7 +128,7 @@ class ToolboxUI(QMainWindow):
def __init__(self):
from .ui.mainwindow import Ui_MainWindow # pylint: disable=import-outside-toplevel
- super().__init__(flags=Qt.Window)
+ super().__init__(flags=Qt.WindowType.Window)
self.set_app_style()
self.set_error_mode()
self._qsettings = QSettings("SpineProject", "Spine Toolbox", self)
@@ -227,16 +227,16 @@ def __init__(self):
def eventFilter(self, obj, ev):
# Save/restore splitter states when hiding/showing execution lists
if obj == self.ui.listView_console_executions:
- if ev.type() == QEvent.Hide:
+ if ev.type() == QEvent.Type.Hide:
self._qsettings.setValue("mainWindow/consoleSplitterPosition", self.ui.splitter_console.saveState())
- elif ev.type() == QEvent.Show:
+ elif ev.type() == QEvent.Type.Show:
splitter_state = self._qsettings.value("mainWindow/consoleSplitterPosition", defaultValue="false")
if splitter_state != "false":
self.ui.splitter_console.restoreState(splitter_state)
return super().eventFilter(obj, ev)
def _setup_properties_title(self):
- self.label_item_name.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
+ self.label_item_name.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)
self.label_item_name.setMinimumHeight(28)
self._button_item_dir.setIcon(QIcon(":icons/folder-open-regular.svg"))
layout = QHBoxLayout(self._properties_title)
@@ -316,7 +316,9 @@ def connect_signals(self):
# Consoles
self.jupyter_console_requested.connect(self._setup_jupyter_console)
self.kernel_shutdown.connect(self._handle_kernel_shutdown)
- self.persistent_console_requested.connect(self._setup_persistent_console, Qt.BlockingQueuedConnection)
+ self.persistent_console_requested.connect(
+ self._setup_persistent_console, Qt.ConnectionType.BlockingQueuedConnection
+ )
@staticmethod
def set_app_style():
diff --git a/spinetoolbox/widgets/add_up_spine_opt_wizard.py b/spinetoolbox/widgets/add_up_spine_opt_wizard.py
index fe96373eb..96c470909 100644
--- a/spinetoolbox/widgets/add_up_spine_opt_wizard.py
+++ b/spinetoolbox/widgets/add_up_spine_opt_wizard.py
@@ -26,6 +26,7 @@
QWidget,
QWizard,
QWizardPage,
+ QApplication,
)
from ..config import REQUIRED_SPINE_OPT_VERSION
from ..execution_managers import QProcessExecutionManager
@@ -42,7 +43,6 @@ class _PageId(IntEnum):
FAILURE = auto()
TROUBLESHOOT_PROBLEMS = auto()
TROUBLESHOOT_SOLUTION = auto()
- RESET_REGISTRY = auto()
ADD_UP_SPINE_OPT_AGAIN = auto()
TOTAL_FAILURE = auto()
@@ -69,7 +69,6 @@ def __init__(self, parent, julia_exe, julia_project):
self.setPage(_PageId.FAILURE, FailurePage(self))
self.setPage(_PageId.TROUBLESHOOT_PROBLEMS, TroubleshootProblemsPage(self))
self.setPage(_PageId.TROUBLESHOOT_SOLUTION, TroubleshootSolutionPage(self))
- self.setPage(_PageId.RESET_REGISTRY, ResetRegistryPage(self))
self.setPage(_PageId.ADD_UP_SPINE_OPT_AGAIN, AddUpSpineOptAgainPage(self))
self.setPage(_PageId.TOTAL_FAILURE, TotalFailurePage(self))
self.setStartId(_PageId.INTRO)
@@ -94,7 +93,7 @@ def nextId(self):
class SelectJuliaPage(QWizardPage):
def __init__(self, parent, julia_exe, julia_project):
super().__init__(parent)
- self.setTitle("Select Julia project")
+ self.setTitle("Select Julia")
self._julia_exe = julia_exe
self._julia_project = julia_project
self._julia_exe_line_edit = QLineEdit()
@@ -103,14 +102,14 @@ def __init__(self, parent, julia_exe, julia_project):
self.registerField("julia_exe*", self._julia_exe_line_edit)
self.registerField("julia_project", self._julia_project_line_edit)
layout = QVBoxLayout(self)
- layout.addWidget(QLabel("Julia executable:"))
+ layout.addWidget(QLabel("Julia executable"))
julia_exe_widget = QWidget()
julia_exe_layout = QHBoxLayout(julia_exe_widget)
julia_exe_layout.addWidget(self._julia_exe_line_edit)
julia_exe_button = QPushButton("Browse")
julia_exe_layout.addWidget(julia_exe_button)
layout.addWidget(julia_exe_widget)
- layout.addWidget(QLabel("Julia project (directory):"))
+ layout.addWidget(QLabel("Julia project/environment (directory)"))
julia_project_widget = QWidget()
julia_project_layout = QHBoxLayout(julia_project_widget)
julia_project_layout.addWidget(self._julia_project_line_edit)
@@ -134,7 +133,7 @@ def _select_julia_exe(self, _):
@Slot(bool)
def _select_julia_project(self, _):
julia_project = QFileDialog.getExistingDirectory(
- self, "Select Julia project (directory)", self.field("julia_project")
+ self, "Select Julia project/environment (directory)", self.field("julia_project")
)
if not julia_project:
return
@@ -179,11 +178,11 @@ def initializePage(self):
self._exec_mngr = QProcessExecutionManager(self, julia_exe, args, silent=True)
self.completeChanged.emit()
self._exec_mngr.execution_finished.connect(self._handle_check_install_finished)
- qApp.setOverrideCursor(QCursor(Qt.BusyCursor)) # pylint: disable=undefined-variable
+ QApplication.setOverrideCursor(QCursor(Qt.CursorShape.BusyCursor)) # pylint: disable=undefined-variable
self._exec_mngr.start_execution()
def _handle_check_install_finished(self, ret):
- qApp.restoreOverrideCursor() # pylint: disable=undefined-variable
+ QApplication.restoreOverrideCursor() # pylint: disable=undefined-variable
self._exec_mngr.execution_finished.disconnect(self._handle_check_install_finished)
if self.wizard().currentPage() is not self:
return
@@ -212,20 +211,20 @@ def _handle_check_install_finished(self, ret):
return
msg = (
f"SpineOpt version {spine_opt_version} is installed, "
- f"but version {REQUIRED_SPINE_OPT_VERSION} is required."
+ f"but version {REQUIRED_SPINE_OPT_VERSION} or higher is required."
)
self.layout().addWidget(WrapLabel(msg))
self.wizard().required_action = "update"
self.setFinalPage(False)
self.setCommitPage(True)
- self.setButtonText(QWizard.CommitButton, "Update SpineOpt")
+ self.setButtonText(QWizard.WizardButton.CommitButton, "Update SpineOpt")
self.completeChanged.emit()
return
self.layout().addWidget(QLabel("SpineOpt is not installed."))
self.wizard().required_action = "add"
self.setFinalPage(False)
self.setCommitPage(True)
- self.setButtonText(QWizard.CommitButton, "Install SpineOpt")
+ self.setButtonText(QWizard.WizardButton.CommitButton, "Install SpineOpt")
self.completeChanged.emit()
def nextId(self):
@@ -255,11 +254,11 @@ def initializePage(self):
self.msg_success.emit(f"SpineOpt {process} started")
cmd = julia_exe + " " + " ".join(args)
self.msg.emit(f"$ {cmd}")
- qApp.setOverrideCursor(QCursor(Qt.BusyCursor)) # pylint: disable=undefined-variable
+ QApplication.setOverrideCursor(QCursor(Qt.CursorShape.BusyCursor)) # pylint: disable=undefined-variable
self._exec_mngr.start_execution()
def _handle_spine_opt_add_up_finished(self, ret):
- qApp.restoreOverrideCursor() # pylint: disable=undefined-variable
+ QApplication.restoreOverrideCursor() # pylint: disable=undefined-variable
self._exec_mngr.execution_finished.disconnect(self._handle_spine_opt_add_up_finished)
if self.wizard().currentPage() is not self:
return
@@ -270,9 +269,10 @@ def _handle_spine_opt_add_up_finished(self, ret):
configured = {"add": "installed", "update": "updated"}[self.wizard().required_action]
self.msg_success.emit(f"SpineOpt successfully {configured}")
return
- process = {"add": "installation", "update": "updatee"}[self.wizard().required_action]
+ process = {"add": "installation", "update": "update"}[self.wizard().required_action]
self.msg_error.emit(f"SpineOpt {process} failed")
self.wizard().process_log = self._log.toHtml()
+ self.wizard().process_log_plain = self._log.toPlainText()
def nextId(self):
if self._successful:
@@ -296,13 +296,16 @@ def nextId(self):
class FailurePage(QWizardPage):
- def __init__(self, parent):
- super().__init__(parent)
+ def initializePage(self):
+ process = {"add": "Installation", "update": "Update"}[self.wizard().required_action]
+ self.setTitle(f"{process} failed")
check_box = QCheckBox("Troubleshoot problems")
check_box.setChecked(True)
self.registerField("troubleshoot", check_box)
layout = QVBoxLayout(self)
- msg = "Apologies."
+ msg = ("Apologies. Please see the Troubleshoot problems section "
+ "by clicking Next or click Cancel to close "
+ "the wizard.")
layout.addWidget(WrapLabel(msg))
layout.addStretch()
layout.addWidget(check_box)
@@ -314,10 +317,6 @@ def __init__(self, parent):
def _handle_check_box_clicked(self, checked=False):
self.setFinalPage(not checked)
- def initializePage(self):
- process = {"add": "Installation", "update": "Update"}[self.wizard().required_action]
- self.setTitle(f"{process} failed")
-
def nextId(self):
if self.field("troubleshoot"):
return _PageId.TROUBLESHOOT_PROBLEMS
@@ -329,10 +328,11 @@ def __init__(self, parent):
super().__init__(parent)
self.setTitle("Troubleshooting")
msg = "Select your problem from the list."
- self._button1 = QRadioButton("Installing SpineOpt fails with one of the following messages (or similar):")
- msg1a = MonoSpaceFontTextBrowser(self)
- msg1b = MonoSpaceFontTextBrowser(self)
- msg1a.append(
+ self._button1 = QRadioButton("None of the below")
+ self._button2 = QRadioButton("Installing SpineOpt fails with one of the following messages (or similar):")
+ msg2a = MonoSpaceFontTextBrowser(self)
+ msg2b = MonoSpaceFontTextBrowser(self)
+ msg2a.append(
"""
\u22ee
Updating git-repo `https://github.com/spine-tools/SpineJuliaRegistry`
@@ -341,7 +341,7 @@ def __init__(self, parent):
\u22ee
"""
)
- msg1b.append(
+ msg2b.append(
"""
\u22ee
Updating git-repo `https://github.com/spine-tools/SpineJuliaRegistry`
@@ -350,9 +350,9 @@ def __init__(self, parent):
\u22ee
"""
)
- self._button2 = QRadioButton("On Windows 7, installing SpineOpt fails with the following message (or similar):")
- msg2 = MonoSpaceFontTextBrowser(self)
- msg2.append(
+ self._button3 = QRadioButton("On Windows 7, installing SpineOpt fails with the following message (or similar):")
+ msg3 = MonoSpaceFontTextBrowser(self)
+ msg3.append(
"""
\u22ee
Downloading artifact: OpenBLAS32
@@ -371,13 +371,15 @@ def __init__(self, parent):
layout.addWidget(WrapLabel(msg))
layout.addStretch()
layout.addWidget(self._button1)
- layout.addWidget(msg1a)
- layout.addWidget(msg1b)
layout.addStretch()
layout.addWidget(self._button2)
- layout.addWidget(msg2)
+ layout.addWidget(msg2a)
+ layout.addWidget(msg2b)
+ layout.addStretch()
+ layout.addWidget(self._button3)
+ layout.addWidget(msg3)
layout.addStretch()
- button_view_log = QPushButton("View process log")
+ button_view_log = QPushButton("View log")
widget_view_log = QWidget()
layout_view_log = QHBoxLayout(widget_view_log)
layout_view_log.addStretch()
@@ -386,16 +388,18 @@ def __init__(self, parent):
layout.addStretch()
self.registerField("problem1", self._button1)
self.registerField("problem2", self._button2)
+ self.registerField("problem3", self._button3)
self._button1.toggled.connect(lambda _: self.completeChanged.emit())
self._button2.toggled.connect(lambda _: self.completeChanged.emit())
+ self._button3.toggled.connect(lambda _: self.completeChanged.emit())
button_view_log.clicked.connect(self._show_log)
def isComplete(self):
- return self.field("problem1") or self.field("problem2")
+ return self.field("problem1") or self.field("problem2") or self.field("problem3")
@Slot(bool)
def _show_log(self, _=False):
- log_widget = QWidget(self, f=Qt.Window)
+ log_widget = QWidget(self, f=Qt.WindowType.Window)
layout = QVBoxLayout(log_widget)
log = MonoSpaceFontTextBrowser(log_widget)
log.append(self.wizard().process_log)
@@ -412,97 +416,108 @@ def __init__(self, parent):
self.setCommitPage(True)
QVBoxLayout(self)
- def cleanupPage(self):
- super().cleanupPage()
- self.wizard().reset_registry = False
-
def initializePage(self):
_clear_layout(self.layout())
if self.field("problem1"):
self._initialize_page_solution1()
- elif self.field("problem2"):
+ if self.field("problem2"):
self._initialize_page_solution2()
+ elif self.field("problem3"):
+ self._initialize_page_solution3()
def _initialize_page_solution1(self):
- self.wizard().reset_registry = True
+ action = {"add": "Install SpineOpt", "update": "Update SpineOpt"}[self.wizard().required_action]
+ julia = self.field("julia_exe")
+ env = self.field("julia_project")
+ if not env:
+ install_cmds = f"""
+ julia> import Pkg
+ julia> Pkg.Registry.add("General")
+ julia> Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/spine-tools/SpineJuliaRegistry"))
+ julia> Pkg.add("SpineOpt")
"""
+ else:
+ install_cmds = f"""
+ julia> import Pkg
+ julia> cd("{env}")
+ julia> Pkg.activate(".")
+ julia> Pkg.Registry.add("General")
+ julia> Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/spine-tools/SpineJuliaRegistry"))
+ julia> Pkg.add("SpineOpt")
"""
+ if not env:
+ update_cmds = """
+ julia> import Pkg
+ julia> Pkg.update("SpineOpt")
"""
+ else:
+ update_cmds = f"""
+ julia> import Pkg
+ julia> cd("{env}")
+ julia> Pkg.activate(".")
+ julia> Pkg.update("SpineOpt")
"""
+ action_cmds = {"Install SpineOpt": install_cmds, "Update SpineOpt": update_cmds}
+ self.setTitle("What now?")
+ msg_browser = MonoSpaceFontTextBrowser(self)
+ msg_browser.append(action_cmds[action])
+ label1_txt = (
+ ""
+ f"- Click the {action} button to try again.
"
+ f"- {action} manually. Open your favorite terminal (ie. Command prompt) and start the "
+ f"Julia REPL using command:
{julia}
"
+ "In the Julia REPL, enter the following commands (gray text, not the green one):
"
+ )
+ label2_txt = (
+ "See also up-to-date "
+ "installation "
+ "instructions in SpineOpt documentation.
"
+ )
+ self.layout().addWidget(HyperTextLabel(label1_txt))
+ self.layout().addWidget(msg_browser)
+ self.layout().addWidget(HyperTextLabel(label2_txt))
+ self.setButtonText(QWizard.WizardButton.CommitButton, action)
+
+ def _initialize_page_solution2(self):
+ action = {"add": "Install SpineOpt", "update": "Update SpineOpt"}[self.wizard().required_action]
+ julia = self.field("julia_exe")
self.setTitle("Reset Julia General Registry")
description = (
"The issue you're facing can be due to an error in the installation of the Julia General registry "
- "from the Julia Package Server.
"
- "The simplest solution is to delete any trace of the registry and install it again, from GitHub.
"
- "However, this will also remove all your installed packages.
"
+ "from the Julia Package Server. The simplest solution is to delete any trace of the registry and install "
+ "it again from GitHub."
+ "To do this, open your favorite terminal (ie. Command prompt) and start the Julia REPL using "
+ f"command:
{julia}
In the Julia REPL, enter the commands below (gray text, "
+ "not the green one). Afterwards, try Add/Update SpineOpt again.
"
+ "NOTE: this will also remove all your installed packages.
"
)
+ cmds = f"""
+ julia> import Pkg
+ julia> Pkg.Registry.rm("SpineRegistry")
+ julia> Pkg.Registry.rm("General")
+ julia> Pkg.Registry.add()
"""
+ cmd_browser = MonoSpaceFontTextBrowser(self)
+ cmd_browser.append(cmds)
self.layout().addWidget(HyperTextLabel(description))
- self.setButtonText(QWizard.CommitButton, "Reset registry")
+ self.layout().addWidget(cmd_browser)
+ self.setButtonText(QWizard.WizardButton.CommitButton, action)
- def _initialize_page_solution2(self):
+ def _initialize_page_solution3(self):
action = {"add": "Install SpineOpt", "update": "Update SpineOpt"}[self.wizard().required_action]
- self.setTitle("Update Windows Managemet Framework")
+ self.setTitle("Update Windows Management Framework")
description = (
- "The issue you're facing can be solved by installing Windows Managemet Framework 3 or greater, "
+ "
The issue you're facing can be solved by updating Windows Management Framework to 5.1 or greater, "
"as follows:
"
- "- Install .NET 4.5 "
- "from here.
"
- "- Install Windows management framework 3 or later "
- "from here.
"
+ "- Install latest .NET Framework (minimum 4.5) "
+ "from here.
"
+ "- Install Windows management framework 5.1 or later "
+ "from here.
"
f"- {action} again.
"
"
"
)
self.layout().addWidget(HyperTextLabel(description))
- self.setButtonText(QWizard.CommitButton, action)
+ self.setButtonText(QWizard.WizardButton.CommitButton, action)
def nextId(self):
- if self.field("problem1"):
- return _PageId.RESET_REGISTRY
return _PageId.ADD_UP_SPINE_OPT_AGAIN
-class ResetRegistryPage(QWizardProcessPage):
- def initializePage(self):
- code = (
- "using Pkg; "
- 'rm(joinp ath(DEPOT_PATH[1], "registries", "General"); force=true, recursive=true); '
- 'withenv("JULIA_PKG_SERVER"=>"") do pkg"registry add" end'
- )
- self.setTitle("Resetting Julia General Registry")
- julia_exe = self.field("julia_exe")
- julia_project = self.field("julia_project")
- args = [f"--project={julia_project}", "-e", code]
- self._exec_mngr = QProcessExecutionManager(self, julia_exe, args, semisilent=True)
- self.completeChanged.emit()
- self._exec_mngr.execution_finished.connect(self._handle_registry_reset_finished)
- self.msg_success.emit("Registry reset started")
- cmd = julia_exe + " " + " ".join(args)
- self.msg.emit(f"$ {cmd}")
- qApp.setOverrideCursor(QCursor(Qt.BusyCursor)) # pylint: disable=undefined-variable
- self._exec_mngr.start_execution()
-
- def _handle_registry_reset_finished(self, ret):
- qApp.restoreOverrideCursor() # pylint: disable=undefined-variable
- self._exec_mngr.execution_finished.disconnect(self._handle_registry_reset_finished)
- if self.wizard().currentPage() is not self:
- return
- self._exec_mngr = None
- self._successful = ret == 0
- if self._successful:
- self.msg_success.emit("Registry successfully reset")
- self.setCommitPage(True)
- action = {"add": "Install SpineOpt", "update": "Update SpineOpt"}[self.wizard().required_action]
- self.setButtonText(QWizard.CommitButton, action)
- else:
- # FIXME: Rather, add a button to copy log to clipboard?
- # self.wizard().process_log = self._log.toHtml()
- self.msg_error.emit("Registry reset failed")
- self.completeChanged.emit()
-
- def nextId(self):
- if self._successful:
- return _PageId.ADD_UP_SPINE_OPT_AGAIN
- return _PageId.TOTAL_FAILURE
-
-
class AddUpSpineOptAgainPage(AddUpSpineOptPage):
def nextId(self):
if self._successful:
@@ -513,10 +528,29 @@ def nextId(self):
class TotalFailurePage(QWizardPage):
def __init__(self, parent):
super().__init__(parent)
+ self._copy_label = QLabel()
+
+ def initializePage(self):
self.setTitle("Troubleshooting failed")
- msg = "Please open an issue with SpineOpt."
+ msg = ("
Please open an issue with SpineOpt."
+ "
Copy the log and paste it into the issue description.
")
layout = QVBoxLayout(self)
layout.addWidget(HyperTextLabel(msg))
+ copy_widget = QWidget()
+ copy_button = QPushButton("Copy log")
+ self._copy_label.setText("Log copied to clipboard")
+ self._copy_label.hide()
+ layout_copy = QHBoxLayout(copy_widget)
+ layout_copy.addWidget(copy_button)
+ layout_copy.addWidget(self._copy_label)
+ layout_copy.addStretch()
+ layout.addWidget(copy_widget)
+ copy_button.clicked.connect(self._handle_copy_clicked)
+
+ @Slot(bool)
+ def _handle_copy_clicked(self, _=False):
+ self._copy_label.show()
+ QApplication.clipboard().setText(self.wizard().process_log_plain) # pylint: disable=undefined-variable
def nextId(self):
return -1
diff --git a/spinetoolbox/widgets/install_julia_wizard.py b/spinetoolbox/widgets/install_julia_wizard.py
index d5956c27f..15bafee7a 100644
--- a/spinetoolbox/widgets/install_julia_wizard.py
+++ b/spinetoolbox/widgets/install_julia_wizard.py
@@ -31,6 +31,7 @@
QWidget,
QWizard,
QWizardPage,
+ QApplication,
)
from spine_engine.utils.helpers import resolve_current_python_interpreter
from ..config import APPLICATION_PATH
@@ -156,7 +157,7 @@ def __init__(self, parent):
install_dir_button.clicked.connect(self._select_install_dir)
symlink_dir_button.clicked.connect(self._select_symlink_dir)
self.setCommitPage(True)
- self.setButtonText(QWizard.CommitButton, "Install Julia")
+ self.setButtonText(QWizard.WizardButton.CommitButton, "Install Julia")
def initializePage(self):
self._install_dir_line_edit.setText(jill_install.default_install_dir())
@@ -215,12 +216,12 @@ def initializePage(self):
self.msg_success.emit("Julia installation started")
cmd = python + " " + " ".join(args)
self.msg.emit(f"$ {cmd}")
- qApp.setOverrideCursor(QCursor(Qt.BusyCursor)) # pylint: disable=undefined-variable
+ QApplication.setOverrideCursor(QCursor(Qt.CursorShape.BusyCursor)) # pylint: disable=undefined-variable
self._exec_mngr.start_execution()
@Slot(int)
def _handle_julia_install_finished(self, ret):
- qApp.restoreOverrideCursor() # pylint: disable=undefined-variable
+ QApplication.restoreOverrideCursor() # pylint: disable=undefined-variable
self._exec_mngr.execution_finished.disconnect(self._handle_julia_install_finished)
if self.wizard().currentPage() != self:
return
diff --git a/tests/widgets/test_AddUpSpineOptWizard.py b/tests/widgets/test_AddUpSpineOptWizard.py
index a73bfb19f..128cfcd69 100644
--- a/tests/widgets/test_AddUpSpineOptWizard.py
+++ b/tests/widgets/test_AddUpSpineOptWizard.py
@@ -41,7 +41,7 @@ def test_spine_opt_installation_succeeds(self):
wizard.restart()
self.assertEqual("Welcome", wizard.currentPage().title())
wizard.next()
- self.assertEqual("Select Julia project", wizard.currentPage().title())
+ self.assertEqual("Select Julia", wizard.currentPage().title())
with mock.patch("spinetoolbox.execution_managers.QProcess") as MockQProcess:
MockQProcess.return_value = MockInstantQProcess(finished_args=(0, MockQProcess.NormalExit))
wizard.next()
@@ -60,7 +60,7 @@ def test_spine_opt_update_succeeds(self):
wizard.restart()
self.assertEqual("Welcome", wizard.currentPage().title())
wizard.next()
- self.assertEqual("Select Julia project", wizard.currentPage().title())
+ self.assertEqual("Select Julia", wizard.currentPage().title())
with mock.patch("spinetoolbox.execution_managers.QProcess") as MockQProcess:
# We need the process to return a version that's lower than required
curr_ver_split = [int(x) for x in REQUIRED_SPINE_OPT_VERSION.split(".")]
@@ -84,7 +84,7 @@ def test_spine_opt_already_up_to_date(self):
wizard.restart()
self.assertEqual("Welcome", wizard.currentPage().title())
wizard.next()
- self.assertEqual("Select Julia project", wizard.currentPage().title())
+ self.assertEqual("Select Julia", wizard.currentPage().title())
with mock.patch("spinetoolbox.execution_managers.QProcess") as MockQProcess:
stdout = REQUIRED_SPINE_OPT_VERSION.encode()
MockQProcess.return_value = MockInstantQProcess(finished_args=(0, MockQProcess.NormalExit), stdout=stdout)
@@ -97,7 +97,7 @@ def _make_failed_wizard(self):
wizard.restart()
self.assertEqual("Welcome", wizard.currentPage().title())
wizard.next()
- self.assertEqual("Select Julia project", wizard.currentPage().title())
+ self.assertEqual("Select Julia", wizard.currentPage().title())
with mock.patch("spinetoolbox.execution_managers.QProcess") as MockQProcess:
MockQProcess.return_value = MockInstantQProcess(finished_args=(0, MockQProcess.NormalExit))
wizard.next()
@@ -120,38 +120,48 @@ def test_registry_reset_succeeds(self):
wizard = self._make_failed_wizard()
wizard.next()
self.assertEqual("Troubleshooting", wizard.currentPage().title())
- wizard.setField("problem1", True)
+ wizard.setField("problem2", True)
wizard.next()
self.assertEqual("Reset Julia General Registry", wizard.currentPage().title())
self.assertTrue(wizard.currentPage().isCommitPage())
- self.assertEqual("Reset registry", wizard.currentPage().buttonText(QWizard.WizardButton.CommitButton))
+ self.assertEqual("Install SpineOpt", wizard.currentPage().buttonText(QWizard.WizardButton.CommitButton))
with mock.patch("spinetoolbox.execution_managers.QProcess") as MockQProcess:
MockQProcess.return_value = MockInstantQProcess(finished_args=(0, MockQProcess.NormalExit))
wizard.next()
- self.assertEqual("Resetting Julia General Registry", wizard.currentPage().title())
- self.assertTrue(wizard.currentPage().isCommitPage())
+ self.assertEqual("Installing SpineOpt", wizard.currentPage().title())
+ wizard.next()
+ self.assertEqual("Installation successful", wizard.currentPage().title())
+ self.assertTrue(wizard.currentPage().isFinalPage())
+
+ def test_what_now_page(self):
+ wizard = self._make_failed_wizard()
+ wizard.next()
+ self.assertEqual("Troubleshooting", wizard.currentPage().title())
+ wizard.setField("problem1", True)
+ wizard.next()
+ self.assertEqual("What now?", wizard.currentPage().title())
self.assertEqual("Install SpineOpt", wizard.currentPage().buttonText(QWizard.WizardButton.CommitButton))
with mock.patch("spinetoolbox.execution_managers.QProcess") as MockQProcess:
- MockQProcess.return_value = MockInstantQProcess(finished_args=(0, MockQProcess.NormalExit))
+ MockQProcess.return_value = MockInstantQProcess(finished_args=(-1, MockQProcess.NormalExit))
wizard.next()
self.assertEqual("Installing SpineOpt", wizard.currentPage().title())
wizard.next()
- self.assertEqual("Installation successful", wizard.currentPage().title())
+ self.assertEqual("Troubleshooting failed", wizard.currentPage().title())
self.assertTrue(wizard.currentPage().isFinalPage())
def test_registry_reset_fails(self):
wizard = self._make_failed_wizard()
wizard.next()
self.assertEqual("Troubleshooting", wizard.currentPage().title())
- wizard.setField("problem1", True)
+ wizard.setField("problem2", True)
wizard.next()
self.assertEqual("Reset Julia General Registry", wizard.currentPage().title())
self.assertTrue(wizard.currentPage().isCommitPage())
- self.assertEqual("Reset registry", wizard.currentPage().buttonText(QWizard.WizardButton.CommitButton))
+ self.assertEqual("Install SpineOpt", wizard.currentPage().buttonText(QWizard.WizardButton.CommitButton))
with mock.patch("spinetoolbox.execution_managers.QProcess") as MockQProcess:
MockQProcess.return_value = MockInstantQProcess(finished_args=(-1, MockQProcess.NormalExit))
wizard.next()
- self.assertEqual("Resetting Julia General Registry", wizard.currentPage().title())
+ self.assertEqual("Installing SpineOpt", wizard.currentPage().title())
wizard.next()
self.assertEqual("Troubleshooting failed", wizard.currentPage().title())
self.assertTrue(wizard.currentPage().isFinalPage())
@@ -160,16 +170,10 @@ def test_registry_reset_succeeds_but_installing_spine_opt_fails_again_afterwards
wizard = self._make_failed_wizard()
wizard.next()
self.assertEqual("Troubleshooting", wizard.currentPage().title())
- wizard.setField("problem1", True)
+ wizard.setField("problem2", True)
wizard.next()
self.assertEqual("Reset Julia General Registry", wizard.currentPage().title())
self.assertTrue(wizard.currentPage().isCommitPage())
- self.assertEqual("Reset registry", wizard.currentPage().buttonText(QWizard.WizardButton.CommitButton))
- with mock.patch("spinetoolbox.execution_managers.QProcess") as MockQProcess:
- MockQProcess.return_value = MockInstantQProcess(finished_args=(0, MockQProcess.NormalExit))
- wizard.next()
- self.assertEqual("Resetting Julia General Registry", wizard.currentPage().title())
- self.assertTrue(wizard.currentPage().isCommitPage())
self.assertEqual("Install SpineOpt", wizard.currentPage().buttonText(QWizard.WizardButton.CommitButton))
with mock.patch("spinetoolbox.execution_managers.QProcess") as MockQProcess:
MockQProcess.return_value = MockInstantQProcess(finished_args=(-1, MockQProcess.NormalExit))
@@ -183,9 +187,9 @@ def test_updating_wmf_succeeds(self):
wizard = self._make_failed_wizard()
wizard.next()
self.assertEqual("Troubleshooting", wizard.currentPage().title())
- wizard.setField("problem2", True)
+ wizard.setField("problem3", True)
wizard.next()
- self.assertEqual("Update Windows Managemet Framework", wizard.currentPage().title())
+ self.assertEqual("Update Windows Management Framework", wizard.currentPage().title())
self.assertTrue(wizard.currentPage().isCommitPage())
self.assertEqual("Install SpineOpt", wizard.currentPage().buttonText(QWizard.WizardButton.CommitButton))
with mock.patch("spinetoolbox.execution_managers.QProcess") as MockQProcess:
@@ -200,9 +204,9 @@ def test_updating_wmf_fails(self):
wizard = self._make_failed_wizard()
wizard.next()
self.assertEqual("Troubleshooting", wizard.currentPage().title())
- wizard.setField("problem2", True)
+ wizard.setField("problem3", True)
wizard.next()
- self.assertEqual("Update Windows Managemet Framework", wizard.currentPage().title())
+ self.assertEqual("Update Windows Management Framework", wizard.currentPage().title())
self.assertTrue(wizard.currentPage().isCommitPage())
self.assertEqual("Install SpineOpt", wizard.currentPage().buttonText(QWizard.WizardButton.CommitButton))
with mock.patch("spinetoolbox.execution_managers.QProcess") as MockQProcess: