[Python-checkins] python/dist/src/Lib trace.py,1.18,1.19
montanaro at users.sourceforge.net
montanaro at users.sourceforge.net
Wed Apr 7 11:46:08 EDT 2004
Update of /cvsroot/python/python/dist/src/Lib
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26703
Modified Files:
trace.py
Log Message:
Added --trackcalls command line arg to display crude caller/callee
relationships at program exit. Output is a bit prettier than that for
--listfuncs but won't parse as easily using downstream postprocessing tools.
Index: trace.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/trace.py,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -d -r1.18 -r1.19
*** trace.py 19 Feb 2004 19:16:50 -0000 1.18
--- trace.py 7 Apr 2004 15:46:05 -0000 1.19
***************
*** 33,36 ****
--- 33,37 ----
trace.py -c -f counts --ignore-dir '$prefix' spam.py eggs
trace.py -t --ignore-dir '$prefix' spam.py eggs
+ trace.py --track-callers spam.py eggs
Sample use, programmatically
***************
*** 77,80 ****
--- 78,83 ----
once and write the results to sys.stdout after the
program exits.
+ -T, --trackcalls Keep track of caller/called pairs and write the
+ results to sys.stdout after the program exits.
-r, --report Generate a report from a counts file; do not execute
any code. `--file' must specify the results file to
***************
*** 192,196 ****
class CoverageResults:
def __init__(self, counts=None, calledfuncs=None, infile=None,
! outfile=None):
self.counts = counts
if self.counts is None:
--- 195,199 ----
class CoverageResults:
def __init__(self, counts=None, calledfuncs=None, infile=None,
! callers=None, outfile=None):
self.counts = counts
if self.counts is None:
***************
*** 201,204 ****
--- 204,211 ----
self.calledfuncs = {}
self.calledfuncs = self.calledfuncs.copy()
+ self.callers = callers
+ if self.callers is None:
+ self.callers = {}
+ self.callers = self.callers.copy()
self.infile = infile
self.outfile = outfile
***************
*** 206,211 ****
# Try to merge existing counts file.
try:
! counts, calledfuncs = pickle.load(open(self.infile, 'rb'))
! self.update(self.__class__(counts, calledfuncs))
except (IOError, EOFError, ValueError), err:
print >> sys.stderr, ("Skipping counts file %r: %s"
--- 213,219 ----
# Try to merge existing counts file.
try:
! counts, calledfuncs, callers = \
! pickle.load(open(self.infile, 'rb'))
! self.update(self.__class__(counts, calledfuncs, callers))
except (IOError, EOFError, ValueError), err:
print >> sys.stderr, ("Skipping counts file %r: %s"
***************
*** 216,221 ****
--- 224,231 ----
counts = self.counts
calledfuncs = self.calledfuncs
+ callers = self.callers
other_counts = other.counts
other_calledfuncs = other.calledfuncs
+ other_callers = other.callers
for key in other_counts.keys():
***************
*** 225,235 ****
calledfuncs[key] = 1
def write_results(self, show_missing=True, summary=False, coverdir=None):
"""
@param coverdir
"""
! for filename, modulename, funcname in self.calledfuncs.keys():
! print ("filename: %s, modulename: %s, funcname: %s"
! % (filename, modulename, funcname))
# turn the counts data ("(filename, lineno) = count") into something
--- 235,267 ----
calledfuncs[key] = 1
+ for key in other_callers.keys():
+ callers[key] = 1
+
def write_results(self, show_missing=True, summary=False, coverdir=None):
"""
@param coverdir
"""
! if self.calledfuncs:
! print "functions called:"
! calls = self.calledfuncs.keys()
! calls.sort()
! for filename, modulename, funcname in calls:
! print ("filename: %s, modulename: %s, funcname: %s"
! % (filename, modulename, funcname))
!
! if self.callers:
! print "calling relationships:"
! calls = self.callers.keys()
! calls.sort()
! lastfile = lastcfile = ""
! for ((pfile, pmod, pfunc), (cfile, cmod, cfunc)) in calls:
! if pfile != lastfile:
! print "***", pfile, "***"
! lastfile = pfile
! lastcfile = ""
! if cfile != pfile and lastcfile != cfile:
! print " -->", cfile
! lastcfile = cfile
! print " %s.%s -> %s.%s" % (pmod, pfunc, cmod, cfunc)
# turn the counts data ("(filename, lineno) = count") into something
***************
*** 287,291 ****
# try and store counts and module info into self.outfile
try:
! pickle.dump((self.counts, self.calledfuncs),
open(self.outfile, 'wb'), 1)
except IOError, err:
--- 319,323 ----
# try and store counts and module info into self.outfile
try:
! pickle.dump((self.counts, self.calledfuncs, self.callers),
open(self.outfile, 'wb'), 1)
except IOError, err:
***************
*** 393,398 ****
class Trace:
! def __init__(self, count=1, trace=1, countfuncs=0, ignoremods=(),
! ignoredirs=(), infile=None, outfile=None):
"""
@param count true iff it should count number of times each
--- 425,430 ----
class Trace:
! def __init__(self, count=1, trace=1, countfuncs=0, countcallers=0,
! ignoremods=(), ignoredirs=(), infile=None, outfile=None):
"""
@param count true iff it should count number of times each
***************
*** 420,424 ****
self.trace = trace
self._calledfuncs = {}
! if countfuncs:
self.globaltrace = self.globaltrace_countfuncs
elif trace and count:
--- 452,459 ----
self.trace = trace
self._calledfuncs = {}
! self._callers = {}
! if countcallers:
! self.globaltrace = self.globaltrace_trackcallers
! elif countfuncs:
self.globaltrace = self.globaltrace_countfuncs
elif trace and count:
***************
*** 472,475 ****
--- 507,537 ----
return result
+ def globaltrace_trackcallers(self, frame, why, arg):
+ """Handler for call events.
+
+ Adds information about who called who to the self._callers dict.
+ """
+ if why == 'call':
+ # XXX Should do a better job of identifying methods
+ code = frame.f_code
+ filename = code.co_filename
+ funcname = code.co_name
+ if filename:
+ modulename = modname(filename)
+ else:
+ modulename = None
+ this_func = (filename, modulename, funcname)
+
+ frame = frame.f_back
+ code = frame.f_code
+ filename = code.co_filename
+ funcname = code.co_name
+ if filename:
+ modulename = modname(filename)
+ else:
+ modulename = None
+ parent_func = (filename, modulename, funcname)
+ self._callers[(parent_func, this_func)] = 1
+
def globaltrace_countfuncs(self, frame, why, arg):
"""Handler for call events.
***************
*** 545,549 ****
return CoverageResults(self.counts, infile=self.infile,
outfile=self.outfile,
! calledfuncs=self._calledfuncs)
def _err_exit(msg):
--- 607,612 ----
return CoverageResults(self.counts, infile=self.infile,
outfile=self.outfile,
! calledfuncs=self._calledfuncs,
! callers=self._callers)
def _err_exit(msg):
***************
*** 557,566 ****
argv = sys.argv
try:
! opts, prog_argv = getopt.getopt(argv[1:], "tcrRf:d:msC:l",
["help", "version", "trace", "count",
"report", "no-report", "summary",
"file=", "missing",
"ignore-module=", "ignore-dir=",
! "coverdir=", "listfuncs",])
except getopt.error, msg:
--- 620,630 ----
argv = sys.argv
try:
! opts, prog_argv = getopt.getopt(argv[1:], "tcrRf:d:msC:lT",
["help", "version", "trace", "count",
"report", "no-report", "summary",
"file=", "missing",
"ignore-module=", "ignore-dir=",
! "coverdir=", "listfuncs",
! "trackcalls"])
except getopt.error, msg:
***************
*** 581,584 ****
--- 645,649 ----
summary = 0
listfuncs = False
+ countcallers = False
for opt, val in opts:
***************
*** 591,594 ****
--- 656,663 ----
sys.exit(0)
+ if opt == "-T" or opt == "--trackcalls":
+ countcallers = True
+ continue
+
if opt == "-l" or opt == "--listfuncs":
listfuncs = True
***************
*** 651,657 ****
_err_exit("cannot specify both --listfuncs and (--trace or --count)")
! if not count and not trace and not report and not listfuncs:
! _err_exit("must specify one of --trace, --count, --report or "
! "--listfuncs")
if report and no_report:
--- 720,726 ----
_err_exit("cannot specify both --listfuncs and (--trace or --count)")
! if not (count or trace or report or listfuncs or countcallers):
! _err_exit("must specify one of --trace, --count, --report, "
! "--listfuncs, or --trackcalls")
if report and no_report:
***************
*** 674,679 ****
t = Trace(count, trace, countfuncs=listfuncs,
! ignoremods=ignore_modules, ignoredirs=ignore_dirs,
! infile=counts_file, outfile=counts_file)
try:
t.run('execfile(%r)' % (progname,))
--- 743,749 ----
t = Trace(count, trace, countfuncs=listfuncs,
! countcallers=countcallers, ignoremods=ignore_modules,
! ignoredirs=ignore_dirs, infile=counts_file,
! outfile=counts_file)
try:
t.run('execfile(%r)' % (progname,))
More information about the Python-checkins
mailing list