Skip to content

Commit

Permalink
Fix resource setup widget bugs (#661)
Browse files Browse the repository at this point in the history
- Add additional guards for missing code setup input
- Disable quick setup button if missing any requisites
- Apply uniqueness to missing template variables warning
- Make `ResourceSetupBaseWidget` "public"
- Fix code full label uniqueness check

Note that the fix in the query that looks for existing codes is a hack due to a potential bug in aiida-core. See aiidateam/aiida-core#6687.
  • Loading branch information
edan-bainglass authored Jan 9, 2025
1 parent 1b245c0 commit 7353264
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 11 deletions.
28 changes: 24 additions & 4 deletions aiidalab_widgets_base/computational_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def __init__(
children.append(self._setup_new_code_output)

# Computer/code setup
self.resource_setup = _ResourceSetupBaseWidget(
self.resource_setup = ResourceSetupBaseWidget(
default_calc_job_plugin=self.default_calc_job_plugin,
enable_quick_setup=enable_quick_setup,
enable_detailed_setup=enable_detailed_setup,
Expand Down Expand Up @@ -1193,6 +1193,13 @@ def on_setup_code(self, _=None):
with self.setup_code_out:
clear_output()

if not self.label.value:
self.message = wrap_message(
"Please provide a code label.",
MessageLevel.WARNING,
)
return False

if not self.computer.value:
self.message = wrap_message(
"Please select an existing computer.",
Expand Down Expand Up @@ -1229,7 +1236,7 @@ def on_setup_code(self, _=None):
qb = orm.QueryBuilder()
qb.append(orm.Computer, filters={"uuid": computer.uuid}, tag="computer")
qb.append(
orm.AbstractCode,
orm.Code,
with_computer="computer",
filters={"label": kwargs["label"]},
)
Expand Down Expand Up @@ -1612,7 +1619,7 @@ def _on_template_variable_filled(self, _):
self.fill()


class _ResourceSetupBaseWidget(ipw.VBox):
class ResourceSetupBaseWidget(ipw.VBox):
"""The widget that allows to setup a computer and code.
This is the building block of the `ComputationalResourcesDatabaseWidget` which
will be directly used by the user.
Expand Down Expand Up @@ -1659,6 +1666,11 @@ def __init__(
default_calc_job_plugin=default_calc_job_plugin,
show_reset_button=False,
)
ipw.dlink(
(self.comp_resources_database, "configured"),
(self.quick_setup_button, "disabled"),
lambda configured: not configured,
)

# All templates
self.template_computer_setup = TemplateVariablesWidget()
Expand Down Expand Up @@ -1877,14 +1889,22 @@ def _on_quick_setup(self, _=None):
)
return

# Raise error if the code is not selected.
if not self.comp_resources_database.code_selector.value:
self.message = wrap_message(
"Please select a code from the database.",
MessageLevel.ERROR,
)
return

# Check if all the template variables are filled.
# If not raise a warning and return (skip the setup).
if (
unfilled_variables := self.template_computer_setup.unfilled_variables
+ self.template_computer_configure.unfilled_variables
+ self.template_code.unfilled_variables
):
var_warn_message = ", ".join([f"<b>{v}</b>" for v in unfilled_variables])
var_warn_message = ", ".join({f"<b>{v}</b>" for v in unfilled_variables})
self.message = wrap_message(
f"Please fill the template variables: {var_warn_message}",
MessageLevel.WARNING,
Expand Down
10 changes: 10 additions & 0 deletions aiidalab_widgets_base/databases.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ class ComputationalResourcesDatabaseWidget(ipw.VBox):
computer_configure = tl.Dict()
code_setup = tl.Dict()

configured = tl.Bool(False)

STYLE = {"description_width": "180px"}
LAYOUT = {"width": "400px"}

Expand Down Expand Up @@ -413,6 +415,8 @@ def _computer_changed(self, change=None):
self.computer_setup = computer_setup
self.computer_configure = computer_configure

self._set_configured()

def _code_changed(self, change=None):
"""Update code settings."""
if change["new"] is None:
Expand All @@ -430,3 +434,9 @@ def _code_changed(self, change=None):
.get("codes", {})
.get(selected_code, {})
)

self._set_configured()

def _set_configured(self):
"""Update state of the widget."""
self.configured = all((self.computer_setup, self.code_setup))
2 changes: 1 addition & 1 deletion aiidalab_widgets_base/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def wrap_message(message, level=MessageLevel.INFO):
# The message is wrapped into a div with the class "alert" and the icon of the given level
return f"""
<div class="alert alert-{level.value}" role="alert" style="margin-bottom: 0px; padding: 6px 12px;">
<i class="fa fa-{mapping[level]}"></i>{message}
<i class="fa fa-{mapping[level]}"></i> {message}
</div>
"""

Expand Down
12 changes: 6 additions & 6 deletions tests/test_computational_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from aiidalab_widgets_base import computational_resources
from aiidalab_widgets_base.computational_resources import (
ComputationalResourcesWidget,
_ResourceSetupBaseWidget,
ResourceSetupBaseWidget,
)

HTML_TAG_CLEANER = re.compile(r"<[^>]*>")
Expand Down Expand Up @@ -496,11 +496,11 @@ def test_template_variables_widget_help_text_disappear_if_no_template_str():
def test_resource_setup_widget_default():
"""Test the _ResourceSetupBaseWidget."""
with pytest.raises(ValueError):
w = _ResourceSetupBaseWidget(
w = ResourceSetupBaseWidget(
enable_detailed_setup=False, enable_quick_setup=False
)

w = _ResourceSetupBaseWidget()
w = ResourceSetupBaseWidget()

# Test message is update correctly. By click setup button without filling in any information.
w._on_quick_setup()
Expand Down Expand Up @@ -587,7 +587,7 @@ def test_resource_setup_widget_for_password_configure(monkeypatch, tmp_path):
# monkeypatch home so the ssh key is generated in the temporary directory
monkeypatch.setenv("HOME", str(tmp_path))

w = _ResourceSetupBaseWidget()
w = ResourceSetupBaseWidget()

# Test select a new resource setup will update the output interface (e.g. ssh_config, computer_setup, code_setup)
# and the computer/code setup widget will be updated accordingly.
Expand Down Expand Up @@ -654,7 +654,7 @@ def test_resource_setup_widget_for_password_configure(monkeypatch, tmp_path):
@pytest.mark.usefixtures("aiida_profile_clean")
def test_resource_setup_widget_computer_change_code_reset():
"""Test the _ResourceSetupBaseWidget that when computer template changed, the code selector widget is reset."""
w = _ResourceSetupBaseWidget()
w = ResourceSetupBaseWidget()

# Test select a new resource setup will update the output interface (e.g. ssh_config, computer_setup, code_setup)
# and the computer/code setup widget will be updated accordingly.
Expand All @@ -673,7 +673,7 @@ def test_resource_setup_widget_computer_change_code_reset():

def test_resource_setup_widget_detailed_setup():
"""Detail branch test of the resource setup widget"""
w = _ResourceSetupBaseWidget()
w = ResourceSetupBaseWidget()

w.comp_resources_database.domain_selector.value = "daint.cscs.ch"
w.comp_resources_database.computer_selector.value = "mc"
Expand Down

0 comments on commit 7353264

Please sign in to comment.