Closed thedrow closed 3 years ago
@thedrow
{'after': ['start']
- 'after' cannot be a list, only str or callable object
TypeError: can only concatenate str (not "list") to str
There seems to be an issue with the resolving the names as @pkonnov points out. I maybe found another bug which is triggered when a state is added during on_enter/exit callbacks. I fixed that one in b8540bc. This works now:
from transitions.extensions.factory import HierarchicalGraphMachine
class Model:
def __init__(self):
self.machine = HierarchicalGraphMachine(self, states=['A', 'B'], initial='A')
def on_enter_B(self):
child_1 = HierarchicalGraphMachine.state_cls(name='a')
child_2 = HierarchicalGraphMachine.state_cls(name='b')
child_3 = HierarchicalGraphMachine.state_cls(name='c')
state = HierarchicalGraphMachine.state_cls(name='C', initial=['a', 'b', 'c'])
state.add_substate([child_1, child_2, child_3])
self.machine.add_state(state)
self.to_C()
model = Model()
model.to_B()
assert model.state == ['C_a', 'C_b', 'C_c']
model.get_graph().draw('test.png', prog='dot')
However, this might be unrelated to the bug you found.
Ah wait, I misread @pkonnov answer. I think it should be possible to use list of strings/callables in any callback property.
@aleneum yes, i also think that this is not related
So either dst=transition['dest']
or src=transition['source']
seems to be a list even though it shouldnt. I cannot reproduce this though. Could you boil it down to a minimal example?
The parameter of this look weird:
> state_machine.add_transition(
f"run_{name}",
state_machine.actor_state.started,
[_get_task_state_name(name, TaskState.initialized), state_machine.actor_state.started.name],
after=[f"run_{name}"],
)
dest
seems to be a list:
self = <jumpstarter.states.ActorStateMachine object at 0x7fcda7d1c190>
trigger = 'run_foo', source = <ActorState.started: 3>
dest = ['foo_task↦initialized', 'started'], conditions = None, unless = None
A transition's dest
cannot be a list.
So maybe I'm getting something wrong. Can't I enter two parallel states? Do I need two different state machines?
Let's clarify the question: I can transition from multiple states to one state but I can't transition from one state to multiple states?
So maybe I'm getting something wrong. Can't I enter two parallel states?
if you refering to two different states then the answer is no. You can only use one destination right now. This state, however, can of course enter it's children in parallel where children's themselves might enter their children in parallel. When you set the destination to be a child, its siblings will not be entered. When I reworked the HSM, I actually tried to go that route (multiple dests mean parallel states) but hit a dead end somewhere.
Let's clarify the question: I can transition from multiple states to one state but I can't transition from one state to multiple states?
When you specifiy multiple sources, transitions
will actually create one transition for each source. A wildcard (*
) will be converted into N transitions where N is the number of root states your machine is currently aware off. The same procedure would not work with dest
since creating multiple dests for one source would always result in a set of transitions where only the first once can theoretically be executed. E.g dict(trigger=go, source='A', dest=['B', 'C'])
will always transition to B
(if you have some conditions like 'is_C' you should consider splitting your definitions.) There have been some discussions about conditional destinations in the issue tracker (for instance here).
Furthermore, the machine does not transition from multiple states to one state but only choses the transition with the currently most fitting source (e.g. dict(trigger='go', source=['A', 'B'], dest='C')
will only exit the state, the model is currently in). It is then evaluated which substates need to be exited based on the current model state and the transition's destination. If that transition cannot be executed for some reason, the trigger is delegated. I wrote something about the execution order here.
But a state machine should be able to enter multiple parallel states even if they are not the initial states, no?
I need to be able to model transitions from multiple states to multiple states. I now understand that's currently not supported and possibly hard to implement but I didn't understand it from the documentation at all. Should I open an issue about it?
But a state machine should be able to enter multiple parallel states even if they are not the initial states, no?
I agree, that this would be quite nice to have. That's why I tried to implement it. Without success though :(. Since parallel state support is quite rare across most FSM implementations I know, I opted to have limited parallel state support in transitions
rather than None
. Unfortunately, I cannot give a reliable ETA as I have no time resources to tackle that issue. I created an issue for that (#507) though just in case someone has the resources and nerves to approach that issue.
I now understand that's currently not supported and possibly hard to implement but I didn't understand it from the documentation at all.
I am sorry to hear that there has been some confusion. Some features are not documented as they should be but if something like dict(trigger='go', source='A', dest=['B', 'C'])
would be possible, I'd totally brag about this in the README. Well, one day I/we might can...
Closing this as it currently does not qualify as a bug. A separate feature request has been created.