diff --git a/aiida/engine/processes/calcjobs/calcjob.py b/aiida/engine/processes/calcjobs/calcjob.py index 3b07181678..2dad3a1ea6 100644 --- a/aiida/engine/processes/calcjobs/calcjob.py +++ b/aiida/engine/processes/calcjobs/calcjob.py @@ -396,6 +396,29 @@ def prepare_for_submission(self, folder: Folder) -> CalcInfo: """ raise NotImplementedError() + def _setup_metadata(self, metadata: dict) -> None: + """Store the metadata on the ProcessNode.""" + computer = metadata.pop('computer', None) + if computer is not None: + self.node.computer = computer + + options = metadata.pop('options', {}) + for option_name, option_value in options.items(): + self.node.set_option(option_name, option_value) + + super()._setup_metadata(metadata) + + def _setup_inputs(self) -> None: + """Create the links between the input nodes and the ProcessNode that represents this process.""" + super()._setup_inputs() + + # If a computer has not yet been set, which should have been done in ``_setup_metadata`` if it was specified + # in the ``metadata`` inputs, set the computer associated with the ``code`` input. Note that not all ``code``s + # will have an associated computer, but in that case the ``computer`` property should return ``None`` and + # nothing would change anyway. + if not self.node.computer: + self.node.computer = self.inputs.code.computer # type: ignore[union-attr] + def _perform_dry_run(self): """Perform a dry run. diff --git a/aiida/engine/processes/process.py b/aiida/engine/processes/process.py index 827f115a25..1cc9e87fd6 100644 --- a/aiida/engine/processes/process.py +++ b/aiida/engine/processes/process.py @@ -11,6 +11,7 @@ import asyncio import collections from collections.abc import Mapping +import copy import enum import inspect import logging @@ -684,27 +685,22 @@ def _setup_db_record(self) -> None: elif isinstance(self.node, orm.WorkflowNode): self.node.base.links.add_incoming(parent_calc, LinkType.CALL_WORK, self.metadata.call_link_label) - self._setup_metadata() + self._setup_metadata(copy.copy(dict(self.inputs.metadata))) self._setup_inputs() - def _setup_metadata(self) -> None: + def _setup_metadata(self, metadata: dict) -> None: """Store the metadata on the ProcessNode.""" version_info = self.runner.plugin_version_provider.get_version_info(self.__class__) self.node.base.attributes.set_many(version_info) - for name, metadata in self.metadata.items(): + for name, value in metadata.items(): if name in ['store_provenance', 'dry_run', 'call_link_label']: continue if name == 'label': - self.node.label = metadata + self.node.label = value elif name == 'description': - self.node.description = metadata - elif name == 'computer': - self.node.computer = metadata - elif name == 'options': - for option_name, option_value in metadata.items(): - self.node.set_option(option_name, option_value) + self.node.description = value else: raise RuntimeError(f'unsupported metadata key: {name}') @@ -716,10 +712,6 @@ def _setup_inputs(self) -> None: if node is None: continue - # Special exception: set computer if node is a remote Code and our node does not yet have a computer set - if isinstance(node, orm.InstalledCode) and not self.node.computer: - self.node.computer = node.computer - # Need this special case for tests that use ProcessNodes as classes if isinstance(self.node, orm.CalculationNode): self.node.base.links.add_incoming(node, LinkType.INPUT_CALC, name) diff --git a/tests/engine/processes/calcjobs/test_calc_job.py b/tests/engine/processes/calcjobs/test_calc_job.py index 85e96e83ee..d0e1c52763 100644 --- a/tests/engine/processes/calcjobs/test_calc_job.py +++ b/tests/engine/processes/calcjobs/test_calc_job.py @@ -874,11 +874,12 @@ class TestImport: """Test the functionality to import existing calculations completed outside of AiiDA.""" @pytest.fixture(autouse=True) - def init_profile(self, aiida_profile_clean, aiida_localhost): # pylint: disable=unused-argument + def init_profile(self, aiida_profile_clean, aiida_localhost, aiida_local_code_factory): # pylint: disable=unused-argument """Initialize the profile.""" # pylint: disable=attribute-defined-outside-init self.computer = aiida_localhost self.inputs = { + 'code': aiida_local_code_factory('core.arithmetic.add', '/bin/bash', computer=aiida_localhost), 'x': orm.Int(1), 'y': orm.Int(2), 'metadata': {