statelyai/xstate-python

How to detect if an event fired no transition ?

Aluriak opened this issue · 1 comments

Hello !

I have a question on states that can't transition following an event. Let me use the basic example, with a simpler main:

from xstate.machine import Machine
import time


# Trafic light example
# green -> yellow -> red -> green ..

lights = Machine(
    {
        "id": "lights",
        "initial": "green",
        "states": {
            "green": {"on": {"TIMER": "yellow"},},
            "yellow": {"on": {"TIMER": "red"}},
            "red": {"on": {"TIMER": "green"}},
        },
    }
)

if __name__ == "__main__":
    state = lights.initial_state
    state = lights.transition(state, "_____")   # that event is not valid
    print(state.value)

    state = lights.transition(state, "TIMER")
    print(state.value)

We obtain the following output (first line as per #25 ) :

{'event': None, 'source': 'lights', 'target': ['#lights.green'], 'cond': None, 'actions': [], 'type': 'external', 'order': -1}
green
yellow

We can see that, when a event is fired but can't be accepted, the returned state equals the input state.

Questions:

  • is that xstate defined behavior ? I would expect None to be returned.
  • it seems to me that a state with an event looping on itself would have the same behavior, hence
  • how can i decide (without parsing the scxml myself) whether a state is looping on itself or if there is no possible transition ?

If not already possible, i think this package should expose a predicate in Machine API, such as can_transition(state, event) -> bool, which returns True if that configuration can perform a transition (either there is a loop, or a new reached state).

That is expected behaviour and a pretty central part of state charts. For each state you explicit which events to react upon - all other events will simply be ignored and the state will therefore stay the same.

I suggest taking a look at the XState JS Docs