Source code for direct.showbase.ObjectReport

"""
>>> from direct.showbase import ObjectReport

>>> o=ObjectReport.ObjectReport('baseline')
>>> run()
...

>>> o2=ObjectReport.ObjectReport('')
>>> o.diff(o2)
"""

__all__ = ['ExclusiveObjectPool', 'ObjectReport']

from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.showbase import DirectObject, ObjectPool, GarbageReport
from direct.showbase.PythonUtil import makeList, Sync
import gc
import sys

if sys.version_info >= (3, 0):
    import builtins
else:
    import __builtin__ as builtins

[docs]class ExclusiveObjectPool(DirectObject.DirectObject): # ObjectPool specialization that excludes particular objects # IDs of objects to globally exclude from reporting _ExclObjs = [] _ExclObjIds = {} _SyncMaster = Sync('ExclusiveObjectPool.ExcludedObjectList') _SerialNumGen = SerialNumGen()
[docs] @classmethod def addExclObjs(cls, *objs): for obj in makeList(objs): if id(obj) not in cls._ExclObjIds: cls._ExclObjs.append(obj) cls._ExclObjIds.setdefault(id(obj), 0) cls._ExclObjIds[id(obj)] += 1 cls._SyncMaster.change()
[docs] @classmethod def removeExclObjs(cls, *objs): for obj in makeList(objs): assert id(obj) in cls._ExclObjIds cls._ExclObjIds[id(obj)] -= 1 if cls._ExclObjIds[id(obj)] == 0: del cls._ExclObjIds[id(obj)] cls._ExclObjs.remove(obj) cls._SyncMaster.change()
[docs] def __init__(self, objects): self._objects = list(objects) self._postFilterObjs = [] self._sync = Sync('%s-%s' % (self.__class__.__name__, self._SerialNumGen.next()), self._SyncMaster) self._sync.invalidate() ExclusiveObjectPool.addExclObjs(self._objects, self._postFilterObjs, self._sync)
[docs] def destroy(self): self.ignoreAll() ExclusiveObjectPool.removeExclObjs(self._objects, self._postFilterObjs, self._sync) del self._objects del self._postFilterObjs del self._sync
def _resync(self): if self._sync.isSynced(self._SyncMaster): return if hasattr(self, '_filteredPool'): ExclusiveObjectPool.removeExclObjs(*self._filteredPool._getInternalObjs()) ExclusiveObjectPool.removeExclObjs(self._filteredPool) del self._filteredPool del self._postFilterObjs[:] for obj in self._objects: if id(obj) not in ExclusiveObjectPool._ExclObjIds: self._postFilterObjs.append(obj) self._filteredPool = ExclusiveObjectPool(self._postFilterObjs) ExclusiveObjectPool.addExclObjs(self._filteredPool) ExclusiveObjectPool.addExclObjs(*self._filteredPool._getInternalObjs()) self._sync.sync(self._SyncMaster)
[docs] def getObjsOfType(self, type): self._resync() return self._filteredPool.getObjsOfType(type)
[docs] def printObjsOfType(self, type): self._resync() return self._filteredPool.printObjsOfType(type)
[docs] def diff(self, other): self._resync() return self._filteredPool.diff(other._filteredPool)
[docs] def typeFreqStr(self): self._resync() return self._filteredPool.typeFreqStr()
def __len__(self): self._resync() return len(self._filteredPool)
[docs]class ObjectReport: """report on every Python object in the current process""" notify = directNotify.newCategory('ObjectReport')
[docs] def __init__(self, name, log=True): gr = GarbageReport.GarbageReport('ObjectReport\'s GarbageReport: %s' % name, log=log) gr.destroy() del gr self._name = name self._pool = ObjectPool.ObjectPool(self._getObjectList()) #ExclusiveObjectPool.addExclObjs(self, self._pool, self._name) if log: self.notify.info('===== ObjectReport: \'%s\' =====\n%s' % (self._name, self.typeFreqStr()))
[docs] def destroy(self): #ExclusiveObjectPool.removeExclObjs(self, self._pool, self._name) self._pool.destroy() del self._pool del self._name
[docs] def typeFreqStr(self): return self._pool.typeFreqStr()
[docs] def diff(self, other): return self._pool.diff(other._pool)
[docs] def getObjectPool(self): return self._pool
def _getObjectList(self): if hasattr(sys, 'getobjects'): return sys.getobjects(0) else: gc.collect() # grab gc's object list gc_objects = gc.get_objects() # use get_referents to find everything else objects = gc_objects objects.append(builtins.__dict__) nextObjList = gc_objects found = set() found.add(id(objects)) found.add(id(found)) found.add(id(gc_objects)) for obj in objects: found.add(id(obj)) # repeatedly call get_referents until we can't find any more objects while len(nextObjList): curObjList = nextObjList nextObjList = [] for obj in curObjList: refs = gc.get_referents(obj) for ref in refs: if id(ref) not in found: found.add(id(ref)) objects.append(ref) nextObjList.append(ref) return objects """ if hasattr(sys, 'getobjects'): return sys.getobjects(0) else: objs = [] stateStack = Stack() root = builtins objIds = set([id(root)]) stateStack.push((root, None, 0)) while True: if len(stateStack) == 0: break obj, adjacents, resumeIndex = stateStack.pop() objs.append(obj) print id(obj) if adjacents is None: adjacents = gc.get_referents(obj) adjacents.extend(gc.get_referrers(obj)) # pare the list down to the ones that have not already been visited # to minimize calls to get_referents/get_referrers newObjs = [] for adj in adjacents: adjId = id(adj) if adjId not in objIds: objIds.add(adjId) newObjs.append(adj) adjacents = newObjs if len(adjacents) == 0: print 'DEAD END' for i in range(resumeIndex, len(adjacents)): adj = adjacents[i] stateStack.push((obj, adjacents, i+1)) stateStack.push((adj, None, 0)) continue """