entities/wfobjs.py
author Aurelien Campeas <aurelien.campeas@logilab.fr>
Wed, 28 May 2014 17:33:16 +0200
changeset 9786 57dbd4450373
parent 9256 697a8181ba30
child 9892 928732ec00dd
permissions -rw-r--r--
[tests/undo] use the new connection api
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8190
2a3c1b787688 [vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
     1
# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
     3
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
     4
# This file is part of CubicWeb.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
     5
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
     6
# CubicWeb is free software: you can redistribute it and/or modify it under the
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
     9
# any later version.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
    10
#
5424
8ecbcbff9777 replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5421
diff changeset
    11
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
    12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
    13
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
    14
# details.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
    15
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
    18
"""workflow handling:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
    20
* entity types defining workflow (Workflow, State, Transition...)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
    21
* workflow history (TrInfo)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
    22
* adapter for workflowable entities (IWorkflowableAdapter)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    23
"""
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
    24
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    26
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    27
2948
d3cd8bd20ee5 override clear_all_caches to clear cwetype_workflow cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2947
diff changeset
    28
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
    29
from logilab.common.deprecation import deprecated
3757
122a01751d59 2.4 compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3698
diff changeset
    30
from logilab.common.compat import any
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    31
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    32
from cubicweb.entities import AnyEntity, fetch_config
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
    33
from cubicweb.view import EntityAdapter
8190
2a3c1b787688 [vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
    34
from cubicweb.predicates import relation_possible
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    35
2988
89d97d7c0508 [wf] use custom exception class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2987
diff changeset
    36
class WorkflowException(Exception): pass
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
    37
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    38
class Workflow(AnyEntity):
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
    39
    __regid__ = 'Workflow'
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    40
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    41
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    42
    def initial(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    43
        """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
    44
        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
    45
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    46
    def is_default_workflow_of(self, etype):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    47
        """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
    48
        entity type
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    49
        """
2943
77622caef9bd [schema] default_workflow_of more naturally expressed as default_workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
    50
        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
    51
                   if et.name == etype)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    52
2976
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    53
    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
    54
        """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
    55
        subworkflows
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    56
        """
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    57
        # infinite loop safety belt
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    58
        if _done is None:
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    59
            _done = set()
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    60
        yield self
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    61
        _done.add(self.eid)
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
    62
        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
    63
                                   '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
    64
                                   {'wf': self.eid}).entities():
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    65
            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
    66
                continue
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    67
            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
    68
                yield subwf
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    69
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    70
    # state / transitions accessors ############################################
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    71
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    72
    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
    73
        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
    74
                                'S state_of WF, WF eid %(wf)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
    75
                                {'n': statename, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    76
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    77
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    78
        return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    79
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    80
    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
    81
        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
    82
                                'S state_of WF, WF eid %(wf)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
    83
                                {'s': eid, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    84
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    85
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    86
        return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    87
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    88
    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
    89
        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
    90
                                'T transition_of WF, WF eid %(wf)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
    91
                                {'n': trname, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    92
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    93
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    94
        return None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    95
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    96
    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
    97
        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
    98
                                'T transition_of WF, WF eid %(wf)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
    99
                                {'t': eid, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   100
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   101
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   102
        return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   103
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   104
    # wf construction methods ##################################################
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   105
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   106
    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
   107
        """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
   108
        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
   109
        self._cw.execute('SET S state_of WF WHERE S eid %(s)s, WF eid %(wf)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   110
                         {'s': state.eid, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   111
        if initial:
3959
e6ecaf93c0ba improve error message for redundant initial workflow states
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 3765
diff changeset
   112
            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
   113
            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
   114
                             'WHERE S eid %(s)s, WF eid %(wf)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   115
                             {'s': state.eid, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   116
        return state
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   117
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   118
    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
   119
                        requiredgroups=(), conditions=(), **kwargs):
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   120
        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
   121
        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
   122
                         'WHERE T eid %(t)s, WF eid %(wf)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   123
                         {'t': tr.eid, 'wf': self.eid})
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
   124
        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
   125
        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
   126
            fromstates = (fromstates,)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   127
        for state in fromstates:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   128
            if hasattr(state, 'eid'):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   129
                state = state.eid
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   130
            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
   131
                             'WHERE S eid %(s)s, T eid %(t)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   132
                             {'s': state, 't': tr.eid})
4645
fd4e32f17211 deprecate Transition.set_transition_permissions in favor of set_permissions (after all we know we're on a transition entity)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4644
diff changeset
   133
        tr.set_permissions(requiredgroups, conditions, reset=False)
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   134
        return tr
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   135
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
   136
    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
   137
                       requiredgroups=(), conditions=(), **kwargs):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   138
        """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
   139
        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
   140
                                  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
   141
        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
   142
            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
   143
                tostate = tostate.eid
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   144
            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
   145
                             'WHERE S eid %(s)s, T eid %(t)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   146
                             {'t': tr.eid, 's': tostate})
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   147
        return tr
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   148
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
   149
    def add_wftransition(self, name, subworkflow, fromstates, exitpoints=(),
3582
28547f21308e two bits of docstring
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3542
diff changeset
   150
                         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
   151
        """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
   152
        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
   153
                                  requiredgroups, conditions, **kwargs)
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   154
        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
   155
            subworkflow = subworkflow.eid
4024
6a14cff373c3 more api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   156
        assert self._cw.execute('SET T subworkflow WF WHERE WF eid %(wf)s,T eid %(t)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   157
                                {'t': tr.eid, 'wf': subworkflow})
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   158
        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
   159
            tr.add_exit_point(fromstate, tostate)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   160
        return tr
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   161
3999
5dd6ffc2ccae added replace_state method to ease workflow migration. backported from forge as a reminder, not really tested yet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3986
diff changeset
   162
    def replace_state(self, todelstate, replacement):
5dd6ffc2ccae added replace_state method to ease workflow migration. backported from forge as a reminder, not really tested yet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3986
diff changeset
   163
        """migration convenience method"""
5dd6ffc2ccae added replace_state method to ease workflow migration. backported from forge as a reminder, not really tested yet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3986
diff changeset
   164
        if not hasattr(todelstate, 'eid'):
5dd6ffc2ccae added replace_state method to ease workflow migration. backported from forge as a reminder, not really tested yet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3986
diff changeset
   165
            todelstate = self.state_by_name(todelstate)
5dd6ffc2ccae added replace_state method to ease workflow migration. backported from forge as a reminder, not really tested yet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3986
diff changeset
   166
        if not hasattr(replacement, 'eid'):
5dd6ffc2ccae added replace_state method to ease workflow migration. backported from forge as a reminder, not really tested yet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3986
diff changeset
   167
            replacement = self.state_by_name(replacement)
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4716
diff changeset
   168
        execute = self._cw.execute
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   169
        execute('SET X in_state S WHERE S eid %(s)s', {'s': todelstate.eid})
3999
5dd6ffc2ccae added replace_state method to ease workflow migration. backported from forge as a reminder, not really tested yet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3986
diff changeset
   170
        execute('SET X from_state NS WHERE X to_state OS, OS eid %(os)s, NS eid %(ns)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   171
                {'os': todelstate.eid, 'ns': replacement.eid})
3999
5dd6ffc2ccae added replace_state method to ease workflow migration. backported from forge as a reminder, not really tested yet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3986
diff changeset
   172
        execute('SET X to_state NS WHERE X to_state OS, OS eid %(os)s, NS eid %(ns)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   173
                {'os': todelstate.eid, 'ns': replacement.eid})
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   174
        todelstate.cw_delete()
3999
5dd6ffc2ccae added replace_state method to ease workflow migration. backported from forge as a reminder, not really tested yet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3986
diff changeset
   175
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   176
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   177
class BaseTransition(AnyEntity):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   178
    """customized class for abstract transition
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   179
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   180
    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
   181
    fired by the logged user
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
    """
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   183
    __regid__ = 'BaseTransition'
7827
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7406
diff changeset
   184
    fetch_attrs, cw_fetch_order = fetch_config(['name', 'type'])
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   185
2951
d0b77dd27740 [wf] BaseTransition is a virtual type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2948
diff changeset
   186
    def __init__(self, *args, **kwargs):
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8216
diff changeset
   187
        if self.cw_etype == 'BaseTransition':
2988
89d97d7c0508 [wf] use custom exception class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2987
diff changeset
   188
            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
   189
        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
   190
2975
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   191
    @property
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   192
    def workflow(self):
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   193
        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
   194
2991
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   195
    def has_input_state(self, state):
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   196
        if hasattr(state, 'eid'):
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   197
            state = state.eid
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   198
        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
   199
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   200
    def may_be_fired(self, eid):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   201
        """return true if the logged user may fire this transition
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   203
        `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
   204
        """
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   205
        user = self._cw.user
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
        # 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
   207
        groups = frozenset(g.name for g in self.require_group)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
        if groups:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
            matches = user.matching_groups(groups)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
            if matches:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
                return matches
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   212
            if 'owners' in groups and user.owns(eid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
                return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   214
        # check one of the rql expression conditions matches if any
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   215
        if self.condition:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   216
            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
   217
                if rqlexpr.check_expression(self._cw, eid):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   218
                    return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   219
        if self.condition or groups:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   220
            return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   221
        return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   222
4645
fd4e32f17211 deprecate Transition.set_transition_permissions in favor of set_permissions (after all we know we're on a transition entity)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4644
diff changeset
   223
    def set_permissions(self, requiredgroups=(), conditions=(), reset=True):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   224
        """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
   225
        transition
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   226
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   227
        if reset:
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   228
            self._cw.execute('DELETE T require_group G WHERE T eid %(x)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   229
                             {'x': self.eid})
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   230
            self._cw.execute('DELETE T condition R WHERE T eid %(x)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   231
                             {'x': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   232
        for gname in requiredgroups:
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   233
            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
   234
                                    'WHERE T eid %(x)s, G name %(gn)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   235
                                    {'x': self.eid, 'gn': gname})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   236
            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
   237
        if isinstance(conditions, basestring):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   238
            conditions = (conditions,)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   239
        for expr in conditions:
3542
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   240
            if isinstance(expr, basestring):
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   241
                kwargs = {'expr': unicode(expr)}
3542
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   242
            else:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   243
                assert isinstance(expr, dict)
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   244
                kwargs = expr
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   245
            kwargs['x'] = self.eid
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   246
            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
   247
            self._cw.execute('INSERT RQLExpression X: X exprtype "ERQLExpression", '
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   248
                             'X expression %(expr)s, X mainvars %(mainvars)s, '
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   249
                             'T condition X WHERE T eid %(x)s', kwargs)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   250
        # XXX clear caches?
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   251
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 Transition(BaseTransition):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   254
    """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
   255
    __regid__ = 'Transition'
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   256
8212
a045d3821990 [workflow view] Display a non-localized version of state/transition names (closes #1912537).
Damien Garaud <damien.garaud@logilab.fr>
parents: 7990
diff changeset
   257
    def dc_long_title(self):
a045d3821990 [workflow view] Display a non-localized version of state/transition names (closes #1912537).
Damien Garaud <damien.garaud@logilab.fr>
parents: 7990
diff changeset
   258
        return '%s (%s)' % (self.name, self._cw._(self.name))
a045d3821990 [workflow view] Display a non-localized version of state/transition names (closes #1912537).
Damien Garaud <damien.garaud@logilab.fr>
parents: 7990
diff changeset
   259
4644
021035b9a7ab introduce 'go back' transition: transition without destination state will go to the state we were coming from
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4436
diff changeset
   260
    def destination(self, entity):
021035b9a7ab introduce 'go back' transition: transition without destination state will go to the state we were coming from
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4436
diff changeset
   261
        try:
021035b9a7ab introduce 'go back' transition: transition without destination state will go to the state we were coming from
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4436
diff changeset
   262
            return self.destination_state[0]
021035b9a7ab introduce 'go back' transition: transition without destination state will go to the state we were coming from
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4436
diff changeset
   263
        except IndexError:
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   264
            return entity.cw_adapt_to('IWorkflowable').latest_trinfo().previous_state
4644
021035b9a7ab introduce 'go back' transition: transition without destination state will go to the state we were coming from
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4436
diff changeset
   265
4646
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   266
    def potential_destinations(self):
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   267
        try:
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   268
            yield self.destination_state[0]
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   269
        except IndexError:
4647
6d7589b4ae6f [workflow] fix potential destination for go back transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4646
diff changeset
   270
            for incomingstate in self.reverse_allowed_transition:
6d7589b4ae6f [workflow] fix potential destination for go back transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4646
diff changeset
   271
                for tr in incomingstate.reverse_destination_state:
6d7589b4ae6f [workflow] fix potential destination for go back transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4646
diff changeset
   272
                    for previousstate in tr.reverse_allowed_transition:
6d7589b4ae6f [workflow] fix potential destination for go back transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4646
diff changeset
   273
                        yield previousstate
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   274
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   275
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   276
class WorkflowTransition(BaseTransition):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   277
    """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
   278
    __regid__ = 'WorkflowTransition'
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   279
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   280
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   281
    def subwf(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   282
        return self.subworkflow[0]
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   283
4646
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   284
    def destination(self, entity):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   285
        return self.subwf.initial
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   286
4646
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   287
    def potential_destinations(self):
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   288
        yield self.subwf.initial
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   289
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   290
    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
   291
        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
   292
            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
   293
        if tostate is None:
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   294
            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
   295
                             'X subworkflow_state FS WHERE T eid %(t)s, FS eid %(fs)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   296
                             {'t': self.eid, 'fs': fromstate})
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
        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
   298
            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
   299
                tostate = tostate.eid
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   300
            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
   301
                             '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
   302
                             'WHERE T eid %(t)s, FS eid %(fs)s, TS eid %(ts)s',
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   303
                             {'t': self.eid, 'fs': fromstate, 'ts': tostate})
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   304
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
   305
    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
   306
        """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
   307
        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
   308
            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
   309
        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
   310
            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
   311
        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
   312
            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
   313
        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
   314
            # go back to state from which we've entered the subworkflow
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   315
            return entity.cw_adapt_to('IWorkflowable').subworkflow_input_trinfo().previous_state
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   316
        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
   317
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   318
    @cached
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   319
    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
   320
        result = {}
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   321
        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
   322
            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
   323
        return result
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   324
7293
97505b798975 [entity 3.13 api] rename clear_all_caches into cw_clear_all_cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   325
    def cw_clear_all_caches(self):
97505b798975 [entity 3.13 api] rename clear_all_caches into cw_clear_all_cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   326
        super(WorkflowTransition, self).cw_clear_all_caches()
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   327
        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
   328
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   329
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   330
class SubWorkflowExitPoint(AnyEntity):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   331
    """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
   332
    __regid__ = 'SubWorkflowExitPoint'
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   333
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   334
    @property
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   335
    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
   336
        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
   337
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   338
    @property
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   339
    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
   340
        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
   341
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   342
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   343
class State(AnyEntity):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   344
    """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
   345
    __regid__ = 'State'
7827
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7406
diff changeset
   346
    fetch_attrs, cw_fetch_order = fetch_config(['name'])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   347
    rest_attr = 'eid'
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   348
8212
a045d3821990 [workflow view] Display a non-localized version of state/transition names (closes #1912537).
Damien Garaud <damien.garaud@logilab.fr>
parents: 7990
diff changeset
   349
    def dc_long_title(self):
a045d3821990 [workflow view] Display a non-localized version of state/transition names (closes #1912537).
Damien Garaud <damien.garaud@logilab.fr>
parents: 7990
diff changeset
   350
        return '%s (%s)' % (self.name, self._cw._(self.name))
a045d3821990 [workflow view] Display a non-localized version of state/transition names (closes #1912537).
Damien Garaud <damien.garaud@logilab.fr>
parents: 7990
diff changeset
   351
2975
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   352
    @property
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   353
    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
   354
        # take care, may be missing in multi-sources configuration
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   355
        return self.state_of and self.state_of[0] or None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   356
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   357
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   358
class TrInfo(AnyEntity):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   359
    """customized class for Transition information entities
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   360
    """
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   361
    __regid__ = 'TrInfo'
7827
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7406
diff changeset
   362
    fetch_attrs, cw_fetch_order = fetch_config(['creation_date', 'comment'],
9bbf83f68bcc [entity] upgrade fetch_[unrelated_]order to benefit from changes introduced in 3.14 (closes #1942758)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7406
diff changeset
   363
                                               pclass=None) # don't want modification_date
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   364
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   365
    def for_entity(self):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   366
        return self.wf_info_for[0]
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   367
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   368
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   369
    def previous_state(self):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   370
        return self.from_state[0]
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   371
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   372
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   373
    def new_state(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   374
        return self.to_state[0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   375
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   376
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   377
    def transition(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   378
        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
   379
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   380
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   381
9256
697a8181ba30 remove 3.9 bw compat
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8930
diff changeset
   382
class IWorkflowableAdapter(EntityAdapter):
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   383
    """base adapter providing workflow helper methods for workflowable entities.
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   384
    """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   385
    __regid__ = 'IWorkflowable'
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   386
    __select__ = relation_possible('in_state')
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   387
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   388
    @cached
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   389
    def cwetype_workflow(self):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   390
        """return the default workflow for entities of this type"""
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   391
        # XXX CWEType method
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   392
        wfrset = self._cw.execute('Any WF WHERE ET default_workflow WF, '
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8216
diff changeset
   393
                                  'ET name %(et)s', {'et': self.entity.cw_etype})
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   394
        if wfrset:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   395
            return wfrset.get_entity(0, 0)
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8216
diff changeset
   396
        self.warning("can't find any workflow for %s", self.entity.cw_etype)
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   397
        return None
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   398
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   399
    @property
2978
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   400
    def main_workflow(self):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   401
        """return current workflow applied to this entity"""
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   402
        if self.entity.custom_workflow:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   403
            return self.entity.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
   404
        return self.cwetype_workflow()
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   405
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   406
    @property
2978
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   407
    def current_workflow(self):
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   408
        """return current workflow applied to this entity"""
2991
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   409
        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
   410
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   411
    @property
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   412
    def current_state(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   413
        """return current state entity"""
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   414
        return self.entity.in_state and self.entity.in_state[0] or None
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   415
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   416
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   417
    def state(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   418
        """return current state name"""
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   419
        try:
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   420
            return self.current_state.name
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   421
        except AttributeError:
6904
cf869016a823 [workflow] fix warning: we want to see the adapted entity, not the adapter
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5557
diff changeset
   422
            self.warning('entity %s has no state', self.entity)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   423
            return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   424
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   425
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   426
    def printable_state(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   427
        """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
   428
        state = self.current_state
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   429
        if state:
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   430
            return self._cw._(state.name)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   431
        return u''
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   432
2947
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   433
    @property
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   434
    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
   435
        """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
   436
        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
   437
        """
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   438
        return self.entity.reverse_wf_info_for
2947
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   439
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   440
    def latest_trinfo(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   441
        """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
   442
        try:
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   443
            return self.workflow_history[-1]
3765
769dc0107f31 latst_trinfo : do not crash on absent wf history
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3757
diff changeset
   444
        except IndexError:
769dc0107f31 latst_trinfo : do not crash on absent wf history
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3757
diff changeset
   445
            return None
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   446
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   447
    def possible_transitions(self, type='normal'):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   448
        """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
   449
        expected to be in this state
3986
cc29eddf51ad add postcommit_event on Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3982
diff changeset
   450
        used only by the UI
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   451
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   452
        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
   453
            return
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   454
        rset = self._cw.execute(
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   455
            '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
   456
            'T type TT, T type %(type)s, '
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   457
            '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
   458
            {'x': self.current_state.eid, 'type': type,
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   459
             'wfeid': self.current_workflow.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   460
        for tr in rset.entities():
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   461
            if tr.may_be_fired(self.entity.eid):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   462
                yield tr
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   463
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   464
    def subworkflow_input_trinfo(self):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   465
        """return the TrInfo which has be recorded when this entity went into
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   466
        the current sub-workflow
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   467
        """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   468
        if self.main_workflow.eid == self.current_workflow.eid:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   469
            return # doesn't make sense
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   470
        subwfentries = []
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   471
        for trinfo in self.workflow_history:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   472
            if (trinfo.transition and
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   473
                trinfo.previous_state.workflow.eid != trinfo.new_state.workflow.eid):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   474
                # entering or leaving a subworkflow
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   475
                if (subwfentries and
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   476
                    subwfentries[-1].new_state.workflow.eid == trinfo.previous_state.workflow.eid and
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   477
                    subwfentries[-1].previous_state.workflow.eid == trinfo.new_state.workflow.eid):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   478
                    # leave
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   479
                    del subwfentries[-1]
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   480
                else:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   481
                    # enter
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   482
                    subwfentries.append(trinfo)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   483
        if not subwfentries:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   484
            return None
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   485
        return subwfentries[-1]
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   486
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   487
    def subworkflow_input_transition(self):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   488
        """return the transition which has went through the current sub-workflow
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   489
        """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   490
        return getattr(self.subworkflow_input_trinfo(), 'transition', None)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   491
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
   492
    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
   493
        kwargs = {}
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   494
        if comment is not None:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   495
            kwargs['comment'] = comment
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   496
            if commentformat is not None:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   497
                kwargs['comment_format'] = commentformat
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   498
        kwargs['wf_info_for'] = self.entity
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
   499
        if treid is not None:
4024
6a14cff373c3 more api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   500
            kwargs['by_transition'] = self._cw.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
   501
        if tseid is not None:
4024
6a14cff373c3 more api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   502
            kwargs['to_state'] = self._cw.entity_from_eid(tseid)
3720
5376aaadd16b backport stable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3675 3698
diff changeset
   503
        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
   504
7404
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   505
    def _get_transition(self, tr):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   506
        assert self.current_workflow
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   507
        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
   508
            _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
   509
            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
   510
                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
   511
            tr = _tr
7404
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   512
        return tr
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   513
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   514
    def fire_transition(self, tr, comment=None, commentformat=None):
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   515
        """change the entity's state by firing given transition (name or entity)
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   516
        in entity's workflow
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   517
        """
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   518
        tr = self._get_transition(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
   519
        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
   520
7404
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   521
    def fire_transition_if_possible(self, tr, comment=None, commentformat=None):
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   522
        """change the entity's state by firing given transition (name or entity)
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   523
        in entity's workflow if this transition is possible
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   524
        """
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   525
        tr = self._get_transition(tr)
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   526
        if any(tr_ for tr_ in self.possible_transitions()
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   527
               if tr_.eid == tr.eid):
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   528
            self.fire_transition(tr)
02a786d7ebce [workflow] new 'fire_transition_if_possible' method on IWorkflowable to fire a transition if it's possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7401
diff changeset
   529
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
   530
    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
   531
        """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
   532
        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
   533
        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
   534
        fire_transition should be used.
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   535
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   536
        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
   537
        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
   538
            stateeid = statename.eid
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   539
        else:
7990
a673d1d9a738 [diet] drop pre 3.6 API compatibility (but attempt to keep data cmopatibility). Closes #2017916
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7894
diff changeset
   540
            state = self.current_workflow.state_by_name(statename)
2980
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   541
            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
   542
                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
   543
                                                                statename))
2980
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   544
            stateeid = state.eid
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   545
        # 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
   546
        return self._add_trinfo(comment, commentformat, tr and tr.eid, stateeid)
7401
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   547
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   548
    def set_initial_state(self, statename):
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   549
        """set a newly created entity's state to the given state (name or entity)
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   550
        in entity's workflow. This is useful if you don't want it to be the
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   551
        workflow's initial state.
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   552
        """
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   553
        assert self.current_workflow
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   554
        if hasattr(statename, 'eid'):
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   555
            stateeid = statename.eid
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   556
        else:
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   557
            state = self.current_workflow.state_by_name(statename)
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   558
            if state is None:
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   559
                raise WorkflowException('not a %s state: %s' % (self.__regid__,
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   560
                                                                statename))
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   561
            stateeid = state.eid
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   562
        self._cw.execute('SET X in_state S WHERE X eid %(x)s, S eid %(s)s',
fded980bbd65 [workflow] add method on IWorkflowable to set initial state of an entity (closes #1686357)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6904
diff changeset
   563
                         {'x': self.entity.eid, 's': stateeid})