I am not aware of a convenient way to store the actual model and its function in YAML/JSON. I assume that the workflow you mentioned just stores the function names in JSON like this:
{
"states": ["A", "B", "C"],
"initial": "A",
"transitions": [
{"trigger": "go", "source": "A", "dest": "B", "after": "func_A"},
{"trigger": "go", "source": "B", "dest": "C", "after": "func_B"}
]
}
or YAML:
---
initial: A
states:
- A
- B
- C
transitions:
-
after: func_A
dest: B
source: A
trigger: go
-
after: func_B
dest: C
source: B
trigger: go
When you store callbacks as Strings they will be evaluated the moment, the Event (in this case go
) is triggered. Let's assume we have loaded the JSON/YAML above into a Python dictionary called d
. When the dict keys are identical to transitions
keywords, you can initialise a model like this:
from transitions import Machine
class Model:
def func_A(self):
print("func A")
def func_B(self):
print("func B")
model = Model()
m = Machine(model, **d)
model.go()
model.go()
You could add a description field model
to your YAML which specifies which model class to load (e.g. 'module.models.TestModel') and import the model definition dynamically with importlib
. Or you can define the required model implicitly (e.g. REST endpoint '/TestModel' initialises a TestModel).
If you really want to store your model class definition in YAML, you may serialise the class definition with pickle/dill:
d["model"] = pickle.dumps(Model)
SerialisedModel = pickle.loads(d.pop("model"))
model = SerialisedModel()
m = Machine(model, **d)
If you just want to store the current state, you can serialise your Machine
instance directly:
d["machine_object"] = pickle.dumps(m)
This is way less transparent than the previous approach though.
In any case you should avoid defining callbacks with function references since this might lead to problems later on. Maybe pickle/dill can handle this as well but I would not count on it.
More sophisticated solutions have been proposed by Dave Kuhlmann here. His post includes approaches to a) export an FSM to JSON (Machine -> JSON), b) generate Python FSM code from JSON and c) inject an FSM into a class from JSON. All of this should be easily transferable to YAML.