Skip to content

Commit bbea390

Browse files
committed
allow extra args to enter function, don't pass oldState, newState but store them instead
1 parent 88ef2ac commit bbea390

File tree

2 files changed

+66
-57
lines changed

2 files changed

+66
-57
lines changed

direct/src/fsm/FSM.py

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,22 @@ class FSM(DirectObject.DirectObject):
2222
particular state, define a method named enterState() and/or
2323
exitState(), where "State" is the name of the state, e.g.:
2424
25-
def enterRed(self, oldState, newState):
25+
def enterRed(self):
2626
... do stuff ...
2727
28-
def exitRed(self, oldState, newState):
28+
def exitRed(self):
2929
... cleanup stuff ...
3030
31-
def enterYellow(self, oldState, newState):
31+
def enterYellow(self):
3232
... do stuff ...
3333
34-
def exitYellow(self, oldState, newState):
34+
def exitYellow(self):
3535
... cleanup stuff ...
3636
37-
def enterGreen(self, oldState, newState):
37+
def enterGreen(self):
3838
... do stuff ...
3939
40-
def exitGreen(self, oldState, newState):
40+
def exitGreen(self):
4141
... cleanup stuff ...
4242
4343
Both functions are supplied the previous state name and the new
@@ -134,7 +134,7 @@ def forceTransition(self, newState):
134134
bypasses the filterState() function, and just calls
135135
exitState() followed by enterState()."""
136136

137-
assert(isinstance(newState, types.StringType))
137+
assert(isinstance(newState, types.StringTypes))
138138

139139
self.__setState(newState)
140140

@@ -147,13 +147,14 @@ def request(self, request, *args):
147147
148148
The return value is the same as the return value of
149149
filterState() (that is, None if the request does not provoke a
150-
state transition, or the name of the new state otherwise.)
150+
state transition, otherwise it is a tuple containing the name
151+
of the state followed by any optional args.)
151152
152153
If the FSM is currently in transition (i.e. in the middle of
153154
executing an enterState or exitState function), the request is
154155
denied and None is returned."""
155156

156-
assert(isinstance(request, types.StringType))
157+
assert(isinstance(request, types.StringTypes))
157158
self.notify.debug("%s.request(%s, %s" % (self.name, request, str(args)[1:]))
158159

159160
if not self.state:
@@ -167,8 +168,13 @@ def request(self, request, *args):
167168
func = self.defaultFilter
168169
result = func(request, args)
169170
if result:
170-
assert(isinstance(result, types.StringType))
171-
self.__setState(result)
171+
if isinstance(result, types.StringTypes):
172+
# If the return value is a string, it's just the name
173+
# of the state. Wrap it in a tuple for consistency.
174+
result = (result,)
175+
176+
# Otherwise, assume it's a (name, *args) tuple
177+
self.__setState(*result)
172178

173179
return result
174180

@@ -182,14 +188,14 @@ def defaultFilter(self, request, args):
182188

183189
if request == 'Off':
184190
# We can always go to the "Off" state.
185-
return request
191+
return (request,) + args
186192

187193
if self.defaultTransitions is None:
188194
# If self.defaultTransitions is None, it means to accept
189195
# all requests whose name begins with a capital letter.
190196
# These are direct requests to a particular state.
191197
if request[0] in string.uppercase:
192-
return request
198+
return (request,) + args
193199

194200
else:
195201
# If self.defaultTransitions is not None, it is a map of
@@ -200,7 +206,7 @@ def defaultFilter(self, request, args):
200206
if request in self.defaultTransitions.get(self.state, []):
201207
# This transition is listed in the defaultTransitions map;
202208
# accept it.
203-
return request
209+
return (request,) + args
204210

205211
# If self.defaultTransitions is not None, it is an error
206212
# to request a direct state transition (capital letter
@@ -222,26 +228,29 @@ def filterOff(self, request, args):
222228
return self.defaultFilter(request, args)
223229

224230

225-
def __setState(self, newState):
231+
def __setState(self, newState, *args):
226232
# Internal function to change unconditionally to the indicated
227233
# state.
228234
assert(self.state)
229235

230-
oldState = self.state
236+
self.oldState = self.state
237+
self.newState = newState
231238
self.state = None
232-
self.__callTransitionFunc("exit" + oldState, oldState, newState)
233-
self.__callTransitionFunc("enter" + newState, oldState, newState)
239+
self.__callTransitionFunc("exit" + self.oldState)
240+
self.__callTransitionFunc("enter" + self.newState, *args)
234241
self.state = newState
242+
del self.oldState
243+
del self.newState
235244

236245

237-
def __callTransitionFunc(self, name, oldState, newState):
246+
def __callTransitionFunc(self, name, *args):
238247
# Calls the appropriate enter or exit function when
239248
# transitioning between states, if it exists.
240249
assert(self.state == None)
241250

242251
func = getattr(self, name, None)
243252
if func:
244-
func(oldState, newState)
253+
func(*args)
245254

246255
def __repr__(self):
247256
return self.__str__()

direct/src/fsm/SampleFSM.py

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,62 +15,62 @@ def __init__(self, name):
1515
'Green' : ['Yellow'],
1616
}
1717

18-
def enterRed(self, oldState, newState):
19-
print "enterRed(self, '%s', '%s')" % (oldState, newState)
18+
def enterRed(self):
19+
print "enterRed(self, '%s', '%s')" % (self.oldState, self.newState)
2020

21-
def exitRed(self, oldState, newState):
22-
print "exitRed(self, '%s', '%s')" % (oldState, newState)
21+
def exitRed(self):
22+
print "exitRed(self, '%s', '%s')" % (self.oldState, self.newState)
2323

24-
def enterYellow(self, oldState, newState):
25-
print "enterYellow(self, '%s', '%s')" % (oldState, newState)
24+
def enterYellow(self):
25+
print "enterYellow(self, '%s', '%s')" % (self.oldState, self.newState)
2626

27-
def exitYellow(self, oldState, newState):
28-
print "exitYellow(self, '%s', '%s')" % (oldState, newState)
27+
def exitYellow(self):
28+
print "exitYellow(self, '%s', '%s')" % (self.oldState, self.newState)
2929

30-
def enterGreen(self, oldState, newState):
31-
print "enterGreen(self, '%s', '%s')" % (oldState, newState)
30+
def enterGreen(self):
31+
print "enterGreen(self, '%s', '%s')" % (self.oldState, self.newState)
3232

33-
def exitGreen(self, oldState, newState):
34-
print "exitGreen(self, '%s', '%s')" % (oldState, newState)
33+
def exitGreen(self):
34+
print "exitGreen(self, '%s', '%s')" % (self.oldState, self.newState)
3535

3636

3737
class NewStyle(FSM.FSM):
3838

39-
def enterRed(self, oldState, newState):
40-
print "enterRed(self, '%s', '%s')" % (oldState, newState)
39+
def enterRed(self):
40+
print "enterRed(self, '%s', '%s')" % (self.oldState, self.newState)
4141

4242
def filterRed(self, request, args):
4343
print "filterRed(self, '%s', %s)" % (request, args)
4444
if request == 'advance':
4545
return 'Green'
4646
return self.defaultFilter(request, args)
4747

48-
def exitRed(self, oldState, newState):
49-
print "exitRed(self, '%s', '%s')" % (oldState, newState)
48+
def exitRed(self):
49+
print "exitRed(self, '%s', '%s')" % (self.oldState, self.newState)
5050

51-
def enterYellow(self, oldState, newState):
52-
print "enterYellow(self, '%s', '%s')" % (oldState, newState)
51+
def enterYellow(self):
52+
print "enterYellow(self, '%s', '%s')" % (self.oldState, self.newState)
5353

5454
def filterYellow(self, request, args):
5555
print "filterYellow(self, '%s', %s)" % (request, args)
5656
if request == 'advance':
5757
return 'Red'
5858
return self.defaultFilter(request, args)
5959

60-
def exitYellow(self, oldState, newState):
61-
print "exitYellow(self, '%s', '%s')" % (oldState, newState)
60+
def exitYellow(self):
61+
print "exitYellow(self, '%s', '%s')" % (self.oldState, self.newState)
6262

63-
def enterGreen(self, oldState, newState):
64-
print "enterGreen(self, '%s', '%s')" % (oldState, newState)
63+
def enterGreen(self):
64+
print "enterGreen(self, '%s', '%s')" % (self.oldState, self.newState)
6565

6666
def filterGreen(self, request, args):
6767
print "filterGreen(self, '%s', %s)" % (request, args)
6868
if request == 'advance':
6969
return 'Yellow'
7070
return self.defaultFilter(request, args)
7171

72-
def exitGreen(self, oldState, newState):
73-
print "exitGreen(self, '%s', '%s')" % (oldState, newState)
72+
def exitGreen(self):
73+
print "exitGreen(self, '%s', '%s')" % (self.oldState, self.newState)
7474

7575

7676
class ToonEyes(FSM.FSM):
@@ -91,7 +91,7 @@ def defaultFilter(self, request, args):
9191
# Unexpected command requests are quietly ignored.
9292
return None
9393

94-
def enterOpen(self, oldState, newState):
94+
def enterOpen(self):
9595
print "swap in eyes open model"
9696

9797
def filterOpen(self, request, args):
@@ -105,18 +105,18 @@ def __unblink(self, task):
105105
self.request('unblink')
106106
return Task.done
107107

108-
def enterClosed(self, oldState, newState):
108+
def enterClosed(self):
109109
print "swap in eyes closed model"
110110

111111
def filterClosed(self, request, args):
112112
if request == 'unblink':
113113
return 'Open'
114114
return self.defaultFilter(request, args)
115115

116-
def enterSurprised(self, oldState, newState):
116+
def enterSurprised(self):
117117
print "swap in eyes surprised model"
118118

119-
def enterOff(self, oldState, newState):
119+
def enterOff(self):
120120
taskMgr.remove(self.__unblinkName)
121121

122122

@@ -127,7 +127,7 @@ def enterOff(self, oldState, newState):
127127
## >>> foo = SampleFSM.ClassicStyle('foo')
128128
## >>> foo.request('Red')
129129
## enterRed(self, 'Off', 'Red')
130-
## 'Red'
130+
## ('Red',)
131131
## >>> foo.request('Yellow')
132132
## Traceback (most recent call last):
133133
## File "<stdin>", line 1, in ?
@@ -141,7 +141,7 @@ def enterOff(self, oldState, newState):
141141
## >>> foo.request('Green')
142142
## exitRed(self, 'Red', 'Green')
143143
## enterGreen(self, 'Red', 'Green')
144-
## 'Green'
144+
## ('Green',)
145145
## >>>
146146

147147
####
@@ -151,27 +151,27 @@ def enterOff(self, oldState, newState):
151151
## >>> foo = SampleFSM.NewStyle('foo')
152152
## >>> foo.request('Red')
153153
## enterRed(self, 'Off', 'Red')
154-
## 'Red'
154+
## ('Red',)
155155
## >>> foo.request('advance')
156156
## filterRed(self, 'advance', ())
157157
## exitRed(self, 'Red', 'Green')
158158
## enterGreen(self, 'Red', 'Green')
159-
## 'Green'
159+
## ('Green',)
160160
## >>> foo.request('advance')
161161
## filterGreen(self, 'advance', ())
162162
## exitGreen(self, 'Green', 'Yellow')
163163
## enterYellow(self, 'Green', 'Yellow')
164-
## 'Yellow'
164+
## ('Yellow',)
165165
## >>> foo.request('advance')
166166
## filterYellow(self, 'advance', ())
167167
## exitYellow(self, 'Yellow', 'Red')
168168
## enterRed(self, 'Yellow', 'Red')
169-
## 'Red'
169+
## ('Red',)
170170
## >>> foo.request('advance')
171171
## filterRed(self, 'advance', ())
172172
## exitRed(self, 'Red', 'Green')
173173
## enterGreen(self, 'Red', 'Green')
174-
## 'Green'
174+
## ('Green',)
175175
## >>>
176176

177177
####
@@ -183,11 +183,11 @@ def enterOff(self, oldState, newState):
183183
## swap in eyes open model
184184
## >>> eyes.request('blink')
185185
## swap in eyes closed model
186-
## 'Closed'
186+
## ('Closed',)
187187
## >>> run()
188188
## swap in eyes open model
189189
## >>> eyes.request('Surprised')
190190
## swap in eyes surprised model
191-
## 'Surprised'
191+
## ('Surprised',)
192192
## >>> eyes.request('blink')
193193
## >>>

0 commit comments

Comments
 (0)