From fb4e249175ae0bda580b3d0473903b127216480c Mon Sep 17 00:00:00 2001 From: Jusong Yu Date: Fri, 19 May 2023 11:46:52 +0000 Subject: [PATCH 1/4] proof-of-concept --- .../computational_resources.py | 233 +++++++++++++++--- aiidalab_widgets_base/databases.py | 2 +- notebooks/computational_resources.ipynb | 129 +++++++++- 3 files changed, 318 insertions(+), 46 deletions(-) diff --git a/aiidalab_widgets_base/computational_resources.py b/aiidalab_widgets_base/computational_resources.py index d4837f575..438817daa 100644 --- a/aiidalab_widgets_base/computational_resources.py +++ b/aiidalab_widgets_base/computational_resources.py @@ -23,6 +23,149 @@ STYLE = {"description_width": "180px"} LAYOUT = {"width": "400px"} +class QuickSetupWidget(ipw.VBox): + """Quick setup widget.""" + default_calc_job_plugin = traitlets.Unicode(allow_none=True) + + computer_setup = traitlets.Dict() + code_setup = traitlets.Dict() + + def __init__(self, **kwargs): + quick_setup_button = ipw.Button(description="Quick Setup") + quick_setup_button.on_click(self.quick_setup) + self.comp_resources_database = ComputationalResourcesDatabaseWidget( + default_calc_job_plugin=self.default_calc_job_plugin + ) + self.comp_resources_database.observe(self._on_select_computer, names="computer_setup") + self.comp_resources_database.observe(self._on_select_code, names="code_setup") + + # The placeholder for the template variables + self.template_variables = ipw.VBox( + children=[], layout=ipw.Layout(display="flex", flex_flow="column") + ) + self.template_variables_dict = {} + + self.ssh_computer_setup = SshComputerSetup() + + # Set the initial value to computer/code setup template + self.computer_setup = self.comp_resources_database.computer_setup + self.code_setup = self.comp_resources_database.code_setup + + super().__init__( + children=[ + ipw.HTML( + """Please select the computer/code from a database to pre-fill the fields below.""" + ), + self.comp_resources_database, + self.ssh_computer_setup.username, + self.template_variables, + quick_setup_button, + self.ssh_computer_setup.password_box, + # self.aiida_code_setup.setup_code_out, # TODO: add this back using interfacet to update + ] + ) + + def _on_select_computer(self, change): + """Update the computer setup template.""" + from jinja2 import Environment, meta + from jinja2.nodes import Filter + + if change["new"] is None: + return + + # Set the initial value to computer/code setup template when new computer is selected + self.computer_setup = self.comp_resources_database.computer_setup + + for _, template_str in change["new"].get('setup', {}).items(): + env = Environment() + parsed_template = env.parse(template_str) + # vars is a set of all variables in the template + # while filters is a list of all filters in the template, not all variables have filter. + vars = meta.find_undeclared_variables(parsed_template) + filters = [node for node in parsed_template.find_all(Filter)] + + default_values = {ftr.node.name: ftr.args[0].value for ftr in filters if ftr.name == 'default'} + + for var in vars: + self.template_variables_dict[var] = ipw.Text( + description=f"{var}:", + value=default_values.get(var, ""), + layout=LAYOUT, style=STYLE, + ) + + self.template_variables.children = tuple(self.template_variables_dict.values()) + + def _on_select_code(self, change): + """Update the code setup template.""" + # TODO: add this + + def quick_setup(self, _=None): + """Fill the tempalte and setup the computer and code to interface + This action will only trigger the setup of the widget, not the actual setup of the computer and code. + The actual setup will be triggered from DetailedSetupWidget from ComputationalResourcesWidget. + """ + from jinja2 import Environment, ChainableUndefined, meta + + # From the remote original setup, fill the template + computer_setup = self.computer_setup + + for key, value in computer_setup.get('setup',{}).items(): + env = Environment(undefined=ChainableUndefined) + template_vars = meta.find_undeclared_variables(env.parse(value)) + vars_dict = {} + + if template_vars: + # Read the template variables from the widget + for var in template_vars: + vars_dict[var] = self.template_variables_dict.get(var).value + + # re-render the template + value = env.from_string(value).render(**vars_dict) + computer_setup['setup'][key] = value + else: + computer_setup['setup'][key] = value + + self.computer_setup = {**self.computer_setup} + print(self.computer_setup) + +class DetailedSetupWidget(ipw.VBox): + + computer_setup = traitlets.Dict() + code_setup = traitlets.Dict() + + def __init__(self, **kargs): + + self.ssh_computer_setup = SshComputerSetup() + # TODO: link + + self.aiida_computer_setup = AiidaComputerSetup() + + self.aiida_code_setup = AiidaCodeSetup() + + self.detailed_setup = ipw.Accordion( + children=[ + self.ssh_computer_setup, + self.aiida_computer_setup, + self.aiida_code_setup, + ], + ) + + self.detailed_setup.set_title(0, "Set up password-less SSH connection") + self.detailed_setup.set_title(1, "Set up a computer in AiiDA") + self.detailed_setup.set_title(2, "Set up a code in AiiDA") + + super().__init__( + children=[ + self.detailed_setup, + ], + ) + + @traitlets.observe('computer_setup') + def _computer_setup_changed(self, change): + print("WHANTABOUTME") + self.aiida_computer_setup.computer_setup = change['new'] + + class ComputationalResourcesWidget(ipw.VBox): """Code selection widget. @@ -96,15 +239,15 @@ def __init__(self, description="Select code:", path_to_root="../", **kwargs): (self.ssh_computer_setup, "ssh_config"), ) - self.aiida_computer_setup = AiidaComputerSetup() - ipw.dlink( - (self.aiida_computer_setup, "message"), - (self.setup_message, "message"), - ) - ipw.dlink( - (self.comp_resources_database, "computer_setup"), - (self.aiida_computer_setup, "computer_setup"), - ) + # self.aiida_computer_setup = AiidaComputerSetup() + # ipw.dlink( + # (self.aiida_computer_setup, "message"), + # (self.setup_message, "message"), + # ) + # ipw.dlink( + # (self.comp_resources_database, "computer_setup"), + # (self.aiida_computer_setup, "computer_setup"), + # ) # Set up AiiDA code. self.aiida_code_setup = AiidaCodeSetup() @@ -120,34 +263,56 @@ def __init__(self, description="Select code:", path_to_root="../", **kwargs): # After a successfull computer setup the codes widget should be refreshed. # E.g. the list of available computers needs to be updated. - self.aiida_computer_setup.on_setup_computer_success( - self.aiida_code_setup.refresh - ) + # self.aiida_computer_setup.on_setup_computer_success( + # self.aiida_code_setup.refresh + # ) # Quick setup. - quick_setup_button = ipw.Button(description="Quick Setup") - quick_setup_button.on_click(self.quick_setup) - self.quick_setup = ipw.VBox( - children=[ - self.ssh_computer_setup.username, - quick_setup_button, - self.aiida_code_setup.setup_code_out, - ] - ) + # quick_setup_button = ipw.Button(description="Quick Setup") + # quick_setup_button.on_click(self.quick_setup) + # self.quick_setup = ipw.VBox( + # children=[ + # ipw.HTML( + # """Please select the computer/code from a database to pre-fill the fields below.""" + # ), + # self.comp_resources_database, + # self.ssh_computer_setup.username, + # quick_setup_button, + # self.ssh_computer_setup.password_box, + # self.aiida_code_setup.setup_code_out, + # ] + # ) + self.quick_setup = QuickSetupWidget() + self.quick_setup.observe(self._quick_setup, "computer_setup") # Detailed setup. - self.detailed_setup = ipw.Accordion( - children=[ - self.ssh_computer_setup, - self.aiida_computer_setup, - self.aiida_code_setup, - ] - ) - self.detailed_setup.set_title(0, "Set up password-less SSH connection") - self.detailed_setup.set_title(1, "Set up a computer in AiiDA") - self.detailed_setup.set_title(2, "Set up a code in AiiDA") + # self.detailed_setup = ipw.Accordion( + # children=[ + # self.ssh_computer_setup, + # self.aiida_computer_setup, + # self.aiida_code_setup, + # ] + # ) + # self.detailed_setup.set_title(0, "Set up password-less SSH connection") + # self.detailed_setup.set_title(1, "Set up a computer in AiiDA") + # self.detailed_setup.set_title(2, "Set up a code in AiiDA") + self.detailed_setup = DetailedSetupWidget() + + # ipw.dlink( + # (self.quick_setup, "computer_setup"), + # (self.detailed_setup, "computer_setup"), + # ) + # ipw.dlink( + # (self.quick_setup, "code_setup"), + # (self.detailed_setup, "code_setup"), + # ) self.refresh() + + def _quick_setup(self, change): + if change["new"] is not None: + self.detailed_setup.aiida_computer_setup.computer_setup = change["new"] + # self.detailed_setup.code_setup = self.comp_resources_database.code_setup def quick_setup(self, _=None): """Go through all the setup steps automatically.""" @@ -227,11 +392,6 @@ def _setup_new_code(self, _=None): setup_tab.set_title(0, "Quick Setup") setup_tab.set_title(1, "Detailed Setup") children = [ - ipw.HTML( - """Please select the computer/code from a database to pre-fill the fields below.""" - ), - self.comp_resources_database, - self.ssh_computer_setup.password_box, self.setup_message, setup_tab, ] @@ -953,6 +1113,7 @@ def _reset(self): @traitlets.observe("computer_setup") def _observe_computer_setup(self, _=None): # Setup. + print("THISSHOULDNOTBEHERE") if not self.computer_setup: self._reset() return diff --git a/aiidalab_widgets_base/databases.py b/aiidalab_widgets_base/databases.py index 08bf34c31..ecfce2b67 100644 --- a/aiidalab_widgets_base/databases.py +++ b/aiidalab_widgets_base/databases.py @@ -282,7 +282,7 @@ def clean_up_database(self, database, plugin): def update(self, _=None): database = requests.get( - "https://aiidateam.github.io/aiida-code-registry/database_v2_1.json" + "https://unkcpz.github.io/aiida-code-registry/database_v2_1.json" ).json() self.database = ( self.clean_up_database(database, self.default_calc_job_plugin) diff --git a/notebooks/computational_resources.ipynb b/notebooks/computational_resources.ipynb index 0a8eb4d5e..c6d2d224d 100644 --- a/notebooks/computational_resources.ipynb +++ b/notebooks/computational_resources.ipynb @@ -2,10 +2,25 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "4013ce60", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/javascript": [ + "IPython.OutputArea.prototype._should_scroll = function(lines) {\n", + " return false;\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "%%javascript\n", "IPython.OutputArea.prototype._should_scroll = function(lines) {\n", @@ -15,34 +30,130 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "53f49d32", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1a68907476e64d14933a2a7c9d7bbab4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import aiidalab_widgets_base as awb" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "id": "56116f88", "metadata": {}, "outputs": [], "source": [ "resources1 = awb.ComputationalResourcesWidget()\n", - "resources2 = awb.ComputationalResourcesWidget()" + "# resources2 = awb.ComputationalResourcesWidget()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "b75b6687", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "28f16cd4c27e4932b0327e4634623b1e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "ComputationalResourcesWidget(children=(HBox(children=(Dropdown(description='Select code:', disabled=True, opti…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "display(resources1)\n", - "display(resources2)" + "# display(resources2)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "15b22b09", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'setup': {'label': 'daint-hybrid',\n", + " 'hostname': 'daint.cscs.ch',\n", + " 'description': 'Piz Daint supercomputer at CSCS Lugano, Switzerland, using the hybrid partition. HyperThreading is off',\n", + " 'transport': 'core.ssh',\n", + " 'scheduler': 'core.slurm',\n", + " 'shebang': '#!/bin/bash -l',\n", + " 'mpiprocs_per_machine': 12,\n", + " 'num_cores_per_mpiproc': 1,\n", + " 'work_dir': '/scratch/snx3000/{username}/aiida/',\n", + " 'mpirun_command': 'srun -n {tot_num_mpiprocs}',\n", + " 'prepend_text': '#SBATCH --partition=normal\\n#SBATCH --account=jyu\\n#SBATCH --constraint=gpu\\n#SBATCH --hint=nomultithread\\nexport OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK\\nexport CRAY_CUDA_MPS=1\\nulimit -s unlimited'},\n", + " 'configure': {'safe_interval': 60,\n", + " 'proxy_command': 'ssh -q -Y {username}@ela.cscs.ch netcat daint.cscs.ch 22'}}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "resources1.detailed_setup.aiida_computer_setup.computer_setup" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "b286d587", + "metadata": {}, + "outputs": [], + "source": [ + "qs = awb.computational_resources.QuickSetupWidget()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "47b3bc92", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1b3490e58521429c89ce6947b5afdb1a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "QuickSetupWidget(children=(HTML(value='Please select the computer/code from a database to pre-fill the fields …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(qs)" ] } ], From d4de7ce54863db03dc173ec2e73b29af15e315e7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 May 2023 11:48:05 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../computational_resources.py | 93 +++++++++------- notebooks/computational_resources.ipynb | 105 ++---------------- 2 files changed, 62 insertions(+), 136 deletions(-) diff --git a/aiidalab_widgets_base/computational_resources.py b/aiidalab_widgets_base/computational_resources.py index 438817daa..65e5580d7 100644 --- a/aiidalab_widgets_base/computational_resources.py +++ b/aiidalab_widgets_base/computational_resources.py @@ -23,34 +23,38 @@ STYLE = {"description_width": "180px"} LAYOUT = {"width": "400px"} + class QuickSetupWidget(ipw.VBox): """Quick setup widget.""" + default_calc_job_plugin = traitlets.Unicode(allow_none=True) - + computer_setup = traitlets.Dict() code_setup = traitlets.Dict() - + def __init__(self, **kwargs): quick_setup_button = ipw.Button(description="Quick Setup") quick_setup_button.on_click(self.quick_setup) self.comp_resources_database = ComputationalResourcesDatabaseWidget( default_calc_job_plugin=self.default_calc_job_plugin ) - self.comp_resources_database.observe(self._on_select_computer, names="computer_setup") + self.comp_resources_database.observe( + self._on_select_computer, names="computer_setup" + ) self.comp_resources_database.observe(self._on_select_code, names="code_setup") - + # The placeholder for the template variables self.template_variables = ipw.VBox( children=[], layout=ipw.Layout(display="flex", flex_flow="column") ) self.template_variables_dict = {} - + self.ssh_computer_setup = SshComputerSetup() - + # Set the initial value to computer/code setup template self.computer_setup = self.comp_resources_database.computer_setup self.code_setup = self.comp_resources_database.code_setup - + super().__init__( children=[ ipw.HTML( @@ -64,82 +68,86 @@ def __init__(self, **kwargs): # self.aiida_code_setup.setup_code_out, # TODO: add this back using interfacet to update ] ) - + def _on_select_computer(self, change): """Update the computer setup template.""" from jinja2 import Environment, meta from jinja2.nodes import Filter - + if change["new"] is None: return - + # Set the initial value to computer/code setup template when new computer is selected self.computer_setup = self.comp_resources_database.computer_setup - - for _, template_str in change["new"].get('setup', {}).items(): + + for _, template_str in change["new"].get("setup", {}).items(): env = Environment() parsed_template = env.parse(template_str) # vars is a set of all variables in the template # while filters is a list of all filters in the template, not all variables have filter. vars = meta.find_undeclared_variables(parsed_template) filters = [node for node in parsed_template.find_all(Filter)] - - default_values = {ftr.node.name: ftr.args[0].value for ftr in filters if ftr.name == 'default'} - + + default_values = { + ftr.node.name: ftr.args[0].value + for ftr in filters + if ftr.name == "default" + } + for var in vars: self.template_variables_dict[var] = ipw.Text( description=f"{var}:", value=default_values.get(var, ""), - layout=LAYOUT, style=STYLE, + layout=LAYOUT, + style=STYLE, ) - + self.template_variables.children = tuple(self.template_variables_dict.values()) - + def _on_select_code(self, change): """Update the code setup template.""" # TODO: add this - + def quick_setup(self, _=None): """Fill the tempalte and setup the computer and code to interface This action will only trigger the setup of the widget, not the actual setup of the computer and code. The actual setup will be triggered from DetailedSetupWidget from ComputationalResourcesWidget. """ - from jinja2 import Environment, ChainableUndefined, meta - - # From the remote original setup, fill the template + from jinja2 import ChainableUndefined, Environment, meta + + # From the remote original setup, fill the template computer_setup = self.computer_setup - - for key, value in computer_setup.get('setup',{}).items(): + + for key, value in computer_setup.get("setup", {}).items(): env = Environment(undefined=ChainableUndefined) template_vars = meta.find_undeclared_variables(env.parse(value)) vars_dict = {} - + if template_vars: # Read the template variables from the widget for var in template_vars: vars_dict[var] = self.template_variables_dict.get(var).value - + # re-render the template value = env.from_string(value).render(**vars_dict) - computer_setup['setup'][key] = value + computer_setup["setup"][key] = value else: - computer_setup['setup'][key] = value - + computer_setup["setup"][key] = value + self.computer_setup = {**self.computer_setup} print(self.computer_setup) - + + class DetailedSetupWidget(ipw.VBox): - computer_setup = traitlets.Dict() code_setup = traitlets.Dict() - + def __init__(self, **kargs): - self.ssh_computer_setup = SshComputerSetup() # TODO: link - + self.aiida_computer_setup = AiidaComputerSetup() - + self.aiida_code_setup = AiidaCodeSetup() self.detailed_setup = ipw.Accordion( @@ -149,22 +157,21 @@ def __init__(self, **kargs): self.aiida_code_setup, ], ) - + self.detailed_setup.set_title(0, "Set up password-less SSH connection") self.detailed_setup.set_title(1, "Set up a computer in AiiDA") self.detailed_setup.set_title(2, "Set up a code in AiiDA") - + super().__init__( children=[ self.detailed_setup, ], ) - - @traitlets.observe('computer_setup') + + @traitlets.observe("computer_setup") def _computer_setup_changed(self, change): print("WHANTABOUTME") - self.aiida_computer_setup.computer_setup = change['new'] - + self.aiida_computer_setup.computer_setup = change["new"] class ComputationalResourcesWidget(ipw.VBox): @@ -297,7 +304,7 @@ def __init__(self, description="Select code:", path_to_root="../", **kwargs): # self.detailed_setup.set_title(1, "Set up a computer in AiiDA") # self.detailed_setup.set_title(2, "Set up a code in AiiDA") self.detailed_setup = DetailedSetupWidget() - + # ipw.dlink( # (self.quick_setup, "computer_setup"), # (self.detailed_setup, "computer_setup"), @@ -308,7 +315,7 @@ def __init__(self, description="Select code:", path_to_root="../", **kwargs): # ) self.refresh() - + def _quick_setup(self, change): if change["new"] is not None: self.detailed_setup.aiida_computer_setup.computer_setup = change["new"] diff --git a/notebooks/computational_resources.ipynb b/notebooks/computational_resources.ipynb index c6d2d224d..0b46bb3b6 100644 --- a/notebooks/computational_resources.ipynb +++ b/notebooks/computational_resources.ipynb @@ -2,25 +2,10 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "4013ce60", "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "IPython.OutputArea.prototype._should_scroll = function(lines) {\n", - " return false;\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "%%javascript\n", "IPython.OutputArea.prototype._should_scroll = function(lines) {\n", @@ -30,30 +15,17 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "53f49d32", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "1a68907476e64d14933a2a7c9d7bbab4", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "import aiidalab_widgets_base as awb" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "56116f88", "metadata": {}, "outputs": [], @@ -64,25 +36,10 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "b75b6687", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "28f16cd4c27e4932b0327e4634623b1e", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "ComputationalResourcesWidget(children=(HBox(children=(Dropdown(description='Select code:', disabled=True, opti…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "display(resources1)\n", "# display(resources2)" @@ -90,40 +47,17 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "15b22b09", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'setup': {'label': 'daint-hybrid',\n", - " 'hostname': 'daint.cscs.ch',\n", - " 'description': 'Piz Daint supercomputer at CSCS Lugano, Switzerland, using the hybrid partition. HyperThreading is off',\n", - " 'transport': 'core.ssh',\n", - " 'scheduler': 'core.slurm',\n", - " 'shebang': '#!/bin/bash -l',\n", - " 'mpiprocs_per_machine': 12,\n", - " 'num_cores_per_mpiproc': 1,\n", - " 'work_dir': '/scratch/snx3000/{username}/aiida/',\n", - " 'mpirun_command': 'srun -n {tot_num_mpiprocs}',\n", - " 'prepend_text': '#SBATCH --partition=normal\\n#SBATCH --account=jyu\\n#SBATCH --constraint=gpu\\n#SBATCH --hint=nomultithread\\nexport OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK\\nexport CRAY_CUDA_MPS=1\\nulimit -s unlimited'},\n", - " 'configure': {'safe_interval': 60,\n", - " 'proxy_command': 'ssh -q -Y {username}@ela.cscs.ch netcat daint.cscs.ch 22'}}" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "resources1.detailed_setup.aiida_computer_setup.computer_setup" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "b286d587", "metadata": {}, "outputs": [], @@ -133,25 +67,10 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "47b3bc92", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "1b3490e58521429c89ce6947b5afdb1a", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "QuickSetupWidget(children=(HTML(value='Please select the computer/code from a database to pre-fill the fields …" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "display(qs)" ] From e399897535515555b6432084b1ed6619a352f9c0 Mon Sep 17 00:00:00 2001 From: Jusong Yu Date: Fri, 19 May 2023 12:15:36 +0000 Subject: [PATCH 3/4] fix the computer_setup update with dict copy --- aiidalab_widgets_base/computational_resources.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/aiidalab_widgets_base/computational_resources.py b/aiidalab_widgets_base/computational_resources.py index 65e5580d7..3f3ce1630 100644 --- a/aiidalab_widgets_base/computational_resources.py +++ b/aiidalab_widgets_base/computational_resources.py @@ -29,7 +29,7 @@ class QuickSetupWidget(ipw.VBox): default_calc_job_plugin = traitlets.Unicode(allow_none=True) - computer_setup = traitlets.Dict() + computer_setup = traitlets.Dict().tag(sync=True) code_setup = traitlets.Dict() def __init__(self, **kwargs): @@ -114,9 +114,10 @@ def quick_setup(self, _=None): The actual setup will be triggered from DetailedSetupWidget from ComputationalResourcesWidget. """ from jinja2 import ChainableUndefined, Environment, meta + import copy # From the remote original setup, fill the template - computer_setup = self.computer_setup + computer_setup = copy.deepcopy(self.computer_setup) # The dict is nested, so we need deepcopy for key, value in computer_setup.get("setup", {}).items(): env = Environment(undefined=ChainableUndefined) @@ -134,12 +135,12 @@ def quick_setup(self, _=None): else: computer_setup["setup"][key] = value - self.computer_setup = {**self.computer_setup} + self.computer_setup = computer_setup print(self.computer_setup) class DetailedSetupWidget(ipw.VBox): - computer_setup = traitlets.Dict() + computer_setup = traitlets.Dict().tag(sync=True) code_setup = traitlets.Dict() def __init__(self, **kargs): @@ -318,7 +319,9 @@ def __init__(self, description="Select code:", path_to_root="../", **kwargs): def _quick_setup(self, change): if change["new"] is not None: + print("HETNNNNN") self.detailed_setup.aiida_computer_setup.computer_setup = change["new"] + self.detailed_setup.aiida_computer_setup._observe_computer_setup() # self.detailed_setup.code_setup = self.comp_resources_database.code_setup def quick_setup(self, _=None): @@ -814,7 +817,7 @@ def _observe_ssh_config(self, _=None): class AiidaComputerSetup(ipw.VBox): """Inform AiiDA about a computer.""" - computer_setup = traitlets.Dict(allow_none=True) + computer_setup = traitlets.Dict(allow_none=True).tag(sync=True) message = traitlets.Unicode() def __init__(self, **kwargs): From defecb8944d25f34ab67bac1fc160feaaf1902bb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 May 2023 12:25:25 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- aiidalab_widgets_base/computational_resources.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/aiidalab_widgets_base/computational_resources.py b/aiidalab_widgets_base/computational_resources.py index 3f3ce1630..ef24102fd 100644 --- a/aiidalab_widgets_base/computational_resources.py +++ b/aiidalab_widgets_base/computational_resources.py @@ -113,11 +113,14 @@ def quick_setup(self, _=None): This action will only trigger the setup of the widget, not the actual setup of the computer and code. The actual setup will be triggered from DetailedSetupWidget from ComputationalResourcesWidget. """ - from jinja2 import ChainableUndefined, Environment, meta import copy + from jinja2 import ChainableUndefined, Environment, meta + # From the remote original setup, fill the template - computer_setup = copy.deepcopy(self.computer_setup) # The dict is nested, so we need deepcopy + computer_setup = copy.deepcopy( + self.computer_setup + ) # The dict is nested, so we need deepcopy for key, value in computer_setup.get("setup", {}).items(): env = Environment(undefined=ChainableUndefined)