diff --git a/aiida/engine/processes/process.py b/aiida/engine/processes/process.py index 069b84ae26..bbb2dcdf40 100644 --- a/aiida/engine/processes/process.py +++ b/aiida/engine/processes/process.py @@ -903,6 +903,8 @@ def exposed_outputs( for port_namespace in self._get_namespace_list(namespace=namespace, agglomerate=agglomerate): # only the top-level key is stored in _exposed_outputs for top_name in top_namespace_map: + if namespace is not None and namespace not in self.spec()._exposed_outputs: # pylint: disable=protected-access + raise KeyError(f'the namespace `{namespace}` is not an exposed namespace.') if top_name in self.spec()._exposed_outputs[port_namespace][process_class]: # pylint: disable=protected-access output_key_map[top_name] = port_namespace diff --git a/tests/engine/test_process.py b/tests/engine/test_process.py index 738607f75f..691e3a3d96 100644 --- a/tests/engine/test_process.py +++ b/tests/engine/test_process.py @@ -393,3 +393,46 @@ def define(cls, spec): 'output': node_output, }) self.assertEqual(exposed_outputs, expected) + + def test_exposed_outputs_non_existing_namespace(self): + """Test the ``Process.exposed_outputs`` method for non-existing namespace.""" + from aiida.common.links import LinkType + from aiida.engine.utils import instantiate_process + from aiida.manage.manager import get_manager + + runner = get_manager().get_runner() + + class ChildProcess(Process): + """Dummy process with normal output and output namespace.""" + + _node_class = orm.WorkflowNode + + @classmethod + def define(cls, spec): + super(ChildProcess, cls).define(spec) + spec.input('input', valid_type=orm.Int) + spec.output('output', valid_type=orm.Int) + spec.output('name.space', valid_type=orm.Int) + + class ParentProcess(Process): + """Dummy process that exposes the outputs of ``ChildProcess``.""" + + _node_class = orm.WorkflowNode + + @classmethod + def define(cls, spec): + super(ParentProcess, cls).define(spec) + spec.input('input', valid_type=orm.Int) + spec.expose_outputs(ChildProcess, namespace='child') + + node_child = orm.WorkflowNode().store() + node_output = orm.Int(1).store() + node_output.add_incoming(node_child, link_label='output', link_type=LinkType.RETURN) + node_name_space = orm.Int(1).store() + node_name_space.add_incoming(node_child, link_label='name__space', link_type=LinkType.RETURN) + + process = instantiate_process(runner, ParentProcess, input=orm.Int(1)) + + # If the ``namespace`` does not exist, for example because it is slightly misspelled, a ``KeyError`` is raised + with self.assertRaises(KeyError): + process.exposed_outputs(node_child, ChildProcess, namespace='cildh')