Merge branch 'master' into bbmaster
This commit is contained in:
commit
2be1e6df6b
4 changed files with 76 additions and 5 deletions
|
@ -2,8 +2,6 @@
|
|||
Stateful Objects
|
||||
================
|
||||
|
||||
($Id$)
|
||||
|
||||
>>> from cybertools.stateful.definition import StatesDefinition
|
||||
>>> from cybertools.stateful.definition import State, Transition
|
||||
>>> from cybertools.stateful.definition import registerStatesDefinition
|
||||
|
@ -13,7 +11,9 @@ We start with a simple demonstration class that provides stateful
|
|||
behaviour directly.
|
||||
|
||||
>>> class Demo(Stateful):
|
||||
... pass
|
||||
... currentActors = None
|
||||
... def getActors(self):
|
||||
... return self.currentActors
|
||||
|
||||
>>> demo = Demo()
|
||||
|
||||
|
@ -57,6 +57,43 @@ of the current state we get an error.
|
|||
>>> demo.getState()
|
||||
'draft'
|
||||
|
||||
Check condition
|
||||
---------------
|
||||
|
||||
>>> def checkIfEmpty(obj):
|
||||
... return getattr(obj, 'empty', True)
|
||||
|
||||
>>> removeAction = demo.getStatesDefinition().transitions.remove
|
||||
>>> removeAction.condition = checkIfEmpty
|
||||
>>> removeAction in demo.getAvailableTransitions()
|
||||
True
|
||||
|
||||
>>> demo.empty = False
|
||||
>>> removeAction in demo.getAvailableTransitions()
|
||||
False
|
||||
|
||||
Check actors
|
||||
------------
|
||||
|
||||
>>> removeAction.actors = ['master']
|
||||
|
||||
>>> demo.getActors()
|
||||
|
||||
>>> demo.empty = True
|
||||
>>> removeAction in demo.getAvailableTransitionsForUser()
|
||||
True
|
||||
|
||||
>>> demo.currentActors = ['dummy']
|
||||
>>> demo.getActors()
|
||||
['dummy']
|
||||
|
||||
>>> removeAction in demo.getAvailableTransitionsForUser()
|
||||
False
|
||||
|
||||
>>> demo.currentActors = ['master']
|
||||
>>> removeAction in demo.getAvailableTransitionsForUser()
|
||||
True
|
||||
|
||||
|
||||
Stateful Adapters
|
||||
=================
|
||||
|
@ -94,3 +131,4 @@ back the state that is stored with the object.
|
|||
>>> statefulDemo = IStateful(demo)
|
||||
>>> statefulDemo.getState()
|
||||
'finished'
|
||||
|
||||
|
|
|
@ -80,6 +80,9 @@ class Stateful(object):
|
|||
def getStatesDefinition(self):
|
||||
return statesDefinitions.get(self.statesDefinition, None)
|
||||
|
||||
def getActors(self):
|
||||
return None
|
||||
|
||||
def notify(self, transition, previousState):
|
||||
""" To be implemented by subclass.
|
||||
"""
|
||||
|
|
|
@ -55,6 +55,8 @@ class Action(object):
|
|||
allowed = True
|
||||
permission = None
|
||||
roles = []
|
||||
actors = []
|
||||
condition = None
|
||||
doBefore = []
|
||||
schema = None
|
||||
|
||||
|
@ -69,8 +71,6 @@ class Transition(Action):
|
|||
|
||||
implements(ITransition)
|
||||
|
||||
actors = None
|
||||
|
||||
def __init__(self, name, title, targetState, **kw):
|
||||
super(Transition, self).__init__(name, title, **kw)
|
||||
self.targetState = targetState
|
||||
|
@ -127,12 +127,25 @@ class StatesDefinition(object):
|
|||
def isAllowed(self, action, obj):
|
||||
if not action.allowed:
|
||||
return False
|
||||
if action.condition and not action.condition(obj):
|
||||
return False
|
||||
if not self.checkActors(action.actors, obj):
|
||||
return False
|
||||
if not self.checkRoles(action.roles, obj):
|
||||
return False
|
||||
if not self.checkPermission(action.permission, obj):
|
||||
return False
|
||||
return True
|
||||
|
||||
def checkActors(self, actors, obj):
|
||||
stfActors = obj.getActors()
|
||||
if stfActors is None:
|
||||
return True
|
||||
for actor in actors:
|
||||
if actor in stfActors:
|
||||
return True
|
||||
return False
|
||||
|
||||
def checkRoles(self, roles, obj):
|
||||
return True
|
||||
|
||||
|
|
|
@ -50,6 +50,12 @@ class IAction(Interface):
|
|||
'to execute this action; no check when empty.')
|
||||
permission = Attribute('The name of a permission that is needed for '
|
||||
'executing this action; no check when empty.')
|
||||
actors = Attribute('A collection of names of actors or groups that should be '
|
||||
'able to execute this action; no check when empty. '
|
||||
'See the IStateful.getActors().')
|
||||
condition = Attribute('A boolean function with a stateful object as '
|
||||
'parameter. The action is only allowed if return value '
|
||||
'is True. No check when condition is None.')
|
||||
schema = Attribute('An optional schema (a sequence of field specifications) '
|
||||
'that provides information on fields to be shown in a '
|
||||
'form used for executing the action.')
|
||||
|
@ -97,6 +103,17 @@ class IStateful(Interface):
|
|||
for the current state.
|
||||
"""
|
||||
|
||||
def getActors():
|
||||
""" Return a collection of names of actors or groups that will be
|
||||
used for checking if a certain transition is allowed. May be
|
||||
None in which case not checking should be applied.
|
||||
"""
|
||||
|
||||
def notify(transition, previousState):
|
||||
""" This method will be called upon completion of a transition.
|
||||
"""
|
||||
|
||||
|
||||
request = Attribute('Optional publication request.')
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue