diff --git a/product/CMFActivity/ActivityTool.py b/product/CMFActivity/ActivityTool.py index 3de22b73c7cfb30d9e1bfcc4fd0e9eb679f276b2..a7db8acba954fa615740217e901c67225154ddb4 100644 --- a/product/CMFActivity/ActivityTool.py +++ b/product/CMFActivity/ActivityTool.py @@ -434,6 +434,26 @@ Named Parameters: %r def getExecutionState(self): 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 def activity_dict(): @@ -1291,21 +1311,21 @@ class ActivityTool (Folder, UniqueObject): active_obj = subobj.activate(activity=activity, **activity_kw) getattr(active_obj, alternate_method_id)(*m.args, **m.kw) else: - expanded_object_list.append([subobj, m.args, m.kw]) + expanded_object_list.append(GroupedMessage(subobj, m)) except: m.setExecutionState(MESSAGE_NOT_EXECUTED, context=self) expanded_object_list = sum(message_dict.itervalues(), []) try: - if len(expanded_object_list) > 0: + if expanded_object_list: traverse = self.getPortalObject().unrestrictedTraverse # FIXME: how to apply security here? # NOTE: The callee must update each processed item of - # expanded_object_list, by appending: - # - exc_info in case of error (so its length becomes 6) - # - None or the result to post on the active process otherwise - # (length=4) - # Skipped item must not be touched (length=3). + # expanded_object_list, by setting: + # - 'exc_info' in case of error + # - 'result' otherwise, with None or the result to post + # on the active process + # Skipped item must not be touched. traverse(method_id)(expanded_object_list) except: # In this case, the group method completely failed. @@ -1314,7 +1334,7 @@ class ActivityTool (Folder, UniqueObject): m.setExecutionState(MESSAGE_NOT_EXECUTED, exc_info, log=False) LOG('WARNING ActivityTool', 0, '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) if error_log is not None: error_log.raising(exc_info) @@ -1323,25 +1343,24 @@ class ActivityTool (Folder, UniqueObject): for m, expanded_object_list in message_dict.iteritems(): result_list = [] for result in expanded_object_list: - if len(result) != 4: - break # message marked as failed by the group_method_id - elif result[3] is not None: - result_list.append(result) + try: + if result.result is not None: + result_list.append(result) + except AttributeError: + exc_info = getattr(result, "exc_info", (SkippedMessage,)) + break # failed or skipped message else: try: if result_list and m.active_process: active_process = traverse(m.active_process) for result in result_list: - m.activateResult(active_process, result[3], result[0]) + m.activateResult(active_process, result.result, result.obj) except: - pass + exc_info = None else: m.setExecutionState(MESSAGE_EXECUTED, context=self) continue - exc_info = result[3:] - m.setExecutionState(MESSAGE_NOT_EXECUTED, - tuple(exc_info) if exc_info else (SkippedMessage,), - context=self) + m.setExecutionState(MESSAGE_NOT_EXECUTED, exc_info, context=self) if self.activity_tracking: activity_tracking_logger.info('invoked group messages') @@ -1351,9 +1370,9 @@ class ActivityTool (Folder, UniqueObject): def group_method(message_list): try: 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: - m += sys.exc_info() + m.raised() return group_method dummyGroupMethod = dummyGroupMethod() diff --git a/product/CMFActivity/tests/testCMFActivity.py b/product/CMFActivity/tests/testCMFActivity.py index 9eddf4db404f549bd2e2cb92cd0d0b99588fdcf6..ede407cd21a61f79b59ed943580da9529f298382 100644 --- a/product/CMFActivity/tests/testCMFActivity.py +++ b/product/CMFActivity/tests/testCMFActivity.py @@ -43,7 +43,6 @@ from AccessControl.SecurityManagement import newSecurityManager from zLOG import LOG from ZODB.POSException import ConflictError from DateTime import DateTime -import cPickle as pickle from Products.CMFActivity.ActivityTool import Message import gc import random @@ -1418,9 +1417,9 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor): def setFoobar(self, object_list): foobar_list.append(len(object_list)) for m in object_list: - obj, args, kw = m - obj.foobar = getattr(obj.aq_base, 'foobar', 0) + kw.get('number', 1) - m.append(None) + obj = m.object + obj.foobar = getattr(obj.aq_base, 'foobar', 0) + m.kw.get('number', 1) + m.result = None from Products.ERP5Type.Core.Folder import Folder Folder.setFoobar = setFoobar @@ -2723,8 +2722,7 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor): def doSomething(self, message_list): r = [] for m in message_list: - r.append((m[0].getPath(), m[1], m[2])) - m.append(None) + m.result = r.append((m.object.getPath(), m.args, m.kw)) r.sort() group_method_call_list.append(r) activity_tool.__class__.doSomething = doSomething @@ -2946,8 +2944,7 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor): def invokeGroup(self, message_list): r = [] for m in message_list: - r.append(c.index(m[0])) - m.append(None) + m.result = r.append(c.index(m.object)) r.sort() invoked.append(r) category_tool.__class__.invokeGroup = invokeGroup diff --git a/product/ERP5/Tool/RuleTool.py b/product/ERP5/Tool/RuleTool.py index d561afe6cad221e5a395bff1d864d6a2a0bb5138..5c7ccd25d068e71c31ec16da79903ea576923a29 100644 --- a/product/ERP5/Tool/RuleTool.py +++ b/product/ERP5/Tool/RuleTool.py @@ -144,19 +144,19 @@ class RuleTool(BaseTool): def updateSimulation(self, message_list): expandable_dict = defaultdict(list) for m in message_list: - expandable_dict[m[0]].append(m) - for expandable, message_list in expandable_dict.iteritems(): - try: + expandable_dict[m.object].append(m) + try: + for expandable, message_list in expandable_dict.iteritems(): kw = {} for m in message_list: - kw.update(m[2]) - m.append(None) + kw.update(m.kw) + m.result = None LOG("RuleTool", INFO, "Updating simulation for %s: %r" % (expandable.getPath(), kw)) expandable._updateSimulation(**kw) - except Exception: - exc_info = sys.exc_info() - for m in message_list: - m[3:] = exc_info + except Exception: + exc_info = sys.exc_info() + for m in message_list: + m.raised(exc_info) InitializeClass(RuleTool) diff --git a/product/ERP5Catalog/CatalogTool.py b/product/ERP5Catalog/CatalogTool.py index 6310d72e8486e8e18f2ab8e111cb9606db8ac6bd..cd097a888e4b5021e3cd13614a980a56eeb0b77d 100644 --- a/product/ERP5Catalog/CatalogTool.py +++ b/product/ERP5Catalog/CatalogTool.py @@ -39,6 +39,7 @@ from Products.CMFCore.utils import UniqueObject, _getAuthenticatedUser, getToolB from Products.ERP5Type.Globals import InitializeClass, DTMLFile from Acquisition import aq_base, aq_inner, aq_parent, ImplicitAcquisitionWrapper from Products.CMFActivity.ActiveObject import ActiveObject +from Products.CMFActivity.ActivityTool import GroupedMessage from Products.ERP5Type.TransactionalVariable import getTransactionalVariable from AccessControl.PermissionRole import rolesForPermissionOn @@ -789,29 +790,28 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject): def catalogObjectList(self, object_list, *args, **kw): """Catalog a list of objects""" m = object_list[0] - if type(m) is list: - tmp_object_list = [x[0] for x in object_list] - super(CatalogTool, self).catalogObjectList(tmp_object_list, **m[2]) + if isinstance(m, GroupedMessage): + tmp_object_list = [x.object for x in object_list] + super(CatalogTool, self).catalogObjectList(tmp_object_list, **m.kw) if tmp_object_list: exc_info = sys.exc_info() for x in object_list: - if x[0] in tmp_object_list: - x += exc_info # failed + if x.object in tmp_object_list: + x.raised(exc_info) else: - x.append(None) # success, no result + x.result = None else: super(CatalogTool, self).catalogObjectList(object_list, *args, **kw) security.declarePrivate('uncatalogObjectList') def uncatalogObjectList(self, message_list): """Uncatalog a list of objects""" - # XXX: this is currently only a placeholder for further optimization - # (for the moment, it's not faster than the dummy group method) + # TODO: this is currently only a placeholder for further optimization try: for m in message_list: - m.append(self.unindexObject(*m[1], **m[2])) + m.result = self.unindexObject(*m.args, **m.kw) except Exception: - m += sys.exc_info() + m.raised() security.declarePrivate('unindexObject') def unindexObject(self, object=None, path=None, uid=None,sql_catalog_id=None):