diff --git a/aiida/backends/tests/engine/test_process_function.py b/aiida/backends/tests/engine/test_process_function.py index a0a96281e5b..f5ddda1a62a 100644 --- a/aiida/backends/tests/engine/test_process_function.py +++ b/aiida/backends/tests/engine/test_process_function.py @@ -36,7 +36,7 @@ class TestProcessFunction(AiidaTestCase): function would complain as the dummy node class is not recognized as a valid process node. """ - # pylint: disable=too-many-public-methods + # pylint: disable=too-many-public-methods,too-many-instance-attributes def setUp(self): super(TestProcessFunction, self).setUp() @@ -86,6 +86,11 @@ def function_defaults( }): # pylint: disable=unused-argument,dangerous-default-value,missing-docstring return data_a + @workfunction + def function_default_from_docs(): + """Description taken from the docs.""" + return + @workfunction def function_exit_code(exit_status, exit_message): return ExitCode(exit_status.value, exit_message.value) @@ -107,6 +112,7 @@ def function_out_unstored(): self.function_args_and_kwargs = function_args_and_kwargs self.function_args_and_default = function_args_and_default self.function_defaults = function_defaults + self.function_default_from_docs = function_default_from_docs self.function_exit_code = function_exit_code self.function_excepts = function_excepts self.function_out_unstored = function_out_unstored @@ -300,6 +306,18 @@ def test_function_defaults(self): self.assertEqual(node.label, CUSTOM_LABEL) self.assertEqual(node.description, CUSTOM_DESCRIPTION) + def test_function_default_label_description(self): + """Verify unless specified label and description are taken from function name and docstring respectively.""" + metadata = {'label': CUSTOM_LABEL, 'description': CUSTOM_DESCRIPTION} + + _, node = self.function_default_from_docs.run_get_node() + self.assertEqual(node.label, 'function_default_from_docs') + self.assertEqual(node.description, 'Description taken from the docs.') + + _, node = self.function_default_from_docs.run_get_node(metadata=metadata) + self.assertEqual(node.label, CUSTOM_LABEL) + self.assertEqual(node.description, CUSTOM_DESCRIPTION) + def test_launchers(self): """Verify that the various launchers are working.""" result = run(self.function_return_true) diff --git a/aiida/engine/processes/functions.py b/aiida/engine/processes/functions.py index b1a4d131ef6..2f97bd08292 100644 --- a/aiida/engine/processes/functions.py +++ b/aiida/engine/processes/functions.py @@ -221,6 +221,16 @@ def _define(cls, spec): spec.input(arg, valid_type=valid_type, default=default) + # Set defaults for label and description based on function name and docstring, if not explicitly defined + port_label = spec.inputs['metadata']['label'] + port_description = spec.inputs['metadata']['description'] + + if not port_label.has_default(): + port_label.default = func.__name__ + + if not port_description.has_default() and func.__doc__: + port_description.default = func.__doc__ + # If the function support kwargs then allow dynamic inputs, otherwise disallow spec.inputs.dynamic = keywords is not None