Skip to content

Commit

Permalink
Restore ExitCode to being a namedtuple
Browse files Browse the repository at this point in the history
Changing the `ExitCode` from a namedtuple to a class breaks backwards
compatibility since the class won't have the functionalities of a tuple
such as expanding an instance in its attributes. By subclassing from the
namedtuple definition we keep all that functionality while still being
able to implement additional methods, such as in this case `format`.

Co-Authored-By: Dominik Gresch <greschd@users.noreply.github.com>
  • Loading branch information
sphuber and greschd committed Mar 23, 2020
1 parent 9051177 commit 4ec0662
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
15 changes: 9 additions & 6 deletions aiida/engine/processes/exit_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,22 @@
# For further information please visit http://www.aiida.net #
###########################################################################
"""A namedtuple and namespace for ExitCodes that can be used to exit from Processes."""
from collections import namedtuple
from aiida.common.extendeddicts import AttributeDict

__all__ = ('ExitCode', 'ExitCodesNamespace')


class ExitCode:
class ExitCode(namedtuple('ExitCode', ['status', 'message', 'invalidates_cache'])):
"""A simple data class to define an exit code for a :class:`~aiida.engine.processes.process.Process`.
When an instance of this clas is returned from a `Process._run()` call, it will be interpreted that the `Process`
should be terminated and that the exit status and message of the namedtuple should be set to the corresponding
attributes of the node.
.. note:: this class explicitly sub-classes a namedtuple to not break backwards compatibility and to have it behave
exactly as a tuple.
:param status: positive integer exit status, where a non-zero value indicated the process failed, default is `0`
:type status: int
Expand All @@ -30,11 +34,6 @@ class ExitCode:
:type invalidates_cache: bool
"""

def __init__(self, status=0, message=None, invalidates_cache=False):
self.status = status
self.message = message
self.invalidates_cache = invalidates_cache

def format(self, **kwargs):
"""Create a clone of this exit code where the template message is replaced by the keyword arguments.
Expand All @@ -53,6 +52,10 @@ def __eq__(self, other):
return all(getattr(self, attr) == getattr(other, attr) for attr in ['status', 'message', 'invalidates_cache'])


# Set the defaults for the `ExitCode` attributes
ExitCode.__new__.__defaults__ = (0, None, False)


class ExitCodesNamespace(AttributeDict):
"""A namespace of `ExitCode` instances that can be accessed through getattr as well as getitem.
Expand Down
13 changes: 13 additions & 0 deletions tests/engine/processes/text_exit_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,16 @@ def test_exit_code_template_message():

assert exit_code_base != exit_code_called # Calling the exit code should return a new instance
assert exit_code_called.message == message_template.format(parameter=parameter_name)


def test_exit_code_expand_tuple():
"""Test that an exit code instance can be expanded in its attributes like a tuple."""
status = 418
message = 'I am a teapot'
invalidates_cache = True

status_exp, message_exp, invalidates_cache_exp = ExitCode(418, message, True)

assert status == status_exp
assert message == message_exp
assert invalidates_cache == invalidates_cache_exp

0 comments on commit 4ec0662

Please sign in to comment.