@@ -21,6 +21,57 @@ A {ref}`StateMachine` should have one and only one `initial` {ref}`state`.
2121The initial {ref}` state ` is entered when the machine starts and the corresponding entering
2222state {ref}` actions ` are called if defined.
2323
24+ ## State Transitions
25+
26+ All states should have at least one transition to and from another state.
27+
28+ If any states are unreachable from the initial state, an ` InvalidDefinition ` exception will be thrown.
29+
30+ ``` py
31+ >> > from statemachine import StateMachine, State
32+
33+ >> > class TrafficLightMachine (StateMachine ):
34+ ... " A workflow machine"
35+ ... red = State(' Red' , initial = True , value = 1 )
36+ ... green = State(' Green' , value = 2 )
37+ ... orange = State(' Orange' , value = 3 )
38+ ... hazard = State(' Hazard' , value = 4 )
39+ ...
40+ ... cycle = red.to(green) | green.to(orange) | orange.to(red)
41+ ... blink = hazard.to.itself()
42+ Traceback (most recent call last):
43+ ...
44+ InvalidDefinition: There are unreachable states. The statemachine graph should have a single component. Disconnected states: [' hazard' ]
45+ ```
46+
47+ ` StateMachine ` will also check that all non-final states have an outgoing transition, and warn you if any states would result in
48+ the statemachine becoming trapped in a non-final state with no further transitions possible.
49+
50+ ``` {note}
51+ This will currently issue a warning, but can be turned into an exception by setting `strict_states=True` on the class.
52+ ```
53+
54+ ``` py
55+ >> > from statemachine import StateMachine, State
56+
57+ >> > class TrafficLightMachine (StateMachine , strict_states = True ):
58+ ... " A workflow machine"
59+ ... red = State(' Red' , initial = True , value = 1 )
60+ ... green = State(' Green' , value = 2 )
61+ ... orange = State(' Orange' , value = 3 )
62+ ... hazard = State(' Hazard' , value = 4 )
63+ ...
64+ ... cycle = red.to(green) | green.to(orange) | orange.to(red)
65+ ... fault = red.to(hazard) | green.to(hazard) | orange.to(hazard)
66+ Traceback (most recent call last):
67+ ...
68+ InvalidDefinition: All non- final states should have at least one outgoing transition. These states have no outgoing transition: [' hazard' ]
69+ ```
70+
71+ ``` {warning}
72+ `strict_states=True` will become the default behaviour in future versions.
73+ ```
74+
2475
2576(final-state)=
2677## Final state
@@ -47,7 +98,35 @@ InvalidDefinition: Cannot declare transitions from final state. Invalid state(s)
4798
4899```
49100
50- You can retrieve all final states.
101+ If you mark any states as final, ` StateMachine ` will check that all non-final states have a path to reach at least one final state.
102+
103+ ``` {note}
104+ This will currently issue a warning, but can be turned into an exception by setting `strict_states=True` on the class.
105+ ```
106+
107+ ``` py
108+ >> > class CampaignMachine (StateMachine , strict_states = True ):
109+ ... " A workflow machine"
110+ ... draft = State(' Draft' , initial = True , value = 1 )
111+ ... producing = State(' Being produced' , value = 2 )
112+ ... abandoned = State(' Abandoned' , value = 3 )
113+ ... closed = State(' Closed' , final = True , value = 4 )
114+ ...
115+ ... add_job = draft.to.itself() | producing.to.itself()
116+ ... produce = draft.to(producing)
117+ ... abandon = producing.to(abandoned) | abandoned.to(abandoned)
118+ ... deliver = producing.to(closed)
119+ Traceback (most recent call last):
120+ ...
121+ InvalidDefinition: All non- final states should have at least one path to a final state. These states have no path to a final state: [' abandoned' ]
122+
123+ ```
124+
125+ ``` {warning}
126+ `strict_states=True` will become the default behaviour in future versions.
127+ ```
128+
129+ You can query a list of all final states from your statemachine.
51130
52131``` py
53132>> > class CampaignMachine (StateMachine ):
@@ -65,6 +144,9 @@ You can retrieve all final states.
65144>> > machine.final_states
66145[State(' Closed' , id = ' closed' , value = 3 , initial = False , final = True )]
67146
147+ >> > machine.current_state in machine.final_states
148+ False
149+
68150```
69151
70152## States from Enum types
0 commit comments