diff options
Diffstat (limited to '')
| -rw-r--r-- | src/mailman/workflows/base.py (renamed from src/mailman/app/workflow.py) | 82 |
1 files changed, 35 insertions, 47 deletions
diff --git a/src/mailman/app/workflow.py b/src/mailman/workflows/base.py index 92b78c184..8153bf77d 100644 --- a/src/mailman/app/workflow.py +++ b/src/mailman/workflows/base.py @@ -22,9 +22,12 @@ import json import logging from collections import deque -from mailman.interfaces.workflow import IWorkflowStateManager + +from mailman.interfaces.workflows import IWorkflow, IWorkflowStateManager +from mailman.utilities.modules import abstract_component from public import public from zope.component import getUtility +from zope.interface import implementer COMMASPACE = ', ' @@ -32,38 +35,27 @@ log = logging.getLogger('mailman.error') @public +@abstract_component +@implementer(IWorkflow) class Workflow: """Generic workflow.""" - SAVE_ATTRIBUTES = () - INITIAL_STATE = None + initial_state = None + save_attributes = () def __init__(self): self.token = None self._next = deque() - self.push(self.INITIAL_STATE) + self.push(self.initial_state) self.debug = False self._count = 0 - @property - def name(self): - return self.__class__.__name__ - def __iter__(self): + """See `IWorkflow`.""" return self - def push(self, step): - self._next.append(step) - - def _pop(self): - name = self._next.popleft() - step = getattr(self, '_step_{}'.format(name)) - self._count += 1 - if self.debug: # pragma: nocover - print('[{:02d}] -> {}'.format(self._count, name), file=sys.stderr) - return name, step - def __next__(self): + """See `IWorkflow`.""" try: name, step = self._pop() return step() @@ -73,13 +65,20 @@ class Workflow: log.exception('deque: {}'.format(COMMASPACE.join(self._next))) raise - def run_thru(self, stop_after): - """Run the state machine through and including the given step. + def push(self, step): + """See `IWorkflow`.""" + self._next.append(step) + + def _pop(self): + name = self._next.pop() + step = getattr(self, '_step_{}'.format(name)) + self._count += 1 + if self.debug: # pragma: nocover + print('[{:02d}] -> {}'.format(self._count, name), file=sys.stderr) + return name, step - :param stop_after: Name of method, sans prefix to run the - state machine through. In other words, the state machine runs - until the named method completes. - """ + def run_thru(self, stop_after): + """See `IWorkflow`.""" results = [] while True: try: @@ -93,12 +92,7 @@ class Workflow: return results def run_until(self, stop_before): - """Trun the state machine until (not including) the given step. - - :param stop_before: Name of method, sans prefix that the - state machine is run until the method is reached. Unlike - `run_thru()` the named method is not run. - """ + """See `IWorkflow`.""" results = [] while True: try: @@ -116,35 +110,29 @@ class Workflow: return results def save(self): + """See `IWorkflow`.""" assert self.token, 'Workflow token must be set' state_manager = getUtility(IWorkflowStateManager) - data = {attr: getattr(self, attr) for attr in self.SAVE_ATTRIBUTES} - # Note: only the next step is saved, not the whole stack. This is not - # an issue in practice, since there's never more than a single step in - # the queue anyway. If we want to support more than a single step in - # the queue *and* want to support state saving/restoring, change this - # method and the restore() method. + data = {attr: getattr(self, attr) for attr in self.save_attributes} + # Save the workflow stack. if len(self._next) == 0: - step = None - elif len(self._next) == 1: - step = self._next[0] + steps = '[]' else: - raise AssertionError( - "Can't save a workflow state with more than one step " - "in the queue") - state_manager.save(self.token, step, json.dumps(data)) + steps = json.dumps(list(self._next)) + state_manager.save(self.token, steps, json.dumps(data)) def restore(self): + """See `IWorkflow`.""" state_manager = getUtility(IWorkflowStateManager) state = state_manager.restore(self.token) if state is None: # The token doesn't exist in the database. raise LookupError(self.token) self._next.clear() - if state.step: - self._next.append(state.step) + if state.steps: + self._next.extend(json.loads(state.steps)) data = json.loads(state.data) - for attr in self.SAVE_ATTRIBUTES: + for attr in self.save_attributes: try: setattr(self, attr, data[attr]) except KeyError: |
