bug in inspect (was cgitb vs traceback)
Robin Becker
robin at reportlab.com
Mon May 10 14:23:21 EDT 2004
Robin Becker wrote:
> def raise_an_error():
> a = 3
> b = 4
> c = 0
> try:
> a = a/c
> except:
> import sys, cgitb, traceback, inspect
> tbt,tbv,tb = sys.exc_info()
> print 'traceback\n',''.join(traceback.format_exception(tbt,tbv,tb))
> print '\n\ncgitb\n',cgitb.text((tbt,tbv,tb),1)
>
> raise_an_error()
>
..... the above script demonstrates a bug in the inspect module's getinnerframes
function which is using the frame f_lineno instead of the traceback's tb_lineno.
eg
from inspect.py:getinnerframes we see that the traceback is followed and the
frame only is passed to getframeinfo which then has to use frame.f_lineno.
tb.tb_frame.f_lineno==tb.tb_lineno is not always true.
What this means is that a wrong line of code can be cited for the error in the
returned lines. A fix is to allow getframeinfo to have an optional lineno passed
in which getinnerframes can set using tb.tb_lineno. If not set or None
getframeinfo can use frame.f_lineno as before.
def getframeinfo(frame, context=1):
"""Get information about a frame or traceback object.
......."""
if istraceback(frame):
frame = frame.tb_frame
if not isframe(frame):
raise TypeError('arg is not a frame or traceback object')
filename = getsourcefile(frame) or getfile(frame)
lineno = frame.f_lineno
.......
def getinnerframes(tb, context=1):
"""Get a list of records for a traceback's frame and all lower frames.
Each record contains a frame object, filename, line number, function
name, a list of lines of context, and index within the context."""
framelist = []
while tb:
framelist.append((tb.tb_frame,) + getframeinfo(tb, context))
tb = tb.tb_next
return framelist
--
Robin Becker
More information about the Python-list
mailing list