def _pre_process_event(self, event): current = self._current if current is None: raise excp.NotInitialized("Can not process event '%s'; the state" " machine hasn't been initialized" % event) if self._states[current.name]['terminal']: raise excp.InvalidState("Can not transition from terminal" " state '%s' on event '%s'" % (current.name, event)) if event not in self._transitions[current.name]: raise excp.NotFound("Can not transition from state '%s' on" " event '%s' (no defined transition)" % (current.name, event))
def add_transition(self, start, end, event, replace=False): """Adds an allowed transition from start -> end for the given event. :param start: starting state :param end: ending state :param event: event that causes start state to transition to end state :param replace: replace existing event instead of raising a :py:class:`~automaton.exceptions.Duplicate` exception when the transition already exists. """ if self.frozen: raise excp.FrozenMachine() if start not in self._states: raise excp.NotFound("Can not add a transition on event '%s' that" " starts in a undefined state '%s'" % (event, start)) if end not in self._states: raise excp.NotFound("Can not add a transition on event '%s' that" " ends in a undefined state '%s'" % (event, end)) if self._states[start]['terminal']: raise excp.InvalidState("Can not add a transition on event '%s'" " that starts in the terminal state '%s'" % (event, start)) if event in self._transitions[start] and not replace: target = self._transitions[start][event] if target.name != end: raise excp.Duplicate( "Cannot add transition from" " '%(start_state)s' to '%(end_state)s'" " on event '%(event)s' because a" " transition from '%(start_state)s'" " to '%(existing_end_state)s' on" " event '%(event)s' already exists." % { 'existing_end_state': target.name, 'end_state': end, 'event': event, 'start_state': start }) else: target = _Jump(end, self._states[end]['on_enter'], self._states[start]['on_exit']) self._transitions[start][event] = target
def initialize(self, start_state=None): """Sets up the state machine (sets current state to start state...). :param start_state: explicit start state to use to initialize the state machine to. If ``None`` is provided then the machine's default start state will be used instead. """ if start_state is None: start_state = self._default_start_state if start_state not in self._states: raise excp.NotFound("Can not start from a undefined" " state '%s'" % (start_state)) if self._states[start_state]['terminal']: raise excp.InvalidState("Can not start from a terminal" " state '%s'" % (start_state)) # No on enter will be called, since we are priming the state machine # and have not really transitioned from anything to get here, we will # though allow on_exit to be called on the event that causes this # to be moved from... self._current = _Jump(start_state, None, self._states[start_state]['on_exit'])