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