示例#1
0
    def _create_transitions(self, transitions):
        """creates a dictionary of (old state name, new state name): Transition key value pairs"""

        if has_doubles([(t["old_state"], t.get("new_state"))
                        for t in transitions]):
            raise MachineError(
                "two transitions between same states in state machine configuration"
            )

        transition_dict = {}
        transitions = self._expand_transitions(transitions)
        for transition in transitions:
            old_path, new_path = Path(transition["old_state"]), Path(
                transition["new_state"])

            if (old_path, new_path) in transition_dict:
                raise MachineError(
                    "two transitions between same sub_states in state machine")

            if not (old_path.has_in(self) and new_path.has_in(self)):
                raise MachineError(
                    "non-existing state when constructing transitions")

            transition_dict[old_path,
                            new_path] = self.transition_class(machine=self,
                                                              **transition)
        return transition_dict
示例#2
0
 def set_state(self, obj, state):
     """ Executes the transition when called by setting the state: obj.state = 'some_state' """
     if obj.state != state:
         transition = self._get_transition(Path(obj.state), Path(state))
         if not transition:
             raise TransitionError("transition <%s, %s> does not exist" %
                                   (obj.state, state))
         transition.execute(obj)
示例#3
0
 def __getitem__(self, key):
     """
     Gets sub states according to string key or transition according to the 2-tuple (e.g.
         key: ("on.washing", "off.broken"))
     """
     if isinstance(key, str):
         return self.sub_states[key]
     elif isinstance(key, tuple) and len(key) == 2:
         return self.transitions[Path(key[0]), Path(key[1])]
     raise KeyError("key is not a string or 2-tuple")
示例#4
0
 def _create_triggering(self, transitions):
     """creates a dictionary of (old state name/path, trigger name): Transition key value pairs"""
     trigger_dict = defaultdict(list)
     for transition in transitions:
         old_path, new_path = Path(transition["old_state"]), Path(
             transition["new_state"])
         for trigger_name in listify(transition.get("triggers", ())):
             trigger_dict[(old_path,
                           trigger_name)].append(self.transitions[old_path,
                                                                  new_path])
     return self._check_triggering(trigger_dict)
示例#5
0
    def __init__(self,
                 machine=None,
                 on_entry=(),
                 on_exit=(),
                 condition=(),
                 *args,
                 **kwargs):
        """
        Constructor of ChildState:

        :param machine: state machine that contains this state
        :param on_entry: callback(s) that will be called, when an object enters this state
        :param on_exit: callback(s) that will be called, when an object exits this state
        :param condition: callback(s) (all()) that determine whether entry in this state is allowed
        """
        super(State, self).__init__(*args, **kwargs)
        self.machine = machine
        self.on_entry = callbackify(on_entry)
        self.on_exit = callbackify(on_exit)
        self.condition = callbackify(condition) if condition else None
        self.initial_path = Path()
        self.before_entry = []
        self.after_entry = []
        self.before_exit = []
        self.after_exit = []
示例#6
0
 def full_path(self):
     """ returns the path from the top state machine to this state """
     try:
         return self.__full_path
     except AttributeError:
         self.__full_path = Path(reversed([s.name for s in self.iter_up()]))
         return self.__full_path
示例#7
0
 def __init__(self,
              machine,
              old_state,
              new_state,
              on_transfer=(),
              condition=(),
              triggers=(),
              info=""):
     self.machine = machine
     self._validate_states(old_state, new_state)
     self.old_path = Path(old_state)
     self.new_path = Path(new_state)
     self.old_state = self.old_path.get_in(machine)
     self.new_state = self.new_path.get_in(machine)
     self.on_transfer = callbackify(on_transfer)
     self.condition = callbackify(condition) if condition else None
     self.triggers = triggers
     self.info = info
示例#8
0
 def get_initial_path(self, initial=None):
     """ returns the path string to the actual initial state the object will be in """
     try:
         full_initial_path = Path(
             initial
             or ()).get_in(self).get_nested_initial_state().full_path
     except KeyError:
         raise TransitionError("state '%s' does not exist in state '%s'" %
                               (initial, self.name))
     return full_initial_path.tail(self.full_path)
示例#9
0
 def clear_before_entry(self, state):
     """ clears all dynamic (post-construction) callbacks to be called on entry of this or a sub-state"""
     Path(state).get_in(self).before_entry[:] = []
示例#10
0
 def do_enter(self, obj, *args, **kwargs):
     for state in Path(obj.state).tail(self.full_path).iter_in(self):
         state._enter(obj, *args, **kwargs)
示例#11
0
 def do_exit(self, obj, *args, **kwargs):
     for state in Path(obj.state).tail(self.full_path).iter_out(self):
         state._exit(obj, *args, **kwargs)
示例#12
0
 def do_prepare(self, obj, *args, **kwargs):
     for state in Path(obj.state).tail(self.full_path).iter_out(
             self, include=True):
         state.prepare(obj, *args, **kwargs)
示例#13
0
 def trigger(self, obj, trigger, *args, **kwargs):
     """ Executes the transition when called through a trigger """
     for transition in self._get_transitions(Path(obj.state), trigger):
         if transition.execute(obj=obj, *args, **kwargs):
             return True
     return False
示例#14
0
 def inner_trigger(*args, **kwargs):
     for transition in self._get_transitions(Path(obj.state), trigger):
         if transition.execute(obj, *args, **kwargs):
             return True
     return False
示例#15
0
 def clear_after_exit(self, state):
     """ clears all dynamic (post-construction) callbacks to be called on exit of this or a sub-state"""
     Path(state).get_in(self).after_exit[:] = []
示例#16
0
 def add_before_entry(self, state, *callbacks):
     """ adds a dynamic (post-construction) callback to be called on entry of this or a sub-state"""
     Path(state).get_in(self).before_entry.extend(callbacks)
示例#17
0
 def add_after_exit(self, state, *callbacks):
     """ adds a dynamic (post-construction) callback to be called on exit of this or a sub-state"""
     Path(state).get_in(self).after_exit.extend(callbacks)