@@ -53,22 +53,22 @@ def __call__(self, *args, **kwargs):
5353
5454class Transition (object ):
5555
56- def __init__ (self , source , destination , key = None , validators = None ):
56+ def __init__ (self , source , destination , identifier = None , validators = None ):
5757 self .source = source
5858 self .destination = destination
59- self .key = key
59+ self .identifier = identifier
6060 self .validators = validators or []
6161
6262 def __repr__ (self ):
63- return "{}({!r}, {!r}, key ={!r})" .format (
64- type (self ).__name__ , self .source , self .destination , self .key )
63+ return "{}({!r}, {!r}, identifier ={!r})" .format (
64+ type (self ).__name__ , self .source , self .destination , self .identifier )
6565
6666 def __or__ (self , other ):
67- return CombinedTransition (self , other , key = self .key )
67+ return CombinedTransition (self , other , identifier = self .identifier )
6868
69- def __contribute_to_class__ (self , managed , key ):
69+ def __contribute_to_class__ (self , managed , identifier ):
7070 self .managed = managed
71- self .key = key
71+ self .identifier = identifier
7272
7373 def __get__ (self , instance , owner ):
7474 def callable (* args , ** kwargs ):
@@ -85,7 +85,12 @@ def _can_run(self, instance):
8585
8686 def _run (self , instance , * args , ** kwargs ):
8787 if not self ._can_run (instance ):
88- raise LookupError (_ ("Transition is not supported." ))
88+ raise LookupError (
89+ _ ("Can't {} when in {}." ).format (
90+ self .identifier ,
91+ instance .current_state .name
92+ )
93+ )
8994
9095 self ._validate (* args , ** kwargs )
9196 return instance ._activate (self , * args , ** kwargs )
@@ -105,17 +110,22 @@ def _left(self):
105110 def _right (self ):
106111 return self .destination
107112
108- def __contribute_to_class__ (self , managed , key ):
109- super (CombinedTransition , self ).__contribute_to_class__ (managed , key )
110- self ._left .__contribute_to_class__ (managed , key )
111- self ._right .__contribute_to_class__ (managed , key )
113+ def __contribute_to_class__ (self , managed , identifier ):
114+ super (CombinedTransition , self ).__contribute_to_class__ (managed , identifier )
115+ self ._left .__contribute_to_class__ (managed , identifier )
116+ self ._right .__contribute_to_class__ (managed , identifier )
112117
113118 def _can_run (self , instance ):
114119 return instance .current_state in [self ._left .source , self ._right .source ]
115120
116121 def _run (self , instance , * args , ** kwargs ):
117122 if not self ._can_run (instance ):
118- raise LookupError (_ ("Transition is not supported." ))
123+ raise LookupError (
124+ _ ("Can't {} when in {}." ).format (
125+ self .identifier ,
126+ instance .current_state .name
127+ )
128+ )
119129
120130 self ._validate (* args , ** kwargs )
121131 transition = self ._left if instance .current_state == self ._left .source else self ._right
@@ -184,11 +194,19 @@ def __init__(cls, name, bases, attrs):
184194 cls .states_map = {s .value : s for s in cls .states }
185195
186196
197+ class Model (object ):
198+ state = None
199+
200+ def __repr__ (self ):
201+ return 'Model(state={})' .format (self .state )
202+
203+
187204class BaseStateMachine (object ):
188205
189- def __init__ (self , model , state_field = 'state' ):
190- self .model = model
206+ def __init__ (self , model = None , state_field = 'state' , start_value = None ):
207+ self .model = model if model else Model ()
191208 self .state_field = state_field
209+ self .start_value = start_value
192210
193211 self .check ()
194212
@@ -214,7 +232,10 @@ def check(self):
214232 self .initial_state = initials [0 ]
215233
216234 if self .current_state_value is None :
217- self .current_state_value = self .initial_state .value
235+ if self .start_value :
236+ self .current_state_value = self .start_value
237+ else :
238+ self .current_state_value = self .initial_state .value
218239
219240 @property
220241 def current_state_value (self ):
@@ -223,7 +244,7 @@ def current_state_value(self):
223244 @current_state_value .setter
224245 def current_state_value (self , value ):
225246 if value not in self .states_map :
226- raise Exception (_ ("{!r} is not a valid state value." ).format (value ))
247+ raise ValueError (_ ("{!r} is not a valid state value." ).format (value ))
227248 setattr (self .model , self .state_field , value )
228249
229250 @property
@@ -234,7 +255,7 @@ def current_state(self):
234255 def allowed_transitions (self ):
235256 "get the callable proxy of the current allowed transitions"
236257 return [
237- getattr (self , t .key )
258+ getattr (self , t .identifier )
238259 for t in self .current_state .transitions if t ._can_run (self )
239260 ]
240261
@@ -243,19 +264,20 @@ def current_state(self, value):
243264 self .current_state_value = value .value
244265
245266 def _activate (self , transition , * args , ** kwargs ):
246- on_event = getattr (self , 'on_{}' .format (transition .key ), None )
267+ on_event = getattr (self , 'on_{}' .format (transition .identifier ), None )
247268 result = on_event (* args , ** kwargs ) if callable (on_event ) else None
248269 self .current_state = transition .destination
249270 return result
250271
251- def get_transition (self , transition_key ):
252- transition = getattr (self , transition_key , None )
272+ def get_transition (self , transition_identifier ):
273+ transition = getattr (self , transition_identifier , None )
253274 if not hasattr (transition , 'source' ) or not callable (transition ):
254- raise ValueError ('{!r} is not a valid transition key' .format (transition_key ))
275+ raise ValueError (
276+ '{!r} is not a valid transition identifier' .format (transition_identifier ))
255277 return transition
256278
257- def run (self , transition_key , * args , ** kwargs ):
258- transition = self .get_transition (transition_key )
279+ def run (self , transition_identifier , * args , ** kwargs ):
280+ transition = self .get_transition (transition_identifier )
259281 return transition (* args , ** kwargs )
260282
261283
0 commit comments