I am using Fysom to create FSM. I want to use callbacks in an other way:
TABLE = {
'initial': 'OFF',
'events': [{'name': 'load', 'src': 'OFF', 'dst': 'LOADED'},],
'callbacks': {'onload': myfunction,}}
fsm = Fysom(TABLE)
Here if I launch fsm.onload()
it will execute myfunction
. Instead I want If I launch myfunction()
it will lunch fsm.onload()
.
I took a look on the script and related part is here:
def _enter_state(self, e):
'''
Executes the callback for onenter_state_ or on_state_.
'''
for fnname in ['onenter' + e.dst, 'on' + e.dst]:
if hasattr(self, fnname):
return getattr(self, fnname)(e)
I don't see how to change this peace of code for my purpose.
You cannot implement callbacks "in the other direction" without touching myfunction
.
A callback is actually an inverted call (hollywood principle), so the inverse of a callback is a simple call.
What this means is that myfunction
should call the state machine transition directly. As a consequence, the state machine object must be in the scope of myfunction
.
At this point you have some possibilities for implementation :
Have myfunction
be a closure :
def outer():
fsm = Fysom(TABLE)
def myfunction():
print("I call the state machine transition when called")
fsm.onload()
return fsm
Use a global state machine or scope it in a class :
class Foo(object):
def __init__(self):
self.fsm = Fysom(TABLE)
def my_method(self):
self.fsm.onload()
Create a decorator that calls the state transition method before/after executing the function. Then decorate away with
fsm = Fysom(TABLE)
@transition(fsm, "onload")
def myfunction():
pass
Note that this also requires fsm
to be defined in this scope.