1- from threading import Lock
21from typing import TYPE_CHECKING
3- from weakref import proxy
42
53from ..event_data import EventData
64from ..event_data import TriggerData
75from ..exceptions import TransitionNotAllowed
8- from ..state import State
9- from ..transition import Transition
6+ from .base import BaseEngine
107
118if TYPE_CHECKING :
12- from ..statemachine import StateMachine
9+ from ..transition import Transition
1310
1411
15- class SyncEngine :
16- def __init__ (self , sm : "StateMachine" , rtc : bool = True ):
17- sm ._engine = self
18- self .sm = proxy (sm )
19- self ._sentinel = object ()
20- self ._rtc = rtc
21- self ._processing = Lock ()
12+ class SyncEngine (BaseEngine ):
13+ def start (self ):
14+ super ().start ()
2215 self .activate_initial_state ()
2316
2417 def activate_initial_state (self ):
@@ -54,7 +47,7 @@ def processing_loop(self):
5447 """
5548 if not self ._rtc :
5649 # The machine is in "synchronous" mode
57- trigger_data = self .sm . _external_queue .popleft ()
50+ trigger_data = self ._external_queue .popleft ()
5851 return self ._trigger (trigger_data )
5952
6053 # We make sure that only the first event enters the processing critical section,
@@ -68,74 +61,72 @@ def processing_loop(self):
6861 first_result = self ._sentinel
6962 try :
7063 # Execute the triggers in the queue in FIFO order until the queue is empty
71- while self .sm . _external_queue :
72- trigger_data = self .sm . _external_queue .popleft ()
64+ while self ._external_queue :
65+ trigger_data = self ._external_queue .popleft ()
7366 try :
7467 result = self ._trigger (trigger_data )
7568 if first_result is self ._sentinel :
7669 first_result = result
7770 except Exception :
7871 # Whe clear the queue as we don't have an expected behavior
7972 # and cannot keep processing
80- self .sm . _external_queue .clear ()
73+ self ._external_queue .clear ()
8174 raise
8275 finally :
8376 self ._processing .release ()
8477 return first_result if first_result is not self ._sentinel else None
8578
8679 def _trigger (self , trigger_data : TriggerData ):
87- event_data = None
80+ executed = False
8881 if trigger_data .event == "__initial__" :
89- transition = Transition (State (), self .sm ._get_initial_state (), event = "__initial__" )
90- transition ._specs .clear ()
91- event_data = EventData (trigger_data = trigger_data , transition = transition )
92- self ._activate (event_data )
82+ transition = self ._initial_transition (trigger_data )
83+ self ._activate (trigger_data , transition )
9384 return self ._sentinel
9485
9586 state = self .sm .current_state
9687 for transition in state .transitions :
9788 if not transition .match (trigger_data .event ):
9889 continue
9990
100- event_data = EventData (trigger_data = trigger_data , transition = transition )
101- args , kwargs = event_data .args , event_data .extended_kwargs
102- self .sm ._callbacks_registry .call (transition .validators .key , * args , ** kwargs )
103- if not self .sm ._callbacks_registry .all (transition .cond .key , * args , ** kwargs ):
91+ executed , result = self ._activate (trigger_data , transition )
92+ if not executed :
10493 continue
10594
106- result = self ._activate (event_data )
107- event_data .result = result
108- event_data .executed = True
10995 break
11096 else :
11197 if not self .sm .allow_event_without_transition :
11298 raise TransitionNotAllowed (trigger_data .event , state )
11399
114- return event_data . result if event_data else None
100+ return result if executed else None
115101
116- def _activate (self , event_data : EventData ):
102+ def _activate (self , trigger_data : TriggerData , transition : "Transition" ):
103+ event_data = EventData (trigger_data = trigger_data , transition = transition )
117104 args , kwargs = event_data .args , event_data .extended_kwargs
118- transition = event_data .transition
119- source = event_data .state
105+
106+ self .sm ._callbacks .call (transition .validators .key , * args , ** kwargs )
107+ if not self .sm ._callbacks .all (transition .cond .key , * args , ** kwargs ):
108+ return False , None
109+
110+ source = transition .source
120111 target = transition .target
121112
122- result = self .sm ._callbacks_registry .call (transition .before .key , * args , ** kwargs )
113+ result = self .sm ._callbacks .call (transition .before .key , * args , ** kwargs )
123114 if source is not None and not transition .internal :
124- self .sm ._callbacks_registry .call (source .exit .key , * args , ** kwargs )
115+ self .sm ._callbacks .call (source .exit .key , * args , ** kwargs )
125116
126- result += self .sm ._callbacks_registry .call (transition .on .key , * args , ** kwargs )
117+ result += self .sm ._callbacks .call (transition .on .key , * args , ** kwargs )
127118
128119 self .sm .current_state = target
129120 event_data .state = target
130121 kwargs ["state" ] = target
131122
132123 if not transition .internal :
133- self .sm ._callbacks_registry .call (target .enter .key , * args , ** kwargs )
134- self .sm ._callbacks_registry .call (transition .after .key , * args , ** kwargs )
124+ self .sm ._callbacks .call (target .enter .key , * args , ** kwargs )
125+ self .sm ._callbacks .call (transition .after .key , * args , ** kwargs )
135126
136127 if len (result ) == 0 :
137128 result = None
138129 elif len (result ) == 1 :
139130 result = result [0 ]
140131
141- return result
132+ return True , result
0 commit comments