cubicweb/entities/wfobjs.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 06 Jun 2016 15:26:49 +0200
changeset 11699 b48020a80dc3
parent 11057 0b59724cb3f2
child 11767 432f87a63057
permissions -rw-r--r--
Store user groups and properties as session data * stop retrieving them systematically, only when need, * reimplement session synchronization hooks with some cleanups along the way, * cleanup call to set language: not needed from the base request nor from the server side, only for the web request (on the server side, language is necessary only for notification and such code should set it explicitly). There is still a XXX remaining about one can only "enter" a connection once and this is a problem in some cases. IMO, this restriction could be removed. Closes #13500113.
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
"""
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10473
diff changeset
    24
from __future__ import print_function
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
    25
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    26
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    27
10682
7e111b606005 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
    28
from six import text_type, string_types
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    29
2948
d3cd8bd20ee5 override clear_all_caches to clear cwetype_workflow cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2947
diff changeset
    30
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
    31
from logilab.common.deprecation import deprecated
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    32
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    33
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
    34
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
    35
from cubicweb.predicates import relation_possible
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    36
10096
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
    37
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
    38
try:
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
    39
    from cubicweb import server
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
    40
except ImportError:
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
    41
    # We need to lookup DEBUG from there,
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
    42
    # however a pure dbapi client may not have it.
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
    43
    class server(object): pass
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
    44
    server.DEBUG = False
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
    45
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
    46
2988
89d97d7c0508 [wf] use custom exception class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2987
diff changeset
    47
class WorkflowException(Exception): pass
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
    48
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    49
class Workflow(AnyEntity):
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
    50
    __regid__ = 'Workflow'
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    51
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    52
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    53
    def initial(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    54
        """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
    55
        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
    56
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    57
    def is_default_workflow_of(self, etype):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    58
        """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
    59
        entity type
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    60
        """
2943
77622caef9bd [schema] default_workflow_of more naturally expressed as default_workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
    61
        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
    62
                   if et.name == etype)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    63
2976
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    64
    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
    65
        """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
    66
        subworkflows
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    67
        """
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    68
        # infinite loop safety belt
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    69
        if _done is None:
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    70
            _done = set()
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    71
        yield self
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    72
        _done.add(self.eid)
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
    73
        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
    74
                                   '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
    75
                                   {'wf': self.eid}).entities():
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    76
            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
    77
                continue
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    78
            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
    79
                yield subwf
d01417c14f35 [wf] new iter_worfklows method on workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2975
diff changeset
    80
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    81
    # state / transitions accessors ############################################
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    82
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    83
    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
    84
        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
    85
                                '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
    86
                                {'n': statename, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    87
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    88
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    89
        return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    90
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    91
    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
    92
        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
    93
                                '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
    94
                                {'s': eid, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    95
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    96
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    97
        return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    98
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
    99
    def 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
   100
        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
   101
                                'T transition_of WF, WF eid %(wf)s',
10682
7e111b606005 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   102
                                {'n': text_type(trname), 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   103
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   104
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   105
        return None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   106
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   107
    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
   108
        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
   109
                                '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
   110
                                {'t': eid, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   111
        if rset:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   112
            return rset.get_entity(0, 0)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   113
        return None
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   114
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   115
    # wf construction methods ##################################################
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   116
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   117
    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
   118
        """add a state to this workflow"""
10682
7e111b606005 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   119
        state = self._cw.create_entity('State', name=text_type(name), **kwargs)
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   120
        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
   121
                         {'s': state.eid, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   122
        if initial:
3959
e6ecaf93c0ba improve error message for redundant initial workflow states
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 3765
diff changeset
   123
            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
   124
            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
   125
                             '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
   126
                             {'s': state.eid, 'wf': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   127
        return state
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   128
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   129
    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
   130
                        requiredgroups=(), conditions=(), **kwargs):
10682
7e111b606005 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   131
        tr = self._cw.create_entity(trtype, name=text_type(name), **kwargs)
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   132
        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
   133
                         '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
   134
                         {'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
   135
        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
   136
        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
   137
            fromstates = (fromstates,)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   138
        for state in fromstates:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   139
            if hasattr(state, 'eid'):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   140
                state = state.eid
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   141
            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
   142
                             '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
   143
                             {'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
   144
        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
   145
        return tr
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   146
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
   147
    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
   148
                       requiredgroups=(), conditions=(), **kwargs):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   149
        """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
   150
        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
   151
                                  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
   152
        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
   153
            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
   154
                tostate = tostate.eid
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   155
            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
   156
                             '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
   157
                             {'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
   158
        return tr
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   159
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
   160
    def add_wftransition(self, name, subworkflow, fromstates, exitpoints=(),
3582
28547f21308e two bits of docstring
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3542
diff changeset
   161
                         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
   162
        """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
   163
        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
   164
                                  requiredgroups, conditions, **kwargs)
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   165
        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
   166
            subworkflow = subworkflow.eid
4024
6a14cff373c3 more api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   167
        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
   168
                                {'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
   169
        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
   170
            tr.add_exit_point(fromstate, tostate)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   171
        return tr
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   172
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
   173
    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
   174
        """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
   175
        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
   176
            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
   177
        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
   178
            replacement = self.state_by_name(replacement)
10374
699e49d76334 [wf] Fix Workflow.replace_state()
Christophe de Vienne <christophe@unlish.com>
parents: 10096
diff changeset
   179
        args = {'os': todelstate.eid, 'ns': replacement.eid}
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
   180
        execute = self._cw.execute
10374
699e49d76334 [wf] Fix Workflow.replace_state()
Christophe de Vienne <christophe@unlish.com>
parents: 10096
diff changeset
   181
        execute('SET X in_state NS WHERE X in_state OS, '
699e49d76334 [wf] Fix Workflow.replace_state()
Christophe de Vienne <christophe@unlish.com>
parents: 10096
diff changeset
   182
                'NS eid %(ns)s, OS eid %(os)s', args)
699e49d76334 [wf] Fix Workflow.replace_state()
Christophe de Vienne <christophe@unlish.com>
parents: 10096
diff changeset
   183
        execute('SET X from_state NS WHERE X from_state OS, '
699e49d76334 [wf] Fix Workflow.replace_state()
Christophe de Vienne <christophe@unlish.com>
parents: 10096
diff changeset
   184
                'OS eid %(os)s, NS eid %(ns)s', args)
699e49d76334 [wf] Fix Workflow.replace_state()
Christophe de Vienne <christophe@unlish.com>
parents: 10096
diff changeset
   185
        execute('SET X to_state NS WHERE X to_state OS, '
699e49d76334 [wf] Fix Workflow.replace_state()
Christophe de Vienne <christophe@unlish.com>
parents: 10096
diff changeset
   186
                'OS eid %(os)s, NS eid %(ns)s', args)
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
   187
        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
   188
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   189
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   190
class BaseTransition(AnyEntity):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   191
    """customized class for abstract transition
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   192
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   193
    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
   194
    fired by the logged user
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
    """
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   196
    __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
   197
    fetch_attrs, cw_fetch_order = fetch_config(['name', 'type'])
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   198
2951
d0b77dd27740 [wf] BaseTransition is a virtual type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2948
diff changeset
   199
    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
   200
        if self.cw_etype == 'BaseTransition':
2988
89d97d7c0508 [wf] use custom exception class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2987
diff changeset
   201
            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
   202
        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
   203
2975
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   204
    @property
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   205
    def workflow(self):
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   206
        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
   207
2991
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   208
    def has_input_state(self, state):
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   209
        if hasattr(state, 'eid'):
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   210
            state = state.eid
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   211
        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
   212
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   213
    def may_be_fired(self, eid):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   214
        """return true if the logged user may fire this transition
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   215
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   216
        `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
   217
        """
10096
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
   218
        DBG = False
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
   219
        if server.DEBUG & server.DBG_SEC:
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
   220
            if 'transition' in server._SECURITY_CAPS:
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
   221
                DBG = True
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   222
        user = self._cw.user
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   223
        # 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
   224
        groups = frozenset(g.name for g in self.require_group)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   225
        if groups:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   226
            matches = user.matching_groups(groups)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   227
            if matches:
10096
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
   228
                if DBG:
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10473
diff changeset
   229
                    print('may_be_fired: %r may fire: user matches %s' % (self.name, groups))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   230
                return matches
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   231
            if 'owners' in groups and user.owns(eid):
10096
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
   232
                if DBG:
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10473
diff changeset
   233
                    print('may_be_fired: %r may fire: user is owner' % self.name)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   234
                return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   235
        # check one of the rql expression conditions matches if any
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   236
        if self.condition:
10096
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
   237
            if DBG:
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10473
diff changeset
   238
                print('my_be_fired: %r: %s' %
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10473
diff changeset
   239
                      (self.name, [(rqlexpr.expression,
10096
decd60fa8cc5 [entities/wfobjs] add missing `DBG_SEC` debugging informations and a new `transition` capability
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10095
diff changeset
   240
                                    rqlexpr.check_expression(self._cw, eid))
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10473
diff changeset
   241
                                    for rqlexpr in self.condition]))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   242
            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
   243
                if rqlexpr.check_expression(self._cw, eid):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   244
                    return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   245
        if self.condition or groups:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   246
            return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   247
        return True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   248
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
   249
    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
   250
        """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
   251
        transition
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   252
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   253
        if reset:
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   254
            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
   255
                             {'x': self.eid})
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   256
            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
   257
                             {'x': self.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   258
        for gname in requiredgroups:
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   259
            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
   260
                                    'WHERE T eid %(x)s, G name %(gn)s',
10682
7e111b606005 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   261
                                    {'x': self.eid, 'gn': text_type(gname)})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   262
            assert rset, '%s is not a known group' % gname
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
   263
        if isinstance(conditions, string_types):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   264
            conditions = (conditions,)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   265
        for expr in conditions:
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
   266
            if isinstance(expr, string_types):
10682
7e111b606005 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   267
                kwargs = {'expr': text_type(expr)}
3542
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   268
            else:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   269
                assert isinstance(expr, dict)
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   270
                kwargs = expr
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   271
            kwargs['x'] = self.eid
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   272
            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
   273
            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
   274
                             '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
   275
                             '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
   276
        # XXX clear caches?
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   277
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
class Transition(BaseTransition):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   280
    """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
   281
    __regid__ = 'Transition'
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   282
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
   283
    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
   284
        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
   285
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
   286
    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
   287
        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
   288
            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
   289
        except IndexError:
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   290
            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
   291
4646
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   292
    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
   293
        try:
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   294
            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
   295
        except IndexError:
4647
6d7589b4ae6f [workflow] fix potential destination for go back transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4646
diff changeset
   296
            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
   297
                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
   298
                    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
   299
                        yield previousstate
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   300
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   301
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   302
class WorkflowTransition(BaseTransition):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   303
    """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
   304
    __regid__ = 'WorkflowTransition'
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   305
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   306
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   307
    def subwf(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   308
        return self.subworkflow[0]
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   309
4646
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   310
    def destination(self, entity):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   311
        return self.subwf.initial
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   312
4646
322c3dd96dd5 [workflow] finish refactoring introduced by 021035b9a7ab for 'go back' transition:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4645
diff changeset
   313
    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
   314
        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
   315
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   316
    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
   317
        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
   318
            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
   319
        if tostate is None:
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   320
            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
   321
                             '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
   322
                             {'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
   323
        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
   324
            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
   325
                tostate = tostate.eid
3629
559cad62c786 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3589 3628
diff changeset
   326
            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
   327
                             '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
   328
                             '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
   329
                             {'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
   330
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
   331
    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
   332
        """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
   333
        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
   334
            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
   335
        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
   336
            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
   337
        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
   338
            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
   339
        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
   340
            # 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
   341
            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
   342
        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
   343
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   344
    @cached
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   345
    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
   346
        result = {}
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   347
        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
   348
            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
   349
        return result
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   350
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
   351
    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
   352
        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
   353
        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
   354
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   355
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   356
class SubWorkflowExitPoint(AnyEntity):
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   357
    """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
   358
    __regid__ = 'SubWorkflowExitPoint'
2986
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   359
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   360
    @property
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   361
    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
   362
        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
   363
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   364
    @property
d8f2e53702be [wf] new methods to build wf w/ workflow transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2980
diff changeset
   365
    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
   366
        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
   367
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   368
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   369
class State(AnyEntity):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   370
    """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
   371
    __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
   372
    fetch_attrs, cw_fetch_order = fetch_config(['name'])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   373
    rest_attr = 'eid'
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   374
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
   375
    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
   376
        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
   377
2975
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   378
    @property
fed52d317ba7 [wf] new .workflow property on states and transitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2954
diff changeset
   379
    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
   380
        # 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
   381
        return self.state_of and self.state_of[0] or None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   382
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   383
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   384
class TrInfo(AnyEntity):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   385
    """customized class for Transition information entities
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   386
    """
3377
dd9d292b6a6d use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   387
    __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
   388
    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
   389
                                               pclass=None) # don't want modification_date
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   390
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   391
    def for_entity(self):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   392
        return self.wf_info_for[0]
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   393
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   394
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   395
    def previous_state(self):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   396
        return self.from_state[0]
1572
469787f6ea2b delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1154
diff changeset
   397
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   398
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   399
    def new_state(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   400
        return self.to_state[0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   401
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   402
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   403
    def transition(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   404
        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
   405
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   406
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   407
9256
697a8181ba30 remove 3.9 bw compat
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8930
diff changeset
   408
class IWorkflowableAdapter(EntityAdapter):
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   409
    """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
   410
    """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   411
    __regid__ = 'IWorkflowable'
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   412
    __select__ = relation_possible('in_state')
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   413
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   414
    @cached
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   415
    def cwetype_workflow(self):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   416
        """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
   417
        # XXX CWEType method
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   418
        wfrset = self._cw.execute('Any WF WHERE ET default_workflow WF, '
10682
7e111b606005 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   419
                                  'ET name %(et)s', {'et': text_type(self.entity.cw_etype)})
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   420
        if wfrset:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   421
            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
   422
        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
   423
        return None
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   424
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   425
    @property
2978
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   426
    def main_workflow(self):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   427
        """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
   428
        if self.entity.custom_workflow:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   429
            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
   430
        return self.cwetype_workflow()
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   431
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   432
    @property
2978
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   433
    def current_workflow(self):
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   434
        """return current workflow applied to this entity"""
2991
dab951c08896 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2990
diff changeset
   435
        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
   436
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2976
diff changeset
   437
    @property
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   438
    def current_state(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   439
        """return current state entity"""
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   440
        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
   441
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   442
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   443
    def state(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   444
        """return current state name"""
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   445
        try:
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   446
            return self.current_state.name
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   447
        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
   448
            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
   449
            return None
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
    @property
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   452
    def printable_state(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   453
        """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
   454
        state = self.current_state
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   455
        if state:
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   456
            return self._cw._(state.name)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   457
        return u''
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   458
2947
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   459
    @property
083593802120 [wf] new workflow_history property, nicer the reverse_wf_info_for...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2946
diff changeset
   460
    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
   461
        """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
   462
        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
   463
        """
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   464
        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
   465
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   466
    def latest_trinfo(self):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   467
        """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
   468
        try:
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   469
            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
   470
        except IndexError:
769dc0107f31 latst_trinfo : do not crash on absent wf history
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3757
diff changeset
   471
            return None
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   472
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   473
    def possible_transitions(self, type='normal'):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   474
        """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
   475
        expected to be in this state
3986
cc29eddf51ad add postcommit_event on Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3982
diff changeset
   476
        used only by the UI
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   477
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   478
        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
   479
            return
3406
e343f37f7013 use self._cw instead of self.req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3405
diff changeset
   480
        rset = self._cw.execute(
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   481
            '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
   482
            'T type TT, T type %(type)s, '
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3038
diff changeset
   483
            'T name TN, T transition_of WF, WF eid %(wfeid)s',
10682
7e111b606005 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   484
            {'x': self.current_state.eid, 'type': text_type(type),
5174
78438ad513ca #759035: Automate addition of eid cachekey in RQL analysis
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4835
diff changeset
   485
             'wfeid': self.current_workflow.eid})
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   486
        for tr in rset.entities():
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   487
            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
   488
                yield tr
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   489
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   490
    def subworkflow_input_trinfo(self):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   491
        """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
   492
        the current sub-workflow
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   493
        """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   494
        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
   495
            return # doesn't make sense
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   496
        subwfentries = []
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   497
        for trinfo in self.workflow_history:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   498
            if (trinfo.transition and
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   499
                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
   500
                # entering or leaving a subworkflow
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   501
                if (subwfentries and
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   502
                    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
   503
                    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
   504
                    # leave
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   505
                    del subwfentries[-1]
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   506
                else:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   507
                    # enter
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   508
                    subwfentries.append(trinfo)
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   509
        if not subwfentries:
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   510
            return None
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   511
        return subwfentries[-1]
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   512
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   513
    def subworkflow_input_transition(self):
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   514
        """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
   515
        """
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   516
        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
   517
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
    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
   519
        kwargs = {}
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   520
        if comment is not None:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   521
            kwargs['comment'] = comment
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   522
            if commentformat is not None:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   523
                kwargs['comment_format'] = commentformat
5556
9ab2b4c74baf [entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   524
        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
   525
        if treid is not None:
4024
6a14cff373c3 more api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   526
            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
   527
        if tseid is not None:
4024
6a14cff373c3 more api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   528
            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
   529
        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
   530
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
   531
    def _get_transition(self, tr):
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   532
        assert self.current_workflow
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
   533
        if isinstance(tr, string_types):
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
   534
            _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
   535
            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
   536
                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
   537
            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
   538
        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
   539
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
   540
    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
   541
        """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
   542
        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
   543
        """
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
   544
        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
   545
        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
   546
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
   547
    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
   548
        """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
   549
        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
   550
        """
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
   551
        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
   552
        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
   553
               if tr_.eid == tr.eid):
10831
f1b5a5ea0da0 [entities] parameters should be given to fire_transition, else they are simply ignored
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10682
diff changeset
   554
            self.fire_transition(tr, comment, commentformat)
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
   555
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
   556
    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
   557
        """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
   558
        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
   559
        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
   560
        fire_transition should be used.
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   561
        """
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   562
        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
   563
        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
   564
            stateeid = statename.eid
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   565
        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
   566
            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
   567
            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
   568
                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
   569
                                                                statename))
2980
292387ed37f3 [wf] allow state entity as argument to change_state
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   570
            stateeid = state.eid
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2917
diff changeset
   571
        # 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
   572
        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
   573
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
   574
    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
   575
        """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
   576
        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
   577
        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
   578
        """
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
   579
        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
   580
        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
   581
            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
   582
        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
   583
            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
   584
            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
   585
                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
   586
                                                                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
   587
            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
   588
        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
   589
                         {'x': self.entity.eid, 's': stateeid})