--- a/entities/wfobjs.py Fri Feb 12 15:18:00 2010 +0100
+++ b/entities/wfobjs.py Wed Mar 24 10:23:31 2010 +0100
@@ -15,12 +15,12 @@
from cubicweb.entities import AnyEntity, fetch_config
from cubicweb.interfaces import IWorkflowable
-from cubicweb.common.mixins import MI_REL_TRIGGERS
+from cubicweb.mixins import MI_REL_TRIGGERS
class WorkflowException(Exception): pass
class Workflow(AnyEntity):
- id = 'Workflow'
+ __regid__ = 'Workflow'
@property
def initial(self):
@@ -52,7 +52,7 @@
_done = set()
yield self
_done.add(self.eid)
- for tr in self.req.execute('Any T WHERE T is WorkflowTransition, '
+ for tr in self._cw.execute('Any T WHERE T is WorkflowTransition, '
'T transition_of WF, WF eid %(wf)s',
{'wf': self.eid}).entities():
if tr.subwf.eid in _done:
@@ -63,7 +63,7 @@
# state / transitions accessors ############################################
def state_by_name(self, statename):
- rset = self.req.execute('Any S, SN WHERE S name SN, S name %(n)s, '
+ rset = self._cw.execute('Any S, SN WHERE S name SN, S name %(n)s, '
'S state_of WF, WF eid %(wf)s',
{'n': statename, 'wf': self.eid}, 'wf')
if rset:
@@ -71,7 +71,7 @@
return None
def state_by_eid(self, eid):
- rset = self.req.execute('Any S, SN WHERE S name SN, S eid %(s)s, '
+ rset = self._cw.execute('Any S, SN WHERE S name SN, S eid %(s)s, '
'S state_of WF, WF eid %(wf)s',
{'s': eid, 'wf': self.eid}, ('wf', 's'))
if rset:
@@ -79,7 +79,7 @@
return None
def transition_by_name(self, trname):
- rset = self.req.execute('Any T, TN WHERE T name TN, T name %(n)s, '
+ rset = self._cw.execute('Any T, TN WHERE T name TN, T name %(n)s, '
'T transition_of WF, WF eid %(wf)s',
{'n': trname, 'wf': self.eid}, 'wf')
if rset:
@@ -87,7 +87,7 @@
return None
def transition_by_eid(self, eid):
- rset = self.req.execute('Any T, TN WHERE T name TN, T eid %(t)s, '
+ rset = self._cw.execute('Any T, TN WHERE T name TN, T eid %(t)s, '
'T transition_of WF, WF eid %(wf)s',
{'t': eid, 'wf': self.eid}, ('wf', 't'))
if rset:
@@ -98,20 +98,20 @@
def add_state(self, name, initial=False, **kwargs):
"""add a state to this workflow"""
- state = self.req.create_entity('State', name=unicode(name), **kwargs)
- self.req.execute('SET S state_of WF WHERE S eid %(s)s, WF eid %(wf)s',
+ state = self._cw.create_entity('State', name=unicode(name), **kwargs)
+ self._cw.execute('SET S state_of WF WHERE S eid %(s)s, WF eid %(wf)s',
{'s': state.eid, 'wf': self.eid}, ('s', 'wf'))
if initial:
assert not self.initial, "Initial state already defined as %s" % self.initial
- self.req.execute('SET WF initial_state S '
+ self._cw.execute('SET WF initial_state S '
'WHERE S eid %(s)s, WF eid %(wf)s',
{'s': state.eid, 'wf': self.eid}, ('s', 'wf'))
return state
def _add_transition(self, trtype, name, fromstates,
requiredgroups=(), conditions=(), **kwargs):
- tr = self.req.create_entity(trtype, name=unicode(name), **kwargs)
- self.req.execute('SET T transition_of WF '
+ tr = self._cw.create_entity(trtype, name=unicode(name), **kwargs)
+ self._cw.execute('SET T transition_of WF '
'WHERE T eid %(t)s, WF eid %(wf)s',
{'t': tr.eid, 'wf': self.eid}, ('t', 'wf'))
assert fromstates, fromstates
@@ -120,10 +120,10 @@
for state in fromstates:
if hasattr(state, 'eid'):
state = state.eid
- self.req.execute('SET S allowed_transition T '
+ self._cw.execute('SET S allowed_transition T '
'WHERE S eid %(s)s, T eid %(t)s',
{'s': state, 't': tr.eid}, ('s', 't'))
- tr.set_transition_permissions(requiredgroups, conditions, reset=False)
+ tr.set_permissions(requiredgroups, conditions, reset=False)
return tr
def add_transition(self, name, fromstates, tostate=None,
@@ -134,7 +134,7 @@
if tostate is not None:
if hasattr(tostate, 'eid'):
tostate = tostate.eid
- self.req.execute('SET T destination_state S '
+ self._cw.execute('SET T destination_state S '
'WHERE S eid %(s)s, T eid %(t)s',
{'t': tr.eid, 's': tostate}, ('s', 't'))
return tr
@@ -146,7 +146,7 @@
requiredgroups, conditions, **kwargs)
if hasattr(subworkflow, 'eid'):
subworkflow = subworkflow.eid
- assert self.req.execute('SET T subworkflow WF WHERE WF eid %(wf)s,T eid %(t)s',
+ assert self._cw.execute('SET T subworkflow WF WHERE WF eid %(wf)s,T eid %(t)s',
{'t': tr.eid, 'wf': subworkflow}, ('wf', 't'))
for fromstate, tostate in exitpoints:
tr.add_exit_point(fromstate, tostate)
@@ -161,9 +161,9 @@
execute = self._cw.unsafe_execute
execute('SET X in_state S WHERE S eid %(s)s', {'s': todelstate.eid}, 's')
execute('SET X from_state NS WHERE X to_state OS, OS eid %(os)s, NS eid %(ns)s',
- {'os': todelstate.eid, 'ns': newstate.eid}, 's')
+ {'os': todelstate.eid, 'ns': replacement.eid}, 's')
execute('SET X to_state NS WHERE X to_state OS, OS eid %(os)s, NS eid %(ns)s',
- {'os': todelstate.eid, 'ns': newstate.eid}, 's')
+ {'os': todelstate.eid, 'ns': replacement.eid}, 's')
todelstate.delete()
@@ -173,11 +173,11 @@
provides a specific may_be_fired method to check if the relation may be
fired by the logged user
"""
- id = 'BaseTransition'
+ __regid__ = 'BaseTransition'
fetch_attrs, fetch_order = fetch_config(['name'])
def __init__(self, *args, **kwargs):
- if self.id == 'BaseTransition':
+ if self.__regid__ == 'BaseTransition':
raise WorkflowException('should not be instantiated')
super(BaseTransition, self).__init__(*args, **kwargs)
@@ -195,7 +195,7 @@
`eid` is the eid of the object on which we may fire the transition
"""
- user = self.req.user
+ user = self._cw.user
# check user is at least in one of the required groups if any
groups = frozenset(g.name for g in self.require_group)
if groups:
@@ -207,7 +207,7 @@
# check one of the rql expression conditions matches if any
if self.condition:
for rqlexpr in self.condition:
- if rqlexpr.check_expression(self.req, eid):
+ if rqlexpr.check_expression(self._cw, eid):
return True
if self.condition or groups:
return False
@@ -219,20 +219,19 @@
"""
if self.transition_of:
return self.transition_of[0].rest_path(), {}
- return super(Transition, self).after_deletion_path()
+ return super(BaseTransition, self).after_deletion_path()
- def set_transition_permissions(self, requiredgroups=(), conditions=(),
- reset=True):
+ def set_permissions(self, requiredgroups=(), conditions=(), reset=True):
"""set or add (if `reset` is False) groups and conditions for this
transition
"""
if reset:
- self.req.execute('DELETE T require_group G WHERE T eid %(x)s',
+ self._cw.execute('DELETE T require_group G WHERE T eid %(x)s',
{'x': self.eid}, 'x')
- self.req.execute('DELETE T condition R WHERE T eid %(x)s',
+ self._cw.execute('DELETE T condition R WHERE T eid %(x)s',
{'x': self.eid}, 'x')
for gname in requiredgroups:
- rset = self.req.execute('SET T require_group G '
+ rset = self._cw.execute('SET T require_group G '
'WHERE T eid %(x)s, G name %(gn)s',
{'x': self.eid, 'gn': gname}, 'x')
assert rset, '%s is not a known group' % gname
@@ -246,18 +245,35 @@
kwargs = expr
kwargs['x'] = self.eid
kwargs.setdefault('mainvars', u'X')
- self.req.execute('INSERT RQLExpression X: X exprtype "ERQLExpression", '
+ self._cw.execute('INSERT RQLExpression X: X exprtype "ERQLExpression", '
'X expression %(expr)s, X mainvars %(mainvars)s, '
- 'T condition X WHERE T eid %(x)s', kwargs, 'x')
+ 'T condition X WHERE T eid %(x)s',kwargs, 'x')
# XXX clear caches?
+ @deprecated('[3.6.1] use set_permission')
+ def set_transition_permissions(self, requiredgroups=(), conditions=(),
+ reset=True):
+ return self.set_permissions(requiredgroups, conditions, reset)
+
class Transition(BaseTransition):
"""customized class for Transition entities"""
- id = 'Transition'
+ __regid__ = 'Transition'
+
+ def destination(self, entity):
+ try:
+ return self.destination_state[0]
+ except IndexError:
+ return entity.latest_trinfo().previous_state
- def destination(self):
- return self.destination_state[0]
+ def potential_destinations(self):
+ try:
+ yield self.destination_state[0]
+ except IndexError:
+ for incomingstate in self.reverse_allowed_transition:
+ for tr in incomingstate.reverse_destination_state:
+ for previousstate in tr.reverse_allowed_transition:
+ yield previousstate
def parent(self):
return self.workflow
@@ -265,26 +281,29 @@
class WorkflowTransition(BaseTransition):
"""customized class for WorkflowTransition entities"""
- id = 'WorkflowTransition'
+ __regid__ = 'WorkflowTransition'
@property
def subwf(self):
return self.subworkflow[0]
- def destination(self):
+ def destination(self, entity):
return self.subwf.initial
+ def potential_destinations(self):
+ yield self.subwf.initial
+
def add_exit_point(self, fromstate, tostate):
if hasattr(fromstate, 'eid'):
fromstate = fromstate.eid
if tostate is None:
- self.req.execute('INSERT SubWorkflowExitPoint X: T subworkflow_exit X, '
+ self._cw.execute('INSERT SubWorkflowExitPoint X: T subworkflow_exit X, '
'X subworkflow_state FS WHERE T eid %(t)s, FS eid %(fs)s',
{'t': self.eid, 'fs': fromstate}, ('t', 'fs'))
else:
if hasattr(tostate, 'eid'):
tostate = tostate.eid
- self.req.execute('INSERT SubWorkflowExitPoint X: T subworkflow_exit X, '
+ self._cw.execute('INSERT SubWorkflowExitPoint X: T subworkflow_exit X, '
'X subworkflow_state FS, X destination_state TS '
'WHERE T eid %(t)s, FS eid %(fs)s, TS eid %(ts)s',
{'t': self.eid, 'fs': fromstate, 'ts': tostate},
@@ -301,7 +320,7 @@
if tostateeid is None:
# go back to state from which we've entered the subworkflow
return entity.subworkflow_input_trinfo().previous_state
- return self.req.entity_from_eid(tostateeid)
+ return self._cw.entity_from_eid(tostateeid)
@cached
def exit_points(self):
@@ -311,13 +330,13 @@
return result
def clear_all_caches(self):
- super(WorkflowableMixIn, self).clear_all_caches()
+ super(WorkflowTransition, self).clear_all_caches()
clear_cache(self, 'exit_points')
class SubWorkflowExitPoint(AnyEntity):
"""customized class for SubWorkflowExitPoint entities"""
- id = 'SubWorkflowExitPoint'
+ __regid__ = 'SubWorkflowExitPoint'
@property
def subwf_state(self):
@@ -333,7 +352,7 @@
class State(AnyEntity):
"""customized class for State entities"""
- id = 'State'
+ __regid__ = 'State'
fetch_attrs, fetch_order = fetch_config(['name'])
rest_attr = 'eid'
@@ -349,7 +368,7 @@
class TrInfo(AnyEntity):
"""customized class for Transition information entities
"""
- id = 'TrInfo'
+ __regid__ = 'TrInfo'
fetch_attrs, fetch_order = fetch_config(['creation_date', 'comment'],
pclass=None) # don't want modification_date
@property
@@ -410,7 +429,7 @@
"""return current state name translated to context's language"""
state = self.current_state
if state:
- return self.req._(state.name)
+ return self._cw._(state.name)
return u''
@property
@@ -430,11 +449,12 @@
@cached
def cwetype_workflow(self):
"""return the default workflow for entities of this type"""
- wfrset = self.req.execute('Any WF WHERE ET default_workflow WF, '
- 'ET name %(et)s', {'et': self.id})
+ # XXX CWEType method
+ wfrset = self._cw.execute('Any WF WHERE ET default_workflow WF, '
+ 'ET name %(et)s', {'et': self.__regid__})
if wfrset:
return wfrset.get_entity(0, 0)
- self.warning("can't find any workflow for %s", self.id)
+ self.warning("can't find any workflow for %s", self.__regid__)
return None
def possible_transitions(self, type='normal'):
@@ -444,7 +464,7 @@
"""
if self.current_state is None or self.current_workflow is None:
return
- rset = self.req.execute(
+ rset = self._cw.execute(
'Any T,TT, TN WHERE S allowed_transition T, S eid %(x)s, '
'T type TT, T type %(type)s, '
'T name TN, T transition_of WF, WF eid %(wfeid)s',
@@ -462,10 +482,10 @@
kwargs['comment_format'] = commentformat
kwargs['wf_info_for'] = self
if treid is not None:
- kwargs['by_transition'] = self.req.entity_from_eid(treid)
+ kwargs['by_transition'] = self._cw.entity_from_eid(treid)
if tseid is not None:
- kwargs['to_state'] = self.req.entity_from_eid(tseid)
- return self.req.create_entity('TrInfo', **kwargs)
+ kwargs['to_state'] = self._cw.entity_from_eid(tseid)
+ return self._cw.create_entity('TrInfo', **kwargs)
def fire_transition(self, tr, comment=None, commentformat=None):
"""change the entity's state by firing transition of the given name in
@@ -474,7 +494,8 @@
assert self.current_workflow
if isinstance(tr, basestring):
_tr = self.current_workflow.transition_by_name(tr)
- assert _tr is not None, 'not a %s transition: %s' % (self.id, tr)
+ assert _tr is not None, 'not a %s transition: %s' % (
+ self.__regid__, tr)
tr = _tr
return self._add_trinfo(comment, commentformat, tr.eid)
@@ -494,7 +515,7 @@
else:
state = self.current_workflow.state_by_name(statename)
if state is None:
- raise WorkflowException('not a %s state: %s' % (self.id,
+ raise WorkflowException('not a %s state: %s' % (self.__regid__,
statename))
stateeid = state.eid
# XXX try to find matching transition?
@@ -532,7 +553,7 @@
super(WorkflowableMixIn, self).clear_all_caches()
clear_cache(self, 'cwetype_workflow')
- @deprecated('get transition from current workflow and use its may_be_fired method')
+ @deprecated('[3.5] get transition from current workflow and use its may_be_fired method')
def can_pass_transition(self, trname):
"""return the Transition instance if the current user can fire the
transition with the given name, else None
@@ -542,8 +563,8 @@
return tr
@property
- @deprecated('use printable_state')
+ @deprecated('[3.5] use printable_state')
def displayable_state(self):
- return self.req._(self.state)
+ return self._cw._(self.state)
MI_REL_TRIGGERS[('in_state', 'subject')] = WorkflowableMixIn