Commit da234001 by Julien Muchembled

CMFActivity: new invokeGroup API

The recent API change was not enough.
A grouping method may need more information: in particular, the dummy grouping
method must be fixed to change user.
1 parent 0cf9f566
...@@ -434,6 +434,26 @@ Named Parameters: %r ...@@ -434,6 +434,26 @@ Named Parameters: %r
def getExecutionState(self): def getExecutionState(self):
return self.is_executed return self.is_executed
class GroupedMessage(object):
__slots__ = 'object', '_message', 'result', 'exc_info'
def __init__(self, object, message):
self.object = object
self._message = message
args = property(lambda self: self._message.args)
kw = property(lambda self: self._message.kw)
def raised(self, exc_info=None):
self.exc_info = exc_info or sys.exc_info()
try:
del self.result
except AttributeError:
pass
# XXX: Allowing restricted code to implement a grouping method is questionable
# but there already exist some.
allow_class(GroupedMessage)
# Activity Registration # Activity Registration
def activity_dict(): def activity_dict():
...@@ -1291,21 +1311,21 @@ class ActivityTool (Folder, UniqueObject): ...@@ -1291,21 +1311,21 @@ class ActivityTool (Folder, UniqueObject):
active_obj = subobj.activate(activity=activity, **activity_kw) active_obj = subobj.activate(activity=activity, **activity_kw)
getattr(active_obj, alternate_method_id)(*m.args, **m.kw) getattr(active_obj, alternate_method_id)(*m.args, **m.kw)
else: else:
expanded_object_list.append([subobj, m.args, m.kw]) expanded_object_list.append(GroupedMessage(subobj, m))
except: except:
m.setExecutionState(MESSAGE_NOT_EXECUTED, context=self) m.setExecutionState(MESSAGE_NOT_EXECUTED, context=self)
expanded_object_list = sum(message_dict.itervalues(), []) expanded_object_list = sum(message_dict.itervalues(), [])
try: try:
if len(expanded_object_list) > 0: if expanded_object_list:
traverse = self.getPortalObject().unrestrictedTraverse traverse = self.getPortalObject().unrestrictedTraverse
# FIXME: how to apply security here? # FIXME: how to apply security here?
# NOTE: The callee must update each processed item of # NOTE: The callee must update each processed item of
# expanded_object_list, by appending: # expanded_object_list, by setting:
# - exc_info in case of error (so its length becomes 6) # - 'exc_info' in case of error
# - None or the result to post on the active process otherwise # - 'result' otherwise, with None or the result to post
# (length=4) # on the active process
# Skipped item must not be touched (length=3). # Skipped item must not be touched.
traverse(method_id)(expanded_object_list) traverse(method_id)(expanded_object_list)
except: except:
# In this case, the group method completely failed. # In this case, the group method completely failed.
...@@ -1314,7 +1334,7 @@ class ActivityTool (Folder, UniqueObject): ...@@ -1314,7 +1334,7 @@ class ActivityTool (Folder, UniqueObject):
m.setExecutionState(MESSAGE_NOT_EXECUTED, exc_info, log=False) m.setExecutionState(MESSAGE_NOT_EXECUTED, exc_info, log=False)
LOG('WARNING ActivityTool', 0, LOG('WARNING ActivityTool', 0,
'Could not call method %s on objects %s' % 'Could not call method %s on objects %s' %
(method_id, [x[0] for x in expanded_object_list]), error=exc_info) (method_id, [x.obj for x in expanded_object_list]), error=exc_info)
error_log = getattr(self, 'error_log', None) error_log = getattr(self, 'error_log', None)
if error_log is not None: if error_log is not None:
error_log.raising(exc_info) error_log.raising(exc_info)
...@@ -1323,25 +1343,24 @@ class ActivityTool (Folder, UniqueObject): ...@@ -1323,25 +1343,24 @@ class ActivityTool (Folder, UniqueObject):
for m, expanded_object_list in message_dict.iteritems(): for m, expanded_object_list in message_dict.iteritems():
result_list = [] result_list = []
for result in expanded_object_list: for result in expanded_object_list:
if len(result) != 4: try:
break # message marked as failed by the group_method_id if result.result is not None:
elif result[3] is not None: result_list.append(result)
result_list.append(result) except AttributeError:
exc_info = getattr(result, "exc_info", (SkippedMessage,))
break # failed or skipped message
else: else:
try: try:
if result_list and m.active_process: if result_list and m.active_process:
active_process = traverse(m.active_process) active_process = traverse(m.active_process)
for result in result_list: for result in result_list:
m.activateResult(active_process, result[3], result[0]) m.activateResult(active_process, result.result, result.obj)
except: except:
pass exc_info = None
else: else:
m.setExecutionState(MESSAGE_EXECUTED, context=self) m.setExecutionState(MESSAGE_EXECUTED, context=self)
continue continue
exc_info = result[3:] m.setExecutionState(MESSAGE_NOT_EXECUTED, exc_info, context=self)
m.setExecutionState(MESSAGE_NOT_EXECUTED,
tuple(exc_info) if exc_info else (SkippedMessage,),
context=self)
if self.activity_tracking: if self.activity_tracking:
activity_tracking_logger.info('invoked group messages') activity_tracking_logger.info('invoked group messages')
...@@ -1351,9 +1370,9 @@ class ActivityTool (Folder, UniqueObject): ...@@ -1351,9 +1370,9 @@ class ActivityTool (Folder, UniqueObject):
def group_method(message_list): def group_method(message_list):
try: try:
for m in message_list: for m in message_list:
m.append(getattr(m[0], method_id)(*m[1], **m[2])) m.result = getattr(m.object, method_id)(*m.args, **m.kw)
except Exception: except Exception:
m += sys.exc_info() m.raised()
return group_method return group_method
dummyGroupMethod = dummyGroupMethod() dummyGroupMethod = dummyGroupMethod()
......
...@@ -43,7 +43,6 @@ from AccessControl.SecurityManagement import newSecurityManager ...@@ -43,7 +43,6 @@ from AccessControl.SecurityManagement import newSecurityManager
from zLOG import LOG from zLOG import LOG
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
from DateTime import DateTime from DateTime import DateTime
import cPickle as pickle
from Products.CMFActivity.ActivityTool import Message from Products.CMFActivity.ActivityTool import Message
import gc import gc
import random import random
...@@ -1418,9 +1417,9 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor): ...@@ -1418,9 +1417,9 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor):
def setFoobar(self, object_list): def setFoobar(self, object_list):
foobar_list.append(len(object_list)) foobar_list.append(len(object_list))
for m in object_list: for m in object_list:
obj, args, kw = m obj = m.object
obj.foobar = getattr(obj.aq_base, 'foobar', 0) + kw.get('number', 1) obj.foobar = getattr(obj.aq_base, 'foobar', 0) + m.kw.get('number', 1)
m.append(None) m.result = None
from Products.ERP5Type.Core.Folder import Folder from Products.ERP5Type.Core.Folder import Folder
Folder.setFoobar = setFoobar Folder.setFoobar = setFoobar
...@@ -2723,8 +2722,7 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor): ...@@ -2723,8 +2722,7 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor):
def doSomething(self, message_list): def doSomething(self, message_list):
r = [] r = []
for m in message_list: for m in message_list:
r.append((m[0].getPath(), m[1], m[2])) m.result = r.append((m.object.getPath(), m.args, m.kw))
m.append(None)
r.sort() r.sort()
group_method_call_list.append(r) group_method_call_list.append(r)
activity_tool.__class__.doSomething = doSomething activity_tool.__class__.doSomething = doSomething
...@@ -2946,8 +2944,7 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor): ...@@ -2946,8 +2944,7 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor):
def invokeGroup(self, message_list): def invokeGroup(self, message_list):
r = [] r = []
for m in message_list: for m in message_list:
r.append(c.index(m[0])) m.result = r.append(c.index(m.object))
m.append(None)
r.sort() r.sort()
invoked.append(r) invoked.append(r)
category_tool.__class__.invokeGroup = invokeGroup category_tool.__class__.invokeGroup = invokeGroup
......
...@@ -144,19 +144,19 @@ class RuleTool(BaseTool): ...@@ -144,19 +144,19 @@ class RuleTool(BaseTool):
def updateSimulation(self, message_list): def updateSimulation(self, message_list):
expandable_dict = defaultdict(list) expandable_dict = defaultdict(list)
for m in message_list: for m in message_list:
expandable_dict[m[0]].append(m) expandable_dict[m.object].append(m)
for expandable, message_list in expandable_dict.iteritems(): try:
try: for expandable, message_list in expandable_dict.iteritems():
kw = {} kw = {}
for m in message_list: for m in message_list:
kw.update(m[2]) kw.update(m.kw)
m.append(None) m.result = None
LOG("RuleTool", INFO, "Updating simulation for %s: %r" LOG("RuleTool", INFO, "Updating simulation for %s: %r"
% (expandable.getPath(), kw)) % (expandable.getPath(), kw))
expandable._updateSimulation(**kw) expandable._updateSimulation(**kw)
except Exception: except Exception:
exc_info = sys.exc_info() exc_info = sys.exc_info()
for m in message_list: for m in message_list:
m[3:] = exc_info m.raised(exc_info)
InitializeClass(RuleTool) InitializeClass(RuleTool)
...@@ -39,6 +39,7 @@ from Products.CMFCore.utils import UniqueObject, _getAuthenticatedUser, getToolB ...@@ -39,6 +39,7 @@ from Products.CMFCore.utils import UniqueObject, _getAuthenticatedUser, getToolB
from Products.ERP5Type.Globals import InitializeClass, DTMLFile from Products.ERP5Type.Globals import InitializeClass, DTMLFile
from Acquisition import aq_base, aq_inner, aq_parent, ImplicitAcquisitionWrapper from Acquisition import aq_base, aq_inner, aq_parent, ImplicitAcquisitionWrapper
from Products.CMFActivity.ActiveObject import ActiveObject from Products.CMFActivity.ActiveObject import ActiveObject
from Products.CMFActivity.ActivityTool import GroupedMessage
from Products.ERP5Type.TransactionalVariable import getTransactionalVariable from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
from AccessControl.PermissionRole import rolesForPermissionOn from AccessControl.PermissionRole import rolesForPermissionOn
...@@ -789,29 +790,28 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject): ...@@ -789,29 +790,28 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject):
def catalogObjectList(self, object_list, *args, **kw): def catalogObjectList(self, object_list, *args, **kw):
"""Catalog a list of objects""" """Catalog a list of objects"""
m = object_list[0] m = object_list[0]
if type(m) is list: if isinstance(m, GroupedMessage):
tmp_object_list = [x[0] for x in object_list] tmp_object_list = [x.object for x in object_list]
super(CatalogTool, self).catalogObjectList(tmp_object_list, **m[2]) super(CatalogTool, self).catalogObjectList(tmp_object_list, **m.kw)
if tmp_object_list: if tmp_object_list:
exc_info = sys.exc_info() exc_info = sys.exc_info()
for x in object_list: for x in object_list:
if x[0] in tmp_object_list: if x.object in tmp_object_list:
x += exc_info # failed x.raised(exc_info)
else: else:
x.append(None) # success, no result x.result = None
else: else:
super(CatalogTool, self).catalogObjectList(object_list, *args, **kw) super(CatalogTool, self).catalogObjectList(object_list, *args, **kw)
security.declarePrivate('uncatalogObjectList') security.declarePrivate('uncatalogObjectList')
def uncatalogObjectList(self, message_list): def uncatalogObjectList(self, message_list):
"""Uncatalog a list of objects""" """Uncatalog a list of objects"""
# XXX: this is currently only a placeholder for further optimization # TODO: this is currently only a placeholder for further optimization
# (for the moment, it's not faster than the dummy group method)
try: try:
for m in message_list: for m in message_list:
m.append(self.unindexObject(*m[1], **m[2])) m.result = self.unindexObject(*m.args, **m.kw)
except Exception: except Exception:
m += sys.exc_info() m.raised()
security.declarePrivate('unindexObject') security.declarePrivate('unindexObject')
def unindexObject(self, object=None, path=None, uid=None,sql_catalog_id=None): def unindexObject(self, object=None, path=None, uid=None,sql_catalog_id=None):
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!