Merge "Ensure state machine can be frozen"

This commit is contained in:
Jenkins
2014-10-18 20:16:29 +00:00
committed by Gerrit Code Review
3 changed files with 28 additions and 0 deletions

View File

@@ -196,6 +196,7 @@ class _MachineBuilder(object):
m.add_reaction(st.SCHEDULING, 'schedule', schedule)
m.add_reaction(st.WAITING, 'wait', wait)
m.freeze()
return (m, memory)

View File

@@ -351,6 +351,15 @@ class FSMTest(test.TestCase):
self.assertIn(('up', 'fall', 'down'), transitions)
self.assertIn(('down', 'jump', 'up'), transitions)
def test_freeze(self):
self.jumper.freeze()
self.assertRaises(fsm.FrozenMachine, self.jumper.add_state, 'test')
self.assertRaises(fsm.FrozenMachine,
self.jumper.add_transition, 'test', 'test', 'test')
self.assertRaises(fsm.FrozenMachine,
self.jumper.add_reaction,
'test', 'test', lambda *args: 'test')
def test_invalid_callbacks(self):
m = fsm.FSM('working')
m.add_state('working')

View File

@@ -33,6 +33,12 @@ class _Jump(object):
self.on_exit = on_exit
class FrozenMachine(Exception):
"""Exception raised when a frozen machine is modified."""
def __init__(self):
super(FrozenMachine, self).__init__("Frozen machine can't be modified")
class NotInitialized(excp.TaskFlowException):
"""Error raised when an action is attempted on a not inited machine."""
@@ -62,6 +68,7 @@ class FSM(object):
self._states = OrderedDict()
self._start_state = start_state
self._current = None
self.frozen = False
@property
def start_state(self):
@@ -89,6 +96,8 @@ class FSM(object):
parameter which is the event that is being processed that caused the
state transition.
"""
if self.frozen:
raise FrozenMachine()
if state in self._states:
raise excp.Duplicate("State '%s' already defined" % state)
if on_enter is not None:
@@ -123,6 +132,8 @@ class FSM(object):
this process typically repeats) until the state machine reaches a
terminal state.
"""
if self.frozen:
raise FrozenMachine()
if state not in self._states:
raise excp.NotFound("Can not add a reaction to event '%s' for an"
" undefined state '%s'" % (event, state))
@@ -135,6 +146,8 @@ class FSM(object):
def add_transition(self, start, end, event):
"""Adds an allowed transition from start -> end for the given event."""
if self.frozen:
raise FrozenMachine()
if start not in self._states:
raise excp.NotFound("Can not add a transition on event '%s' that"
" starts in a undefined state '%s'" % (event,
@@ -220,8 +233,13 @@ class FSM(object):
event = cb(old_state, new_state, event, *args, **kwargs)
def __contains__(self, state):
"""Returns if this state exists in the machines known states."""
return state in self._states
def freeze(self):
"""Freezes & stops addition of states, transitions, reactions..."""
self.frozen = True
@property
def states(self):
"""Returns the state names."""