1
- from threading import Lock
2
1
from typing import TYPE_CHECKING
3
- from weakref import proxy
4
2
5
3
from ..event_data import EventData
6
4
from ..event_data import TriggerData
7
5
from ..exceptions import TransitionNotAllowed
8
- from ..state import State
9
- from ..transition import Transition
6
+ from .base import BaseEngine
10
7
11
8
if TYPE_CHECKING :
12
- from ..statemachine import StateMachine
9
+ from ..transition import Transition
13
10
14
11
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 ()
22
15
self .activate_initial_state ()
23
16
24
17
def activate_initial_state (self ):
@@ -54,7 +47,7 @@ def processing_loop(self):
54
47
"""
55
48
if not self ._rtc :
56
49
# The machine is in "synchronous" mode
57
- trigger_data = self .sm . _external_queue .popleft ()
50
+ trigger_data = self ._external_queue .popleft ()
58
51
return self ._trigger (trigger_data )
59
52
60
53
# We make sure that only the first event enters the processing critical section,
@@ -68,74 +61,72 @@ def processing_loop(self):
68
61
first_result = self ._sentinel
69
62
try :
70
63
# 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 ()
73
66
try :
74
67
result = self ._trigger (trigger_data )
75
68
if first_result is self ._sentinel :
76
69
first_result = result
77
70
except Exception :
78
71
# Whe clear the queue as we don't have an expected behavior
79
72
# and cannot keep processing
80
- self .sm . _external_queue .clear ()
73
+ self ._external_queue .clear ()
81
74
raise
82
75
finally :
83
76
self ._processing .release ()
84
77
return first_result if first_result is not self ._sentinel else None
85
78
86
79
def _trigger (self , trigger_data : TriggerData ):
87
- event_data = None
80
+ executed = False
88
81
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 )
93
84
return self ._sentinel
94
85
95
86
state = self .sm .current_state
96
87
for transition in state .transitions :
97
88
if not transition .match (trigger_data .event ):
98
89
continue
99
90
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 :
104
93
continue
105
94
106
- result = self ._activate (event_data )
107
- event_data .result = result
108
- event_data .executed = True
109
95
break
110
96
else :
111
97
if not self .sm .allow_event_without_transition :
112
98
raise TransitionNotAllowed (trigger_data .event , state )
113
99
114
- return event_data . result if event_data else None
100
+ return result if executed else None
115
101
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 )
117
104
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
120
111
target = transition .target
121
112
122
- result = self .sm ._callbacks_registry .call (transition .before .key , * args , ** kwargs )
113
+ result = self .sm ._callbacks .call (transition .before .key , * args , ** kwargs )
123
114
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 )
125
116
126
- result += self .sm ._callbacks_registry .call (transition .on .key , * args , ** kwargs )
117
+ result += self .sm ._callbacks .call (transition .on .key , * args , ** kwargs )
127
118
128
119
self .sm .current_state = target
129
120
event_data .state = target
130
121
kwargs ["state" ] = target
131
122
132
123
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 )
135
126
136
127
if len (result ) == 0 :
137
128
result = None
138
129
elif len (result ) == 1 :
139
130
result = result [0 ]
140
131
141
- return result
132
+ return True , result
0 commit comments