summaryrefslogtreecommitdiff
path: root/src/mailman/app/workflow.py
diff options
context:
space:
mode:
authorJ08nY2017-08-07 19:00:49 +0200
committerJ08nY2017-08-07 19:00:49 +0200
commitee9da27283ffb7adc836f764f1442cd06e3fb2a5 (patch)
tree2b687f39714580b1de70baf9e3dd9957326c4989 /src/mailman/app/workflow.py
parentd107fd41f03b57f7731b60bb7ba921febc3ce3b9 (diff)
parentb902d7858d8302d248add89a5983c521c3581c4c (diff)
downloadmailman-ee9da27283ffb7adc836f764f1442cd06e3fb2a5.tar.gz
mailman-ee9da27283ffb7adc836f764f1442cd06e3fb2a5.tar.zst
mailman-ee9da27283ffb7adc836f764f1442cd06e3fb2a5.zip
Diffstat (limited to 'src/mailman/app/workflow.py')
-rw-r--r--src/mailman/app/workflow.py151
1 files changed, 0 insertions, 151 deletions
diff --git a/src/mailman/app/workflow.py b/src/mailman/app/workflow.py
deleted file mode 100644
index 92b78c184..000000000
--- a/src/mailman/app/workflow.py
+++ /dev/null
@@ -1,151 +0,0 @@
-# Copyright (C) 2015-2017 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""Generic workflow."""
-
-import sys
-import json
-import logging
-
-from collections import deque
-from mailman.interfaces.workflow import IWorkflowStateManager
-from public import public
-from zope.component import getUtility
-
-
-COMMASPACE = ', '
-log = logging.getLogger('mailman.error')
-
-
-@public
-class Workflow:
- """Generic workflow."""
-
- SAVE_ATTRIBUTES = ()
- INITIAL_STATE = None
-
- def __init__(self):
- self.token = None
- self._next = deque()
- self.push(self.INITIAL_STATE)
- self.debug = False
- self._count = 0
-
- @property
- def name(self):
- return self.__class__.__name__
-
- def __iter__(self):
- 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):
- try:
- name, step = self._pop()
- return step()
- except IndexError:
- raise StopIteration
- except:
- 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.
-
- :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.
- """
- results = []
- while True:
- try:
- name, step = self._pop()
- except (StopIteration, IndexError):
- # We're done.
- break
- results.append(step())
- if name == stop_after:
- break
- 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.
- """
- results = []
- while True:
- try:
- name, step = self._pop()
- except (StopIteration, IndexError):
- # We're done.
- break
- if name == stop_before:
- # Stop executing, but not before we push the last state back
- # onto the deque. Otherwise, resuming the state machine would
- # skip this step.
- self._next.appendleft(name)
- break
- results.append(step())
- return results
-
- def save(self):
- 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.
- if len(self._next) == 0:
- step = None
- elif len(self._next) == 1:
- step = self._next[0]
- 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))
-
- def restore(self):
- 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)
- data = json.loads(state.data)
- for attr in self.SAVE_ATTRIBUTES:
- try:
- setattr(self, attr, data[attr])
- except KeyError:
- pass