1111from .callbacks import CallbackSpecList
1212from .event import Event
1313from .exceptions import InvalidDefinition
14+ from .graph import disconnected_states
1415from .graph import iterate_states
1516from .graph import iterate_states_and_transitions
16- from .graph import visit_connected_states
17+ from .graph import states_without_path_to_final_states
1718from .i18n import _
1819from .state import State
1920from .states import States
2425class StateMachineMetaclass (type ):
2526 "Metaclass for constructing StateMachine classes"
2627
28+ validate_disconnected_states : bool = True
29+ """If `True`, the state machine will validate that there are no unreachable states."""
30+
2731 def __init__ (
2832 cls ,
2933 name : str ,
@@ -179,7 +183,7 @@ def _check_trap_states(cls):
179183 def _check_reachable_final_states (cls ):
180184 if not any (s .final for s in cls .states ):
181185 return # No need to check final reachability
182- disconnected_states = cls ._states_without_path_to_final_states ( )
186+ disconnected_states = list ( states_without_path_to_final_states ( cls .states ) )
183187 if disconnected_states :
184188 message = _ (
185189 "All non-final states should have at least one path to a final state. "
@@ -190,26 +194,18 @@ def _check_reachable_final_states(cls):
190194 else :
191195 warnings .warn (message , UserWarning , stacklevel = 1 )
192196
193- def _states_without_path_to_final_states (cls ):
194- return [
195- state
196- for state in cls .states
197- if not state .final and not any (s .final for s in visit_connected_states (state ))
198- ]
199-
200- def _disconnected_states (cls , starting_state ):
201- visitable_states = set (visit_connected_states (starting_state ))
202- return set (cls .states ) - visitable_states
203-
204197 def _check_disconnected_state (cls ):
205- disconnected_states = cls ._disconnected_states (cls .initial_state )
206- if disconnected_states :
198+ if not cls .validate_disconnected_states :
199+ return
200+ assert cls .initial_state
201+ states = disconnected_states (cls .initial_state , set (cls .states_map .values ()))
202+ if states :
207203 raise InvalidDefinition (
208204 _ (
209205 "There are unreachable states. "
210206 "The statemachine graph should have a single component. "
211207 "Disconnected states: {}"
212- ).format ([s .id for s in disconnected_states ])
208+ ).format ([s .id for s in states ])
213209 )
214210
215211 def _setup (cls ):
0 commit comments