[gen] Added and changed some methods on the basic workflow objects in order to ease modifications on workflow objects (states, transitions).

This commit is contained in:
Gaetan Delannay 2014-04-17 17:10:38 +02:00
parent b5d38ad150
commit 75f5407e48
2 changed files with 58 additions and 4 deletions

View file

@ -41,6 +41,10 @@ class Role:
# An ungrantable role is one that is, like the Anonymous or # An ungrantable role is one that is, like the Anonymous or
# Authenticated roles, automatically attributed to a user. # Authenticated roles, automatically attributed to a user.
def __repr__(self):
loc = self.local and ' (local)' or ''
return '<Role %s%s>' % (self.name, loc)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class State: class State:
'''Represents a workflow state.''' '''Represents a workflow state.'''
@ -94,17 +98,22 @@ class State:
self.permissions[permission] = rolesList self.permissions[permission] = rolesList
def getUsedRoles(self): return self.usedRoles.values() def getUsedRoles(self): return self.usedRoles.values()
def updatePermissions(self, perms):
'''Update self.permissions with dict p_perms.'''
self.permissions.update(perms)
self.standardizeRoles()
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class Transition: class Transition:
'''Represents a workflow transition.''' '''Represents a workflow transition.'''
def __init__(self, states, condition=True, action=None, notify=None, def __init__(self, states, condition=True, action=None, notify=None,
show=True, confirm=False, group=None): show=True, confirm=False, group=None):
self.states = states # In its simpler form, it is a tuple with 2 # In its simpler form, "states" is a list of 2 states:
# states: (fromState, toState). But it can also be a tuple of several # (fromState, toState). But it can also be a list of several
# (fromState, toState) sub-tuples. This way, you may define only 1 # (fromState, toState) sub-lists. This way, you may define only 1
# transition at several places in the state-transition diagram. It may # transition at several places in the state-transition diagram. It may
# be useful for "undo" transitions, for example. # be useful for "undo" transitions, for example.
self.states = self.standardiseStates(states)
self.condition = condition self.condition = condition
if isinstance(condition, basestring): if isinstance(condition, basestring):
# The condition specifies the name of a role. # The condition specifies the name of a role.
@ -117,6 +126,15 @@ class Transition:
self.confirm = confirm # If True, a confirm popup will show up. self.confirm = confirm # If True, a confirm popup will show up.
self.group = Group.get(group) self.group = Group.get(group)
def standardiseStates(self, states):
'''Get p_states as a list or a list of lists. Indeed, the user may also
specify p_states a tuple or tuple of tuples. Having lists allows us
to easily perform changes in states if required.'''
if isinstance(states[0], State):
if isinstance(states, tuple): return list(states)
return states
return [[start, end] for start, end in states]
def getName(self, wf): def getName(self, wf):
'''Returns the name for this state in workflow p_wf.''' '''Returns the name for this state in workflow p_wf.'''
for name in dir(wf): for name in dir(wf):
@ -135,6 +153,42 @@ class Transition:
Else, returns False.''' Else, returns False.'''
return isinstance(self.states[0], State) return isinstance(self.states[0], State)
def _replaceStateIn(self, oldState, newState, states):
'''Replace p_oldState by p_newState in p_states.'''
if oldState not in states: return
i = states.index(oldState)
del states[i]
states.insert(i, newState)
def replaceState(self, oldState, newState):
'''Replace p_oldState by p_newState in self.states.'''
if self.isSingle():
self._replaceStateIn(oldState, newState, self.states)
else:
for i in range(len(self.states)):
self._replaceStateIn(oldState, newState, self.states[i])
def removeState(self, state):
'''For a multi-state transition, this method removes every state pair
containing p_state.'''
if self.isSingle(): raise Exception('To use for multi-transitions only')
i = len(self.states) - 1
while i >= 0:
if state in self.states[i]:
del self.states[i]
i -= 1
# This transition may become a single-state-pair transition.
if len(self.states) == 1:
self.states = self.states[0]
def setState(self, state):
'''Configure this transition as being an auto-transition on p_state.
This can be useful if, when changing a workflow, one wants to remove
a state by isolating him from the rest of the state diagram and
disable some transitions by making them auto-transitions of this
disabled state.'''
self.states = [state, state]
def isShowable(self, workflow, obj): def isShowable(self, workflow, obj):
'''Is this transition showable?''' '''Is this transition showable?'''
if callable(self.show): if callable(self.show):

View file

@ -699,7 +699,7 @@ class AbstractWrapper(object):
elif name == 'siteUrl': return self.o.getTool().getSiteUrl() elif name == 'siteUrl': return self.o.getTool().getSiteUrl()
# Now, let's try to return a real attribute. # Now, let's try to return a real attribute.
res = object.__getattribute__(self, name) res = object.__getattribute__(self, name)
# If we got an Appy type, return the value of this type for this object # If we got an Appy field, return its value for this object
if isinstance(res, Field): if isinstance(res, Field):
o = self.o o = self.o
if isinstance(res, Ref): if isinstance(res, Ref):