Skip to content

Instantly share code, notes, and snippets.

@matze
Created February 7, 2014 11:06
Show Gist options
  • Save matze/8860802 to your computer and use it in GitHub Desktop.
Save matze/8860802 to your computer and use it in GitHub Desktop.
class State(object):
def __init__(self, default=None):
self.default = default
def __get__(self, instance, owner):
return self._value(instance)
def _value(self, instance):
if not hasattr(instance, '_state_value'):
setattr(instance, '_state_value', self.default)
return getattr(instance, '_state_value')
def transition(self, source='*', target=None, immediate=None, check=None):
def wrapped(func):
transitions = {}
sources = [source] if isinstance(source, basestring) else source
targets = [target] if isinstance(target, basestring) else target
for s in sources:
transitions[s] = targets
def try_transition(target, instance, *args, **kwargs):
current = self._value(instance)
succ = transitions.get(current, transitions.get('*', None))
if not succ:
raise RuntimeError("Transition not allowed")
target = check(instance) if isinstance(target, list) else target
setattr(instance, '_state_value', target)
def call_func(instance, *args, **kwargs):
if immediate:
try_transition(immediate, instance)
result = func(instance, *args, **kwargs)
try_transition(target, instance)
return result
return call_func
return wrapped
class Thing(object):
state = State(default='standby')
def __init__(self):
self._velocity = 0
def get_state(self):
return 'standby' if not self._velocity else 'moving'
@state.transition(source='*', target=['standby', 'moving'], check=get_state)
def set_velocity(self, velocity):
print velocity
self._velocity = velocity
@state.transition(source='standby', target='moving')
def start(self):
self._velocity = 10
@state.transition(source='moving', target='standby')
def stop(self):
self._velocity = 0
thing = Thing()
thing.start()
print thing.state
thing.stop()
print thing.state
thing.set_velocity(1)
print thing.state
thing.set_velocity(0)
print thing.state
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment