Repository: spotify/luigi
File: luigi/execution_summary.py (Python)

Code before:
"""

import textwrap
import collections
import functools

import luigi


class execution_summary(luigi.Config):
    summary_length = luigi.IntParameter(default=5)
    legacy_run_result = luigi.BoolParameter(default=True)


class LuigiRunResult:
    """
    Result of the execution (build/run) will be of type LuigiRunResult instead of
    the regular Boolean response if [execution_summary]legacy_run_result is set
    to False in the config.
    """
    def __init__(self, worker, worker_add_run_status=True):
        self.worker = worker
        self.task_groups = _summary_dict(worker)
        self.summary_detailed = summary(worker)
        self.summary, smiley, _ = self._progress_summary()
        self.status = True if smiley == ":)" else False
        self.status_legacy = worker_add_run_status
        self.response = self._response()

    def _response(self):
        if not execution_summary().legacy_run_result:
            return self
        else:
            return dict(success=self.status_legacy, worker=self.worker)

    def _progress_summary(self):
        smiley, reason = _tasks_status(self.task_groups)
        return "The progress looks {0} because {1}".format(smiley, reason), smiley, reason

    def __str__(self):
        return self.summary

    def __repr__(self):
        return self.__str__()


def _partition_tasks(worker):
    """
    Takes a worker and sorts out tasks based on their status.
    Still_pending_not_ext is only used to get upstream_failure, upstream_missing_dependency and run_by_other_worker
    """

Review comment (refactor):
While this code really looks cute, I think it would be better to refactor part of the current execution summary code so that you can play around on structured data (like enums) over hard coded strings like this. Would that make sense?

Code after:
"""

import textwrap
import collections
import functools
import enum

import luigi


class execution_summary(luigi.Config):
    summary_length = luigi.IntParameter(default=5)


class LuigiStatusCode(enum.Enum):
    """
    All possible status codes for the attribute ``status`` in :class:`~luigi.execution_summary.LuigiRunResult` when
    the argument ``detailed_summary=True`` in *luigi.run() / luigi.build*.
    Here are the codes and what they mean:

    =============================  ==========================================================
    Status Code Name               Meaning
    =============================  ==========================================================
    SUCCESS                        There were no failed tasks or missing dependencies
    SUCCESS_WITH_RETRY             There were failed tasks but they all succeeded in a retry
    FAILED                         There were failed tasks
    FAILED_AND_SCHEDULING_FAILED   There were failed tasks and tasks whose scheduling failed
    SCHEDULING_FAILED              There were tasks whose scheduling failed
    NOT_RUN                        There were tasks that were not granted run permission by the scheduler
    MISSING_EXT                    There were missing external dependencies
    =============================  ==========================================================

    """
    SUCCESS = (":)", "there were no failed tasks or missing dependencies")
    SUCCESS_WITH_RETRY = (":)", "there were failed tasks but they all succeeded in a retry")
    FAILED = (":(", "there were failed tasks")
    FAILED_AND_SCHEDULING_FAILED = (":(", "there were failed tasks and tasks whose scheduling failed")
    SCHEDULING_FAILED = (":(", "there were tasks whose scheduling failed")
    NOT_RUN = (":|", "there were tasks that were not granted run permission by the scheduler")
    MISSING_EXT = (":|", "there were missing external dependencies")


class LuigiRunResult(object):
    """
    The result of a call to build/run when passing the detailed_summary=True argument.

    Attributes:
        - one_line_summary (str): One line summary of the progress.
        - summary_text (str): Detailed summary of the progress.
        - status (LuigiStatusCode): Luigi Status Code. See :class:`~luigi.execution_summary.LuigiStatusCode` for what these codes mean.
        - worker (luigi.worker.worker): Worker object. See :class:`~luigi.worker.worker`.