1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
|
"""
General-purpose reference tracker.
Usage: call track(obj).
"""
import sys, os, types
import gc
from rpython.translator.tool.graphpage import GraphPage, DotGen
from rpython.tool.uid import uid
MARKER = object()
class BaseRefTrackerPage(GraphPage):
def compute(self, objectlist):
assert objectlist[0] is MARKER
self.objectlist = objectlist
dotgen = DotGen('reftracker')
id2typename = {}
nodes = {}
edges = {}
def addedge(o1, o2):
key = (uid(o1), uid(o2))
edges[key] = self.edgelabel(o1, o2)
for i in range(1, len(objectlist)):
typename, s, linktext = self.formatobject(objectlist[i])
word = '0x%x' % uid(objectlist[i])
if linktext:
self.links[word] = linktext
s = '<%s> %s\\n%s' % (typename, word, s)
nodename = 'node%d' % len(nodes)
dotgen.emit_node(nodename, label=s, shape="box")
nodes[uid(objectlist[i])] = nodename
for o2 in self.get_referents(objectlist[i]):
if o2 is None:
continue
addedge(objectlist[i], o2)
id2typename[uid(o2)] = self.shortrepr(o2)
del o2
for o2 in self.get_referrers(objectlist[i]):
if o2 is None:
continue
if type(o2) is list and o2 and o2[0] is MARKER:
continue
addedge(o2, objectlist[i])
id2typename[uid(o2)] = self.shortrepr(o2)
del o2
for ids, label in edges.items():
for id1 in ids:
if id1 not in nodes:
nodename = 'node%d' % len(nodes)
word = '0x%x' % id1
s = '<%s> %s' % (id2typename[id1], word)
dotgen.emit_node(nodename, label=s)
nodes[id1] = nodename
self.links[word] = s
id1, id2 = ids
dotgen.emit_edge(nodes[id1], nodes[id2], label=label)
self.source = dotgen.generate(target=None)
def followlink(self, word):
id1 = int(word, 16)
found = None
objectlist = self.objectlist
for i in range(1, len(objectlist)):
for o2 in self.get_referents(objectlist[i]):
if uid(o2) == id1:
found = o2
for o2 in self.get_referrers(objectlist[i]):
if uid(o2) == id1:
found = o2
if found is not None:
objectlist = objectlist + [found]
else:
print '*** NOTE: object not found'
return self.newpage(objectlist)
def formatobject(self, o):
header = self.shortrepr(o, compact=False)
secondline = repr(o.__class__)
return header, secondline, repr(o)
def shortrepr(self, o, compact=True):
t = type(o)
if t is types.FrameType:
if compact:
return 'frame %r' % (o.f_code.co_name,)
else:
return 'frame %r' % (o.f_code,)
s = repr(o)
if len(s) > 50:
s = s[:20] + ' ... ' + s[-20:]
if s.startswith('<') and s.endswith('>'):
s = s[1:-1]
return s
def edgelabel(self, o1, o2):
return ''
def newpage(self, objectlist):
return self.__class__(objectlist)
class RefTrackerPage(BaseRefTrackerPage):
get_referrers = staticmethod(gc.get_referrers)
get_referents = staticmethod(gc.get_referents)
def edgelabel(self, o1, o2):
slst = []
if type(o1) in (list, tuple):
for i in range(len(o1)):
if o1[i] is o2:
slst.append('[%d]' % i)
elif type(o1) is dict:
for k, v in o1.items():
if v is o2:
slst.append('[%r]' % (k,))
else:
for basetype in type(o1).__mro__:
for key, value in basetype.__dict__.items():
if (type(value) is MemberDescriptorType or
type(value) is AttributeType):
try:
o1value = value.__get__(o1)
except:
pass
else:
if o1value is o2:
slst.append(str(key))
return ', '.join(slst)
def track(*objs):
"""Invoke a dot+pygame object reference tracker."""
page = RefTrackerPage([MARKER] + list(objs))
del objs
gc.collect()
gc.collect()
page.display()
def track_server(*objs, **kwds):
page = RefTrackerPage([MARKER] + list(objs))
del objs
gc.collect()
gc.collect()
try:
port = kwds.pop('port')
except KeyError:
port = 8888
from rpython.translator.tool.graphserver import run_server
run_server(page, port)
class _A(object):
__slots__ = 'a'
class _B(object):
pass
MemberDescriptorType = type(_A.a)
AttributeType = type(_B.__dict__['__dict__'])
if __name__ == '__main__':
try:
sys.path.remove(os.getcwd())
except ValueError:
pass
class A(object):
__slots__ = ['a']
d = {"lskjadldjslkj": "adjoiadoixmdoiemdwoi"}
a1 = A()
a1.a = d
track(d)
|