Пример #1
0
    class state_info(object):
        """
        An extra object that hijacks the actual state methods.
        """
        @property
        def name(si_self):
            """
            The name of the current state
            """
            return getattr(self, field)

        @property
        def description(si_self):
            """
            The description of the current state
            """
            si = machine.get_state(getattr(self, field))
            return si.description

        @property
        def in_group(si_self):
            """
            In what groups is this state? It's a dictionary that will return
            ``True`` for the state groups that this state is in.
            """
            return machine.get_state_groups(getattr(self, field))

        def possible_transitions(si_self):
            """
            Return list of transitions which can be made from the current
            state.
            """
            for name in machine.transitions:
                t = machine.transitions[name]
                if getattr(self, field) in t.from_states:
                    yield t

        def test_transition(si_self, transition, user=None):
            """
            Check whether we could execute this transition.

            :param str transition: the transition name
            :param user: the user that will execute the transition. Used for
                permission checking
            :type: :class:`django.contrib.auth.models.User` or ``None``

            :returns:``True`` when we expect this transition to be executed
                successfully. It will raise an ``Exception`` when this
                transition is impossible or not allowed.
            """
            # Transition name should be known
            if not machine.has_transition(transition):
                raise UnknownTransition(self, transition)

            t = machine.get_transitions(transition)

            if getattr(self, field) not in t.from_states:
                raise TransitionCannotStart(self, transition)

            # User should have permissions for this transition
            if user and not t.has_permission(self, user):
                raise PermissionDenied(self, transition, user)

            # Transition should validate
            validation_errors = list(t.validate(self))
            if validation_errors:
                raise TransitionNotValidated(si_self, transition,
                                             validation_errors)

            return True

        def make_transition(si_self, transition, user=None, **kwargs):
            """
            Executes state transition.

            :param str transition: the transition name
            :param user: the user that will execute the transition. Used for
                permission checking
            :type: :class:`django.contrib.auth.models.User` or ``None``
            :param dict kwargs: the kwargs that will be passed to
                :meth:`~django_states.machine.StateTransition.handler`
            """
            # Transition name should be known
            if not machine.has_transition(transition):
                raise UnknownTransition(self, transition)
            t = machine.get_transitions(transition)

            _state_log_model = getattr(self, '_%s_log_model' % field, None)

            # Start transition log
            if _state_log_model:
                # Try to serialize kwargs, for the log. Save null
                # when it's not serializable.
                try:
                    serialized_kwargs = json.dumps(kwargs)
                except TypeError:
                    serialized_kwargs = json.dumps(None)

                transition_log = _state_log_model.objects.create(
                    on=self,
                    from_state=getattr(self, field),
                    to_state=t.to_state,
                    user=user,
                    serialized_kwargs=serialized_kwargs)

            # Test transition (access/execution validation)
            try:
                si_self.test_transition(transition, user)
            except TransitionException, e:
                if _state_log_model:
                    transition_log.make_transition('fail')
                raise e

            # Execute
            if _state_log_model:
                transition_log.make_transition('start')

            try:
                from_state = getattr(self, field)

                before_state_execute.send(sender=self,
                                          from_state=from_state,
                                          to_state=t.to_state)
                # First call handler (handler should still see the original
                # state.)
                t.handler(self, user, **kwargs)

                # Then set new state and save.
                setattr(self, field, t.to_state)
                self.save()
                after_state_execute.send(sender=self,
                                         from_state=from_state,
                                         to_state=t.to_state)
            except Exception, e:
                if _state_log_model:
                    transition_log.make_transition('fail')

                # Print original traceback for debugging
                import traceback
                traceback.print_exc()
                raise e
Пример #2
0
        def make_transition(si_self, transition, user=None, **kwargs):
            """
            Executes state transition.

            :param str transition: the transition name
            :param user: the user that will execute the transition. Used for
                permission checking
            :type: :class:`django.contrib.auth.models.User` or ``None``
            :param dict kwargs: the kwargs that will be passed to
                :meth:`~django_states.machine.StateTransition.handler`
            """
            # Transition name should be known
            if not machine.has_transition(transition):
                raise UnknownTransition(self, transition)
            t = machine.get_transitions(transition)

            _state_log_model = getattr(self, '_%s_log_model' % field, None)

            # Start transition log
            if _state_log_model:
                # Try to serialize kwargs, for the log. Save null
                # when it's not serializable.
                try:
                    serialized_kwargs = json.dumps(kwargs)
                except TypeError:
                    serialized_kwargs = json.dumps(None)

                transition_log = _state_log_model.objects.create(
                    on=self, from_state=getattr(self, field), to_state=t.to_state,
                    user=user, serialized_kwargs=serialized_kwargs)

            # Test transition (access/execution validation)
            try:
                si_self.test_transition(transition, user)
            except TransitionException as e:
                if _state_log_model:
                    transition_log.make_transition('fail')
                raise e

            # Execute
            if _state_log_model:
                transition_log.make_transition('start')

            try:
                from_state = getattr(self, field)

                before_state_execute.send(sender=self,
                                          from_state=from_state,
                                          to_state=t.to_state)
                # First call handler (handler should still see the original
                # state.)
                t.handler(self, user, **kwargs)

                # Then set new state and save.
                setattr(self, field, t.to_state)
                self.save()
                after_state_execute.send(sender=self,
                                         from_state=from_state,
                                         to_state=t.to_state)
            except Exception as e:
                if _state_log_model:
                    transition_log.make_transition('fail')

                raise
            else:
                if _state_log_model:
                    transition_log.make_transition('complete')

                # *After completion*, call the handler of this state
                # definition
                machine.get_state(t.to_state).handler(self)
Пример #3
0
        def make_transition(si_self, transition, user=None, **kwargs):
            """
            Executes state transition.

            :param str transition: the transition name
            :param user: the user that will execute the transition. Used for
                permission checking
            :type: :class:`django.contrib.auth.models.User` or ``None``
            :param dict kwargs: the kwargs that will be passed to
                :meth:`~django_states.machine.StateTransition.handler`
            """
            # Transition name should be known
            if not machine.has_transition(transition):
                raise UnknownTransition(self, transition)
            t = machine.get_transitions(transition)

            _state_log_model = getattr(self, "_{}_log_model".format(field),
                                       None)

            # Start transition log
            if _state_log_model:
                # Try to serialize kwargs, for the log. Save null
                # when it's not serializable.
                try:
                    serialized_kwargs = json.dumps(kwargs)
                except TypeError:
                    serialized_kwargs = json.dumps(None)

                transition_log = _state_log_model.objects.create(
                    on=self,
                    from_state=getattr(self, field),
                    to_state=t.to_state,
                    user=user,
                    serialized_kwargs=serialized_kwargs,
                )

            # Test transition (access/execution validation)
            try:
                si_self.test_transition(transition, user)
            except TransitionException as e:
                if _state_log_model:
                    transition_log.make_transition("fail")
                raise e

            # Execute
            if _state_log_model:
                transition_log.make_transition("start")

            try:
                from_state = getattr(self, field)

                before_state_execute.send(sender=self,
                                          from_state=from_state,
                                          to_state=t.to_state)
                # First call handler (handler should still see the original
                # state.)
                t.handler(self, user, **kwargs)

                # Then set new state and save.
                setattr(self, field, t.to_state)
                self.save()
                after_state_execute.send(sender=self,
                                         from_state=from_state,
                                         to_state=t.to_state)
            except Exception as e:
                if _state_log_model:
                    transition_log.make_transition("fail")

                raise
            else:
                if _state_log_model:
                    transition_log.make_transition("complete")

                # *After completion*, call the handler of this state
                # definition
                machine.get_state(t.to_state).handler(self)