diff --git a/src/aiidalab_qe/app/configuration/__init__.py b/src/aiidalab_qe/app/configuration/__init__.py
index 6b5414d29..17d932b3e 100644
--- a/src/aiidalab_qe/app/configuration/__init__.py
+++ b/src/aiidalab_qe/app/configuration/__init__.py
@@ -6,7 +6,6 @@
from __future__ import annotations
import ipywidgets as ipw
-import traitlets as tl
from aiidalab_qe.app.parameters import DEFAULT_PARAMETERS
from aiidalab_qe.app.utils import get_entry_items
@@ -15,7 +14,7 @@
ConfigurationSettingsModel,
ConfigurationSettingsPanel,
)
-from aiidalab_qe.common.widgets import QeDependentWizardStep
+from aiidalab_qe.common.wizard import QeConfirmableDependentWizardStep
from .advanced import (
AdvancedConfigurationSettingsModel,
@@ -27,14 +26,18 @@
DEFAULT: dict = DEFAULT_PARAMETERS # type: ignore
-class ConfigureQeAppWorkChainStep(QeDependentWizardStep[ConfigurationStepModel]):
+class ConfigureQeAppWorkChainStep(
+ QeConfirmableDependentWizardStep[ConfigurationStepModel]
+):
missing_information_warning = "Missing input structure. Please set it first."
def __init__(self, model: ConfigurationStepModel, **kwargs):
- super().__init__(model=model, **kwargs)
- self._model.observe(
- self._on_confirmation_change,
- "confirmed",
+ super().__init__(
+ model=model,
+ confirm_kwargs={
+ "tooltip": "Confirm the currently selected settings and go to the next step",
+ },
+ **kwargs,
)
self._model.observe(
self._on_input_structure_change,
@@ -69,6 +72,8 @@ def __init__(self, model: ConfigurationStepModel, **kwargs):
self._fetch_plugin_calculation_settings()
def _render(self):
+ super()._render()
+
# RelaxType: degrees of freedom in geometry optimization
self.relax_type_help = ipw.HTML()
ipw.dlink(
@@ -115,22 +120,7 @@ def _render(self):
self.sub_steps.set_title(0, "Step 2.1: Select which properties to calculate")
self.sub_steps.set_title(1, "Step 2.2: Customize calculation parameters")
- self.confirm_button = ipw.Button(
- description="Confirm",
- tooltip="Confirm the currently selected settings and go to the next step.",
- button_style="success",
- icon="check-circle",
- disabled=True,
- layout=ipw.Layout(width="auto"),
- )
- ipw.dlink(
- (self, "state"),
- (self.confirm_button, "disabled"),
- lambda state: state != self.State.CONFIGURED,
- )
- self.confirm_button.on_click(self.confirm)
-
- self.children = [
+ self.content.children = [
InAppGuide(identifier="configuration-step"),
ipw.HTML("""
@@ -140,28 +130,22 @@ def _render(self):
self.relax_type_help,
self.relax_type,
self.sub_steps,
- self.confirm_button,
+ ]
+
+ self.children = [
+ self.content,
+ self.confirm_box,
]
def _post_render(self):
self._update_tabs()
- def is_saved(self):
- return self._model.confirmed
-
- def confirm(self, _=None):
- self._model.confirm()
-
def reset(self):
self._model.reset()
if self.rendered:
self.sub_steps.selected_index = None
self.tabs.selected_index = 0
- @tl.observe("previous_step_state")
- def _on_previous_step_state_change(self, _):
- self._update_state()
-
def _on_tab_change(self, change):
if (tab_index := change["new"]) is None:
return
@@ -173,9 +157,6 @@ def _on_input_structure_change(self, _):
self._model.update()
self.reset()
- def _on_confirmation_change(self, _):
- self._update_state()
-
def _update_tabs(self):
children = []
titles = []
diff --git a/src/aiidalab_qe/app/configuration/model.py b/src/aiidalab_qe/app/configuration/model.py
index ceb19dc07..b8b664c88 100644
--- a/src/aiidalab_qe/app/configuration/model.py
+++ b/src/aiidalab_qe/app/configuration/model.py
@@ -6,12 +6,11 @@
from aiida_quantumespresso.common.types import RelaxType
from aiidalab_qe.app.parameters import DEFAULT_PARAMETERS
from aiidalab_qe.common.mixins import (
- Confirmable,
HasInputStructure,
HasModels,
)
from aiidalab_qe.common.panel import ConfigurationSettingsModel
-from aiidalab_qe.common.widgets import QeWizardStepModel
+from aiidalab_qe.common.wizard import QeConfirmableWizardStepModel
DEFAULT: dict = DEFAULT_PARAMETERS # type: ignore
@@ -19,10 +18,9 @@
class ConfigurationStepModel(
- QeWizardStepModel,
+ QeConfirmableWizardStepModel,
HasModels[ConfigurationSettingsModel],
HasInputStructure,
- Confirmable,
):
identifier = "configuration"
diff --git a/src/aiidalab_qe/app/main.py b/src/aiidalab_qe/app/main.py
index e482b73c1..a36c54c3a 100644
--- a/src/aiidalab_qe/app/main.py
+++ b/src/aiidalab_qe/app/main.py
@@ -23,14 +23,14 @@ class QeApp:
def __init__(
self,
process=None,
- qe_auto_setup=True,
+ auto_setup=True,
bug_report_url=DEFAULT_BUG_REPORT_URL,
show_log=False,
):
"""Initialize the AiiDAlab QE application with the necessary setup."""
self.process = process
- self.qe_auto_setup = qe_auto_setup
+ self.auto_setup = auto_setup
self.log_widget = None
self._load_styles()
@@ -83,7 +83,7 @@ def _load_styles(self):
def load(self):
"""Initialize the WizardApp and integrate the app into the main view."""
self.app = WizardApp(
- qe_auto_setup=self.qe_auto_setup,
+ auto_setup=self.auto_setup,
log_widget=self.log_widget,
)
self.view.main.children = [self.app]
diff --git a/src/aiidalab_qe/app/result/__init__.py b/src/aiidalab_qe/app/result/__init__.py
index 1f474136e..a3fbe841c 100644
--- a/src/aiidalab_qe/app/result/__init__.py
+++ b/src/aiidalab_qe/app/result/__init__.py
@@ -3,7 +3,8 @@
from aiida.engine import ProcessState
from aiidalab_qe.common.infobox import InAppGuide
-from aiidalab_qe.common.widgets import LoadingWidget, QeDependentWizardStep
+from aiidalab_qe.common.widgets import LoadingWidget
+from aiidalab_qe.common.wizard import QeDependentWizardStep
from aiidalab_widgets_base import ProcessMonitor, WizardAppWidgetStep
from .components import ResultsComponent
diff --git a/src/aiidalab_qe/app/result/model.py b/src/aiidalab_qe/app/result/model.py
index d8cdb4f87..c6b6c5564 100644
--- a/src/aiidalab_qe/app/result/model.py
+++ b/src/aiidalab_qe/app/result/model.py
@@ -7,7 +7,7 @@
from aiida import orm
from aiida.engine.processes import control
from aiidalab_qe.common.mixins import HasModels, HasProcess
-from aiidalab_qe.common.widgets import QeWizardStepModel
+from aiidalab_qe.common.wizard import QeWizardStepModel
from .components import ResultsComponentModel
diff --git a/src/aiidalab_qe/app/static/styles/custom.css b/src/aiidalab_qe/app/static/styles/custom.css
index 914686bbd..d47bf643a 100644
--- a/src/aiidalab_qe/app/static/styles/custom.css
+++ b/src/aiidalab_qe/app/static/styles/custom.css
@@ -118,3 +118,8 @@ footer {
padding: 0 5px;
margin: -1px;
}
+
+.blocker-messages .alert {
+ margin-bottom: 0;
+ padding: 10px;
+}
diff --git a/src/aiidalab_qe/app/structure/__init__.py b/src/aiidalab_qe/app/structure/__init__.py
index 8f2b85af3..31ee86477 100644
--- a/src/aiidalab_qe/app/structure/__init__.py
+++ b/src/aiidalab_qe/app/structure/__init__.py
@@ -17,7 +17,8 @@
ShakeNBreakEditor,
)
from aiidalab_qe.common.infobox import InAppGuide
-from aiidalab_qe.common.widgets import CategorizedStructureExamplesWidget, QeWizardStep
+from aiidalab_qe.common.widgets import CategorizedStructureExamplesWidget
+from aiidalab_qe.common.wizard import QeConfirmableWizardStep
from aiidalab_widgets_base import (
BasicCellEditor,
BasicStructureEditor,
@@ -25,7 +26,7 @@
StructureUploadWidget,
)
-# The Examples list of (name, file) tuple curretly passed to
+# The Examples list of (name, file) tuple currently passed to
# StructureExamplesWidget.
file_path = pathlib.Path(__file__).parent
Examples = [
@@ -39,25 +40,38 @@
]
-class StructureSelectionStep(QeWizardStep[StructureStepModel]):
+class StructureSelectionStep(QeConfirmableWizardStep[StructureStepModel]):
"""Integrated widget for the selection and edition of structure.
The widget includes a structure manager that allows to select a structure
from different sources. It also includes the structure editor. Both the
structure importers and the structure editors can be extended by plugins.
"""
- def __init__(self, model: StructureStepModel, **kwargs):
- super().__init__(model=model, **kwargs)
+ def __init__(self, model: StructureStepModel, auto_setup=True, **kwargs):
+ super().__init__(
+ model=model,
+ confirm_kwargs={
+ "tooltip": "Confirm the currently selected structure and go to the next step",
+ },
+ **kwargs,
+ )
+ self._model.observe(
+ self._on_installation_change,
+ ["installing_sssp", "sssp_installed"],
+ )
self._model.observe(
- self._on_confirmation_change,
- "confirmed",
+ self._on_sssp_installed,
+ "sssp_installed",
)
self._model.observe(
self._on_input_structure_change,
"input_structure",
)
+ self._install_sssp(auto_setup)
def _render(self):
+ super()._render()
+
examples_by_category = {"Simple crystals": Examples}
plugin_structure_examples = {
item["title"]: item["structures"]
@@ -65,7 +79,7 @@ def _render(self):
"aiidalab_qe.properties", "structure_examples"
).values()
}
- examples_by_category.update(plugin_structure_examples)
+ examples_by_category |= plugin_structure_examples
importers = [
StructureUploadWidget(title="Upload file"),
@@ -129,27 +143,7 @@ def _render(self):
(self.structure_name_text, "value"),
)
- self.confirm_button = ipw.Button(
- description="Confirm",
- tooltip="Confirm the currently selected structure and go to the next step.",
- button_style="success",
- icon="check-circle",
- layout=ipw.Layout(width="auto"),
- )
- ipw.dlink(
- (self, "state"),
- (self.confirm_button, "disabled"),
- lambda state: state != self.State.CONFIGURED,
- )
- self.confirm_button.on_click(self.confirm)
-
- self.message_area = ipw.HTML()
- ipw.dlink(
- (self._model, "message_area"),
- (self.message_area, "value"),
- )
-
- self.children = [
+ self.content.children = [
InAppGuide(identifier="structure-step"),
ipw.HTML("""
@@ -161,20 +155,23 @@ def _render(self):
"""),
self.manager,
self.structure_name_text,
- self.message_area,
- self.confirm_button,
]
- # after rendering the widget, nglview needs to be resized
+
+ self.confirm_box.children += (self.sssp_installation,)
+
+ self.children = [
+ self.content,
+ self.confirm_box,
+ ]
+
+ def _post_render(self):
+ # After rendering the widget, nglview needs to be resized
# to properly display the structure
self.manager.viewer._viewer.handle_resize()
- def is_saved(self):
- return self._model.confirmed
-
def confirm(self, _=None):
self.manager.store_structure()
- self._model.message_area = ""
- self._model.confirm()
+ super().confirm()
def can_reset(self):
return self._model.confirmed
@@ -182,12 +179,39 @@ def can_reset(self):
def reset(self):
self._model.reset()
+ def _on_installation_change(self, _):
+ self._model.update_blockers()
+
+ def _on_sssp_installed(self, _):
+ self._toggle_sssp_installation_widget()
+
def _on_input_structure_change(self, _):
self._model.update_widget_text()
self._update_state()
- def _on_confirmation_change(self, _):
- self._update_state()
+ def _install_sssp(self, auto_setup):
+ from aiidalab_qe.common.setup_pseudos import PseudosInstallWidget
+
+ self.sssp_installation = PseudosInstallWidget(auto_start=False)
+ ipw.dlink(
+ (self.sssp_installation, "busy"),
+ (self._model, "installing_sssp"),
+ )
+ ipw.dlink(
+ (self.sssp_installation, "installed"),
+ (self._model, "installing_sssp"),
+ lambda installed: not installed,
+ )
+ ipw.dlink(
+ (self.sssp_installation, "installed"),
+ (self._model, "sssp_installed"),
+ )
+ if auto_setup:
+ self.sssp_installation.refresh()
+
+ def _toggle_sssp_installation_widget(self):
+ sssp_installation_display = "none" if self._model.sssp_installed else "block"
+ self.sssp_installation.layout.display = sssp_installation_display
def _update_state(self):
if self._model.confirmed:
diff --git a/src/aiidalab_qe/app/structure/model.py b/src/aiidalab_qe/app/structure/model.py
index 8cbaf4c2c..25b264d19 100644
--- a/src/aiidalab_qe/app/structure/model.py
+++ b/src/aiidalab_qe/app/structure/model.py
@@ -1,24 +1,31 @@
import traitlets as tl
-from aiidalab_qe.common.mixins import Confirmable, HasInputStructure
-from aiidalab_qe.common.widgets import QeWizardStepModel
+from aiidalab_qe.common.mixins import HasInputStructure
+from aiidalab_qe.common.wizard import QeConfirmableWizardStepModel
class StructureStepModel(
- QeWizardStepModel,
+ QeConfirmableWizardStepModel,
HasInputStructure,
- Confirmable,
):
identifier = "structure"
structure_name = tl.Unicode("")
manager_output = tl.Unicode("")
- message_area = tl.Unicode("")
+
+ installing_sssp = tl.Bool(False)
+ sssp_installed = tl.Bool(allow_none=True)
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.confirmation_exceptions += [
+ "installing_sssp",
+ "sssp_installed",
+ ]
def update_widget_text(self):
if not self.has_structure:
self.structure_name = ""
- self.message_area = ""
else:
self.manager_output = ""
self.structure_name = str(self.input_structure.get_formula())
@@ -27,4 +34,7 @@ def reset(self):
self.input_structure = None
self.structure_name = ""
self.manager_output = ""
- self.message_area = ""
+
+ def _check_blockers(self):
+ if not self.sssp_installed:
+ yield "The SSSP library is not installed"
diff --git a/src/aiidalab_qe/app/submission/__init__.py b/src/aiidalab_qe/app/submission/__init__.py
index c3777adfd..d2ad699f2 100644
--- a/src/aiidalab_qe/app/submission/__init__.py
+++ b/src/aiidalab_qe/app/submission/__init__.py
@@ -6,7 +6,6 @@
from __future__ import annotations
import ipywidgets as ipw
-import traitlets as tl
from aiidalab_qe.app.parameters import DEFAULT_PARAMETERS
from aiidalab_qe.app.utils import get_entry_items
@@ -18,8 +17,8 @@
ResourceSettingsPanel,
)
from aiidalab_qe.common.setup_codes import QESetupWidget
-from aiidalab_qe.common.setup_pseudos import PseudosInstallWidget
-from aiidalab_qe.common.widgets import LinkButton, QeDependentWizardStep
+from aiidalab_qe.common.widgets import LinkButton
+from aiidalab_qe.common.wizard import QeConfirmableDependentWizardStep
from .global_settings import GlobalResourceSettingsModel, GlobalResourceSettingsPanel
from .model import SubmissionStepModel
@@ -27,33 +26,18 @@
DEFAULT: dict = DEFAULT_PARAMETERS # type: ignore
-class SubmitQeAppWorkChainStep(QeDependentWizardStep[SubmissionStepModel]):
+class SubmitQeAppWorkChainStep(QeConfirmableDependentWizardStep[SubmissionStepModel]):
missing_information_warning = "Missing input structure and/or configuration parameters. Please set them first."
- def __init__(self, model: SubmissionStepModel, qe_auto_setup=True, **kwargs):
- super().__init__(model=model, **kwargs)
- self._model.observe(
- self._on_submission,
- "confirmed",
- )
- self._model.observe(
- self._on_input_parameters_change,
- "input_parameters",
- )
- self._model.observe(
- self._on_submission_blockers_change,
- [
- "internal_submission_blockers",
- "external_submission_blockers",
- ],
- )
- self._model.observe(
- self._on_installation_change,
- ["installing_sssp", "sssp_installed"],
- )
- self._model.observe(
- self._on_sssp_installed,
- "sssp_installed",
+ def __init__(self, model: SubmissionStepModel, auto_setup=True, **kwargs):
+ super().__init__(
+ model=model,
+ confirm_kwargs={
+ "description": "Submit",
+ "tooltip": "Submit the calculation with the selected parameters.",
+ "icon": "play",
+ },
+ **kwargs,
)
self._model.observe(
self._on_installation_change,
@@ -63,6 +47,10 @@ def __init__(self, model: SubmissionStepModel, qe_auto_setup=True, **kwargs):
self._on_qe_installed,
"qe_installed",
)
+ self._model.observe(
+ self._on_input_parameters_change,
+ "input_parameters",
+ )
global_resources_model = GlobalResourceSettingsModel()
self.global_resources = GlobalResourceSettingsPanel(
@@ -74,12 +62,12 @@ def __init__(self, model: SubmissionStepModel, qe_auto_setup=True, **kwargs):
(global_resources_model, "plugin_overrides"),
)
global_resources_model.observe(
- self._on_plugin_submission_blockers_change,
- ["submission_blockers"],
+ self._on_plugin_blockers_change,
+ "blockers",
)
global_resources_model.observe(
- self._on_plugin_submission_warning_messages_change,
- ["submission_warning_messages"],
+ self._on_plugin_warning_messages_change,
+ ["warning_messages"],
)
self.settings = {
@@ -87,10 +75,11 @@ def __init__(self, model: SubmissionStepModel, qe_auto_setup=True, **kwargs):
}
self._fetch_plugin_resource_settings()
- self._install_sssp(qe_auto_setup)
- self._set_up_qe(qe_auto_setup)
+ self._set_up_qe(auto_setup)
def _render(self):
+ super()._render()
+
self.process_label = ipw.Text(
description="Label:",
layout=ipw.Layout(width="auto", indent="0px"),
@@ -108,31 +97,10 @@ def _render(self):
(self.process_description, "value"),
)
- self.submit_button = ipw.Button(
- description="Submit",
- tooltip="Submit the calculation with the selected parameters.",
- icon="play",
- button_style="success",
- layout=ipw.Layout(width="auto", flex="1 1 auto"),
- disabled=True,
- )
- ipw.dlink(
- (self, "state"),
- (self.submit_button, "disabled"),
- lambda state: state != self.State.CONFIGURED,
- )
- self.submit_button.on_click(self.submit)
-
- self.submission_blocker_messages = ipw.HTML()
+ self.warning_messages = ipw.HTML()
ipw.dlink(
- (self._model, "submission_blocker_messages"),
- (self.submission_blocker_messages, "value"),
- )
-
- self.submission_warning_messages = ipw.HTML()
- ipw.dlink(
- (self._model, "submission_warning_messages"),
- (self.submission_warning_messages, "value"),
+ (self._model, "warning_messages"),
+ (self.warning_messages, "value"),
)
self.setup_new_codes_button = LinkButton(
@@ -158,7 +126,7 @@ def _render(self):
"selected_index",
)
- self.children = [
+ self.content.children = [
InAppGuide(identifier="submission-step"),
ipw.HTML("""
@@ -179,10 +147,6 @@ def _render(self):
layout=ipw.Layout(grid_gap="5px"),
),
self.tabs,
- self.sssp_installation,
- self.qe_setup,
- self.submission_blocker_messages,
- self.submission_warning_messages,
ipw.HTML("""
Label your job and provide a brief description. These details
@@ -193,22 +157,21 @@ def _render(self):
"""),
self.process_label,
self.process_description,
- self.submit_button,
+ ]
+
+ self.confirm_box.children += (self.qe_setup,)
+
+ self.children = [
+ self.content,
+ self.confirm_box,
]
def _post_render(self):
self._update_tabs()
- def submit(self, _=None):
- self._model.confirm()
-
def reset(self):
self._model.reset()
- @tl.observe("previous_step_state")
- def _on_previous_step_state_change(self, _):
- self._update_state()
-
def _on_tab_change(self, change):
if (tab_index := change["new"]) is None:
return
@@ -219,55 +182,28 @@ def _on_input_parameters_change(self, _):
self._model.update_process_label()
self._model.update_plugin_inclusion()
self._model.update_plugin_overrides()
- self._model.update_submission_blockers()
+ self._model.update_blockers()
self._update_tabs()
def _on_plugin_overrides_change(self, _):
self._model.update_plugin_overrides()
- def _on_plugin_submission_blockers_change(self, _):
- self._model.update_submission_blockers()
-
- def _on_plugin_submission_warning_messages_change(self, _):
- self._model.update_submission_warnings()
+ def _on_plugin_blockers_change(self, _):
+ self._model.update_blockers()
- def _on_submission_blockers_change(self, _):
- self._model.update_submission_blocker_message()
- self._update_state()
+ def _on_plugin_warning_messages_change(self, _):
+ self._model.update_warnings()
def _on_installation_change(self, _):
- self._model.update_submission_blockers()
+ self._model.update_blockers()
def _on_qe_installed(self, _):
self._toggle_qe_installation_widget()
if self._model.qe_installed:
self._model.update()
+ self._refresh_resources()
- def _on_sssp_installed(self, _):
- self._toggle_sssp_installation_widget()
-
- def _on_submission(self, _):
- self._update_state()
-
- def _install_sssp(self, qe_auto_setup):
- self.sssp_installation = PseudosInstallWidget(auto_start=False)
- ipw.dlink(
- (self.sssp_installation, "busy"),
- (self._model, "installing_sssp"),
- )
- ipw.dlink(
- (self.sssp_installation, "installed"),
- (self._model, "installing_sssp"),
- lambda installed: not installed,
- )
- ipw.dlink(
- (self.sssp_installation, "installed"),
- (self._model, "sssp_installed"),
- )
- if qe_auto_setup:
- self.sssp_installation.refresh()
-
- def _set_up_qe(self, qe_auto_setup):
+ def _set_up_qe(self, auto_setup):
self.qe_setup = QESetupWidget(auto_start=False)
ipw.dlink(
(self.qe_setup, "busy"),
@@ -282,13 +218,9 @@ def _set_up_qe(self, qe_auto_setup):
(self.qe_setup, "installed"),
(self._model, "qe_installed"),
)
- if qe_auto_setup:
+ if auto_setup:
self.qe_setup.refresh()
- def _toggle_sssp_installation_widget(self):
- sssp_installation_display = "none" if self._model.sssp_installed else "block"
- self.sssp_installation.layout.display = sssp_installation_display
-
def _toggle_qe_installation_widget(self):
qe_installation_display = "none" if self._model.qe_installed else "block"
self.qe_setup.layout.display = qe_installation_display
@@ -342,12 +274,12 @@ def _fetch_plugin_resource_settings(self):
"override",
)
model.observe(
- self._on_plugin_submission_blockers_change,
- ["submission_blockers"],
+ self._on_plugin_blockers_change,
+ "blockers",
)
model.observe(
- self._on_plugin_submission_warning_messages_change,
- ["submission_warning_messages"],
+ self._on_plugin_warning_messages_change,
+ "warning_messages",
)
self._model.add_model(identifier, model)
diff --git a/src/aiidalab_qe/app/submission/global_settings/model.py b/src/aiidalab_qe/app/submission/global_settings/model.py
index afd43eeab..fd116314d 100644
--- a/src/aiidalab_qe/app/submission/global_settings/model.py
+++ b/src/aiidalab_qe/app/submission/global_settings/model.py
@@ -141,7 +141,7 @@ def check_resources(self):
# List of possible suggestions for warnings:
suggestions = {
- "more_resources": f"
Increase the resources (total number of CPUs should be equal or more than {min(100,estimated_CPUs)}, if possible) ",
+ "more_resources": f"Increase the resources (total number of CPUs should be equal or more than {min(100, estimated_CPUs)}, if possible) ",
"change_configuration": "Review the configuration (e.g. choosing fast protocol - this will affect precision) ",
"go_remote": "Select a code that runs on a larger machine",
"avoid_overloading": "Reduce the number of CPUs to avoid the overloading of the local machine ",
@@ -194,7 +194,7 @@ def check_resources(self):
+ ""
)
- self.submission_warning_messages = (
+ self.warning_messages = (
""
if (on_localhost and num_cpus / machine_cpus) <= 0.8
and (not large_system or estimated_CPUs <= num_cpus)
@@ -207,7 +207,7 @@ def check_resources(self):
def _get_properties(self) -> list[str]:
return self.input_parameters.get("workchain", {}).get("properties", [])
- def _check_submission_blockers(self):
+ def _check_blockers(self):
# No pw code selected
pw_code_model = self.get_model("quantumespresso__pw")
if pw_code_model and not pw_code_model.selected:
diff --git a/src/aiidalab_qe/app/submission/global_settings/setting.py b/src/aiidalab_qe/app/submission/global_settings/setting.py
index d7f330d2b..412731c53 100644
--- a/src/aiidalab_qe/app/submission/global_settings/setting.py
+++ b/src/aiidalab_qe/app/submission/global_settings/setting.py
@@ -91,7 +91,7 @@ def _on_code_activation_change(self, change):
self._toggle_code(change["owner"])
def _on_code_selection_change(self, _):
- self._model.update_submission_blockers()
+ self._model.update_blockers()
def _on_pw_code_resource_change(self, _):
self._model.check_resources()
diff --git a/src/aiidalab_qe/app/submission/model.py b/src/aiidalab_qe/app/submission/model.py
index ff93bb032..c30072537 100644
--- a/src/aiidalab_qe/app/submission/model.py
+++ b/src/aiidalab_qe/app/submission/model.py
@@ -10,19 +10,18 @@
from aiida.engine import ProcessBuilderNamespace, submit
from aiida.orm.utils.serialize import serialize
from aiidalab_qe.app.parameters import DEFAULT_PARAMETERS
-from aiidalab_qe.common.mixins import Confirmable, HasInputStructure, HasModels
+from aiidalab_qe.common.mixins import HasInputStructure, HasModels
from aiidalab_qe.common.panel import PluginResourceSettingsModel, ResourceSettingsModel
-from aiidalab_qe.common.widgets import QeWizardStepModel
+from aiidalab_qe.common.wizard import QeConfirmableWizardStepModel
from aiidalab_qe.workflows import QeAppWorkChain
DEFAULT: dict = DEFAULT_PARAMETERS # type: ignore
class SubmissionStepModel(
- QeWizardStepModel,
+ QeConfirmableWizardStepModel,
HasModels[ResourceSettingsModel],
HasInputStructure,
- Confirmable,
):
identifier = "submission"
@@ -32,32 +31,20 @@ class SubmissionStepModel(
process_label = tl.Unicode("")
process_description = tl.Unicode("")
- internal_submission_blockers = tl.List(tl.Unicode())
- external_submission_blockers = tl.List(tl.Unicode())
- submission_blocker_messages = tl.Unicode("")
- submission_warning_messages = tl.Unicode("")
+ warning_messages = tl.Unicode("")
installing_qe = tl.Bool(False)
- installing_sssp = tl.Bool(False)
qe_installed = tl.Bool(allow_none=True)
- sssp_installed = tl.Bool(allow_none=True)
plugin_overrides = tl.List(tl.Unicode())
- confirmation_exceptions = [
- "confirmed",
- "internal_submission_blockers",
- "external_submission_blockers",
- "submission_blocker_messages",
- "submission_warning_messages",
- "installing_qe",
- "installing_sssp",
- "qe_installed",
- "sssp_installed",
- ]
-
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
+ self.confirmation_exceptions += [
+ "warning_messages",
+ "installing_qe",
+ "qe_installed",
+ ]
self._default_models = {
"global",
@@ -72,15 +59,6 @@ def __init__(self, *args, **kwargs):
"""
- @property
- def is_blocked(self):
- return any(
- [
- *self.internal_submission_blockers,
- *self.external_submission_blockers,
- ]
- )
-
def confirm(self):
super().confirm()
if not self.process_node:
@@ -152,32 +130,11 @@ def update_plugin_overrides(self):
and model.override
]
- def update_submission_blockers(self):
- submission_blockers = list(self._check_submission_blockers())
- for _, model in self.get_models():
- submission_blockers += model.submission_blockers
- self.internal_submission_blockers = submission_blockers
-
- def update_submission_warnings(self):
- submission_warning_messages = self._check_submission_warnings()
+ def update_warnings(self):
+ warning_messages = self._check_warnings()
for _, model in self.get_models():
- submission_warning_messages += model.submission_warning_messages
- self.submission_warning_messages = submission_warning_messages
-
- def update_submission_blocker_message(self):
- blockers = self.internal_submission_blockers + self.external_submission_blockers
- if any(blockers):
- formatted = "\n".join(f"
{item}" for item in blockers)
- self.submission_blocker_messages = f"""
-
-
The submission is blocked due to the following reason(s):
-
-
- """
- else:
- self.submission_blocker_messages = ""
+ warning_messages += model.warning_messages
+ self.warning_messages = warning_messages
def get_model_state(self) -> dict[str, dict[str, dict]]:
parameters: dict = deepcopy(self.input_parameters) # type: ignore
@@ -295,13 +252,13 @@ def _create_builder(self, parameters) -> ProcessBuilderNamespace:
return builder
- def _check_submission_blockers(self):
- if self.installing_qe or self.installing_sssp:
- yield "Background setup processes must finish."
+ def _check_blockers(self):
+ if self.installing_qe:
+ yield "Installing Quantum ESPRESSO codes..."
- if not self.sssp_installed:
- yield "The SSSP library is not installed."
+ if not self.qe_installed:
+ yield "Quantum ESPRESSO is not yet installed"
- def _check_submission_warnings(self):
+ def _check_warnings(self):
"""Check for any warnings that should be displayed to the user."""
return ""
diff --git a/src/aiidalab_qe/app/wizard_app.py b/src/aiidalab_qe/app/wizard_app.py
index 93944ec18..d75a2fe3e 100644
--- a/src/aiidalab_qe/app/wizard_app.py
+++ b/src/aiidalab_qe/app/wizard_app.py
@@ -13,7 +13,8 @@
from aiidalab_qe.app.submission import SubmitQeAppWorkChainStep
from aiidalab_qe.app.submission.model import SubmissionStepModel
from aiidalab_qe.common.infobox import InAppGuide
-from aiidalab_qe.common.widgets import LoadingWidget, QeWizardStep
+from aiidalab_qe.common.widgets import LoadingWidget
+from aiidalab_qe.common.wizard import QeWizardStep
from aiidalab_widgets_base import WizardAppWidget
@@ -23,7 +24,7 @@ class WizardApp(ipw.VBox):
# The PK or UUID of the work chain node.
process = tl.Union([tl.Unicode(), tl.Int()], allow_none=True)
- def __init__(self, qe_auto_setup=True, **kwargs):
+ def __init__(self, auto_setup=True, **kwargs):
# Initialize the models
self.structure_model = StructureStepModel()
self.configure_model = ConfigurationStepModel()
@@ -36,6 +37,7 @@ def __init__(self, qe_auto_setup=True, **kwargs):
self.structure_step = StructureSelectionStep(
model=self.structure_model,
auto_advance=True,
+ auto_setup=auto_setup,
)
self.configure_step = ConfigureQeAppWorkChainStep(
model=self.configure_model,
@@ -44,7 +46,7 @@ def __init__(self, qe_auto_setup=True, **kwargs):
self.submit_step = SubmitQeAppWorkChainStep(
model=self.submit_model,
auto_advance=True,
- qe_auto_setup=qe_auto_setup,
+ auto_setup=auto_setup,
)
self.results_step = ViewQeAppWorkChainStatusAndResultsStep(
model=self.results_model,
@@ -113,8 +115,6 @@ def __init__(self, qe_auto_setup=True, **kwargs):
self.structure_step.state = QeWizardStep.State.READY
- self._update_blockers()
-
@property
def steps(self):
return self._wizard_app_widget.steps
@@ -132,11 +132,9 @@ def _on_step_change(self, change):
def _on_structure_confirmation_change(self, _):
self._update_configuration_step()
- self._update_blockers()
def _on_configuration_confirmation_change(self, _):
self._update_submission_step()
- self._update_blockers()
def _on_submission(self, _):
self._update_results_step()
@@ -175,13 +173,6 @@ def _lock_app(self):
):
model.unobserve_all("confirmed")
- def _update_blockers(self):
- self.submit_model.external_submission_blockers = [
- f"Unsaved changes in the
{title} step. Please confirm the changes before submitting."
- for title, step in self.steps[:2]
- if not step.is_saved()
- ]
-
def _update_from_process(self, pk):
if pk is None:
self._wizard_app_widget.reset()
diff --git a/src/aiidalab_qe/common/mixins.py b/src/aiidalab_qe/common/mixins.py
index 220f6a8bb..782d45046 100644
--- a/src/aiidalab_qe/common/mixins.py
+++ b/src/aiidalab_qe/common/mixins.py
@@ -125,3 +125,37 @@ def _on_any_change(self, change):
def _unconfirm(self):
self.confirmed = False
+
+
+class HasBlockers(tl.HasTraits):
+ blockers = tl.List(tl.Unicode())
+ blocker_messages = tl.Unicode("")
+
+ @property
+ def is_blocked(self):
+ return any(self.blockers)
+
+ def update_blockers(self):
+ blockers = list(self._check_blockers())
+ if isinstance(self, HasModels):
+ for _, model in self.get_models():
+ if isinstance(model, HasBlockers):
+ blockers += model.blockers
+ self.blockers = blockers
+
+ def update_blocker_messages(self):
+ if self.is_blocked:
+ formatted = "\n".join(f"
{item}" for item in self.blockers)
+ self.blocker_messages = f"""
+
+
The step is blocked due to the following reason(s):
+
+
+ """
+ else:
+ self.blocker_messages = ""
+
+ def _check_blockers(self):
+ raise NotImplementedError
diff --git a/src/aiidalab_qe/common/panel.py b/src/aiidalab_qe/common/panel.py
index 5a42fd075..543094dc2 100644
--- a/src/aiidalab_qe/common/panel.py
+++ b/src/aiidalab_qe/common/panel.py
@@ -18,7 +18,7 @@
from aiidalab_qe.app.parameters import DEFAULT_PARAMETERS
from aiidalab_qe.common.code.model import CodeModel
from aiidalab_qe.common.infobox import InAppGuide
-from aiidalab_qe.common.mixins import Confirmable, HasModels, HasProcess
+from aiidalab_qe.common.mixins import Confirmable, HasBlockers, HasModels, HasProcess
from aiidalab_qe.common.mvc import Model
from aiidalab_qe.common.widgets import (
LoadingWidget,
@@ -88,7 +88,7 @@ def __init__(self, **kwargs):
)
-class SettingsModel(PanelModel):
+class SettingsModel(PanelModel, HasBlockers):
"""Base model for settings models."""
dependencies: list[str] = []
@@ -206,8 +206,7 @@ class ResourceSettingsModel(SettingsModel, HasModels[CodeModel]):
value_trait=tl.Dict(),
)
- submission_blockers = tl.List(tl.Unicode())
- submission_warning_messages = tl.Unicode("")
+ warning_messages = tl.Unicode("")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -223,9 +222,6 @@ def refresh_codes(self):
for _, code_model in self.get_models():
code_model.update(self.DEFAULT_USER_EMAIL, refresh=True)
- def update_submission_blockers(self):
- self.submission_blockers = list(self._check_submission_blockers())
-
def get_model_state(self):
return {
"codes": {
@@ -250,7 +246,7 @@ def set_selected_codes(self, code_data=DEFAULT["codes"]):
if identifier in code_data:
code_model.set_model_state(code_data[identifier])
- def _check_submission_blockers(self):
+ def _check_blockers(self):
return []
@@ -267,6 +263,10 @@ def __init__(self, model, **kwargs):
def _on_code_resource_change(self, _):
pass
+ def _on_code_options_change(self, change: dict):
+ widget: ipw.Dropdown = change["owner"]
+ widget.disabled = not widget.options
+
def _toggle_code(self, code_model: CodeModel):
if not self.rendered:
return
@@ -348,6 +348,10 @@ def _render_code_widget(
"max_wallclock_seconds",
],
)
+ code_widget.code_selection.code_select_dropdown.observe(
+ self._on_code_options_change,
+ "options",
+ )
code_widgets = self.code_widgets_container.children[:-1] # type: ignore
self.code_widgets_container.children = [*code_widgets, code_widget]
code_model.is_rendered = True
diff --git a/src/aiidalab_qe/common/widgets.py b/src/aiidalab_qe/common/widgets.py
index 5c492c6aa..a50746308 100644
--- a/src/aiidalab_qe/common/widgets.py
+++ b/src/aiidalab_qe/common/widgets.py
@@ -5,7 +5,6 @@
import base64
import hashlib
-import os
import subprocess
import typing as t
from copy import deepcopy
@@ -26,11 +25,9 @@
from aiida.orm import CalcJobNode, load_code, load_node
from aiida.orm import Data as orm_Data
-from aiidalab_qe.common.mvc import Model
from aiidalab_widgets_base import (
ComputationalResourcesWidget,
StructureExamplesWidget,
- WizardAppWidgetStep,
)
from aiidalab_widgets_base.utils import (
StatusHTML,
@@ -1189,80 +1186,6 @@ def _on_disabled(self, change):
self.remove_class("disabled")
-class QeWizardStepModel(Model):
- identifier = "QE wizard"
-
-
-QWSM = t.TypeVar("QWSM", bound=QeWizardStepModel)
-
-
-class QeWizardStep(ipw.VBox, WizardAppWidgetStep, t.Generic[QWSM]):
- def __init__(self, model: QWSM, **kwargs):
- self.loading_message = LoadingWidget(f"Loading {model.identifier} step")
- super().__init__(children=[self.loading_message], **kwargs)
- self._model = model
- self.rendered = False
- self._background_class = ""
-
- def render(self):
- if self.rendered:
- return
- self._render()
- self.rendered = True
- self._post_render()
-
- @traitlets.observe("state")
- def _on_state_change(self, change):
- self._update_background_color(change["new"])
-
- def _render(self):
- raise NotImplementedError()
-
- def _post_render(self):
- pass
-
- def _update_background_color(self, state: WizardAppWidgetStep.State):
- self.remove_class(self._background_class)
- self._background_class = f"qe-app-step-{state.name.lower()}"
- self.add_class(self._background_class)
-
-
-class QeDependentWizardStep(QeWizardStep[QWSM]):
- missing_information_warning = "Missing information"
-
- previous_step_state = traitlets.UseEnum(WizardAppWidgetStep.State)
-
- def __init__(self, model: QWSM, **kwargs):
- super().__init__(model, **kwargs)
- self.previous_children = list(self.children)
- self.warning_message = ipw.HTML(
- f"""
-
- Warning: {self.missing_information_warning}
-
- """
- )
-
- def render(self):
- if "PYTEST_CURRENT_TEST" in os.environ:
- super().render()
- return
- if self.previous_step_state is WizardAppWidgetStep.State.SUCCESS:
- self._hide_missing_information_warning()
- if not self.rendered:
- super().render()
- self.previous_children = list(self.children)
- else:
- self._show_missing_information_warning()
-
- def _show_missing_information_warning(self):
- self.children = [self.warning_message]
- self.rendered = False
-
- def _hide_missing_information_warning(self):
- self.children = self.previous_children
-
-
class TableWidget(anywidget.AnyWidget):
_esm = """
function render({ model, el }) {
diff --git a/src/aiidalab_qe/common/wizard.py b/src/aiidalab_qe/common/wizard.py
new file mode 100644
index 000000000..3e9bee8de
--- /dev/null
+++ b/src/aiidalab_qe/common/wizard.py
@@ -0,0 +1,224 @@
+from __future__ import annotations
+
+import os
+import typing as t
+
+import ipywidgets as ipw
+import traitlets as tl
+
+from aiidalab_qe.common.mixins import Confirmable, HasBlockers, HasModels
+from aiidalab_qe.common.mvc import Model
+from aiidalab_widgets_base import WizardAppWidgetStep
+
+from .widgets import LoadingWidget
+
+
+class QeWizardStepModel(Model):
+ identifier = "QE wizard"
+
+
+WSM = t.TypeVar("WSM", bound=QeWizardStepModel)
+
+
+class QeWizardStep(ipw.VBox, WizardAppWidgetStep, t.Generic[WSM]):
+ def __init__(self, model: WSM, **kwargs):
+ self.loading_message = LoadingWidget(f"Loading {model.identifier} step")
+ super().__init__(children=[self.loading_message], **kwargs)
+ self._model = model
+ self.rendered = False
+ self._background_class = ""
+
+ def render(self):
+ if self.rendered:
+ return
+ self._render()
+ self.rendered = True
+ self._post_render()
+
+ @tl.observe("state")
+ def _on_state_change(self, change):
+ self._update_background_color(change["new"])
+
+ def _render(self):
+ raise NotImplementedError()
+
+ def _post_render(self):
+ pass
+
+ def _update_background_color(self, state: WizardAppWidgetStep.State):
+ self.remove_class(self._background_class)
+ self._background_class = f"qe-app-step-{state.name.lower()}"
+ self.add_class(self._background_class)
+
+ def _update_state(self):
+ pass
+
+
+class QeConfirmableWizardStepModel(
+ QeWizardStepModel,
+ Confirmable,
+ HasBlockers,
+):
+ blockers = tl.List(tl.Unicode())
+ blocker_messages = tl.Unicode("")
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.confirmation_exceptions += [
+ "blockers",
+ "blocker_messages",
+ ]
+
+ @property
+ def is_blocked(self):
+ return any(self.blockers)
+
+ def update_blockers(self):
+ blockers = list(self._check_blockers())
+ if isinstance(self, HasModels):
+ for _, model in self.get_models():
+ if isinstance(model, HasBlockers):
+ blockers += model.blockers
+ self.blockers = blockers
+
+ def update_blocker_messages(self):
+ if self.is_blocked:
+ formatted = "\n".join(f"
{item}" for item in self.blockers)
+ self.blocker_messages = f"""
+
+
The step is blocked due to the following reason(s):
+
+
+ """
+ else:
+ self.blocker_messages = ""
+
+ def _check_blockers(self):
+ raise NotImplementedError
+
+
+CWSM = t.TypeVar("CWSM", bound=QeConfirmableWizardStepModel)
+
+
+class QeConfirmableWizardStep(QeWizardStep[CWSM]):
+ def __init__(
+ self,
+ model: CWSM,
+ confirm_kwargs=None,
+ **kwargs,
+ ):
+ super().__init__(model, **kwargs)
+ self._model.observe(
+ self._on_confirmation_change,
+ "confirmed",
+ )
+ self._model.observe(
+ self._on_blockers_change,
+ "blockers",
+ )
+
+ if confirm_kwargs is None:
+ confirm_kwargs = {}
+
+ self.confirm_button_style = confirm_kwargs.get("button_style", "success")
+ self.confirm_button_icon = confirm_kwargs.get("icon", "check-circle")
+ self.confirm_button_description = confirm_kwargs.get("description", "Confirm")
+ self.confirm_button_tooltip = confirm_kwargs.get("tooltip", "Confirm")
+
+ def _render(self):
+ self.content = ipw.VBox()
+
+ self.confirm_button = ipw.Button(
+ description=self.confirm_button_description,
+ tooltip=self.confirm_button_tooltip,
+ button_style=self.confirm_button_style,
+ icon=self.confirm_button_icon,
+ layout=ipw.Layout(width="auto"),
+ disabled=not self._model.is_blocked,
+ )
+ ipw.dlink(
+ (self, "state"),
+ (self.confirm_button, "disabled"),
+ lambda state: self._model.is_blocked or state != self.State.CONFIGURED,
+ )
+ self.confirm_button.on_click(self.confirm)
+
+ self.blocker_messages = ipw.HTML()
+ self.blocker_messages.add_class("blocker-messages")
+ ipw.dlink(
+ (self._model, "blocker_messages"),
+ (self.blocker_messages, "value"),
+ )
+
+ self.confirm_box = ipw.VBox(
+ children=[
+ self.confirm_button,
+ self.blocker_messages,
+ ]
+ )
+ self.children += (self.confirm_box,)
+
+ def _on_confirmation_change(self, _):
+ self._update_state()
+
+ def _on_blockers_change(self, _):
+ if self.rendered:
+ self._enable_confirm_button()
+ self._model.update_blocker_messages()
+ self._update_state()
+
+ def confirm(self, _=None):
+ self._model.confirm()
+
+ def _enable_confirm_button(self):
+ can_confirm = self._model.is_blocked or self.state != self.State.CONFIGURED
+ self.confirm_button.disabled = can_confirm
+
+
+class QeDependentWizardStep(QeWizardStep[WSM]):
+ missing_information_warning = "Missing information"
+
+ previous_step_state = tl.UseEnum(WizardAppWidgetStep.State)
+
+ def __init__(self, model: WSM, **kwargs):
+ super().__init__(model, **kwargs)
+ self.previous_children = list(self.children)
+ self.warning_message = ipw.HTML(
+ f"""
+
+ Warning: {self.missing_information_warning}
+
+ """
+ )
+
+ def render(self):
+ if "PYTEST_CURRENT_TEST" in os.environ:
+ super().render()
+ return
+ if self.previous_step_state is WizardAppWidgetStep.State.SUCCESS:
+ self._hide_missing_information_warning()
+ if not self.rendered:
+ super().render()
+ self.previous_children = list(self.children)
+ else:
+ self._show_missing_information_warning()
+
+ @tl.observe("previous_step_state")
+ def _on_previous_step_state_change(self, _):
+ self._update_state()
+
+ def _show_missing_information_warning(self):
+ self.children = [self.warning_message]
+ self.rendered = False
+
+ def _hide_missing_information_warning(self):
+ self.children = self.previous_children
+
+
+class QeConfirmableDependentWizardStep(
+ QeDependentWizardStep[CWSM],
+ QeConfirmableWizardStep[CWSM],
+):
+ pass
diff --git a/tests/conftest.py b/tests/conftest.py
index 3df3a57e3..a49feda48 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -418,14 +418,14 @@ def _smearing_settings_generator(**kwargs):
@pytest.fixture
def app(pw_code, dos_code, projwfc_code, projwfc_bands_code):
- app = WizardApp(qe_auto_setup=False)
+ app = WizardApp(auto_setup=False)
- # Since we use `qe_auto_setup=False`, which will skip the pseudo library
+ # Since we use `auto_setup=False`, which will skip the pseudo library
# installation, we need to mock set the installation status to `True` to
# avoid the blocker message pop up in the submission step.
+ app.structure_model.installing_sssp = False
+ app.structure_model.sssp_installed = True
app.submit_model.installing_qe = False
- app.submit_model.installing_sssp = False
- app.submit_model.sssp_installed = True
app.submit_model.qe_installed = True
# set up codes
diff --git a/tests/test_app.py b/tests/test_app.py
index 92ad482ac..3ecf4ddcd 100644
--- a/tests/test_app.py
+++ b/tests/test_app.py
@@ -2,7 +2,7 @@
def test_reload_and_reset(generate_qeapp_workchain):
- app = WizardApp(qe_auto_setup=False)
+ app = WizardApp(auto_setup=False)
workchain = generate_qeapp_workchain(
relax_type="positions",
spin_type="collinear",
@@ -30,25 +30,3 @@ def test_selecting_new_structure_unconfirms_model(generate_structure_data):
model.confirm()
model.input_structure = generate_structure_data()
assert not model.confirmed
-
-
-def test_unsaved_changes(app_to_submit):
- """Test if the unsaved changes are handled correctly"""
- from aiidalab_widgets_base import WizardAppWidgetStep
-
- app: WizardApp = app_to_submit
- # go to the configure step, and make some changes
- app._wizard_app_widget.selected_index = 1
- app.configure_model.relax_type = "positions"
- # go to the submit step
- app._wizard_app_widget.selected_index = 2
- # the state of the configure step should be updated.
- assert app.configure_step.state == WizardAppWidgetStep.State.CONFIGURED
- # check if a new blocker is added
- assert len(app.submit_model.external_submission_blockers) == 1
- # confirm the changes
- app._wizard_app_widget.selected_index = 1
- app.configure_model.confirm()
- app._wizard_app_widget.selected_index = 2
- # the blocker should be removed
- assert len(app.submit_model.external_submission_blockers) == 0
diff --git a/tests/test_codes.py b/tests/test_codes.py
index 09ee9f349..1af1cd9eb 100644
--- a/tests/test_codes.py
+++ b/tests/test_codes.py
@@ -18,7 +18,7 @@ def test_set_selected_codes(submit_app_generator):
app: WizardApp = submit_app_generator()
parameters = app.submit_model.get_model_state()
model = SubmissionStepModel()
- _ = SubmitQeAppWorkChainStep(model=model, qe_auto_setup=False)
+ _ = SubmitQeAppWorkChainStep(model=model, auto_setup=False)
for identifier, code_model in app.submit_model.get_model("global").get_models():
model.get_model("global").get_model(identifier).is_active = code_model.is_active
model.qe_installed = True
@@ -42,28 +42,28 @@ def test_update_codes_display(app: WizardApp):
assert global_resources.code_widgets["dos"].layout.display == "block"
-def test_check_submission_blockers(app: WizardApp):
+def test_check_blockers(app: WizardApp):
"""Test check_submission_blockers method."""
model = app.submit_model
- model.update_submission_blockers()
- assert len(model.internal_submission_blockers) == 0
+ model.update_blockers()
+ assert len(model.blockers) == 0
model.input_parameters = {"workchain": {"properties": ["pdos"]}}
- model.update_submission_blockers()
- assert len(model.internal_submission_blockers) == 0
+ model.update_blockers()
+ assert len(model.blockers) == 0
# set dos code to None, will introduce another blocker
dos_code = model.get_model("global").get_model("quantumespresso__dos")
dos_value = dos_code.selected
dos_code.selected = None
- model.update_submission_blockers()
- assert len(model.internal_submission_blockers) == 1
+ model.update_blockers()
+ assert len(model.blockers) == 1
# set dos code back will remove the blocker
dos_code.selected = dos_value
- model.update_submission_blockers()
- assert len(model.internal_submission_blockers) == 0
+ model.update_blockers()
+ assert len(model.blockers) == 0
def test_qeapp_computational_resources_widget(app: WizardApp):
diff --git a/tests/test_submit_qe_workchain.py b/tests/test_submit_qe_workchain.py
index 686981762..0ce85d3d0 100644
--- a/tests/test_submit_qe_workchain.py
+++ b/tests/test_submit_qe_workchain.py
@@ -153,7 +153,7 @@ def test_warning_messages(
pw_code.num_cpus = len(os.sched_getaffinity(0))
global_model.check_resources()
for suggestion in ["avoid_overloading", "go_remote"]:
- assert suggestions[suggestion] in submit_model.submission_warning_messages
+ assert suggestions[suggestion] in submit_model.warning_messages
# now we use a large structure, so we should have the Warning-1 (and 2 if not on localhost)
structure = generate_structure_data("H2O-larger")
@@ -165,7 +165,7 @@ def test_warning_messages(
estimated_CPUs = global_model._estimate_min_cpus(num_sites, volume)
assert estimated_CPUs == 2
for suggestion in ["more_resources", "change_configuration"]:
- assert suggestions[suggestion] in submit_model.submission_warning_messages
+ assert suggestions[suggestion] in submit_model.warning_messages
def builder_to_readable_dict(builder):