Fix Python stepping watchpoints + cy step repeatability
authorMark Florisson <markflorisson88@gmail.com>
Wed, 15 Dec 2010 18:21:34 +0000 (19:21 +0100)
committerMark Florisson <markflorisson88@gmail.com>
Wed, 15 Dec 2010 18:21:34 +0000 (19:21 +0100)
Cython/Debugger/libcython.py
Cython/Debugger/libpython.py
setup.py

index 4648d522a45448b143dc3ebe98fd0dd80e5168e0..85e09419bf22cd67e9d0893a3f43eb89b6cfdbb2 100644 (file)
@@ -882,12 +882,12 @@ class CythonExecutionControlCommand(CythonCommand,
 class CyStep(CythonExecutionControlCommand, libpython.PythonStepperMixin):
     "Step through Cython, Python or C code."
     
-    name = 'cy step'
+    name = 'cy -step'
     stepinto = True
     
     def invoke(self, args, from_tty):
         if self.is_python_function():
-            self.python_step(args, self.stepinto)
+            self.python_step(self.stepinto)
         elif not self.is_cython_function():
             if self.stepinto:
                 command = 'step'
@@ -900,9 +900,9 @@ class CyStep(CythonExecutionControlCommand, libpython.PythonStepperMixin):
 
 
 class CyNext(CyStep):
-    "Step-over Python code."
+    "Step-over Cython, Python or C code."
 
-    name = 'cy next'
+    name = 'cy -next'
     stepinto = False
 
 
@@ -1295,4 +1295,25 @@ class CyLine(gdb.Function, CythonBase):
 
 cython_info = CythonInfo()
 cy = CyCy.register()
-cython_info.cy = cy
\ No newline at end of file
+cython_info.cy = cy
+
+def register_defines():
+    libpython.source_gdb_script(textwrap.dedent("""\
+        define cy step
+        cy -step
+        end
+        
+        define cy next
+        cy -next
+        end
+        
+        document cy step
+        %s
+        end
+        
+        document cy next
+        %s
+        end
+    """) % (CyStep.__doc__, CyNext.__doc__))
+
+register_defines()
\ No newline at end of file
index e9b6d8c353175d66c283e34c2f4578591606e85e..f05579e432d9f727fd7a8d31040527e6cc3988a7 100644 (file)
@@ -1843,6 +1843,39 @@ def get_selected_inferior():
             if thread == selected_thread:
                 return inferior
 
+def source_gdb_script(script_contents, to_string=False):
+    """
+    Source a gdb script with script_contents passed as a string. This is useful
+    to provide defines for py-step and py-next to make them repeatable (this is
+    not possible with gdb.execute()). See 
+    http://sourceware.org/bugzilla/show_bug.cgi?id=12216
+    """
+    fd, filename = tempfile.mkstemp()
+    f = os.fdopen(fd, 'w')
+    f.write(script_contents)
+    f.close()
+    gdb.execute("source %s" % filename, to_string=to_string)
+
+def register_defines():
+    source_gdb_script(textwrap.dedent("""\
+        define py-step
+        -py-step
+        end
+        
+        define py-next
+        -py-next
+        end
+        
+        document py-step
+        %s
+        end
+        
+        document py-next
+        %s
+        end
+    """) % (PyStep.__doc__, PyNext.__doc__))
+    
+
 def stackdepth(frame):
     "Tells the stackdepth of a gdb frame."
     depth = 0
@@ -2194,36 +2227,18 @@ class PythonInfo(LanguageInfo):
 class PythonStepperMixin(object):
     """
     Make this a mixin so CyStep can also inherit from this and use a 
-    CythonCodeStepper at the same time
+    CythonCodeStepper at the same time.
     """
     
-    def _watchpoint_step(self, stepinto):
-        # Set a watchpoint for a frame once as deleting it will make py-step
-        # unrepeatable. 
-        # See http://sourceware.org/bugzilla/show_bug.cgi?id=12216
-        # When the watchpoint goes out of scope it will automatically 
-        # disappear.
-        
-        newframe = gdb.selected_frame()
-        framewrapper = Frame(newframe)
-        if (newframe != getattr(self, 'lastframe', None) and
-            framewrapper.is_evalframeex()):
-            self.lastframe = newframe
-            output = gdb.execute('watch f->f_lasti', to_string=True)
-            
-        self.step(stepinto=stepinto, stepover_command='finish')
+    def python_step(self, stepinto):
+        frame = gdb.selected_frame()
+        framewrapper = Frame(frame)
         
-        # match = re.search(r'[Ww]atchpoint (\d+):', output)
-        # if match:
-            # watchpoint = match.group(1)
-            # gdb.execute('delete %s' % watchpoint)
-    
-    def python_step(self, args, stepinto):
-        if args in ('-w', '--watchpoint'):
-            self._watchpoint_step(stepinto)
-        else:
-            self.step(stepinto)
-    
+        output = gdb.execute('watch f->f_lasti', to_string=True)
+        watchpoint = int(re.search(r'[Ww]atchpoint (\d+):', output).group(1))
+        self.step(stepinto=stepinto, stepover_command='finish')
+        gdb.execute('delete %s' % watchpoint)
+
 
 class PyStep(ExecutionControlCommandBase, PythonStepperMixin):
     "Step through Python code."
@@ -2231,7 +2246,7 @@ class PyStep(ExecutionControlCommandBase, PythonStepperMixin):
     stepinto = True
     
     def invoke(self, args, from_tty):
-        self.python_step(args, stepinto=self.stepinto)
+        self.python_step(stepinto=self.stepinto)
     
 class PyNext(PyStep):
     "Step-over Python code."
@@ -2252,9 +2267,10 @@ class PyCont(ExecutionControlCommandBase):
     
     invoke = ExecutionControlCommandBase.cont
 
-
-py_step = PyStep('py-step', PythonInfo())
-py_next = PyNext('py-next', PythonInfo())
+# Wrap py-step and py-next in gdb defines to make them repeatable.
+py_step = PyStep('-py-step', PythonInfo())
+py_next = PyNext('-py-next', PythonInfo())
+register_defines()
 py_finish = PyFinish('py-finish', PythonInfo())
 py_run = PyRun('py-run', PythonInfo())
 py_cont = PyCont('py-cont', PythonInfo())
@@ -2510,5 +2526,8 @@ class PyExec(gdb.Command):
         
         executor.evalcode(expr, input_type, global_dict, local_dict)
 
-py_exec = FixGdbCommand('py-exec', '-py-exec')
-_py_exec = PyExec("-py-exec", gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
+if hasattr(gdb, 'GdbError'):
+    py_exec = FixGdbCommand('py-exec', '-py-exec')
+    _py_exec = PyExec("-py-exec", gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
+else:
+    warnings.warn("Use gdb 7.2 or higher to use the py-exec command.")
\ No newline at end of file
index a816e6354077984e727a5bd547237bfefb278dc2..ee9e4387efcac11e05b7f192baf0d31399382c74 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -100,7 +100,8 @@ def compile_cython_modules(profile=False, compile_more=False, cython_with_refnan
                         "Cython.Compiler.Parsing",
                         "Cython.Compiler.Visitor",
                         "Cython.Compiler.Code",
-                        "Cython.Runtime.refnanny"]
+                        "Cython.Runtime.refnanny",
+                        "Cython.Debugger.do_repeat",]
     if compile_more:
         compiled_modules.extend([
             "Cython.Compiler.ParseTreeTransforms",