bootstrap-vz/bootstrapvz/common/fsm_proxy.py
2018-02-19 00:31:12 -08:00

61 lines
2 KiB
Python

class FSMProxy(object):
def __init__(self, cfg):
from fysom import Fysom
events = set([event['name'] for event in cfg['events']])
cfg['callbacks'] = self.collect_event_listeners(events, cfg['callbacks'])
self.fsm = Fysom(cfg)
self.attach_proxy_methods(self.fsm, events)
def collect_event_listeners(self, events, callbacks):
callbacks = callbacks.copy()
callback_names = []
for event in events:
callback_names.append(('_before_' + event, 'onbefore' + event))
callback_names.append(('_after_' + event, 'onafter' + event))
for fn_name, listener in callback_names:
fn = getattr(self, fn_name, None)
if callable(fn):
if listener in callbacks:
old_fn = callbacks[listener]
def wrapper(e, old_fn=old_fn, fn=fn):
old_fn(e)
fn(e)
callbacks[listener] = wrapper
else:
callbacks[listener] = fn
return callbacks
def attach_proxy_methods(self, fsm, events):
def make_proxy(fsm, event):
fn = getattr(fsm, event)
def proxy(*args, **kwargs):
if args:
raise FSMProxyError('FSMProxy event listeners only accept named arguments.')
fn(**kwargs)
return proxy
for event in events:
if not hasattr(self, event):
setattr(self, event, make_proxy(fsm, event))
def __getstate__(self):
state = {}
for key, value in self.__dict__.iteritems():
if callable(value) or key == 'fsm':
continue
state[key] = value
state['__class__'] = self.__module__ + '.' + self.__class__.__name__
return state
def __setstate__(self, state):
for key in state:
self.__dict__[key] = state[key]
class FSMProxyError(Exception):
pass