working depth-first object discovery

This commit is contained in:
Darren Ranalli 2006-10-11 21:24:35 +00:00
parent e5903ff101
commit caa7b9404d
1 changed files with 94 additions and 0 deletions

View File

@ -0,0 +1,94 @@
from direct.showbase.PythonUtil import Stack, fastRepr, invertDictLossless
from direct.showbase.PythonUtil import itype, safeRepr
import types
class ContainerReport:
def __init__(self, rootObj, rootObjName=None):
self._rootObj = rootObj
if rootObjName is None:
rootObjName = repr(rootObj)
self._visitedIds = set()
self._id2pathStr = {}
self._id2container = {}
self._id2len = {}
self._stack = Stack()
self._stack.push(rootObj)
self._id2pathStr[id(rootObj)] = rootObjName
self._traverse()
def _examine(self, obj):
# return False if it's an object that can't contain or lead to other objects
if type(obj) in (types.BooleanType, types.BuiltinFunctionType,
types.BuiltinMethodType, types.ComplexType,
types.FloatType, types.IntType, types.LongType,
types.NoneType, types.NotImplementedType,
types.TypeType, types.CodeType):
return False
try:
length = len(obj)
except:
length = None
if length is not None and length > 0:
objId = id(obj)
self._id2container[objId] = obj
self._id2len[objId] = length
return True
def _traverse(self):
while len(self._stack) > 0:
obj = self._stack.pop()
#print '_traverse: %s' % fastRepr(obj, 30)
try:
dirList = dir(obj)
except:
pass
else:
for name in dirList:
if name[-2:] == '__':
continue
attr = getattr(obj, name)
if id(attr) not in self._visitedIds:
self._visitedIds.add(id(attr))
if self._examine(attr):
self._id2pathStr[id(attr)] = self._id2pathStr[id(obj)] + '.%s' % name
self._stack.push(attr)
if type(obj) not in (types.StringType, types.UnicodeType):
if type(obj) is types.DictType:
keys = obj.keys()
for key in keys:
attr = obj[key]
if id(attr) not in self._visitedIds:
self._visitedIds.add(id(attr))
if self._examine(attr):
self._id2pathStr[id(attr)] = self._id2pathStr[id(obj)] + '[%s]' % safeRepr(key)
self._stack.push(attr)
elif type(obj) is not types.FileType:
try:
itr = iter(obj)
except:
pass
else:
try:
index = 0
while 1:
try:
attr = itr.next()
except:
# some custom classes don't do well when iterated
break
if id(attr) not in self._visitedIds:
self._visitedIds.add(id(attr))
if self._examine(attr):
self._id2pathStr[id(attr)] = self._id2pathStr[id(obj)] + '[%s]' % index
self._stack.push(attr)
index += 1
except StopIteration, e:
pass
def __repr__(self):
len2ids = invertDictLossless(self._id2len)
lengths = len2ids.keys()
lengths.sort()
lengths.reverse()
for l in lengths:
for id in len2ids[l]:
obj = self._id2container[id]
print '%s: %s: %s' % (l, repr(itype(obj)), self._id2pathStr[id])