Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 import sys
00032
00033 class StateUndefinedException(Exception):
00034 """A StateUndefinedException is thrown by
00035 an SMC-generated state machine whenever a transition is taken
00036 and there is no state currently set. This occurs when a
00037 transition is issued from within a transition action."""
00038 pass
00039
00040 class TransitionUndefinedException(Exception):
00041 """A TransitionUndefinedException is thrown by
00042 an SMC-generated state machine whenever a transition is taken
00043 which:
00044
00045 - Is not explicitly defined in the current state.
00046 - Is not explicitly defined in the current FSM's default state.
00047 - There is no Default transition in the current state."""
00048 pass
00049
00050
00051 class State(object):
00052 """base State class"""
00053
00054 def __init__(self, name, id):
00055 self._name = name
00056 self._id = id
00057
00058 def getName(self):
00059 """Returns the state's printable name."""
00060 return self._name
00061
00062 def getId(self):
00063 """Returns the state's unique identifier."""
00064 return self._id
00065
00066
00067 class FSMContext(object):
00068 """The user can derive FSM contexts from this class and interface
00069 to them with the methods of this class.
00070
00071 The finite state machine needs to be initialized to the starting
00072 state of the FSM. This must be done manually in the constructor
00073 of the derived class.
00074 """
00075
00076 def __init__(self, state):
00077 self._state = state
00078 self._previous_state = None
00079 self._state_stack = []
00080 self._transition = None
00081 self._debug_flag = False
00082 self._debug_stream = sys.stderr
00083
00084 def getDebugFlag(self):
00085 """Returns the debug flag's current setting."""
00086 return self._debug_flag
00087
00088 def setDebugFlag(self, flag):
00089 """Sets the debug flag.
00090 A true value means debugging is on and false means off."""
00091 self._debug_flag = flag
00092
00093 def getDebugStream(self):
00094 """Returns the stream to which debug output is written."""
00095 return self._debug_stream
00096
00097 def setDebugStream(self, stream):
00098 """Sets the debug output stream."""
00099 self._debug_stream = stream
00100
00101 def getState(self):
00102 """Returns the current state."""
00103 if self._state == None:
00104 raise StateUndefinedException
00105 return self._state
00106
00107 def isInTransition(self):
00108 """Is this state machine already inside a transition?
00109 True if state is undefined."""
00110 if self._state == None:
00111 return True
00112 else:
00113 return False
00114
00115 def getTransition(self):
00116 """Returns the current transition's name.
00117 Used only for debugging purposes."""
00118 return self._transition
00119
00120 def clearState(self):
00121 """Clears the current state."""
00122 self._previous_state = self._state
00123 self._state = None
00124
00125
00126 def getPreviousState(self):
00127 """Returns the state which a transition left.
00128 May be None"""
00129 return self._previous_state
00130
00131
00132 def setState(self, state):
00133 """Sets the current state to the specified state."""
00134 if not isinstance(state, State):
00135 raise ValueError("state should be a statemap.State")
00136 self._state = state
00137 if self._debug_flag:
00138 self._debug_stream.write("NEW STATE : %s\n" % self._state.getName())
00139
00140 def isStateStackEmpty(self):
00141 """Returns True if the state stack is empty and False otherwise."""
00142 return len(self._state_stack) == 0
00143
00144 def getStateStackDepth(self):
00145 """Returns the state stack's depth."""
00146 return len(self._state_stack)
00147
00148 def pushState(self, state):
00149 """Push the current state on top of the state stack
00150 and make the specified state the current state."""
00151 if not isinstance(state, State):
00152 raise ValueError("state should be a statemap.State")
00153 if self._state != None:
00154 self._state_stack.append(self._state)
00155 self._state = state
00156 if self._debug_flag:
00157 self._debug_stream.write("PUSH TO STATE : %s\n" % self._state.getName())
00158
00159 def popState(self):
00160 """Make the state on top of the state stack the current state."""
00161 if len(self._state_stack) == 0:
00162 if self._debug_flag:
00163 self._debug_stream.write("POPPING ON EMPTY STATE STACK.\n")
00164 raise ValueError("empty state stack")
00165 else:
00166 self._state = self._state_stack.pop()
00167 if self._debug_flag:
00168 self._debug_stream.write("POP TO STATE : %s\n" % self._state.getName())
00169
00170 def emptyStateStack(self):
00171 """Remove all states from the state stack."""
00172 self._state_stack = []