[Python-checkins] python/dist/src/Lib bdb.py, 1.44, 1.45 pdb.py, 1.68, 1.69

jlgijsbers at users.sourceforge.net jlgijsbers at users.sourceforge.net
Mon Aug 30 15:29:47 CEST 2004


Update of /cvsroot/python/python/dist/src/Lib
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29399

Modified Files:
	bdb.py pdb.py 
Log Message:
Patch #1003640: replace checkline() function parsing with new breakpoint logic:

1) When a breakpoint is set via a function name: 
- the breakpoint gets the lineno of the def statement
- a new funcname attribute is attached to the breakpoint

2) bdb.effective() calls new function checkfuncname() to handle:
- def statement is executed: don't break. 
- a first executable line of a function with a breakpoint on the lineno of the
def statement is reached: break.

This fixes bugs 976878, 926369 and 875404. Thanks Ilya Sandler.


Index: bdb.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/bdb.py,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- bdb.py	24 Mar 2004 21:57:08 -0000	1.44
+++ bdb.py	30 Aug 2004 13:29:44 -0000	1.45
@@ -113,7 +113,12 @@
             return False
         lineno = frame.f_lineno
         if not lineno in self.breaks[filename]:
-            return False
+            # The line itself has no breakpoint, but maybe the line is the
+            # first line of a function with breakpoint set by function name.
+            lineno = frame.f_code.co_firstlineno
+            if not lineno in self.breaks[filename]:
+                return False
+
         # flag says ok to delete temp. bp
         (bp, flag) = effective(filename, lineno, frame)
         if bp:
@@ -210,7 +215,8 @@
     # Call self.get_*break*() to see the breakpoints or better
     # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().
 
-    def set_break(self, filename, lineno, temporary=0, cond = None):
+    def set_break(self, filename, lineno, temporary=0, cond = None,
+                  funcname=None):
         filename = self.canonic(filename)
         import linecache # Import as late as possible
         line = linecache.getline(filename, lineno)
@@ -222,7 +228,7 @@
         list = self.breaks[filename]
         if not lineno in list:
             list.append(lineno)
-        bp = Breakpoint(filename, lineno, temporary, cond)
+        bp = Breakpoint(filename, lineno, temporary, cond, funcname)
 
     def clear_break(self, filename, lineno):
         filename = self.canonic(filename)
@@ -428,7 +434,10 @@
                 # index 0 is unused, except for marking an
                 # effective break .... see effective()
 
-    def __init__(self, file, line, temporary=0, cond = None):
+    def __init__(self, file, line, temporary=0, cond=None, funcname=None):
+        self.funcname = funcname
+        # Needed if funcname is not None.
+        self.func_first_executable_line = None
         self.file = file    # This better be in canonical form!
         self.line = line
         self.temporary = temporary
@@ -483,6 +492,32 @@
 
 # -----------end of Breakpoint class----------
 
+def checkfuncname(b, frame):
+    """Check whether we should break here because of `b.funcname`."""
+    if not b.funcname:
+        # Breakpoint was set via line number.
+        if b.line != frame.f_lineno:
+            # Breakpoint was set at a line with a def statement and the function
+            # defined is called: don't break.
+            return False
+        return True
+
+    # Breakpoint set via function name.
+
+    if frame.f_code.co_name != b.funcname:
+        # It's not a function call, but rather execution of def statement.
+        return False
+
+    # We are in the right frame.
+    if not b.func_first_executable_line:
+        # The function is entered for the 1st time.
+        b.func_first_executable_line = frame.f_lineno
+
+    if  b.func_first_executable_line != frame.f_lineno:
+        # But we are not at the first line number: don't break.
+        return False
+    return True
+
 # Determines if there is an effective (active) breakpoint at this
 # line of code.  Returns breakpoint number or 0 if none
 def effective(file, line, frame):
@@ -498,6 +533,8 @@
         b = possibles[i]
         if b.enabled == 0:
             continue
+        if not checkfuncname(b, frame):
+            continue
         # Count every hit when bp is enabled
         b.hits = b.hits + 1
         if not b.cond:

Index: pdb.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/pdb.py,v
retrieving revision 1.68
retrieving revision 1.69
diff -u -d -r1.68 -r1.69
--- pdb.py	14 Aug 2004 15:19:27 -0000	1.68
+++ pdb.py	30 Aug 2004 13:29:44 -0000	1.69
@@ -215,6 +215,7 @@
             arg = arg[:comma].rstrip()
         # parse stuff before comma: [filename:]lineno | function
         colon = arg.rfind(':')
+        funcname = None
         if colon >= 0:
             filename = arg[:colon].rstrip()
             f = self.lookupmodule(filename)
@@ -245,6 +246,9 @@
                     if hasattr(func, 'im_func'):
                         func = func.im_func
                     code = func.func_code
+                    #use co_name to identify the bkpt (function names
+                    #could be aliased, but co_name is invariant)
+                    funcname = code.co_name
                     lineno = code.co_firstlineno
                     filename = code.co_filename
                 except:
@@ -257,6 +261,7 @@
                         print ('or was not found '
                                'along sys.path.')
                         return
+                    funcname = ok # ok contains a function name
                     lineno = int(ln)
         if not filename:
             filename = self.defaultFile()
@@ -264,7 +269,7 @@
         line = self.checkline(filename, lineno)
         if line:
             # now set the break point
-            err = self.set_break(filename, line, temporary, cond)
+            err = self.set_break(filename, line, temporary, cond, funcname)
             if err: print '***', err
             else:
                 bp = self.get_breaks(filename, line)[-1]
@@ -319,13 +324,11 @@
         return answer or failed
 
     def checkline(self, filename, lineno):
-        """Return line number of first line at or after input
-        argument such that if the input points to a 'def', the
-        returned line number is the first
-        non-blank/non-comment line to follow.  If the input
-        points to a blank or comment line, return 0.  At end
-        of file, also return 0."""
+        """Check whether specified line seems to be executable.
 
+        Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank
+        line or EOF). Warning: testing is not comprehensive.
+        """
         line = linecache.getline(filename, lineno)
         if not line:
             print 'End of file'
@@ -336,40 +339,6 @@
              (line[:3] == '"""') or line[:3] == "'''"):
             print '*** Blank or comment'
             return 0
-        # When a file is read in and a breakpoint is at
-        # the 'def' statement, the system stops there at
-        # code parse time.  We don't want that, so all breakpoints
-        # set at 'def' statements are moved one line onward
-        if line[:3] == 'def':
-            instr = ''
-            brackets = 0
-            while 1:
-                skipone = 0
-                for c in line:
-                    if instr:
-                        if skipone:
-                            skipone = 0
-                        elif c == '\\':
-                            skipone = 1
-                        elif c == instr:
-                            instr = ''
-                    elif c == '#':
-                        break
-                    elif c in ('"',"'"):
-                        instr = c
-                    elif c in ('(','{','['):
-                        brackets = brackets + 1
-                    elif c in (')','}',']'):
-                        brackets = brackets - 1
-                lineno = lineno+1
-                line = linecache.getline(filename, lineno)
-                if not line:
-                    print 'end of file'
-                    return 0
-                line = line.strip()
-                if not line: continue   # Blank line
-                if brackets <= 0 and line[0] not in ('#','"',"'"):
-                    break
         return lineno
 
     def do_enable(self, arg):



More information about the Python-checkins mailing list