Commit da234001 authored by Julien Muchembled's avatar 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.
parent 0cf9f566
......@@ -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:
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()
......
......@@ -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
......
......@@ -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():
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
m.raised(exc_info)
InitializeClass(RuleTool)
......@@ -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):
......
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