Disable watchpoint stepping by default (use cy step -w or cy step --watchpoint to...
[cython.git] / Cython / Debugger / libcython.py
index 8c49bdd84b38f067336384f5cb86bc8f4340bc2a..4648d522a45448b143dc3ebe98fd0dd80e5168e0 100644 (file)
@@ -256,7 +256,7 @@ class CythonBase(object):
                 filename = None
                 lineno = 0
             else:
-                filename = symbol_and_line_obj.symtab.filename
+                filename = symbol_and_line_obj.symtab.fullname()
                 lineno = symbol_and_line_obj.line
                 if pygments:
                     lexer = pygments.lexers.CLexer(stripall=False)
@@ -835,10 +835,9 @@ class CyBreak(CythonCommand):
         return compl
 
 
-class CythonCodeStepper(CythonCommand, libpython.GenericCodeStepper):
+class CythonInfo(CythonBase, libpython.PythonInfo):
     """
-    Base class for CyStep and CyNext. It implements the interface dictated by
-    libpython.GenericCodeStepper.
+    Implementation of the interface dictated by libpython.LanguageInfo.
     """
     
     def lineno(self, frame):
@@ -848,20 +847,19 @@ class CythonCodeStepper(CythonCommand, libpython.GenericCodeStepper):
         # related code. The C level should be dispatched to the 'step' command.
         if self.is_cython_function(frame):
             return self.get_cython_lineno(frame)
-        else:
-            return libpython.py_step.lineno(frame)
+        return super(CythonInfo, self).lineno(frame)
     
     def get_source_line(self, frame):
         try:
-            line = super(CythonCodeStepper, self).get_source_line(frame)
+            line = super(CythonInfo, self).get_source_line(frame)
         except gdb.GdbError:
             return None
         else:
             return line.strip() or None
 
-    @classmethod
-    def register(cls):
-        return cls(cls.name, stepinto=getattr(cls, 'stepinto', False))
+    def exc_info(self, frame):
+        if self.is_python_function:
+            return super(CythonInfo, self).exc_info(frame)
 
     def runtime_break_functions(self):
         if self.is_cython_function():
@@ -872,8 +870,25 @@ class CythonCodeStepper(CythonCommand, libpython.GenericCodeStepper):
         result.extend(self.cy.functions_by_cname)
         return result
 
+
+class CythonExecutionControlCommand(CythonCommand, 
+                                    libpython.ExecutionControlCommandBase):
+    
+    @classmethod
+    def register(cls):
+        return cls(cls.name, cython_info)
+
+
+class CyStep(CythonExecutionControlCommand, libpython.PythonStepperMixin):
+    "Step through Cython, Python or C code."
+    
+    name = 'cy step'
+    stepinto = True
+    
     def invoke(self, args, from_tty):
-        if not self.is_cython_function() and not self.is_python_function():
+        if self.is_python_function():
+            self.python_step(args, self.stepinto)
+        elif not self.is_cython_function():
             if self.stepinto:
                 command = 'step'
             else:
@@ -881,24 +896,17 @@ class CythonCodeStepper(CythonCommand, libpython.GenericCodeStepper):
                 
             self.finish_executing(gdb.execute(command, to_string=True))
         else:
-            self.step()
-
-
-class CyStep(CythonCodeStepper):
-    "Step through Cython, Python or C code."
-    
-    name = 'cy step'
-    stepinto = True
+            self.step(stepinto=self.stepinto)
 
 
-class CyNext(CythonCodeStepper):
+class CyNext(CyStep):
     "Step-over Python code."
 
     name = 'cy next'
     stepinto = False
 
 
-class CyRun(CythonCodeStepper):
+class CyRun(CythonExecutionControlCommand):
     """
     Run a Cython program. This is like the 'run' command, except that it 
     displays Cython or Python source lines as well
@@ -906,26 +914,26 @@ class CyRun(CythonCodeStepper):
     
     name = 'cy run'
     
-    invoke = CythonCodeStepper.run
+    invoke = CythonExecutionControlCommand.run
 
 
-class CyCont(CyRun):
+class CyCont(CythonExecutionControlCommand):
     """
     Continue a Cython program. This is like the 'run' command, except that it 
     displays Cython or Python source lines as well.
     """
     
     name = 'cy cont'
-    invoke = CythonCodeStepper.cont
+    invoke = CythonExecutionControlCommand.cont
 
 
-class CyFinish(CyRun):
+class CyFinish(CythonExecutionControlCommand):
     """
     Execute until the function returns.
     """
     name = 'cy finish'
 
-    invoke = CythonCodeStepper.finish
+    invoke = CythonExecutionControlCommand.finish
 
 
 class CyUp(CythonCommand):
@@ -961,7 +969,7 @@ class CyDown(CyUp):
     _command = 'down'
 
 
-class CySelect(CythonCodeStepper):
+class CySelect(CythonCommand):
     """
     Select a frame. Use frame numbers as listed in `cy backtrace`.
     This command is useful because `cy backtrace` prints a reversed backtrace.
@@ -979,7 +987,7 @@ class CySelect(CythonCodeStepper):
         while frame.newer():
             frame = frame.newer()
         
-        stackdepth = self._stackdepth(frame)
+        stackdepth = libpython.stackdepth(frame)
         
         try:
             gdb.execute('select %d' % (stackdepth - stackno - 1,))
@@ -1033,7 +1041,7 @@ class CyList(CythonCommand):
     command_class = gdb.COMMAND_FILES
     completer_class = gdb.COMPLETE_NONE
     
-    @dispatch_on_frame(c_command='list')
+    @dispatch_on_frame(c_command='list')
     def invoke(self, _, from_tty):
         sd, lineno = self.get_source_desc()
         source = sd.get_source(lineno - 5, lineno + 5, mark_line=lineno, 
@@ -1200,19 +1208,21 @@ class CyExec(CythonCommand, libpython.PyExec):
         expr, input_type = self.readcode(expr)
         executor = libpython.PythonCodeExecutor()
         
-        # get the dict of Cython globals and construct a dict in the inferior
-        # with Cython locals
-        global_dict = gdb.parse_and_eval(
-            '(PyObject *) PyModule_GetDict(__pyx_m)')
-        local_dict = gdb.parse_and_eval('(PyObject *) PyDict_New()')
-        
-        cython_function = self.get_cython_function()
-        
-        try:
-            self._fill_locals_dict(executor, libpython.pointervalue(local_dict))
-            executor.evalcode(expr, input_type, global_dict, local_dict)
-        finally:
-            executor.decref(libpython.pointervalue(local_dict))
+        with libpython.FetchAndRestoreError():
+            # get the dict of Cython globals and construct a dict in the 
+            # inferior with Cython locals
+            global_dict = gdb.parse_and_eval(
+                '(PyObject *) PyModule_GetDict(__pyx_m)')
+            local_dict = gdb.parse_and_eval('(PyObject *) PyDict_New()')
+            
+            cython_function = self.get_cython_function()
+            
+            try:
+                self._fill_locals_dict(executor, 
+                                       libpython.pointervalue(local_dict))
+                executor.evalcode(expr, input_type, global_dict, local_dict)
+            finally:
+                executor.decref(libpython.pointervalue(local_dict))
 
 
 # Functions
@@ -1283,5 +1293,6 @@ class CyLine(gdb.Function, CythonBase):
     def invoke(self):
         return self.get_cython_lineno()
 
-
-cy = CyCy.register()
\ No newline at end of file
+cython_info = CythonInfo()
+cy = CyCy.register()
+cython_info.cy = cy
\ No newline at end of file