Skip to content

Commit

Permalink
Merge pull request #157 from aiidalab/release/1.0.0b14
Browse files Browse the repository at this point in the history
Release/1.0.0b14
  • Loading branch information
yakutovicha committed Nov 19, 2020
2 parents a082c22 + 0f5df85 commit 5b2a654
Show file tree
Hide file tree
Showing 8 changed files with 685 additions and 531 deletions.
15 changes: 0 additions & 15 deletions .travis.yml

This file was deleted.

10 changes: 5 additions & 5 deletions aiidalab_widgets_base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
from aiida import load_profile
load_profile()

from .codes import CodeDropdown, AiiDACodeSetup, valid_aiidacode_args
from .computers import SshComputerSetup, valid_sshcomputer_args
from .computers import AiidaComputerSetup, valid_aiidacomputer_args
from .codes import CodeDropdown, AiiDACodeSetup
from .computers import SshComputerSetup
from .computers import AiidaComputerSetup
from .computers import ComputerDropdown
from .databases import CodQueryWidget, OptimadeQueryWidget
from .databases import CodQueryWidget, CodeDatabaseWidget, ComputerDatabaseWidget, OptimadeQueryWidget
from .export import ExportButtonWidget
from .process import ProgressBarWidget, ProcessFollowerWidget, ProcessInputsWidget, ProcessOutputsWidget
from .process import ProcessCallStackWidget, RunningCalcJobOutputWidget, SubmitButtonWidget, ProcessReportWidget
Expand All @@ -18,4 +18,4 @@
from .structures_multi import MultiStructureUploadWidget
from .viewers import viewer

__version__ = "1.0.0b13"
__version__ = "1.0.0b14"
209 changes: 77 additions & 132 deletions aiidalab_widgets_base/codes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,11 @@

import ipywidgets as ipw
from IPython.display import clear_output
from traitlets import Bool, Dict, Instance, Unicode, Union, link, validate
from traitlets import Bool, Dict, Instance, Unicode, Union, dlink, link, validate

from aiida.orm import Code, QueryBuilder, User

from aiidalab_widgets_base.utils import predefine_settings, valid_arguments

VALID_AIIDA_CODE_SETUP_ARGUMETNS = {
'label', 'computer', 'plugin', 'description', 'exec_path', 'prepend_text', 'append_text'
}


def valid_aiidacode_args(arguments):
return valid_arguments(arguments, VALID_AIIDA_CODE_SETUP_ARGUMETNS)
from aiida.orm import Code, Computer, QueryBuilder, User
from aiida.plugins.entry_point import get_entry_point_names
from aiidalab_widgets_base.computers import ComputerDropdown


class CodeDropdown(ipw.VBox):
Expand Down Expand Up @@ -49,7 +41,7 @@ def __init__(self, input_plugin, description='Select code:', path_to_root='../',
description (str): Description to display before the dropdown.
"""
self.output = ipw.Output()
self.output = ipw.HTML()

self.input_plugin = input_plugin

Expand Down Expand Up @@ -98,30 +90,30 @@ def _get_codes(self):

@staticmethod
def _full_code_label(code):
return "{}@{}".format(code.label, code.computer.name)
return f"{code.label}@{code.computer.name}"

def refresh(self, _=None):
"""Refresh available codes.
The job of this function is to look in AiiDA database, find available codes and
put them in the dropdown attribute."""
self.output.value = ''

with self.output:
clear_output()
with self.hold_trait_notifications():
self.dropdown.options = self._get_codes()
if not self.dropdown.options:
print("No codes found for input plugin '{}'.".format(self.input_plugin))
self.dropdown.disabled = True
else:
self.dropdown.disabled = False
self.dropdown.value = None
with self.hold_trait_notifications():
self.dropdown.options = self._get_codes()
if not self.dropdown.options:
self.output.value = f"No codes found for input plugin '{self.input_plugin}'."
self.dropdown.disabled = True
else:
self.dropdown.disabled = False
self.dropdown.value = None

@validate('selected_code')
def _validate_selected_code(self, change):
"""If code is provided, set it as it is. If code's name is provided,
select the code and set it."""
code = change['value']
self.output.value = ''

# If code None, set value to None
if code is None:
Expand All @@ -131,166 +123,119 @@ def _validate_selected_code(self, change):
if isinstance(code, str):
if code in self.codes:
return self.codes[code]
raise KeyError("No code named '{}' found in the AiiDA database.".format(code))
self.output.value = f"""No code named '<span style="color:red">{code}</span>'
found in the AiiDA database."""

# Check code by value.
if isinstance(code, Code):
label = self._full_code_label(code)
if label in self.codes:
return code
raise ValueError(
"The code instance '{}' supplied was not found in the AiiDA database. Consider reloading.".format(code))
self.output.value = f"""The code instance '<span style="color:red">{code}</span>'
supplied was not found in the AiiDA database."""

# This place will never be reached, because the trait's type is checked.
return None


class AiiDACodeSetup(ipw.VBox):
"""Class that allows to setup AiiDA code"""
label = Unicode()
computer = Union([Unicode(), Instance(Computer)], allow_none=True)

input_plugin = Unicode()
description = Unicode()
remote_abs_path = Unicode()
prepend_text = Unicode()
append_text = Unicode()

def __init__(self, **kwargs):
from aiida.plugins.entry_point import get_entry_point_names
from aiidalab_widgets_base.computers import ComputerDropdown

style = {"description_width": "200px"}

# list of widgets to be displayed

self._inp_code_label = ipw.Text(description="AiiDA code label:", layout=ipw.Layout(width="500px"), style=style)

self._computer = ComputerDropdown(layout={'margin': '0px 0px 0px 125px'})

self._inp_code_description = ipw.Text(placeholder='No description (yet)',
description="Code description:",
layout=ipw.Layout(width="500px"),
style=style)

self._inp_code_plugin = ipw.Dropdown(options=sorted(get_entry_point_names('aiida.calculations')),
description="Code plugin:",
layout=ipw.Layout(width="500px"),
style=style)

self._exec_path = ipw.Text(placeholder='/path/to/executable',
description="Absolute path to executable:",
# Code label.
inp_label = ipw.Text(description="AiiDA code label:", layout=ipw.Layout(width="500px"), style=style)
link((inp_label, 'value'), (self, 'label'))

# Computer on which the code is installed. Two dlinks are needed to make sure we get a Computer instance.
inp_computer = ComputerDropdown(layout={'margin': '0px 0px 0px 125px'})
dlink((inp_computer, 'selected_computer'), (self, 'computer'))
dlink((self, 'computer'), (inp_computer, 'selected_computer'))

# Code plugin.
inp_code_plugin = ipw.Dropdown(options=sorted(get_entry_point_names('aiida.calculations')),
description="Code plugin:",
layout=ipw.Layout(width="500px"),
style=style)
link((inp_code_plugin, 'value'), (self, 'input_plugin'))

# Code description.
inp_description = ipw.Text(placeholder='No description (yet)',
description="Code description:",
layout=ipw.Layout(width="500px"),
style=style)

self._prepend_text = ipw.Textarea(placeholder='Text to prepend to each command execution',
description='Prepend text:',
layout=ipw.Layout(width="400px"))

self._append_text = ipw.Textarea(placeholder='Text to append to each command execution',
description='Append text:',
layout=ipw.Layout(width="400px"))

self._btn_setup_code = ipw.Button(description="Setup code")
self._btn_setup_code.on_click(self._setup_code)
link((inp_description, 'value'), (self, 'description'))

inp_abs_path = ipw.Text(placeholder='/path/to/executable',
description="Absolute path to executable:",
layout=ipw.Layout(width="500px"),
style=style)
link((inp_abs_path, 'value'), (self, 'remote_abs_path'))

inp_prepend_text = ipw.Textarea(placeholder='Text to prepend to each command execution',
description='Prepend text:',
layout=ipw.Layout(width="400px"))
link((inp_prepend_text, 'value'), (self, 'prepend_text'))

inp_append_text = ipw.Textarea(placeholder='Text to append to each command execution',
description='Append text:',
layout=ipw.Layout(width="400px"))
link((inp_append_text, 'value'), (self, 'append_text'))

btn_setup_code = ipw.Button(description="Setup code")
btn_setup_code.on_click(self._setup_code)
self._setup_code_out = ipw.Output()
children = [
ipw.HBox([
ipw.VBox([
self._inp_code_label, self._computer, self._inp_code_plugin, self._inp_code_description,
self._exec_path
]),
ipw.VBox([self._prepend_text, self._append_text])
ipw.VBox([inp_label, inp_computer, inp_code_plugin, inp_description, inp_abs_path]),
ipw.VBox([inp_prepend_text, inp_append_text])
]),
self._btn_setup_code,
btn_setup_code,
self._setup_code_out,
]
# Check if some settings were already provided
predefine_settings(self, **kwargs)
super(AiiDACodeSetup, self).__init__(children, **kwargs)

def _setup_code(self, change=None): # pylint: disable=unused-argument
def _setup_code(self, _=None):
"""Setup an AiiDA code."""
with self._setup_code_out:
clear_output()
if self.label is None:
print("You did not specify code label")
return
if not self.exec_path:
if not self.remote_abs_path:
print("You did not specify absolute path to the executable")
return
if self.exists():
print("Code {}@{} already exists".format(self.label, self.computer.name))
print(f"Code {self.label}@{self.computer.name} already exists")
return
code = Code(remote_computer_exec=(self.computer, self.exec_path))
code = Code(remote_computer_exec=(self.computer, self.remote_abs_path))
code.label = self.label
code.description = self.description
code.set_input_plugin_name(self.plugin)
code.set_input_plugin_name(self.input_plugin)
code.set_prepend_text(self.prepend_text)
code.set_append_text(self.append_text)
code.store()
code.reveal()
full_string = "{}@{}".format(self.label, self.computer.name)
full_string = f"{self.label}@{self.computer.name}"
print(check_output(['verdi', 'code', 'show', full_string]).decode('utf-8'))

def exists(self):
"""Returns True if the code exists, returns False otherwise."""
from aiida.common import NotExistent, MultipleObjectsError
try:
Code.get_from_string("{}@{}".format(self.label, self.computer.name))
Code.get_from_string(f"{self.label}@{self.computer.name}")
return True
except MultipleObjectsError:
return True
except NotExistent:
return False

@property
def label(self):
if not self._inp_code_label.value.strip():
return None
return self._inp_code_label.value

@label.setter
def label(self, label):
self._inp_code_label.value = label

@property
def description(self):
return self._inp_code_description.value

@description.setter
def description(self, description):
self._inp_code_description.value = description

@property
def plugin(self):
return self._inp_code_plugin.value

@plugin.setter
def plugin(self, plugin):
if plugin in self._inp_code_plugin.options:
self._inp_code_plugin.value = plugin

@property
def exec_path(self):
return self._exec_path.value

@exec_path.setter
def exec_path(self, exec_path):
self._exec_path.value = exec_path

@property
def prepend_text(self):
return self._prepend_text.value

@prepend_text.setter
def prepend_text(self, prepend_text):
self._prepend_text.value = prepend_text

@property
def append_text(self):
return self._append_text.value

@append_text.setter
def append_text(self, append_text):
self._append_text.value = append_text

@property
def computer(self):
return self._computer.selected_computer

@computer.setter
def computer(self, computer):
self._computer.selected_computer = computer

0 comments on commit 5b2a654

Please sign in to comment.