entities/wfobjs.py
author Julien Cristau <julien.cristau@logilab.fr>
Thu, 22 Jan 2015 17:22:09 +0100
changeset 10158 efc8645ece43
parent 9928 0d831b40fa48
child 10095 200bd6a601dc
permissions -rw-r--r--
[server/test] convert new test to 3.19 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
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    30
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    31
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
    32
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
    33
from cubicweb.predicates import relation_possible
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    34
2988
89d97d7c0508 [wf] use custom exception class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2987
diff changeset
    35
class WorkflowException(Exception): pass
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
    36
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    37
class Workflow(AnyEntity):
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
    38
    __regid__ = 'Workflow'
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    39
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    40
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    41
    def initial(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    42
        """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
    43
        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
    44
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    45
    def is_default_workflow_of(self, etype):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    46
        """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
    47
        entity type
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    48
        """
2943
77622caef9bd [schema] default_workflow_of more naturally expressed as default_workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
    49
        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
    50
                   if et.name == etype)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    51
2976
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    52
    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
    53
        """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
    54
        subworkflows
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    55
        """
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    56
        # infinite loop safety belt
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    57
        if _done is None:
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    58
            _done = set()
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    59
        yield self
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    60
        _done.add(self.eid)
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
    61
        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
    62
                                   '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
    63
                                   {'wf': self.eid}).entities():
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    64
            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
    65
                continue
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    66
            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
    67
                yield subwf
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    68
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    69
    # state / transitions accessors ############################################
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    70
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    71
    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
    72
        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
    73
                                '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
    74
                                {'n': statename, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    75
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    76
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    77
        return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    78
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    79
    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
    80
        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
    81
                                '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
    82
                                {'s': eid, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    83
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    84
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    85
        return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    86
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    87
    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
    88
        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
    89
                                '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
    90
                                {'n': trname, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    91
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    92
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    93
        return None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    94
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    95
    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
    96
        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
    97
                                '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
    98
                                {'t': eid, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    99
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   100
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   101
        return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   102
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   103
    # wf construction methods ##################################################
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   104
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   105
    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
   106
        """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
   107
        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
   108
        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
   109
                         {'s': state.eid, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   110
        if initial:
3959
e6ecaf93c0ba improve error message for redundant initial workflow states
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 3765
diff changeset
   111
            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
   112
            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
   113
                             '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
   114
                             {'s': state.eid, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   115
        return state
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   116
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   117
    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
   118
                        requiredgroups=(), conditions=(), **kwargs):
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   119
        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
   120
        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
   121
                         '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
   122
                         {'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
   123
        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
   124
        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
   125
            fromstates = (fromstates,)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   126
        for state in fromstates:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   127
            if hasattr(state, 'eid'):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   128
                state = state.eid
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   129
            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
   130
                             '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
   131
                             {'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
   132
        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
   133
        return tr
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   134
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
   135
    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
   136
                       requiredgroups=(), conditions=(), **kwargs):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   137
        """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
   138
        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
   139
                                  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
   140
        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
   141
            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
   142
                tostate = tostate.eid
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   143
            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
   144
                             '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
   145
                             {'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
   146
        return tr
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   147
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
   148
    def add_wftransition(self, name, subworkflow, fromstates, exitpoints=(),
3582
28547f21308e two bits of docstring
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3542
diff changeset
   149
                         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
   150
        """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
   151
        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
   152
                                  requiredgroups, conditions, **kwargs)
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   153
        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
   154
            subworkflow = subworkflow.eid
4024
6a14cff373c3 more api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   155
        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
   156
                                {'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
   157
        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
   158
            tr.add_exit_point(fromstate, tostate)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   159
        return tr
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   160
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
   161
    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
   162
        """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
   163
        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
   164
            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
   165
        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
   166
            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
   167
        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
   168
        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
   169
        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
   170
                {'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
   171
        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
   172
                {'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
   173
        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
   174
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   175
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   176
class BaseTransition(AnyEntity):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   177
    """customized class for abstract transition
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   178
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   179
    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
   180
    fired by the logged user
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
    """
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   182
    __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
   183
    fetch_attrs, cw_fetch_order = fetch_config(['name', 'type'])
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   184
2951
d0b77dd27740 [wf] BaseTransition is a virtual type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2948
diff changeset
   185
    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
   186
        if self.cw_etype == 'BaseTransition':
2988
89d97d7c0508 [wf] use custom exception class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2987
diff changeset
   187
            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
   188
        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
   189
2975
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   190
    @property
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   191
    def workflow(self):
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   192
        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
   193
2991
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   194
    def has_input_state(self, state):
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   195
        if hasattr(state, 'eid'):
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   196
            state = state.eid
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   197
        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
   198
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   199
    def may_be_fired(self, eid):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   200
        """return true if the logged user may fire this transition
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   202
        `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
   203
        """
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   204
        user = self._cw.user
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   205
        # 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
   206
        groups = frozenset(g.name for g in self.require_group)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   207
        if groups:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
            matches = user.matching_groups(groups)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
            if matches:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
                return matches
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
            if 'owners' in groups and user.owns(eid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   212
                return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
        # check one of the rql expression conditions matches if any
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   214
        if self.condition:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   215
            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
   216
                if rqlexpr.check_expression(self._cw, eid):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   217
                    return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   218
        if self.condition or groups:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   219
            return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   220
        return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   221
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
   222
    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
   223
        """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
   224
        transition
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   225
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   226
        if reset:
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   227
            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
   228
                             {'x': self.eid})
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   229
            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
   230
                             {'x': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   231
        for gname in requiredgroups:
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   232
            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
   233
                                    '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
   234
                                    {'x': self.eid, 'gn': gname})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   235
            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
   236
        if isinstance(conditions, basestring):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   237
            conditions = (conditions,)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   238
        for expr in conditions:
3542
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   239
            if isinstance(expr, basestring):
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   240
                kwargs = {'expr': unicode(expr)}
3542
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   241
            else:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   242
                assert isinstance(expr, dict)
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   243
                kwargs = expr
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   244
            kwargs['x'] = self.eid
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   245
            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
   246
            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
   247
                             '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
   248
                             '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
   249
        # XXX clear caches?
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   250
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
class Transition(BaseTransition):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   253
    """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
   254
    __regid__ = 'Transition'
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   255
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
   256
    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
   257
        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
   258
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
   259
    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
   260
        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
   261
            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
   262
        except IndexError:
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   263
            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
   264
4646
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   265
    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
   266
        try:
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   267
            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
   268
        except IndexError:
4647
6d7589b4ae6f [workflow] fix potential destination for go back transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4646
diff changeset
   269
            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
   270
                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
   271
                    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
   272
                        yield previousstate
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   273
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
class WorkflowTransition(BaseTransition):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   276
    """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
   277
    __regid__ = 'WorkflowTransition'
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   278
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   279
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   280
    def subwf(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   281
        return self.subworkflow[0]
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   282
4646
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   283
    def destination(self, entity):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   284
        return self.subwf.initial
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   285
4646
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   286
    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
   287
        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
   288
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   289
    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
   290
        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
   291
            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
   292
        if tostate is None:
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   293
            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
   294
                             '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
   295
                             {'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
   296
        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
   297
            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
   298
                tostate = tostate.eid
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   299
            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
   300
                             '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
   301
                             '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
   302
                             {'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
   303
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
   304
    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
   305
        """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
   306
        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
   307
            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
   308
        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
   309
            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
   310
        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
   311
            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
   312
        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
   313
            # 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
   314
            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
   315
        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
   316
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   317
    @cached
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   318
    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
   319
        result = {}
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   320
        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
   321
            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
   322
        return result
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   323
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
   324
    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
   325
        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
   326
        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
   327
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
class SubWorkflowExitPoint(AnyEntity):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   330
    """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
   331
    __regid__ = 'SubWorkflowExitPoint'
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   332
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   333
    @property
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   334
    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
   335
        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
   336
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   337
    @property
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   338
    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
   339
        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
   340
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   341
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   342
class State(AnyEntity):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   343
    """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
   344
    __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
   345
    fetch_attrs, cw_fetch_order = fetch_config(['name'])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   346
    rest_attr = 'eid'
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   347
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
   348
    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
   349
        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
   350
2975
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   351
    @property
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   352
    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
   353
        # 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
   354
        return self.state_of and self.state_of[0] or None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   355
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   356
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   357
class TrInfo(AnyEntity):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   358
    """customized class for Transition information entities
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   359
    """
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   360
    __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
   361
    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
   362
                                               pclass=None) # don't want modification_date
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   363
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   364
    def for_entity(self):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   365
        return self.wf_info_for[0]
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   366
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   367
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   368
    def previous_state(self):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   369
        return self.from_state[0]
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   370
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   371
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   372
    def new_state(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   373
        return self.to_state[0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   374
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   375
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   376
    def transition(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   377
        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
   378
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   379
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   380
9256
697a8181ba30 remove 3.9 bw compat
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8930
diff changeset
   381
class IWorkflowableAdapter(EntityAdapter):
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   382
    """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
   383
    """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   384
    __regid__ = 'IWorkflowable'
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   385
    __select__ = relation_possible('in_state')
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   386
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   387
    @cached
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   388
    def cwetype_workflow(self):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   389
        """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
   390
        # XXX CWEType method
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   391
        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
   392
                                  '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
   393
        if wfrset:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   394
            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
   395
        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
   396
        return None
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   397
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   398
    @property
2978
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   399
    def main_workflow(self):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   400
        """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
   401
        if self.entity.custom_workflow:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   402
            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
   403
        return self.cwetype_workflow()
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   404
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   405
    @property
2978
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   406
    def current_workflow(self):
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   407
        """return current workflow applied to this entity"""
2991
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   408
        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
   409
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   410
    @property
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   411
    def current_state(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   412
        """return current state entity"""
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   413
        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
   414
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   415
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   416
    def state(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   417
        """return current state name"""
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   418
        try:
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   419
            return self.current_state.name
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   420
        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
   421
            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
   422
            return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   423
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   424
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   425
    def printable_state(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   426
        """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
   427
        state = self.current_state
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   428
        if state:
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   429
            return self._cw._(state.name)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   430
        return u''
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   431
2947
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   432
    @property
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   433
    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
   434
        """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
   435
        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
   436
        """
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   437
        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
   438
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   439
    def latest_trinfo(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   440
        """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
   441
        try:
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   442
            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
   443
        except IndexError:
769dc0107f31 latst_trinfo : do not crash on absent wf history
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3757
diff changeset
   444
            return None
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   445
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   446
    def possible_transitions(self, type='normal'):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   447
        """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
   448
        expected to be in this state
3986
cc29eddf51ad add postcommit_event on Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3982
diff changeset
   449
        used only by the UI
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   450
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   451
        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
   452
            return
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   453
        rset = self._cw.execute(
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   454
            '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
   455
            'T type TT, T type %(type)s, '
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   456
            '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
   457
            {'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
   458
             'wfeid': self.current_workflow.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   459
        for tr in rset.entities():
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   460
            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
   461
                yield tr
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   462
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   463
    def subworkflow_input_trinfo(self):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   464
        """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
   465
        the current sub-workflow
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   466
        """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   467
        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
   468
            return # doesn't make sense
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   469
        subwfentries = []
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   470
        for trinfo in self.workflow_history:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   471
            if (trinfo.transition and
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   472
                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
   473
                # entering or leaving a subworkflow
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   474
                if (subwfentries and
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   475
                    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
   476
                    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
   477
                    # leave
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   478
                    del subwfentries[-1]
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   479
                else:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   480
                    # enter
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   481
                    subwfentries.append(trinfo)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   482
        if not subwfentries:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   483
            return None
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   484
        return subwfentries[-1]
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   485
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   486
    def subworkflow_input_transition(self):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   487
        """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
   488
        """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   489
        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
   490
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
   491
    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
   492
        kwargs = {}
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   493
        if comment is not None:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   494
            kwargs['comment'] = comment
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   495
            if commentformat is not None:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   496
                kwargs['comment_format'] = commentformat
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   497
        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
   498
        if treid is not None:
4024
6a14cff373c3 more api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   499
            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
   500
        if tseid is not None:
4024
6a14cff373c3 more api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   501
            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
   502
        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
   503
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
   504
    def _get_transition(self, tr):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   505
        assert self.current_workflow
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   506
        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
   507
            _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
   508
            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
   509
                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
   510
            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
   511
        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
   512
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
    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
   514
        """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
   515
        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
   516
        """
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
        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
   518
        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
   519
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
   520
    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
   521
        """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
   522
        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
   523
        """
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
        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
   525
        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
   526
               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
   527
            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
   528
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
   529
    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
   530
        """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
   531
        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
   532
        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
   533
        fire_transition should be used.
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   534
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   535
        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
   536
        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
   537
            stateeid = statename.eid
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   538
        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
   539
            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
   540
            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
   541
                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
   542
                                                                statename))
2980
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   543
            stateeid = state.eid
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   544
        # 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
   545
        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
   546
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
    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
   548
        """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
   549
        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
   550
        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
   551
        """
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
        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
   553
        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
   554
            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
   555
        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
   556
            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
   557
            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
   558
                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
   559
                                                                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
   560
            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
   561
        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
   562
                         {'x': self.entity.eid, 's': stateeid})