Commit b97ae55e authored by iv's avatar iv

ERP5Workflow: perf: avoid expensive operations in getattr

__getattr__ was overriden in order to be able to call the script
using its reference (not prefixed by script_) from another workflow
script (see testTradeReports for example)

the problem is that it was doing a lot of useless getattr (each time,
it was checking for script_foo, even if foo is a transition, state, ...)

we now just change the context given to the script by adding foo
for script_foo to the context dict
parent 0245d4a6
......@@ -45,6 +45,7 @@ from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type.Workflow import addWorkflowFactory
from Products.ERP5Workflow.Document.Transition import TRIGGER_WORKFLOW_METHOD
from Products.ERP5Workflow.Document.Workflow import Workflow
from Products.ERP5Workflow.Document.WorkflowScript import SCRIPT_PREFIX
from types import StringTypes
from zLOG import LOG, INFO, WARNING
......@@ -244,7 +245,10 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow):
before_script_list = tdef.getBeforeScriptValueList()
for script in before_script_list:
if script: script(sci)
if script:
script_context = self._asScriptContext()
script = getattr(script_context, script.id)
script(sci)
return filtered_transition_list
def notifySuccess(self, ob, transition_list, result, args=None, kw=None):
......@@ -309,7 +313,10 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow):
# Execute the "after" script.
after_script_list = tdef.getAfterScriptValueList()
for script in after_script_list:
if script: script(sci) # May throw an exception
if script:
script_context = self._asScriptContext()
script = getattr(script_context, script.id)
script(sci) # May throw an exception
# Queue the "Before Commit" scripts
sm = getSecurityManager()
......@@ -343,7 +350,8 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow):
setSecurityManager(current_security_manager)
def activeScript(self, script_name, ob_url, former_status, tdef_id):
script = self._getOb(script_name)
script_context = self._asScriptContext()
script = getattr(script_context, script_name)
ob = self.unrestrictedTraverse(ob_url)
tdef = self._getOb(tdef_id)
sci = StateChangeInfo(
......
......@@ -57,6 +57,7 @@ from Products.ERP5Type.Utils import UpperCase, convertToMixedCase
from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Workflow.Document.Transition import TRIGGER_AUTOMATIC,\
TRIGGER_USER_ACTION, TRIGGER_WORKFLOW_METHOD
from Products.ERP5Workflow.Document.WorkflowScript import SCRIPT_PREFIX
from tempfile import mktemp
from types import StringTypes
from zLOG import LOG, INFO, WARNING
......@@ -94,12 +95,6 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject):
PropertySheet.Workflow,
)
def __getattr__(self, name):
script = self._getOb("script_" + name, None)
if script:
return script
return super(Workflow, self).__getattr__(name)
def notifyCreated(self, document):
"""
Notifies this workflow after an object has been created and added.
......@@ -665,6 +660,8 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject):
if script.getPortalType() != 'Workflow Script':
raise NotImplementedError ('Unsupported Script %s for state %s' %
(script.id, old_sdef.getReference()))
script_context = self._asScriptContext()
script = getattr(script_context, script.id)
try:
script(sci) # May throw an exception.
except ValidationFailed, validation_exc:
......@@ -763,6 +760,8 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject):
else:
# Pass lots of info to the script in a single parameter.
if script.getPortalType() == 'Workflow Script':
script_context = self._asScriptContext()
script = getattr(script_context, script.id)
script(sci) # May throw an exception.
# Return the new state object.
......@@ -1212,6 +1211,15 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject):
for permission in permission_to_delete:
del state.state_permission_roles_dict[permission]
def _asScriptContext(self):
script_context = self.asContext()
script_prefix_len = len(SCRIPT_PREFIX)
for script_id in self.objectIds(meta_type="ERP5 Python Script"):
if script_id.startswith(SCRIPT_PREFIX):
script = getattr(script_context, script_id)
setattr(script_context, script_id[script_prefix_len:], script)
return script_context
security.declareProtected(Permissions.AccessContentsInformation,
'getSourceValue')
def getSourceValue(self):
......
......@@ -35,6 +35,8 @@ from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.ConsistencyMessage import ConsistencyMessage
from Products.ERP5Type.id_as_reference import IdAsReferenceMixin
SCRIPT_PREFIX = 'script_'
class WorkflowScript(PythonScript, IdAsReferenceMixin("script_", "prefix")):
meta_type = 'ERP5 Python Script'
portal_type = 'Workflow Script'
......
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