cubicweb/entities/wfobjs.py
changeset 12567 26744ad37953
parent 12506 d97f9b8df92a
child 12880 59d4ad7e7df3
equal deleted inserted replaced
12566:6b3523f81f42 12567:26744ad37953
    19 
    19 
    20 * entity types defining workflow (Workflow, State, Transition...)
    20 * entity types defining workflow (Workflow, State, Transition...)
    21 * workflow history (TrInfo)
    21 * workflow history (TrInfo)
    22 * adapter for workflowable entities (IWorkflowableAdapter)
    22 * adapter for workflowable entities (IWorkflowableAdapter)
    23 """
    23 """
    24 from __future__ import print_function
       
    25 
       
    26 
       
    27 
       
    28 from six import text_type, string_types
       
    29 
       
    30 from logilab.common.decorators import cached, clear_cache
    24 from logilab.common.decorators import cached, clear_cache
    31 
    25 
    32 from cubicweb.entities import AnyEntity, fetch_config
    26 from cubicweb.entities import AnyEntity, fetch_config
    33 from cubicweb.view import EntityAdapter
    27 from cubicweb.view import EntityAdapter
    34 from cubicweb.predicates import relation_possible
    28 from cubicweb.predicates import relation_possible
    96         return None
    90         return None
    97 
    91 
    98     def transition_by_name(self, trname):
    92     def transition_by_name(self, trname):
    99         rset = self._cw.execute('Any T, TN WHERE T name TN, T name %(n)s, '
    93         rset = self._cw.execute('Any T, TN WHERE T name TN, T name %(n)s, '
   100                                 'T transition_of WF, WF eid %(wf)s',
    94                                 'T transition_of WF, WF eid %(wf)s',
   101                                 {'n': text_type(trname), 'wf': self.eid})
    95                                 {'n': trname, 'wf': self.eid})
   102         if rset:
    96         if rset:
   103             return rset.get_entity(0, 0)
    97             return rset.get_entity(0, 0)
   104         return None
    98         return None
   105 
    99 
   106     def transition_by_eid(self, eid):
   100     def transition_by_eid(self, eid):
   113 
   107 
   114     # wf construction methods ##################################################
   108     # wf construction methods ##################################################
   115 
   109 
   116     def add_state(self, name, initial=False, **kwargs):
   110     def add_state(self, name, initial=False, **kwargs):
   117         """add a state to this workflow"""
   111         """add a state to this workflow"""
   118         state = self._cw.create_entity('State', name=text_type(name), **kwargs)
   112         state = self._cw.create_entity('State', name=name, **kwargs)
   119         self._cw.execute('SET S state_of WF WHERE S eid %(s)s, WF eid %(wf)s',
   113         self._cw.execute('SET S state_of WF WHERE S eid %(s)s, WF eid %(wf)s',
   120                          {'s': state.eid, 'wf': self.eid})
   114                          {'s': state.eid, 'wf': self.eid})
   121         if initial:
   115         if initial:
   122             assert not self.initial, "Initial state already defined as %s" % self.initial
   116             assert not self.initial, "Initial state already defined as %s" % self.initial
   123             self._cw.execute('SET WF initial_state S '
   117             self._cw.execute('SET WF initial_state S '
   125                              {'s': state.eid, 'wf': self.eid})
   119                              {'s': state.eid, 'wf': self.eid})
   126         return state
   120         return state
   127 
   121 
   128     def _add_transition(self, trtype, name, fromstates,
   122     def _add_transition(self, trtype, name, fromstates,
   129                         requiredgroups=(), conditions=(), **kwargs):
   123                         requiredgroups=(), conditions=(), **kwargs):
   130         tr = self._cw.create_entity(trtype, name=text_type(name), **kwargs)
   124         tr = self._cw.create_entity(trtype, name=name, **kwargs)
   131         self._cw.execute('SET T transition_of WF '
   125         self._cw.execute('SET T transition_of WF '
   132                          'WHERE T eid %(t)s, WF eid %(wf)s',
   126                          'WHERE T eid %(t)s, WF eid %(wf)s',
   133                          {'t': tr.eid, 'wf': self.eid})
   127                          {'t': tr.eid, 'wf': self.eid})
   134         assert fromstates, fromstates
   128         assert fromstates, fromstates
   135         if not isinstance(fromstates, (tuple, list)):
   129         if not isinstance(fromstates, (tuple, list)):
   255             self._cw.execute('DELETE T condition R WHERE T eid %(x)s',
   249             self._cw.execute('DELETE T condition R WHERE T eid %(x)s',
   256                              {'x': self.eid})
   250                              {'x': self.eid})
   257         for gname in requiredgroups:
   251         for gname in requiredgroups:
   258             rset = self._cw.execute('SET T require_group G '
   252             rset = self._cw.execute('SET T require_group G '
   259                                     'WHERE T eid %(x)s, G name %(gn)s',
   253                                     'WHERE T eid %(x)s, G name %(gn)s',
   260                                     {'x': self.eid, 'gn': text_type(gname)})
   254                                     {'x': self.eid, 'gn': gname})
   261             assert rset, '%s is not a known group' % gname
   255             assert rset, '%s is not a known group' % gname
   262         if isinstance(conditions, string_types):
   256         if isinstance(conditions, str):
   263             conditions = (conditions,)
   257             conditions = (conditions,)
   264         for expr in conditions:
   258         for expr in conditions:
   265             if isinstance(expr, string_types):
   259             if isinstance(expr, str):
   266                 kwargs = {'expr': text_type(expr)}
   260                 kwargs = {'expr': expr}
   267             else:
   261             else:
   268                 assert isinstance(expr, dict)
   262                 assert isinstance(expr, dict)
   269                 kwargs = expr
   263                 kwargs = expr
   270             kwargs['x'] = self.eid
   264             kwargs['x'] = self.eid
   271             kwargs.setdefault('mainvars', u'X')
   265             kwargs.setdefault('mainvars', u'X')
   413     @cached
   407     @cached
   414     def cwetype_workflow(self):
   408     def cwetype_workflow(self):
   415         """return the default workflow for entities of this type"""
   409         """return the default workflow for entities of this type"""
   416         # XXX CWEType method
   410         # XXX CWEType method
   417         wfrset = self._cw.execute('Any WF WHERE ET default_workflow WF, '
   411         wfrset = self._cw.execute('Any WF WHERE ET default_workflow WF, '
   418                                   'ET name %(et)s', {'et': text_type(self.entity.cw_etype)})
   412                                   'ET name %(et)s', {'et': self.entity.cw_etype})
   419         if wfrset:
   413         if wfrset:
   420             return wfrset.get_entity(0, 0)
   414             return wfrset.get_entity(0, 0)
   421         self.warning("can't find any workflow for %s", self.entity.cw_etype)
   415         self.warning("can't find any workflow for %s", self.entity.cw_etype)
   422         return None
   416         return None
   423 
   417 
   478             return
   472             return
   479         rset = self._cw.execute(
   473         rset = self._cw.execute(
   480             'Any T,TT, TN WHERE S allowed_transition T, S eid %(x)s, '
   474             'Any T,TT, TN WHERE S allowed_transition T, S eid %(x)s, '
   481             'T type TT, T type %(type)s, '
   475             'T type TT, T type %(type)s, '
   482             'T name TN, T transition_of WF, WF eid %(wfeid)s',
   476             'T name TN, T transition_of WF, WF eid %(wfeid)s',
   483             {'x': self.current_state.eid, 'type': text_type(type),
   477             {'x': self.current_state.eid, 'type': type,
   484              'wfeid': self.current_workflow.eid})
   478              'wfeid': self.current_workflow.eid})
   485         for tr in rset.entities():
   479         for tr in rset.entities():
   486             if tr.may_be_fired(self.entity.eid):
   480             if tr.may_be_fired(self.entity.eid):
   487                 yield tr
   481                 yield tr
   488 
   482 
   527             kwargs['to_state'] = self._cw.entity_from_eid(tseid)
   521             kwargs['to_state'] = self._cw.entity_from_eid(tseid)
   528         return self._cw.create_entity('TrInfo', **kwargs)
   522         return self._cw.create_entity('TrInfo', **kwargs)
   529 
   523 
   530     def _get_transition(self, tr):
   524     def _get_transition(self, tr):
   531         assert self.current_workflow
   525         assert self.current_workflow
   532         if isinstance(tr, string_types):
   526         if isinstance(tr, str):
   533             _tr = self.current_workflow.transition_by_name(tr)
   527             _tr = self.current_workflow.transition_by_name(tr)
   534             assert _tr is not None, 'not a %s transition: %s' % (
   528             assert _tr is not None, 'not a %s transition: %s' % (
   535                 self.__regid__, tr)
   529                 self.__regid__, tr)
   536             tr = _tr
   530             tr = _tr
   537         return tr
   531         return tr