diff --git a/aiida/calculations/arithmetic/add.py b/aiida/calculations/arithmetic/add.py index 5eba578c64..6fccfe8d49 100644 --- a/aiida/calculations/arithmetic/add.py +++ b/aiida/calculations/arithmetic/add.py @@ -33,7 +33,6 @@ def define(cls, spec: CalcJobProcessSpec): spec.inputs['metadata']['options']['output_filename'].default = 'aiida.out' spec.inputs['metadata']['options']['resources'].default = {'num_machines': 1, 'num_mpiprocs_per_machine': 1} # start exit codes - marker for docs - spec.exit_code(300, 'ERROR_NO_RETRIEVED_FOLDER', message='The retrieved output node does not exist.') spec.exit_code(310, 'ERROR_READING_OUTPUT_FILE', message='The output file could not be read.') spec.exit_code(320, 'ERROR_INVALID_OUTPUT', message='The output file contains invalid output.') spec.exit_code(410, 'ERROR_NEGATIVE_NUMBER', message='The sum of the operands is a negative number.') diff --git a/aiida/calculations/templatereplacer.py b/aiida/calculations/templatereplacer.py index aa98da7321..2940093b63 100644 --- a/aiida/calculations/templatereplacer.py +++ b/aiida/calculations/templatereplacer.py @@ -73,8 +73,6 @@ def define(cls, spec): spec.output('output_parameters', valid_type=orm.Dict, required=True) spec.default_output_node = 'output_parameters' - spec.exit_code(100, 'ERROR_NO_RETRIEVED_FOLDER', - message='The retrieved folder data node could not be accessed.') spec.exit_code(101, 'ERROR_NO_TEMPORARY_RETRIEVED_FOLDER', message='The temporary retrieved folder data node could not be accessed.') spec.exit_code(105, 'ERROR_NO_OUTPUT_FILE_NAME_DEFINED', diff --git a/aiida/parsers/plugins/arithmetic/add.py b/aiida/parsers/plugins/arithmetic/add.py index 5f023e5943..f043f3fc63 100644 --- a/aiida/parsers/plugins/arithmetic/add.py +++ b/aiida/parsers/plugins/arithmetic/add.py @@ -21,12 +21,7 @@ def parse(self, **kwargs): from aiida.orm import Int try: - output_folder = self.retrieved - except AttributeError: - return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER - - try: - with output_folder.open(self.node.get_option('output_filename'), 'r') as handle: + with self.retrieved.open(self.node.get_option('output_filename'), 'r') as handle: result = int(handle.read()) except OSError: return self.exit_codes.ERROR_READING_OUTPUT_FILE diff --git a/aiida/parsers/plugins/templatereplacer/doubler.py b/aiida/parsers/plugins/templatereplacer/doubler.py index e3c7d90f8d..9b66f22d51 100644 --- a/aiida/parsers/plugins/templatereplacer/doubler.py +++ b/aiida/parsers/plugins/templatereplacer/doubler.py @@ -10,12 +10,8 @@ """Parser for the `TemplatereplacerCalculation` calculation job doubling a number.""" import os -from aiida.common import exceptions from aiida.orm import Dict from aiida.parsers.parser import Parser -from aiida.plugins import CalculationFactory - -TemplatereplacerCalculation = CalculationFactory('templatereplacer') class TemplatereplacerDoublerParser(Parser): @@ -23,13 +19,9 @@ class TemplatereplacerDoublerParser(Parser): def parse(self, **kwargs): """Parse the contents of the output files retrieved in the `FolderData`.""" + output_folder = self.retrieved template = self.node.inputs.template.get_dict() - try: - output_folder = self.retrieved - except exceptions.NotExistent: - return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER - try: output_file = template['output_file_name'] except KeyError: @@ -77,8 +69,7 @@ def parse(self, **kwargs): @staticmethod def parse_stdout(filelike): - """ - Parse the sum from the output of the ArithmeticAddcalculation written to standard out + """Parse the sum from the output of the ArithmeticAddcalculation written to standard out. :param filelike: filelike object containing the output :returns: the sum diff --git a/docs/source/topics/calculations/include/snippets/calcjobs/arithmetic_add_parser.py b/docs/source/topics/calculations/include/snippets/calcjobs/arithmetic_add_parser.py index 3e3773060e..fb0a7dee32 100644 --- a/docs/source/topics/calculations/include/snippets/calcjobs/arithmetic_add_parser.py +++ b/docs/source/topics/calculations/include/snippets/calcjobs/arithmetic_add_parser.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from aiida.common import exceptions from aiida.orm import Int from aiida.parsers.parser import Parser @@ -8,10 +7,7 @@ class ArithmeticAddParser(Parser): def parse(self, **kwargs): """Parse the contents of the output files retrieved in the `FolderData`.""" - try: - output_folder = self.retrieved - except exceptions.NotExistent: - return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER + output_folder = self.retrieved try: with output_folder.open(self.node.get_option('output_filename'), 'r') as handle: diff --git a/docs/source/topics/calculations/usage.rst b/docs/source/topics/calculations/usage.rst index ee49abfa3d..5226424c3d 100644 --- a/docs/source/topics/calculations/usage.rst +++ b/docs/source/topics/calculations/usage.rst @@ -466,45 +466,32 @@ The advantage of adding the raw output data in different form as output nodes, i This allows one to query for calculations that produced specific outputs with a certain value, which becomes a very powerful approach for post-processing and analyses of big databases. The ``retrieved`` attribute of the parser will return the ``FolderData`` node that should have been attached by the engine containing all the retrieved files, as specified using the :ref:`retrieve list` in the :ref:`preparation step of the calculation job`. -If this node has not been attached for whatever reason, this call will throw an :py:class:`~aiida.common.exceptions.NotExistent` exception. -This is why we wrap the ``self.retrieved`` call in a try-catch block: +This retrieved folder can be used to open and read the contents of the files it contains. +In this example, there should be a single output file that was written by redirecting the standard output of the bash script that added the two integers. +The parser opens this file, reads its content and tries to parse the sum from it: .. literalinclude:: include/snippets/calcjobs/arithmetic_add_parser.py :language: python - :lines: 11-14 + :lines: 12-16 :linenos: - :lineno-start: 11 + :lineno-start: 12 -If the exception is thrown, it means the retrieved files are not available and something must have has gone terribly awry with the calculation. -In this case, there is nothing to do for the parser and so we return an exit code. -Specific exit codes can be referenced by their label, such as ``ERROR_NO_RETRIEVED_FOLDER`` in this example, through the ``self.exit_codes`` property. +Note that this parsing action is wrapped in a try-except block to catch the exceptions that would be thrown if the output file could not be read. +If the exception would not be caught, the engine will catch the exception instead and set the process state of the corresponding calculation to ``Excepted``. +Note that this will happen for any uncaught exception that is thrown during parsing. +Instead, we catch these exceptions and return an exit code that is retrieved by referencing it by its label, such as ``ERROR_READING_OUTPUT_FILE`` in this example, through the ``self.exit_codes`` property. This call will retrieve the corresponding exit code defined on the ``CalcJob`` that we are currently parsing. Returning this exit code from the parser will stop the parsing immediately and will instruct the engine to set its exit status and exit message on the node of this calculation job. -This should scenario should however never occur, but it is just here as a safety. -If the exception would not be caught, the engine will catch the exception instead and set the process state of the corresponding calculation to ``Excepted``. -Note that this will happen for any exception that occurs during parsing. - -Assuming that everything went according to plan during the retrieval, we now have access to those retrieved files and can start to parse them. -In this example, there should be a single output file that was written by redirecting the standard output of the bash script that added the two integers. -The parser opens this file, reads its content and tries to parse the sum from it: - -.. literalinclude:: include/snippets/calcjobs/arithmetic_add_parser.py - :language: python - :lines: 16-20 - :linenos: - :lineno-start: 16 -Note that again we wrap this parsing action in a try-except block. -If the file cannot be found or cannot be read, we return the appropriate exit code. The ``parse_stdout`` method is just a small utility function to separate the actual parsing of the data from the main parser code. In this case, the parsing is so simple that we might have as well kept it in the main method, but this is just to illustrate that you are completely free to organize the code within the ``parse`` method for clarity. If we manage to parse the sum, produced by the calculation, we wrap it in the appropriate :py:class:`~aiida.orm.nodes.data.int.Int` data node class, and register it as an output through the ``out`` method: .. literalinclude:: include/snippets/calcjobs/arithmetic_add_parser.py :language: python - :lines: 25-25 + :lines: 21-21 :linenos: - :lineno-start: 25 + :lineno-start: 21 Note that if we encountered no problems, we do not have to return anything. The engine will interpret this as the calculation having finished successfully.