From 7b8811c80bf9fec37c5eb3377eb4f40b6ad0533d Mon Sep 17 00:00:00 2001 From: Julien Muchembled <jm@nexedi.com> Date: Wed, 2 Jun 2010 14:49:05 +0000 Subject: [PATCH] Revert [35537] and speed up contentValues by optimizing TypesTool.listContentTypes [35537] was committed for performance reason, but it changed the behaviour of Folder.contentValues git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@35908 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ERP5Type/Core/Folder.py | 5 ++- product/ERP5Type/Tool/TypesTool.py | 65 +++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/product/ERP5Type/Core/Folder.py b/product/ERP5Type/Core/Folder.py index 2c1caa6faf..beac777940 100644 --- a/product/ERP5Type/Core/Folder.py +++ b/product/ERP5Type/Core/Folder.py @@ -1431,16 +1431,17 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn, def contentValues(self, *args, **kw): # Returns a list of documents contained in this folder. # ( no docstring to prevent publishing ) + portal_type_id_list = self._getTypesTool().listContentTypes() filter_kw = kw.pop('filter', None) or {} portal_type = kw.pop('portal_type', None) if 'portal_type' in filter_kw: portal_type = filter_kw.pop('portal_type') if portal_type is None: - kw['portal_type'] = self._getTypesTool().listContentTypes() + kw['portal_type'] = portal_type_id_list else: if isinstance(portal_type, str): portal_type = portal_type, - kw['portal_type'] = portal_type + kw['portal_type'] = [x for x in portal_type if x in portal_type_id_list] object_list = self.objectValues(*args, **kw) if filter_kw: object_list = filter(ContentFilter(**filter_kw), object_list) diff --git a/product/ERP5Type/Tool/TypesTool.py b/product/ERP5Type/Tool/TypesTool.py index 554996754a..9f2c2798a9 100644 --- a/product/ERP5Type/Tool/TypesTool.py +++ b/product/ERP5Type/Tool/TypesTool.py @@ -16,6 +16,7 @@ ############################################################################## import imp, sys, warnings +from itertools import chain import zope.interface from Acquisition import aq_base from AccessControl import ClassSecurityInfo @@ -30,6 +31,47 @@ from zLOG import LOG, WARNING, PANIC from Products.ERP5Type.interfaces import ITypeProvider, ITypesTool +class ComposedObjectIds(object): + """Sequence type used to iterate efficiently over a union of folders + + Returned values are ids of contained objects. + This type should used instead of building a simple list from the concatenation + of multiple calls on objectIds. + + Note this class even implements '__contains__', which makes: + 'some_id' in ComposedObjectIds([container]) + faster than: + 'some_id' in container.objectIds() + + XXX Is it only useful for TypesTool ? + If not, this should it be moved in another place, like ERP5Type.Utils + """ + __allow_access_to_unprotected_subobjects__ = 1 + + def __init__(self, container_list): + self._container_list = container_list + + def __contains__(self, item): + for container in self._container_list: + if container.has_key(item): + return True + return False + + def __iter__(self): + return chain(*[container.objectIds() for container in self._container_list]) + + def __len__(self): + return sum(map(len, self._container_list)) + + def __getitem__(self, item): + for container in self._container_list: + count = len(container) + if item < count: + return container.objectIds()[item] + item -= count + raise IndexError + + CMFCore_TypesTool = CMFCore_TypesToolModule.TypesTool class TypeProvider(BaseTool, CMFCore_TypesTool): @@ -54,19 +96,32 @@ class TypesTool(TypeProvider): security = ClassSecurityInfo() security.declareObjectProtected(Permissions.AccessContentsInformation) + def listContentTypes(self, container=None): + """List content types from all providers + """ + if container is not None: + # XXX Slow legacy implementation. Is 'container_list' parameter useful ? + return CMFCore_TypesTool.listContentTypes(self, container) + object_list = [self] + _getOb = self.getPortalObject()._getOb + for provider in self.type_provider_list: + provider_value = _getOb(provider, None) + if provider_value: + object_list.append(provider_value) + return ComposedObjectIds(object_list) + def listTypeInfo(self, container=None): """List type information from all providers """ listTypeInfo = CMFCore_TypesTool.listTypeInfo type_info_list = listTypeInfo(self, container=container) - portal = self.getPortalObject() + _getOb = self.getPortalObject()._getOb for provider in self.type_provider_list: - provider_value = portal._getOb(provider, None) + provider_value = _getOb(provider, None) if provider_value is not None: - type_info_list.extend( - listTypeInfo(provider_value, container=container)) + type_info_list += listTypeInfo(provider_value, container=container) return type_info_list - + def _aq_dynamic(self, id): """Get a type information from a provider """ -- 2.30.9