# who_calls.py
# by Sam Rushing for Medusa
import string
import sys
from log import *
whoCallsError = "whoCallsError"
#--------------------------------------------------------------
# Example use:
#
# import who_calls
# log(who_calls.pretty_who_calls())
#
#--------------------------------------------------------------
def test():
for i in range(1,1000):
pretty_who_calls()
print_top_100()
def who_calls_helper():
tinfo = []
exc_info = sys.exc_info()
f = exc_info[2].tb_frame.f_back
while f:
tinfo.append ( (
f.f_code.co_filename,
f.f_code.co_name,
f.f_lineno )
)
f = f.f_back
del exc_info
return tinfo
def who_calls():
try:
raise whoCallsError
except whoCallsError:
tinfo = who_calls_helper()
return tinfo
def pretty_who_calls(strip=0):
info = who_calls()
buf = []
for file,function,line in info[1 + strip:]:
buf.append(" %s(%s): %s()" % (file,line,function))
return string.join(buf,"\n")
# ---------------------------------------------------------------------------
# used for debugging.
# ---------------------------------------------------------------------------
def compact_traceback ():
t,v,tb = sys.exc_info()
tbinfo = []
if tb is None:
# this should never happen, but then again, lots of things
# should never happen but do.
return (('','',''), str(t), str(v), 'traceback is None!!!')
while 1:
tbinfo.append (
tb.tb_frame.f_code.co_filename,
tb.tb_frame.f_code.co_name,
str(tb.tb_lineno)
)
tb = tb.tb_next
if not tb:
break
# just to be safe
del tb
file, function, line = tbinfo[-1]
info = '[' + string.join (
map (
lambda x: string.join (x, '|'),
tbinfo
),
'] ['
) + ']'
return (file, function, line), str(t), str(v), info
## ----------------------------------------------------
## Refcount printing
import sys
import types
def real_get_refcounts(base = None, set_base = 0):
d = {}
sys.modules
# collect all classes
for modname,m in sys.modules.items():
for sym in dir(m):
o = getattr (m, sym)
if type(o) is types.ClassType:
name = "%s:%s" % (modname,o.__name__)
cnt = sys.getrefcount (o)
if base:
if set_base:
base[name] = cnt
elif cnt > base.get(name, 0):
d[name] = cnt - base.get(name, 0)
else:
d[name] = cnt
return d
def get_refcounts(base=None):
d = real_get_refcounts(base = base)
# sort by refcount
pairs = map (lambda x: (x[1],x[0]), d.items())
pairs.sort()
pairs.reverse()
return pairs
REFCOUNTS = {}
def set_refcount_base():
global REFCOUNTS
real_get_refcounts(REFCOUNTS, set_base = 1)
def print_top_100():
print_top_N(100)
def print_top_N(N):
global REFCOUNTS
for n, c in get_refcounts(REFCOUNTS)[:N]:
log('%10d %s' % (n, c))
|