| # Copyright 1999-2020 Gentoo Authors |
| # Distributed under the terms of the GNU General Public License v2 |
| |
| from collections import deque |
| |
| from portage import os |
| from _emerge.CompositeTask import CompositeTask |
| from _emerge.AsynchronousTask import AsynchronousTask |
| |
| |
| class TaskSequence(CompositeTask): |
| """ |
| A collection of tasks that executes sequentially. Each task |
| must have a addExitListener() method that can be used as |
| a means to trigger movement from one task to the next. |
| """ |
| |
| __slots__ = ("_task_queue",) |
| |
| def __init__(self, **kwargs): |
| AsynchronousTask.__init__(self, **kwargs) |
| self._task_queue = deque() |
| |
| def add(self, task): |
| self._task_queue.append(task) |
| |
| def _start(self): |
| self._start_next_task() |
| |
| def _cancel(self): |
| self._task_queue.clear() |
| CompositeTask._cancel(self) |
| |
| def _start_next_task(self): |
| try: |
| task = self._task_queue.popleft() |
| except IndexError: |
| self._current_task = None |
| self.returncode = os.EX_OK |
| self.wait() |
| return |
| |
| self._start_task(task, self._task_exit_handler) |
| |
| def _task_exit_handler(self, task): |
| if self._default_exit(task) != os.EX_OK: |
| self.wait() |
| elif self._task_queue: |
| self._start_next_task() |
| else: |
| self._final_exit(task) |
| self.wait() |
| |
| def __bool__(self): |
| return bool(self._task_queue) |
| |
| def __len__(self): |
| return len(self._task_queue) |