Transitions and events¶
A machine moves from state to state through transitions. These transitions are caused by events.
Event¶
An event is an external signal that something has happened. They are sent to a state machine, and allow the state machine to react.
An event start a Transition, can be thought of as a “cause” that initiates a change in the state of the system.
In python-statemachine, an event is specified as an attribute of the
statemachine class declaration, or diretly on the event
parameter on
a Transition.
Transition¶
In an executing state machine, a transition is the instantaneous transfer from one state to another. In a state machine, a transition tells us what happens when an Event occurs.
A self transition is a transition that goes from and to the same state.
A transition can define actions that will be executed whenever that transition is executed.
- class statemachine.transition.Transition(source, target, event=None, validators=None, cond=None, unless=None, on=None, before=None, after=None)[source]¶
A transition holds reference to the source and target state.
- Parameters
source (State) – The origin state of the transition.
target (State) – The target state of the transition.
event (Optional[Union[str, List[str]]]) – List of designators of events that trigger this transition. Can be either a list of strings, or a space-separated string list of event descriptors.
validators (Optional[Union[str, Callable, List[Callable]]]) – The validation callbacks to be invoked before the transition is executed.
cond (Optional[Union[str, Callable, List[Callable]]]) – The condition callbacks to be invoked before the transition is executed that should evaluate to True.
unless (Optional[Union[str, Callable, List[Callable]]]) – The condition callbacks to be invoked if the cond is False before the transition is executed.
on (Optional[Union[str, Callable, List[Callable]]]) – The callbacks to be invoked when the transition is executed.
before (Optional[Union[str, Callable, List[Callable]]]) – The callbacks to be invoked before the transition is executed.
after (Optional[Union[str, Callable, List[Callable]]]) – The callbacks to be invoked after the transition is executed.
Self transition¶
A transition that goes from a state to itself.
Syntax:
>>> draft = State("Draft")
>>> draft.to.itself()
TransitionList([Transition(State('Draft', ...
Example¶
Consider this traffic light machine as example:
There’re tree transitions, one starting from green to yellow, another from
yellow to red, and another from red back to green. All these transitions
are triggered by the same Event called cycle
.
This statemachine could be expressed in python-statemachine as:
1"""
2Traffic light machine
3---------------------
4
5Demonstrates the concept of ``cycle`` states.
6
7"""
8from statemachine import State
9from statemachine import StateMachine
10
11
12class TrafficLightMachine(StateMachine):
13 "A traffic light machine"
14 green = State("Green", initial=True)
15 yellow = State("Yellow")
16 red = State("Red")
17
18 cycle = green.to(yellow) | yellow.to(red) | red.to(green)
19
20 def on_cycle(self, event_data=None):
21 return "Running {} from {} to {}".format(
22 event_data.event,
23 event_data.source.id,
24 event_data.target.id,
25 )
At line 18, you can say that this code defines three transitions:
green.to(yellow)
yellow.to(red)
red.to(green)
And these transitions are assigned to the Event cycle
defined at
class level.
When an Event is sent to a stamemachine:
Uses the current State to check for available transitions.
For each possible transition, it checks for those that matches the received Event.
The target state, if the transition succeeds, is determined by a transisition that an event matches and;
All Validators and guards, including Actions atached to the
on_<event>
andbefore_<event>
callbacks.
Triggering events¶
By direct calling the event:
>>> machine = TrafficLightMachine()
>>> machine.cycle()
'Running cycle from green to yellow'
>>> machine.current_state.id
'yellow'
In a running (interpreted) machine, events are sent
:
>>> machine.send("cycle")
'Running cycle from yellow to red'
>>> machine.current_state.id
'red'
You can also pass positional and keyword arguments, that will be propagated
to the actions. On this example, the :code:TrafficLightMachine
implements
an action that echoes
back the params informed.
1class TrafficLightMachine(StateMachine):
2 "A traffic light machine"
3 green = State("Green", initial=True)
4 yellow = State("Yellow")
This action is executed before the transition associated with cycle
event is activated, so you
can also raise an exception at this point to stop a transition to occur.
>>> machine.current_state.id
'red'
>>> machine.cycle()
'Running cycle from red to green'
>>> machine.current_state.id
'green'