Back to index

plone3  3.1.7
class_utility.py
Go to the documentation of this file.
00001 # -*- coding: utf-8 -*-
00002 ## GroupUserFolder
00003 ## Copyright (C)2006 Ingeniweb
00004 
00005 ## This program is free software; you can redistribute it and/or modify
00006 ## it under the terms of the GNU General Public License as published by
00007 ## the Free Software Foundation; either version 2 of the License, or
00008 ## (at your option) any later version.
00009 
00010 ## This program is distributed in the hope that it will be useful,
00011 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 ## GNU General Public License for more details.
00014 
00015 ## You should have received a copy of the GNU General Public License
00016 ## along with this program; see the file COPYING. If not, write to the
00017 ## Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 """
00019 
00020 """
00021 __version__ = "$Revision:  $"
00022 # $Source:  $
00023 # $Id: class_utility.py 30098 2006-09-08 12:35:01Z encolpe $
00024 __docformat__ = 'restructuredtext'
00025 
00026 import string
00027 import re
00028 import threading
00029 import string
00030 
00031 # Base classes global vars management
00032 _BASECLASSESLOCK = threading.RLock()
00033 _BASECLASSES = {}
00034 _BASEMETALOCK = threading.RLock()
00035 _BASEMETA = {}
00036 
00037 def showaq(self, indent=''):
00038     "showaq"
00039     rval = ""
00040     obj = self
00041     base = getattr(obj, 'aq_base', obj)
00042     try: id = base.id
00043     except: id = str(base)
00044     try: id = id()
00045     except: pass
00046 
00047     if hasattr(obj, 'aq_self'):
00048         if hasattr(obj.aq_self, 'aq_self'):
00049             rval = rval + indent + "(" + id + ")\n"
00050             rval = rval + indent + "|  \\\n"
00051             rval = rval + showaq(obj.aq_self, '|   ' + indent)
00052             rval = rval + indent + "|\n"
00053         if hasattr(obj, 'aq_parent'):
00054             rval = rval + indent + id + "\n"
00055             rval = rval + indent + "|\n"
00056             rval = rval + showaq(obj.aq_parent, indent)
00057     else:
00058         rval = rval + indent + id + "\n"
00059     return rval
00060 
00061 
00062 def listBaseMetaTypes(cl, reverse = 0):
00063     """
00064     listBaseMetaTypes(cl, reverse = 0) => list of strings
00065 
00066     List all base meta types for this class.
00067     """
00068     # Look for the class in _BASEMETA cache
00069     try:
00070         return _BASEMETA[cl][reverse]
00071 
00072     except KeyError:
00073         _populateBaseMetaTypes(cl)
00074         return listBaseMetaTypes(cl, reverse)
00075 
00076 def isBaseMetaType(meta, cl):
00077     try:
00078         return _BASEMETA[cl][2].has_key(meta)
00079 
00080     except KeyError:
00081         _populateBaseMetaTypes(cl)
00082         return isBaseMetaType(meta, cl)
00083 
00084 def _populateBaseMetaTypes(cl):
00085     """Fill the base classes structure"""
00086     # Fill the base classes list
00087     try:
00088         ret = [cl.meta_type]
00089     except AttributeError:
00090         ret = []
00091 
00092     for b in cl.__bases__:
00093         ret = list(listBaseMetaTypes(b, 1)) + ret
00094 
00095     # Fill the base classes dict
00096     bases = {}
00097     for b in ret:
00098         bases[b] = 1
00099 
00100     _BASEMETALOCK.acquire()
00101     try:
00102         rev = ret[:]
00103         rev.reverse()
00104         _BASEMETA[cl] = (tuple(rev), tuple(ret), bases)
00105     finally:
00106         _BASEMETALOCK.release()
00107 
00108 def objectIds(container, meta_types = []):
00109     """
00110     """
00111     return map(lambda x: x[0], objectItems(container, meta_types))
00112 
00113 def objectValues(container, meta_types = []):
00114     """
00115     """
00116     return map(lambda x: x[1], objectItems(container, meta_types))
00117 
00118 def objectItems(container, meta_types = []):
00119     """
00120     objectItems(container, meta_types = [])
00121     Same as a container's objectItem method, meta_types are scanned in the base classes too.
00122     Ie. all objects derivated from Folder will be returned by objectItem(x, ['Folder'])
00123     """
00124     # Convert input type
00125     if type(meta_types) not in (type(()), type([])):
00126         meta_types = [meta_types]
00127 
00128     # Special case where meta_types is empty
00129     if not meta_types:
00130         return container.objectItems()
00131 
00132     # Otherwise : check parent for each meta_type
00133     ret = []
00134     for (id, obj) in container.objectItems():
00135         for mt in meta_types:
00136             if isBaseMetaType(mt, obj.__class__):
00137                 ret.append((id, obj))
00138                 break
00139 
00140     return ret
00141 
00142 
00143 
00144 def listBaseClasses(cl, reverse = 0):
00145     """
00146     listBaseClasses(cl, reverse = 0) => list of classes
00147 
00148     List all the base classes of an object.
00149     When reverse is 0, return the self class first.
00150     When reverse is 1, return the self class last.
00151 
00152     WARNING : reverse is 0 or 1, it is an integer, NOT A BOOLEAN ! (optim issue)
00153 
00154     CACHE RESULTS
00155 
00156     WARNING : for optimization issues, the ORIGINAL tuple is returned : please do not change it !
00157     """
00158     # Look for the class in _BASECLASSES cache
00159     try:
00160         return _BASECLASSES[cl][reverse]
00161 
00162     except:
00163         _populateBaseClasses(cl)
00164         return listBaseClasses(cl, reverse)
00165 
00166 
00167 def isBaseClass(base, cl):
00168     """
00169     isBaseClass(base, cl) => Boolean
00170     Return true if base is a base class of cl
00171     """
00172     try:
00173         return _BASECLASSES[cl][2].has_key(base)
00174     except:
00175         _populateBaseClasses(cl)
00176         return isBaseClass(base, cl)
00177 
00178 
00179 def _populateBaseClasses(cl):
00180     """Fill the base classes structure"""
00181     # Fill the base classes list
00182     ret = [cl]
00183     for b in cl.__bases__:
00184         ret = list(listBaseClasses(b, 1)) + ret
00185 
00186     # Fill the base classes dict
00187     bases = {}
00188     for b in ret:
00189         bases[b] = 1
00190 
00191     _BASECLASSESLOCK.acquire()
00192     try:
00193         rev = ret[:]
00194         rev.reverse()
00195         _BASECLASSES[cl] = (tuple(rev), tuple(ret), bases)
00196     finally:
00197         _BASECLASSESLOCK.release()