The Workflow library provides a method of running Finite State Machines with memory. It can be used to execute a set of methods, complete with conditions and patterns.
Workflow allows for a number of independent pieces of data to be processed by the same logic, while allowing for the entire process to be forwarded, backwarded, paused, inspected, re-executed, modified and stored.
In [1]:
    
from workflow.engine import GenericWorkflowEngine
    
In [2]:
    
my_engine = GenericWorkflowEngine()
    
In [3]:
    
from functools import wraps
def print_data(obj, eng):
    """Print the data found in the token."""
    print(obj.data)
    
def add_data(number_to_add):
    """Add number_to_add to obj.data."""
    @wraps(add_data)
    def _add_data(obj, eng):
        obj.data += number_to_add
    return _add_data
    
In [4]:
    
my_workflow_definition = [
    add_data(1),
    print_data
]
    
In [5]:
    
class MyObject:
    def __init__(self, data):
        self._data = data
    
    @property
    def data(self):
        return self._data
    
    @data.setter
    def data(self, value):
        print(self)
        self._data = value
    
    def __repr__(self):
        return "{0} : {1}".format(hex(id(self)), self._data)
my_object0 = MyObject(0)
my_object1 = MyObject(1)
    
In [6]:
    
my_engine.callbacks.replace(my_workflow_definition)
    
In [7]:
    
my_engine.process([my_object0, my_object1])
    
    
In [8]:
    
my_engine.process([my_object0, my_object1])
    
    
TODO:
http://workflow.readthedocs.io/en/latest/#loops-and-interrupts