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 ...@@ -45,6 +45,7 @@ from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type.Workflow import addWorkflowFactory from Products.ERP5Type.Workflow import addWorkflowFactory
from Products.ERP5Workflow.Document.Transition import TRIGGER_WORKFLOW_METHOD from Products.ERP5Workflow.Document.Transition import TRIGGER_WORKFLOW_METHOD
from Products.ERP5Workflow.Document.Workflow import Workflow from Products.ERP5Workflow.Document.Workflow import Workflow
from Products.ERP5Workflow.Document.WorkflowScript import SCRIPT_PREFIX
from types import StringTypes from types import StringTypes
from zLOG import LOG, INFO, WARNING from zLOG import LOG, INFO, WARNING
...@@ -244,7 +245,10 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow): ...@@ -244,7 +245,10 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow):
before_script_list = tdef.getBeforeScriptValueList() before_script_list = tdef.getBeforeScriptValueList()
for script in before_script_list: 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 return filtered_transition_list
def notifySuccess(self, ob, transition_list, result, args=None, kw=None): def notifySuccess(self, ob, transition_list, result, args=None, kw=None):
...@@ -309,7 +313,10 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow): ...@@ -309,7 +313,10 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow):
# Execute the "after" script. # Execute the "after" script.
after_script_list = tdef.getAfterScriptValueList() after_script_list = tdef.getAfterScriptValueList()
for script in after_script_list: 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 # Queue the "Before Commit" scripts
sm = getSecurityManager() sm = getSecurityManager()
...@@ -343,7 +350,8 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow): ...@@ -343,7 +350,8 @@ class InteractionWorkflow(IdAsReferenceMixin("", "prefix"), Workflow):
setSecurityManager(current_security_manager) setSecurityManager(current_security_manager)
def activeScript(self, script_name, ob_url, former_status, tdef_id): 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) ob = self.unrestrictedTraverse(ob_url)
tdef = self._getOb(tdef_id) tdef = self._getOb(tdef_id)
sci = StateChangeInfo( sci = StateChangeInfo(
......
...@@ -57,6 +57,7 @@ from Products.ERP5Type.Utils import UpperCase, convertToMixedCase ...@@ -57,6 +57,7 @@ from Products.ERP5Type.Utils import UpperCase, convertToMixedCase
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Workflow.Document.Transition import TRIGGER_AUTOMATIC,\ from Products.ERP5Workflow.Document.Transition import TRIGGER_AUTOMATIC,\
TRIGGER_USER_ACTION, TRIGGER_WORKFLOW_METHOD TRIGGER_USER_ACTION, TRIGGER_WORKFLOW_METHOD
from Products.ERP5Workflow.Document.WorkflowScript import SCRIPT_PREFIX
from tempfile import mktemp from tempfile import mktemp
from types import StringTypes from types import StringTypes
from zLOG import LOG, INFO, WARNING from zLOG import LOG, INFO, WARNING
...@@ -94,12 +95,6 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject): ...@@ -94,12 +95,6 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject):
PropertySheet.Workflow, 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): def notifyCreated(self, document):
""" """
Notifies this workflow after an object has been created and added. Notifies this workflow after an object has been created and added.
...@@ -665,6 +660,8 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject): ...@@ -665,6 +660,8 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject):
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_sdef.getReference())) (script.id, old_sdef.getReference()))
script_context = self._asScriptContext()
script = getattr(script_context, script.id)
try: try:
script(sci) # May throw an exception. script(sci) # May throw an exception.
except ValidationFailed, validation_exc: except ValidationFailed, validation_exc:
...@@ -763,6 +760,8 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject): ...@@ -763,6 +760,8 @@ 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':
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.
...@@ -1212,6 +1211,15 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject): ...@@ -1212,6 +1211,15 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject):
for permission in permission_to_delete: for permission in permission_to_delete:
del state.state_permission_roles_dict[permission] 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, security.declareProtected(Permissions.AccessContentsInformation,
'getSourceValue') 'getSourceValue')
def getSourceValue(self): def getSourceValue(self):
......
...@@ -35,6 +35,8 @@ from Products.ERP5Type import Permissions, PropertySheet ...@@ -35,6 +35,8 @@ from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.ConsistencyMessage import ConsistencyMessage from Products.ERP5Type.ConsistencyMessage import ConsistencyMessage
from Products.ERP5Type.id_as_reference import IdAsReferenceMixin from Products.ERP5Type.id_as_reference import IdAsReferenceMixin
SCRIPT_PREFIX = 'script_'
class WorkflowScript(PythonScript, IdAsReferenceMixin("script_", "prefix")): class WorkflowScript(PythonScript, IdAsReferenceMixin("script_", "prefix")):
meta_type = 'ERP5 Python Script' meta_type = 'ERP5 Python Script'
portal_type = 'Workflow 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