--- /dev/null
+# -*- coding: utf-8 -*-
+## GroupUserFolder
+## Copyright (C)2006 Ingeniweb
+
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+
+## You should have received a copy of the GNU General Public License
+## along with this program; see the file COPYING. If not, write to the
+## Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+"""
+
+"""
+__version__ = "$Revision: $"
+# $Source: $
+# $Id: class_utility.py 30098 2006-09-08 12:35:01Z encolpe $
+__docformat__ = 'restructuredtext'
+
+import string
+import re
+import threading
+import string
+
+# Base classes global vars management
+_BASECLASSESLOCK = threading.RLock()
+_BASECLASSES = {}
+_BASEMETALOCK = threading.RLock()
+_BASEMETA = {}
+
+def showaq(self, indent=''):
+ "showaq"
+ rval = ""
+ obj = self
+ base = getattr(obj, 'aq_base', obj)
+ try: id = base.id
+ except: id = str(base)
+ try: id = id()
+ except: pass
+
+ if hasattr(obj, 'aq_self'):
+ if hasattr(obj.aq_self, 'aq_self'):
+ rval = rval + indent + "(" + id + ")\n"
+ rval = rval + indent + "| \\\n"
+ rval = rval + showaq(obj.aq_self, '| ' + indent)
+ rval = rval + indent + "|\n"
+ if hasattr(obj, 'aq_parent'):
+ rval = rval + indent + id + "\n"
+ rval = rval + indent + "|\n"
+ rval = rval + showaq(obj.aq_parent, indent)
+ else:
+ rval = rval + indent + id + "\n"
+ return rval
+
+
+def listBaseMetaTypes(cl, reverse = 0):
+ """
+ listBaseMetaTypes(cl, reverse = 0) => list of strings
+
+ List all base meta types for this class.
+ """
+ # Look for the class in _BASEMETA cache
+ try:
+ return _BASEMETA[cl][reverse]
+
+ except KeyError:
+ _populateBaseMetaTypes(cl)
+ return listBaseMetaTypes(cl, reverse)
+
+def isBaseMetaType(meta, cl):
+ try:
+ return _BASEMETA[cl][2].has_key(meta)
+
+ except KeyError:
+ _populateBaseMetaTypes(cl)
+ return isBaseMetaType(meta, cl)
+
+def _populateBaseMetaTypes(cl):
+ """Fill the base classes structure"""
+ # Fill the base classes list
+ try:
+ ret = [cl.meta_type]
+ except AttributeError:
+ ret = []
+
+ for b in cl.__bases__:
+ ret = list(listBaseMetaTypes(b, 1)) + ret
+
+ # Fill the base classes dict
+ bases = {}
+ for b in ret:
+ bases[b] = 1
+
+ _BASEMETALOCK.acquire()
+ try:
+ rev = ret[:]
+ rev.reverse()
+ _BASEMETA[cl] = (tuple(rev), tuple(ret), bases)
+ finally:
+ _BASEMETALOCK.release()
+
+def objectIds(container, meta_types = []):
+ """
+ """
+ return map(lambda x: x[0], objectItems(container, meta_types))
+
+def objectValues(container, meta_types = []):
+ """
+ """
+ return map(lambda x: x[1], objectItems(container, meta_types))
+
+def objectItems(container, meta_types = []):
+ """
+ objectItems(container, meta_types = [])
+ Same as a container's objectItem method, meta_types are scanned in the base classes too.
+ Ie. all objects derivated from Folder will be returned by objectItem(x, ['Folder'])
+ """
+ # Convert input type
+ if type(meta_types) not in (type(()), type([])):
+ meta_types = [meta_types]
+
+ # Special case where meta_types is empty
+ if not meta_types:
+ return container.objectItems()
+
+ # Otherwise : check parent for each meta_type
+ ret = []
+ for (id, obj) in container.objectItems():
+ for mt in meta_types:
+ if isBaseMetaType(mt, obj.__class__):
+ ret.append((id, obj))
+ break
+
+ return ret
+
+
+
+def listBaseClasses(cl, reverse = 0):
+ """
+ listBaseClasses(cl, reverse = 0) => list of classes
+
+ List all the base classes of an object.
+ When reverse is 0, return the self class first.
+ When reverse is 1, return the self class last.
+
+ WARNING : reverse is 0 or 1, it is an integer, NOT A BOOLEAN ! (optim issue)
+
+ CACHE RESULTS
+
+ WARNING : for optimization issues, the ORIGINAL tuple is returned : please do not change it !
+ """
+ # Look for the class in _BASECLASSES cache
+ try:
+ return _BASECLASSES[cl][reverse]
+
+ except:
+ _populateBaseClasses(cl)
+ return listBaseClasses(cl, reverse)
+
+
+def isBaseClass(base, cl):
+ """
+ isBaseClass(base, cl) => Boolean
+ Return true if base is a base class of cl
+ """
+ try:
+ return _BASECLASSES[cl][2].has_key(base)
+ except:
+ _populateBaseClasses(cl)
+ return isBaseClass(base, cl)
+
+
+def _populateBaseClasses(cl):
+ """Fill the base classes structure"""
+ # Fill the base classes list
+ ret = [cl]
+ for b in cl.__bases__:
+ ret = list(listBaseClasses(b, 1)) + ret
+
+ # Fill the base classes dict
+ bases = {}
+ for b in ret:
+ bases[b] = 1
+
+ _BASECLASSESLOCK.acquire()
+ try:
+ rev = ret[:]
+ rev.reverse()
+ _BASECLASSES[cl] = (tuple(rev), tuple(ret), bases)
+ finally:
+ _BASECLASSESLOCK.release()