X-Git-Url: https://scm.cri.minesparis.psl.eu/git/GroupUserFolder.git/blobdiff_plain/e9d14b6b5cc9cd4775c60cb340b5c4c787536fc3..3e1ba4932c34812cf2f6f3569b0f0dbea97b7a0b:/Products/GroupUserFolder/class_utility.py diff --git a/Products/GroupUserFolder/class_utility.py b/Products/GroupUserFolder/class_utility.py new file mode 100644 index 0000000..79357bd --- /dev/null +++ b/Products/GroupUserFolder/class_utility.py @@ -0,0 +1,197 @@ +# -*- 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()