[Python-Dev] test_inspect.py still fails under -O

Fredrik Lundh fredrik@effbot.org
Wed, 28 Feb 2001 23:42:56 +0100


tim wrote:

> git.tr[0][1:] is
> 
>     ('@test', 8, 'spam',
>      ['def spam(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h):\n'],
>      0)
> 
> at this point.  The test expects it to be
> 
>     ('@test', 9, 'spam',
>      ['    eggs(b + d, c + f)\n'],
>      0)
> 
> Test passes without -O.

the code doesn't take LINENO optimization into account.
tentative patch follows:

Index: Lib/inspect.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/inspect.py,v
retrieving revision 1.2
diff -u -r1.2 inspect.py
--- Lib/inspect.py      2001/02/28 08:26:44     1.2
+++ Lib/inspect.py      2001/02/28 22:35:49
@@ -561,19 +561,19 @@

     filename = getsourcefile(frame)
     if context > 0:
-        start = frame.f_lineno - 1 - context/2
+        start = _lineno(frame) - 1 - context/2
         try:
             lines, lnum = findsource(frame)
             start = max(start, 1)
             start = min(start, len(lines) - context)
             lines = lines[start:start+context]
-            index = frame.f_lineno - 1 - start
+            index = _lineno(frame) - 1 - start
         except:
             lines = index = None
     else:
         lines = index = None

-    return (filename, frame.f_lineno, frame.f_code.co_name, lines, index)
+    return (filename, _lineno(frame), frame.f_code.co_name, lines, index)

 def getouterframes(frame, context=1):
     """Get a list of records for a frame and all higher (calling) frames.
@@ -614,3 +614,26 @@
 def trace(context=1):
     """Return a list of records for the stack below the current exception."""
     return getinnerframes(sys.exc_traceback, context)
+
+def _lineno(frame):
+    # Coded by Marc-Andre Lemburg from the example of PyCode_Addr2Line()
+    # in compile.c.
+    # Revised version by Jim Hugunin to work with JPython too.
+    # Adapted for inspect.py by Fredrik Lundh
+
+    lineno = frame.f_lineno
+
+    c = frame.f_code
+    if not hasattr(c, 'co_lnotab'):
+        return tb.tb_lineno
+
+    tab = c.co_lnotab
+    line = c.co_firstlineno
+    stopat = frame.f_lasti
+    addr = 0
+    for i in range(0, len(tab), 2):
+        addr = addr + ord(tab[i])
+        if addr > stopat:
+            break
+        line = line + ord(tab[i+1])
+    return line

Cheers /F