1 # -*- coding: utf-8 -*-
3 ## Copyright (C)2006 Ingeniweb
5 ## This program is free software; you can redistribute it and/or modify
6 ## it under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 2 of the License, or
8 ## (at your option) any later version.
10 ## This program is distributed in the hope that it will be useful,
11 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ## GNU General Public License for more details.
15 ## You should have received a copy of the GNU General Public License
16 ## along with this program; see the file COPYING. If not, write to the
17 ## Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 __version__
= "$Revision: $"
23 # $Id: class_utility.py 30098 2006-09-08 12:35:01Z encolpe $
24 __docformat__
= 'restructuredtext'
31 # Base classes global vars management
32 _BASECLASSESLOCK
= threading
.RLock()
34 _BASEMETALOCK
= threading
.RLock()
37 def showaq(self
, indent
=''):
41 base
= getattr(obj
, 'aq_base', obj
)
43 except: id = str(base
)
47 if hasattr(obj
, 'aq_self'):
48 if hasattr(obj
.aq_self
, 'aq_self'):
49 rval
= rval
+ indent
+ "(" + id + ")\n"
50 rval
= rval
+ indent
+ "| \\\n"
51 rval
= rval
+ showaq(obj
.aq_self
, '| ' + indent
)
52 rval
= rval
+ indent
+ "|\n"
53 if hasattr(obj
, 'aq_parent'):
54 rval
= rval
+ indent
+ id + "\n"
55 rval
= rval
+ indent
+ "|\n"
56 rval
= rval
+ showaq(obj
.aq_parent
, indent
)
58 rval
= rval
+ indent
+ id + "\n"
62 def listBaseMetaTypes(cl
, reverse
= 0):
64 listBaseMetaTypes(cl, reverse = 0) => list of strings
66 List all base meta types for this class.
68 # Look for the class in _BASEMETA cache
70 return _BASEMETA
[cl
][reverse
]
73 _populateBaseMetaTypes(cl
)
74 return listBaseMetaTypes(cl
, reverse
)
76 def isBaseMetaType(meta
, cl
):
78 return _BASEMETA
[cl
][2].has_key(meta
)
81 _populateBaseMetaTypes(cl
)
82 return isBaseMetaType(meta
, cl
)
84 def _populateBaseMetaTypes(cl
):
85 """Fill the base classes structure"""
86 # Fill the base classes list
89 except AttributeError:
92 for b
in cl
.__bases
__:
93 ret
= list(listBaseMetaTypes(b
, 1)) + ret
95 # Fill the base classes dict
100 _BASEMETALOCK
.acquire()
104 _BASEMETA
[cl
] = (tuple(rev
), tuple(ret
), bases
)
106 _BASEMETALOCK
.release()
108 def objectIds(container
, meta_types
= []):
111 return map(lambda x
: x
[0], objectItems(container
, meta_types
))
113 def objectValues(container
, meta_types
= []):
116 return map(lambda x
: x
[1], objectItems(container
, meta_types
))
118 def objectItems(container
, meta_types
= []):
120 objectItems(container, meta_types = [])
121 Same as a container's objectItem method, meta_types are scanned in the base classes too.
122 Ie. all objects derivated from Folder will be returned by objectItem(x, ['Folder'])
125 if type(meta_types
) not in (type(()), type([])):
126 meta_types
= [meta_types
]
128 # Special case where meta_types is empty
130 return container
.objectItems()
132 # Otherwise : check parent for each meta_type
134 for (id, obj
) in container
.objectItems():
135 for mt
in meta_types
:
136 if isBaseMetaType(mt
, obj
.__class
__):
137 ret
.append((id, obj
))
144 def listBaseClasses(cl
, reverse
= 0):
146 listBaseClasses(cl, reverse = 0) => list of classes
148 List all the base classes of an object.
149 When reverse is 0, return the self class first.
150 When reverse is 1, return the self class last.
152 WARNING : reverse is 0 or 1, it is an integer, NOT A BOOLEAN ! (optim issue)
156 WARNING : for optimization issues, the ORIGINAL tuple is returned : please do not change it !
158 # Look for the class in _BASECLASSES cache
160 return _BASECLASSES
[cl
][reverse
]
163 _populateBaseClasses(cl
)
164 return listBaseClasses(cl
, reverse
)
167 def isBaseClass(base
, cl
):
169 isBaseClass(base, cl) => Boolean
170 Return true if base is a base class of cl
173 return _BASECLASSES
[cl
][2].has_key(base
)
175 _populateBaseClasses(cl
)
176 return isBaseClass(base
, cl
)
179 def _populateBaseClasses(cl
):
180 """Fill the base classes structure"""
181 # Fill the base classes list
183 for b
in cl
.__bases
__:
184 ret
= list(listBaseClasses(b
, 1)) + ret
186 # Fill the base classes dict
191 _BASECLASSESLOCK
.acquire()
195 _BASECLASSES
[cl
] = (tuple(rev
), tuple(ret
), bases
)
197 _BASECLASSESLOCK
.release()