Commit 18aa5d85 authored by Arnaud Fontaine's avatar Arnaud Fontaine

__getattr__ instead of _asScriptContext().

parent 275291e7
...@@ -241,11 +241,9 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow): ...@@ -241,11 +241,9 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow):
ob, self, former_status, tdef, None, None, kwargs=kw) ob, self, former_status, tdef, None, None, kwargs=kw)
script_value_list = tdef.getBeforeScriptValueList() script_value_list = tdef.getBeforeScriptValueList()
if script_value_list:
script_context = self._asScriptContext()
for script in script_value_list: for script in script_value_list:
if script: if script:
script = getattr(script_context, script.id) script = getattr(self, script.id)
script(sci) # May throw an exception. script(sci) # May throw an exception.
return filtered_transition_list return filtered_transition_list
...@@ -311,11 +309,9 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow): ...@@ -311,11 +309,9 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow):
# Execute the "after" script. # Execute the "after" script.
after_script_value_list = tdef.getAfterScriptValueList() after_script_value_list = tdef.getAfterScriptValueList()
if after_script_value_list:
script_context = self._asScriptContext()
for script in after_script_value_list: for script in after_script_value_list:
if script: if script:
script = getattr(script_context, script.id) script = getattr(self, script.id)
script(sci) # May throw an exception. script(sci) # May throw an exception.
# Queue the "Before Commit" scripts # Queue the "Before Commit" scripts
...@@ -344,16 +340,13 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow): ...@@ -344,16 +340,13 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow):
# between here and when the interaction was executed... So we # between here and when the interaction was executed... So we
# need to switch to the security manager as it was back then # need to switch to the security manager as it was back then
setSecurityManager(security_manager) setSecurityManager(security_manager)
script_context = self._asScriptContext() getattr(self, script_name)(sci)
getattr(script_context, script_name)(sci)
finally: finally:
setSecurityManager(current_security_manager) setSecurityManager(current_security_manager)
security.declarePrivate('activeScript') security.declarePrivate('activeScript')
def activeScript(self, script_name, ob_url, former_status, tdef_id, def activeScript(self, script_name, ob_url, former_status, tdef_id):
script_context=None): script = getattr(self, script_name)
script_context = self._asScriptContext()
script = getattr(script_context, script_name)
ob = self.unrestrictedTraverse(ob_url) ob = self.unrestrictedTraverse(ob_url)
tdef = self._getOb(tdef_id) tdef = self._getOb(tdef_id)
sci = StateChangeInfo( sci = StateChangeInfo(
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
import os import os
import sys import sys
import warnings
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from AccessControl.unauthorized import Unauthorized from AccessControl.unauthorized import Unauthorized
...@@ -794,7 +795,6 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject): ...@@ -794,7 +795,6 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject):
moved_exc = None moved_exc = None
validation_exc = None validation_exc = None
tool = self.getParentValue() tool = self.getParentValue()
script_context = None
object_context = None object_context = None
state_var = self.getStateVariable() state_var = self.getStateVariable()
...@@ -826,14 +826,12 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject): ...@@ -826,14 +826,12 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject):
if sci is None: if sci is None:
sci = StateChangeInfo(document, self, former_status, tdef, old_state, sci = StateChangeInfo(document, self, former_status, tdef, old_state,
new_state, form_kw) new_state, form_kw)
if script_context is None:
script_context = self._asScriptContext()
for script in script_value_list: for script in script_value_list:
# Pass lots of info to the script in a single parameter. # Pass lots of info to the script in a single parameter.
if script.getPortalType() != 'Workflow Script': if script.getPortalType() != 'Workflow Script':
raise NotImplementedError ('Unsupported Script %s for state %s' % raise NotImplementedError ('Unsupported Script %s for state %s' %
(script.id, old_state_reference)) (script.id, old_state_reference))
script = getattr(script_context, script.id) script = getattr(self, script.id)
try: try:
script(sci) # May throw an exception. script(sci) # May throw an exception.
except ValidationFailed, validation_exc: except ValidationFailed, validation_exc:
...@@ -940,9 +938,7 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject): ...@@ -940,9 +938,7 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject):
else: else:
# Pass lots of info to the script in a single parameter. # Pass lots of info to the script in a single parameter.
if script.getPortalType() == 'Workflow Script': if script.getPortalType() == 'Workflow Script':
if script_context is None: script = getattr(self, script.id)
script_context = self._asScriptContext()
script = getattr(script_context, script.id)
script(sci) # May throw an exception. script(sci) # May throw an exception.
# Return the new state object. # Return the new state object.
...@@ -1406,29 +1402,20 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject): ...@@ -1406,29 +1402,20 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject):
acquired_permission_set.remove(permission) acquired_permission_set.remove(permission)
state.setAcquirePermissionList(list(acquired_permission_set)) state.setAcquirePermissionList(list(acquired_permission_set))
def _asScriptContext(self): security.declareProtected(Permissions.AccessContentsInformation,
'getSourceValue')
def getSourceValue(self):
""" """
change the context given to the script by adding foo for script_foo to the returns the source object
context dict in order to be able to call the script using its reference
(= not prefixed by script_) from another workflow script
historically, __getattr__ method of Workflow class was overriden for
the same purpose, but it was heavyweight: doing a lot of useless
operations (each time, it was checking for script_foo, even if foo was a
transition, state, ...)
TODO-ARNAU: Should it be cached somewhere?
""" """
script_context = self.asContext() # this function is redefined here for performance reasons:
# asContext creates a temporary object and temporary object's "activate" # avoiding the usage of categories speeds up workflow *a lot*
# method code is: "return self". This means that the script is not put in source_path_list = [path for path in self.getCategoryList()
# the activity queue as expected but it is instead directly executed. To fix if path.startswith('source/')]
# this, we override the temporary object's "activate" method with the one of if source_path_list:
# the original object. source_id = source_path_list[0].split('/')[-1]
script_context.activate = self.activate return self._getOb(source_id)
for script in self.objectValues(portal_type="Workflow Script"): return None
setattr(script_context, script.getReference(), script)
return script_context
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'scripts') 'scripts')
...@@ -1447,17 +1434,55 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject): ...@@ -1447,17 +1434,55 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject):
script_dict[script.getId()] = script script_dict[script.getId()] = script
return script_dict return script_dict
security.declareProtected(Permissions.AccessContentsInformation, from Products.ERP5Workflow import WITH_DC_WORKFLOW_BACKWARD_COMPATIBILITY
'getSourceValue') if WITH_DC_WORKFLOW_BACKWARD_COMPATIBILITY:
def getSourceValue(self): def __getattr__(self, name):
'''
TODO-arnau: Not efficient. Another possible implementation:
Create a "ScriptContext" (_asScriptContext()) before executing Scripts
but this has the following problem (besides of the fact that this is
ONLY for backward compatibility and should be dropped once all projects
have been migrated):
1. Workflow Script called and a ScriptContext is created to be able to call scripts not having SCRIPT_PREFIX.
2. That script calls a Workflow Script from another Workflow.
=> This will fail as ScriptContext is only created for the Workflow.
def _asScriptContext(self):
""" """
returns the source object change the context given to the script by adding foo for script_foo to the
context dict in order to be able to call the script using its reference
(= not prefixed by script_) from another workflow script
historically, __getattr__ method of Workflow class was overriden for
the same purpose, but it was heavyweight: doing a lot of useless
operations (each time, it was checking for script_foo, even if foo was a
transition, state, ...)
""" """
# this function is redefined here for performance reasons: script_context = self.asContext()
# avoiding the usage of categories speeds up workflow *a lot* # asContext creates a temporary object and temporary object's "activate"
source_path_list = [path for path in self.getCategoryList() # method code is: "return self". This means that the script is not put in
if path.startswith('source/')] # the activity queue as expected but it is instead directly executed. To fix
if source_path_list: # this, we override the temporary object's "activate" method with the one of
source_id = source_path_list[0].split('/')[-1] # the original object.
return self._getOb(source_id) script_context.activate = self.activate
return None for script in self.objectValues(portal_type="Workflow Script"):
setattr(script_context, script.getReference(), script)
return script_context
'''
if name[0] == '_': # Optimization (Folder.__getattr__)
raise AttributeError(name)
try:
return super(Workflow, self).__getattr__(name)
except AttributeError:
if name.startswith(SCRIPT_PREFIX):
raise
prefixed_name = SCRIPT_PREFIX + name
if not hasattr(aq_base(self), prefixed_name):
raise
warnings.warn(
"%r: Script calling %s instead of %s" % (self, name, prefixed_name),
DeprecationWarning)
return self._getOb(prefixed_name)
Workflow.__getattr__ = __getattr__
...@@ -39,6 +39,8 @@ this_module = sys.modules[__name__] ...@@ -39,6 +39,8 @@ this_module = sys.modules[__name__]
document_classes = updateGlobals(this_module, globals(), document_classes = updateGlobals(this_module, globals(),
permissions_module=Permissions) permissions_module=Permissions)
WITH_DC_WORKFLOW_BACKWARD_COMPATIBILITY = True
# Define object classes and tools # Define object classes and tools
object_classes = () object_classes = ()
portal_tools = (WorkflowTool,) portal_tools = (WorkflowTool,)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment