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