entities/wfobjs.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 03 Dec 2009 17:17:43 +0100
changeset 3998 94cc7cad3d2d
parent 3777 3ef8cdb5fb1c
parent 3986 cc29eddf51ad
child 4012 f6c65e04704c
permissions -rw-r--r--
backport stable into default
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     1
"""workflow definition and history related entities
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     2
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     3
:organization: Logilab
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1572
diff changeset
     4
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     5
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1572
diff changeset
     6
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     7
"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     8
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     9
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    10
from warnings import warn
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    11
2948
d3cd8bd20ee5 override clear_all_caches to clear cwetype_workflow cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2947
diff changeset
    12
from logilab.common.decorators import cached, clear_cache
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    13
from logilab.common.deprecation import deprecated
3757
122a01751d59 2.4 compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3698
diff changeset
    14
from logilab.common.compat import any
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    15
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    16
from cubicweb.entities import AnyEntity, fetch_config
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    17
from cubicweb.interfaces import IWorkflowable
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    18
from cubicweb.common.mixins import MI_REL_TRIGGERS
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
2988
89d97d7c0508 [wf] use custom exception class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2987
diff changeset
    20
class WorkflowException(Exception): pass
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
    21
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    22
class Workflow(AnyEntity):
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
    23
    __regid__ = 'Workflow'
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    24
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    25
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    26
    def initial(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    27
        """return the initial state for this workflow"""
2944
3bd49b70f7f9 [wf] return None, not empty list
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2943
diff changeset
    28
        return self.initial_state and self.initial_state[0] or None
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    29
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    30
    def is_default_workflow_of(self, etype):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    31
        """return True if this workflow is the default workflow for the given
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    32
        entity type
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    33
        """
2943
77622caef9bd [schema] default_workflow_of more naturally expressed as default_workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
    34
        return any(et for et in self.reverse_default_workflow
77622caef9bd [schema] default_workflow_of more naturally expressed as default_workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
    35
                   if et.name == etype)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    36
3982
ac2a54a6f36f implements 'parent' method on workflow entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3959
diff changeset
    37
    # XXX define parent() instead? what if workflow of multiple types?
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    38
    def after_deletion_path(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    39
        """return (path, parameters) which should be used as redirect
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    40
        information when this entity is being deleted
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    41
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    42
        if self.workflow_of:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    43
            return self.workflow_of[0].rest_path(), {'vid': 'workflow'}
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    44
        return super(Workflow, self).after_deletion_path()
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    45
2976
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    46
    def iter_workflows(self, _done=None):
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    47
        """return an iterator on actual workflows, eg this workflow and its
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    48
        subworkflows
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    49
        """
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    50
        # infinite loop safety belt
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    51
        if _done is None:
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    52
            _done = set()
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    53
        yield self
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    54
        _done.add(self.eid)
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
    55
        for tr in self._cw.execute('Any T WHERE T is WorkflowTransition, '
2976
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    56
                                   'T transition_of WF, WF eid %(wf)s',
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    57
                                   {'wf': self.eid}).entities():
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    58
            if tr.subwf.eid in _done:
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    59
                continue
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    60
            for subwf in tr.subwf.iter_workflows(_done):
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    61
                yield subwf
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    62
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    63
    # state / transitions accessors ############################################
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    64
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    65
    def state_by_name(self, statename):
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
    66
        rset = self._cw.execute('Any S, SN WHERE S name SN, S name %(n)s, '
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    67
                                'S state_of WF, WF eid %(wf)s',
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    68
                                {'n': statename, 'wf': self.eid}, 'wf')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    69
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    70
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    71
        return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    72
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    73
    def state_by_eid(self, eid):
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
    74
        rset = self._cw.execute('Any S, SN WHERE S name SN, S eid %(s)s, '
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    75
                                'S state_of WF, WF eid %(wf)s',
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    76
                                {'s': eid, 'wf': self.eid}, ('wf', 's'))
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    77
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    78
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    79
        return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    80
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    81
    def transition_by_name(self, trname):
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
    82
        rset = self._cw.execute('Any T, TN WHERE T name TN, T name %(n)s, '
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    83
                                'T transition_of WF, WF eid %(wf)s',
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    84
                                {'n': trname, 'wf': self.eid}, 'wf')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    85
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    86
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    87
        return None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    88
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    89
    def transition_by_eid(self, eid):
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
    90
        rset = self._cw.execute('Any T, TN WHERE T name TN, T eid %(t)s, '
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    91
                                'T transition_of WF, WF eid %(wf)s',
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    92
                                {'t': eid, 'wf': self.eid}, ('wf', 't'))
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    93
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    94
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    95
        return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    96
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    97
    # wf construction methods ##################################################
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    98
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    99
    def add_state(self, name, initial=False, **kwargs):
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   100
        """add a state to this workflow"""
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   101
        state = self._cw.create_entity('State', name=unicode(name), **kwargs)
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   102
        self._cw.execute('SET S state_of WF WHERE S eid %(s)s, WF eid %(wf)s',
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   103
                         {'s': state.eid, 'wf': self.eid}, ('s', 'wf'))
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   104
        if initial:
3959
e6ecaf93c0ba improve error message for redundant initial workflow states
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 3765
diff changeset
   105
            assert not self.initial, "Initial state already defined as %s" % self.initial
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   106
            self._cw.execute('SET WF initial_state S '
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   107
                             'WHERE S eid %(s)s, WF eid %(wf)s',
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   108
                             {'s': state.eid, 'wf': self.eid}, ('s', 'wf'))
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   109
        return state
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   110
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   111
    def _add_transition(self, trtype, name, fromstates,
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   112
                        requiredgroups=(), conditions=(), **kwargs):
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   113
        tr = self._cw.create_entity(trtype, name=unicode(name), **kwargs)
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   114
        self._cw.execute('SET T transition_of WF '
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   115
                         'WHERE T eid %(t)s, WF eid %(wf)s',
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   116
                         {'t': tr.eid, 'wf': self.eid}, ('t', 'wf'))
2987
5082dec70ed8 [wf] ensure fromstates given, allow to give an entity (avoid spotless error, we can iter on entities...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2986
diff changeset
   117
        assert fromstates, fromstates
5082dec70ed8 [wf] ensure fromstates given, allow to give an entity (avoid spotless error, we can iter on entities...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2986
diff changeset
   118
        if not isinstance(fromstates, (tuple, list)):
5082dec70ed8 [wf] ensure fromstates given, allow to give an entity (avoid spotless error, we can iter on entities...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2986
diff changeset
   119
            fromstates = (fromstates,)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   120
        for state in fromstates:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   121
            if hasattr(state, 'eid'):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   122
                state = state.eid
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   123
            self._cw.execute('SET S allowed_transition T '
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   124
                             'WHERE S eid %(s)s, T eid %(t)s',
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   125
                             {'s': state, 't': tr.eid}, ('s', 't'))
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   126
        tr.set_transition_permissions(requiredgroups, conditions, reset=False)
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   127
        return tr
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   128
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   129
    def add_transition(self, name, fromstates, tostate=None,
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   130
                       requiredgroups=(), conditions=(), **kwargs):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   131
        """add a transition to this workflow from some state(s) to another"""
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   132
        tr = self._add_transition('Transition', name, fromstates,
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   133
                                  requiredgroups, conditions, **kwargs)
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   134
        if tostate is not None:
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   135
            if hasattr(tostate, 'eid'):
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   136
                tostate = tostate.eid
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   137
            self._cw.execute('SET T destination_state S '
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   138
                             'WHERE S eid %(s)s, T eid %(t)s',
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   139
                             {'t': tr.eid, 's': tostate}, ('s', 't'))
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   140
        return tr
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   141
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   142
    def add_wftransition(self, name, subworkflow, fromstates, exitpoints=(),
3582
28547f21308e two bits of docstring
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3542
diff changeset
   143
                         requiredgroups=(), conditions=(), **kwargs):
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   144
        """add a workflow transition to this workflow"""
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   145
        tr = self._add_transition('WorkflowTransition', name, fromstates,
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   146
                                  requiredgroups, conditions, **kwargs)
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   147
        if hasattr(subworkflow, 'eid'):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   148
            subworkflow = subworkflow.eid
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   149
        assert _cw.req.execute('SET T subworkflow WF WHERE WF eid %(wf)s,T eid %(t)s',
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   150
                               {'t': tr.eid, 'wf': subworkflow}, ('wf', 't'))
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   151
        for fromstate, tostate in exitpoints:
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   152
            tr.add_exit_point(fromstate, tostate)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   153
        return tr
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   154
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   155
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   156
class BaseTransition(AnyEntity):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   157
    """customized class for abstract transition
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   158
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   159
    provides a specific may_be_fired method to check if the relation may be
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   160
    fired by the logged user
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
    """
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   162
    __regid__ = 'BaseTransition'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
    fetch_attrs, fetch_order = fetch_config(['name'])
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   164
2951
d0b77dd27740 [wf] BaseTransition is a virtual type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2948
diff changeset
   165
    def __init__(self, *args, **kwargs):
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   166
        if self.__regid__ == 'BaseTransition':
2988
89d97d7c0508 [wf] use custom exception class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2987
diff changeset
   167
            raise WorkflowException('should not be instantiated')
2954
48507919b6e3 [wf] oops, BaseTransition.__init__ may be called for subclasses
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2951
diff changeset
   168
        super(BaseTransition, self).__init__(*args, **kwargs)
2951
d0b77dd27740 [wf] BaseTransition is a virtual type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2948
diff changeset
   169
2975
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   170
    @property
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   171
    def workflow(self):
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   172
        return self.transition_of[0]
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   173
2991
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   174
    def has_input_state(self, state):
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   175
        if hasattr(state, 'eid'):
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   176
            state = state.eid
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   177
        return any(s for s in self.reverse_allowed_transition if s.eid == state)
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   178
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   179
    def may_be_fired(self, eid):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   180
        """return true if the logged user may fire this transition
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   182
        `eid` is the eid of the object on which we may fire the transition
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
        """
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   184
        user = self._cw.user
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
        # check user is at least in one of the required groups if any
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
        groups = frozenset(g.name for g in self.require_group)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
        if groups:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   188
            matches = user.matching_groups(groups)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
            if matches:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
                return matches
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
            if 'owners' in groups and user.owns(eid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
                return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
        # check one of the rql expression conditions matches if any
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   194
        if self.condition:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
            for rqlexpr in self.condition:
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   196
                if rqlexpr.check_expression(self._cw, eid):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   197
                    return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   198
        if self.condition or groups:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
            return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   200
        return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
    def after_deletion_path(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
        """return (path, parameters) which should be used as redirect
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   204
        information when this entity is being deleted
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   205
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
        if self.transition_of:
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   207
            return self.transition_of[0].rest_path(), {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
        return super(Transition, self).after_deletion_path()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   210
    def set_transition_permissions(self, requiredgroups=(), conditions=(),
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   211
                                   reset=True):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   212
        """set or add (if `reset` is False) groups and conditions for this
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   213
        transition
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   214
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   215
        if reset:
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   216
            self._cw.execute('DELETE T require_group G WHERE T eid %(x)s',
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   217
                             {'x': self.eid}, 'x')
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   218
            self._cw.execute('DELETE T condition R WHERE T eid %(x)s',
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   219
                             {'x': self.eid}, 'x')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   220
        for gname in requiredgroups:
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   221
            rset = self._cw.execute('SET T require_group G '
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   222
                                    'WHERE T eid %(x)s, G name %(gn)s',
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   223
                                    {'x': self.eid, 'gn': gname}, 'x')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   224
            assert rset, '%s is not a known group' % gname
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   225
        if isinstance(conditions, basestring):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   226
            conditions = (conditions,)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   227
        for expr in conditions:
3542
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   228
            if isinstance(expr, basestring):
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   229
                kwargs = {'expr': unicode(expr)}
3542
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   230
            else:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   231
                assert isinstance(expr, dict)
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   232
                kwargs = expr
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   233
            kwargs['x'] = self.eid
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   234
            kwargs.setdefault('mainvars', u'X')
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   235
            self._cw.execute('INSERT RQLExpression X: X exprtype "ERQLExpression", '
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   236
                             'X expression %(expr)s, T condition X '
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   237
                             'WHERE T eid %(x)s',
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   238
                             'T condition X WHERE T eid %(x)s', kwargs, 'x')
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   239
        # XXX clear caches?
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   240
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   241
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   242
class Transition(BaseTransition):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   243
    """customized class for Transition entities"""
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   244
    __regid__ = 'Transition'
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   245
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   246
    def destination(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   247
        return self.destination_state[0]
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   248
3982
ac2a54a6f36f implements 'parent' method on workflow entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3959
diff changeset
   249
    def parent(self):
ac2a54a6f36f implements 'parent' method on workflow entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3959
diff changeset
   250
        return self.workflow
ac2a54a6f36f implements 'parent' method on workflow entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3959
diff changeset
   251
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   252
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   253
class WorkflowTransition(BaseTransition):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   254
    """customized class for WorkflowTransition entities"""
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   255
    __regid__ = 'WorkflowTransition'
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   256
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   257
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   258
    def subwf(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   259
        return self.subworkflow[0]
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   260
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   261
    def destination(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   262
        return self.subwf.initial
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   263
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   264
    def add_exit_point(self, fromstate, tostate):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   265
        if hasattr(fromstate, 'eid'):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   266
            fromstate = fromstate.eid
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   267
        if tostate is None:
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   268
            self._cw.execute('INSERT SubWorkflowExitPoint X: T subworkflow_exit X, '
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   269
                             'X subworkflow_state FS WHERE T eid %(t)s, FS eid %(fs)s',
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   270
                             {'t': self.eid, 'fs': fromstate}, ('t', 'fs'))
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   271
        else:
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   272
            if hasattr(tostate, 'eid'):
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   273
                tostate = tostate.eid
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   274
            self._cw.execute('INSERT SubWorkflowExitPoint X: T subworkflow_exit X, '
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   275
                             'X subworkflow_state FS, X destination_state TS '
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   276
                             'WHERE T eid %(t)s, FS eid %(fs)s, TS eid %(ts)s',
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   277
                             {'t': self.eid, 'fs': fromstate, 'ts': tostate},
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   278
                             ('t', 'fs', 'ts'))
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   279
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   280
    def get_exit_point(self, entity, stateeid):
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   281
        """if state is an exit point, return its associated destination state"""
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   282
        if hasattr(stateeid, 'eid'):
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   283
            stateeid = stateeid.eid
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   284
        try:
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   285
            tostateeid = self.exit_points()[stateeid]
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   286
        except KeyError:
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   287
            return None
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   288
        if tostateeid is None:
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   289
            # go back to state from which we've entered the subworkflow
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   290
            return entity.subworkflow_input_trinfo().previous_state
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   291
        return self._cw.entity_from_eid(tostateeid)
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   292
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   293
    @cached
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   294
    def exit_points(self):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   295
        result = {}
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   296
        for ep in self.subworkflow_exit:
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   297
            result[ep.subwf_state.eid] = ep.destination and ep.destination.eid
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   298
        return result
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   299
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   300
    def clear_all_caches(self):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   301
        super(WorkflowableMixIn, self).clear_all_caches()
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   302
        clear_cache(self, 'exit_points')
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   303
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   304
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   305
class SubWorkflowExitPoint(AnyEntity):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   306
    """customized class for SubWorkflowExitPoint entities"""
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   307
    __regid__ = 'SubWorkflowExitPoint'
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   308
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   309
    @property
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   310
    def subwf_state(self):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   311
        return self.subworkflow_state[0]
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   312
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   313
    @property
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   314
    def destination(self):
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   315
        return self.destination_state and self.destination_state[0] or None
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   316
3982
ac2a54a6f36f implements 'parent' method on workflow entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3959
diff changeset
   317
    def parent(self):
ac2a54a6f36f implements 'parent' method on workflow entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3959
diff changeset
   318
        return self.reverse_subworkflow_exit[0]
ac2a54a6f36f implements 'parent' method on workflow entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3959
diff changeset
   319
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   320
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   321
class State(AnyEntity):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   322
    """customized class for State entities"""
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   323
    __regid__ = 'State'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   324
    fetch_attrs, fetch_order = fetch_config(['name'])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   325
    rest_attr = 'eid'
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   326
2975
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   327
    @property
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   328
    def workflow(self):
3038
1261c3df0e5a [multi-sources] in ms config we don't have state_of (and probably others, but that's the one used until now...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2991
diff changeset
   329
        # take care, may be missing in multi-sources configuration
1261c3df0e5a [multi-sources] in ms config we don't have state_of (and probably others, but that's the one used until now...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2991
diff changeset
   330
        return self.state_of and self.state_of[0]
2975
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   331
3982
ac2a54a6f36f implements 'parent' method on workflow entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3959
diff changeset
   332
    def parent(self):
ac2a54a6f36f implements 'parent' method on workflow entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3959
diff changeset
   333
        return self.workflow
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   334
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   335
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   336
class TrInfo(AnyEntity):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
    """customized class for Transition information entities
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   338
    """
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   339
    __regid__ = 'TrInfo'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   340
    fetch_attrs, fetch_order = fetch_config(['creation_date', 'comment'],
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   341
                                            pclass=None) # don't want modification_date
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   342
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   343
    def for_entity(self):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   344
        return self.wf_info_for[0]
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   345
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   346
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   347
    def previous_state(self):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   348
        return self.from_state[0]
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   349
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   350
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
    def new_state(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   352
        return self.to_state[0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   354
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   355
    def transition(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   356
        return self.by_transition and self.by_transition[0] or None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   357
3982
ac2a54a6f36f implements 'parent' method on workflow entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3959
diff changeset
   358
    def parent(self):
ac2a54a6f36f implements 'parent' method on workflow entity types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3959
diff changeset
   359
        return self.for_entity
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   360
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   361
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   362
class WorkflowableMixIn(object):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   363
    """base mixin providing workflow helper methods for workflowable entities.
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   364
    This mixin will be automatically set on class supporting the 'in_state'
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   365
    relation (which implies supporting 'wf_info_for' as well)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   366
    """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   367
    __implements__ = (IWorkflowable,)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   368
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   369
    @property
2978
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   370
    def main_workflow(self):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   371
        """return current workflow applied to this entity"""
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   372
        if self.custom_workflow:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   373
            return self.custom_workflow[0]
2946
957fd4b276e2 [wf] refactor current_workflow by extracting cwetype_workflow method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2945
diff changeset
   374
        return self.cwetype_workflow()
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   375
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   376
    @property
2978
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   377
    def current_workflow(self):
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   378
        """return current workflow applied to this entity"""
2991
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   379
        return self.current_state and self.current_state.workflow or self.main_workflow
2978
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   380
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   381
    @property
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   382
    def current_state(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   383
        """return current state entity"""
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   384
        return self.in_state and self.in_state[0] or None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   385
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   386
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   387
    def state(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   388
        """return current state name"""
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   389
        try:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   390
            return self.in_state[0].name
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   391
        except IndexError:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   392
            self.warning('entity %s has no state', self)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   393
            return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   394
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   395
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   396
    def printable_state(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   397
        """return current state name translated to context's language"""
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   398
        state = self.current_state
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   399
        if state:
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   400
            return self._cw._(state.name)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   401
        return u''
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   402
2947
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   403
    @property
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   404
    def workflow_history(self):
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   405
        """return the workflow history for this entity (eg ordered list of
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   406
        TrInfo entities)
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   407
        """
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   408
        return self.reverse_wf_info_for
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   409
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   410
    def latest_trinfo(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   411
        """return the latest transition information for this entity"""
3765
769dc0107f31 latst_trinfo : do not crash on absent wf history
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3757
diff changeset
   412
        try:
769dc0107f31 latst_trinfo : do not crash on absent wf history
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3757
diff changeset
   413
            return self.reverse_wf_info_for[-1]
769dc0107f31 latst_trinfo : do not crash on absent wf history
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3757
diff changeset
   414
        except IndexError:
769dc0107f31 latst_trinfo : do not crash on absent wf history
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3757
diff changeset
   415
            return None
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   416
2946
957fd4b276e2 [wf] refactor current_workflow by extracting cwetype_workflow method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2945
diff changeset
   417
    @cached
957fd4b276e2 [wf] refactor current_workflow by extracting cwetype_workflow method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2945
diff changeset
   418
    def cwetype_workflow(self):
957fd4b276e2 [wf] refactor current_workflow by extracting cwetype_workflow method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2945
diff changeset
   419
        """return the default workflow for entities of this type"""
957fd4b276e2 [wf] refactor current_workflow by extracting cwetype_workflow method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2945
diff changeset
   420
        # XXX CWEType method
3674
387d51af966d backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3629 3663
diff changeset
   421
        wfrset = self._cw.execute('Any WF WHERE ET default_workflow WF, '
3675
5d143781a604 fix merge
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3674
diff changeset
   422
                                  'ET name %(et)s', {'et': self.__regid__})
3663
c74d8ec4cdb2 simpler implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3628
diff changeset
   423
        if wfrset:
2946
957fd4b276e2 [wf] refactor current_workflow by extracting cwetype_workflow method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2945
diff changeset
   424
            return wfrset.get_entity(0, 0)
3675
5d143781a604 fix merge
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3674
diff changeset
   425
        self.warning("can't find any workflow for %s", self.__regid__)
2946
957fd4b276e2 [wf] refactor current_workflow by extracting cwetype_workflow method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2945
diff changeset
   426
        return None
957fd4b276e2 [wf] refactor current_workflow by extracting cwetype_workflow method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2945
diff changeset
   427
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   428
    def possible_transitions(self, type='normal'):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   429
        """generates transition that MAY be fired for the given entity,
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   430
        expected to be in this state
3986
cc29eddf51ad add postcommit_event on Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3982
diff changeset
   431
        used only by the UI
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   432
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   433
        if self.current_state is None or self.current_workflow is None:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   434
            return
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   435
        rset = self._cw.execute(
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   436
            'Any T,TT, TN WHERE S allowed_transition T, S eid %(x)s, '
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   437
            'T type TT, T type %(type)s, '
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   438
            'T name TN, T transition_of WF, WF eid %(wfeid)s',
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   439
            {'x': self.current_state.eid, 'type': type,
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   440
             'wfeid': self.current_workflow.eid}, 'x')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   441
        for tr in rset.entities():
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   442
            if tr.may_be_fired(self.eid):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   443
                yield tr
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   444
2989
dfb3506647e4 [wf] refactor change_state/fire_transition to share more code, change_state can also take an optional tr argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2988
diff changeset
   445
    def _add_trinfo(self, comment, commentformat, treid=None, tseid=None):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   446
        kwargs = {}
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   447
        if comment is not None:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   448
            kwargs['comment'] = comment
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   449
            if commentformat is not None:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   450
                kwargs['comment_format'] = commentformat
3687
859f7d741bfb update for new create_entity implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3663
diff changeset
   451
        kwargs['wf_info_for'] = self
2989
dfb3506647e4 [wf] refactor change_state/fire_transition to share more code, change_state can also take an optional tr argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2988
diff changeset
   452
        if treid is not None:
3687
859f7d741bfb update for new create_entity implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3663
diff changeset
   453
            kwargs['by_transition'] = self.req.entity_from_eid(treid)
2989
dfb3506647e4 [wf] refactor change_state/fire_transition to share more code, change_state can also take an optional tr argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2988
diff changeset
   454
        if tseid is not None:
3687
859f7d741bfb update for new create_entity implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3663
diff changeset
   455
            kwargs['to_state'] = self.req.entity_from_eid(tseid)
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3675 3698
diff changeset
   456
        return self._cw.create_entity('TrInfo', **kwargs)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   457
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   458
    def fire_transition(self, tr, comment=None, commentformat=None):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   459
        """change the entity's state by firing transition of the given name in
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   460
        entity's workflow
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   461
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   462
        assert self.current_workflow
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   463
        if isinstance(tr, basestring):
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   464
            _tr = self.current_workflow.transition_by_name(tr)
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   465
            assert _tr is not None, 'not a %s transition: %s' % (
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   466
                self.__regid__, tr)
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   467
            tr = _tr
2989
dfb3506647e4 [wf] refactor change_state/fire_transition to share more code, change_state can also take an optional tr argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2988
diff changeset
   468
        return self._add_trinfo(comment, commentformat, tr.eid)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   469
2989
dfb3506647e4 [wf] refactor change_state/fire_transition to share more code, change_state can also take an optional tr argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2988
diff changeset
   470
    def change_state(self, statename, comment=None, commentformat=None, tr=None):
2980
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   471
        """change the entity's state to the given state (name or entity) in
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   472
        entity's workflow. This method should only by used by manager to fix an
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   473
        entity's state when their is no matching transition, otherwise
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   474
        fire_transition should be used.
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   475
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   476
        assert self.current_workflow
2980
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   477
        if hasattr(statename, 'eid'):
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   478
            stateeid = statename.eid
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   479
        else:
2980
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   480
            if not isinstance(statename, basestring):
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   481
                warn('give a state name')
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   482
                state = self.current_workflow.state_by_eid(statename)
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   483
            else:
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   484
                state = self.current_workflow.state_by_name(statename)
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   485
            if state is None:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3406
diff changeset
   486
                raise WorkflowException('not a %s state: %s' % (self.__regid__,
2989
dfb3506647e4 [wf] refactor change_state/fire_transition to share more code, change_state can also take an optional tr argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2988
diff changeset
   487
                                                                statename))
2980
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   488
            stateeid = state.eid
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   489
        # XXX try to find matching transition?
2989
dfb3506647e4 [wf] refactor change_state/fire_transition to share more code, change_state can also take an optional tr argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2988
diff changeset
   490
        return self._add_trinfo(comment, commentformat, tr and tr.eid, stateeid)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   491
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   492
    def subworkflow_input_trinfo(self):
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   493
        """return the TrInfo which has be recorded when this entity went into
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   494
        the current sub-workflow
2990
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   495
        """
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   496
        if self.main_workflow.eid == self.current_workflow.eid:
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   497
            return # doesn't make sense
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   498
        subwfentries = []
3621
1ec4452aa36f [wf] fix detection of transition where we've entered a subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3609
diff changeset
   499
        for trinfo in self.workflow_history:
2990
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   500
            if (trinfo.transition and
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   501
                trinfo.previous_state.workflow.eid != trinfo.new_state.workflow.eid):
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   502
                # entering or leaving a subworkflow
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   503
                if (subwfentries and
3621
1ec4452aa36f [wf] fix detection of transition where we've entered a subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3609
diff changeset
   504
                    subwfentries[-1].new_state.workflow.eid == trinfo.previous_state.workflow.eid and
1ec4452aa36f [wf] fix detection of transition where we've entered a subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3609
diff changeset
   505
                    subwfentries[-1].previous_state.workflow.eid == trinfo.new_state.workflow.eid):
2990
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   506
                    # leave
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   507
                    del subwfentries[-1]
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   508
                else:
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   509
                    # enter
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   510
                    subwfentries.append(trinfo)
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   511
        if not subwfentries:
f221ba8552ab [wf] new method on WorkflowableMixIn to get the transition which had led to the current sub-workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2989
diff changeset
   512
            return None
3628
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   513
        return subwfentries[-1]
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   514
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   515
    def subworkflow_input_transition(self):
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   516
        """return the transition which has went through the current sub-workflow
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   517
        """
440931181322 [wf engine] support for subwf exit point with no destination state: go back to state from which we entered into the subworkflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3621
diff changeset
   518
        return getattr(self.subworkflow_input_trinfo(), 'transition', None)
2948
d3cd8bd20ee5 override clear_all_caches to clear cwetype_workflow cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2947
diff changeset
   519
d3cd8bd20ee5 override clear_all_caches to clear cwetype_workflow cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2947
diff changeset
   520
    def clear_all_caches(self):
d3cd8bd20ee5 override clear_all_caches to clear cwetype_workflow cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2947
diff changeset
   521
        super(WorkflowableMixIn, self).clear_all_caches()
d3cd8bd20ee5 override clear_all_caches to clear cwetype_workflow cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2947
diff changeset
   522
        clear_cache(self, 'cwetype_workflow')
d3cd8bd20ee5 override clear_all_caches to clear cwetype_workflow cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2947
diff changeset
   523
3405
9d31c9cb8103 nicer deprecation warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3377
diff changeset
   524
    @deprecated('[3.5] get transition from current workflow and use its may_be_fired method')
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   525
    def can_pass_transition(self, trname):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   526
        """return the Transition instance if the current user can fire the
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   527
        transition with the given name, else None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   528
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   529
        tr = self.current_workflow and self.current_workflow.transition_by_name(trname)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   530
        if tr and tr.may_be_fired(self.eid):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   531
            return tr
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   532
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   533
    @property
3405
9d31c9cb8103 nicer deprecation warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3377
diff changeset
   534
    @deprecated('[3.5] use printable_state')
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   535
    def displayable_state(self):
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   536
        return self._cw._(self.state)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   537
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   538
MI_REL_TRIGGERS[('in_state', 'subject')] = WorkflowableMixIn