From d3129cf67e3fd1cd5b8622ee332dab1317fd75bb 2006-10-30 17:00:39
From: vivainio
Date: 2006-10-30 17:00:39
Subject: [PATCH] Last set of Rocky's patches for pydb integration

---

diff --git a/IPython/Debugger.py b/IPython/Debugger.py
index 1afdc4e..ab4ec5a 100644
--- a/IPython/Debugger.py
+++ b/IPython/Debugger.py
@@ -15,7 +15,7 @@ details on the PSF (Python Software Foundation) standard license, see:
 
 http://www.python.org/2.2.3/license.html
 
-$Id: Debugger.py 1787 2006-09-27 06:56:29Z fperez $"""
+$Id: Debugger.py 1853 2006-10-30 17:00:39Z vivainio $"""
 
 #*****************************************************************************
 #
@@ -40,13 +40,41 @@ import bdb
 import cmd
 import linecache
 import os
-import pdb
 import sys
 
 from IPython import PyColorize, ColorANSI
 from IPython.genutils import Term
 from IPython.excolors import ExceptionColors
 
+# See if we can use pydb.
+has_pydb = False
+prompt = 'ipdb>'
+if sys.version[:3] >= '2.5':
+    try:
+        import pydb
+        if hasattr(pydb.pydb, "runl"):
+            has_pydb = True
+            from pydb import Pdb as OldPdb
+            prompt = 'ipydb>'
+    except ImportError:
+        pass
+
+if has_pydb:
+    from pydb import Pdb as OldPdb
+else:
+    from pdb import Pdb as OldPdb
+
+def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
+    """Make new_fn have old_fn's doc string. This is particularly useful
+    for the do_... commands that hook into the help system.
+    Adapted from from a comp.lang.python posting
+    by Duncan Booth."""
+    def wrapper(*args, **kw):
+        return new_fn(*args, **kw)
+    if old_fn.__doc__:
+        wrapper.__doc__ = old_fn.__doc__ + additional_text
+    return wrapper
+
 def _file_lines(fname):
     """Return the contents of a named file as a list of lines.
 
@@ -62,7 +90,7 @@ def _file_lines(fname):
         outfile.close()
         return out
 
-class Pdb(pdb.Pdb):
+class Pdb(OldPdb):
     """Modified Pdb class, does not load readline."""
 
     if sys.version[:3] >= '2.5':
@@ -70,10 +98,33 @@ class Pdb(pdb.Pdb):
                      stdin=None, stdout=None):
 
             # Parent constructor:
-            pdb.Pdb.__init__(self,completekey,stdin,stdout)
+            OldPdb.__init__(self,completekey,stdin,stdout)
             
             # IPython changes...
-            self.prompt = 'ipdb> ' # The default prompt is '(Pdb)'
+            self.prompt = prompt # The default prompt is '(Pdb)'
+            self.is_pydb = prompt == 'ipydb>'
+
+            if self.is_pydb:
+
+                # iplib.py's ipalias seems to want pdb's checkline
+                # which located in pydb.fn
+                import pydb.fns
+                self.checkline = lambda filename, lineno: \
+                                 pydb.fns.checkline(self, filename, lineno)
+
+                self.curframe = None
+                self.do_restart = self.new_do_restart
+
+                self.old_all_completions = __IPYTHON__.Completer.all_completions
+                __IPYTHON__.Completer.all_completions=self.all_completions
+
+                # Do we have access to pydb's list command parser?
+                self.do_list = decorate_fn_with_doc(self.list_command_pydb,
+                                                    OldPdb.do_list)
+                self.do_l     = self.do_list
+                self.do_frame = decorate_fn_with_doc(self.new_do_frame,
+                                                     OldPdb.do_frame)
+
             self.aliases = {}
 
             # Create color table: we copy the default one from the traceback
@@ -143,17 +194,34 @@ class Pdb(pdb.Pdb):
 
     def interaction(self, frame, traceback):
         __IPYTHON__.set_completer_frame(frame)
-        pdb.Pdb.interaction(self, frame, traceback)
+        OldPdb.interaction(self, frame, traceback)
+
+    def new_do_up(self, arg):
+        OldPdb.do_up(self, arg)
+        __IPYTHON__.set_completer_frame(self.curframe)
+    do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
 
-    def do_up(self, arg):
-        pdb.Pdb.do_up(self, arg)
+    def new_do_down(self, arg):
+        OldPdb.do_down(self, arg)
         __IPYTHON__.set_completer_frame(self.curframe)
-    do_u = do_up
 
-    def do_down(self, arg):
-        pdb.Pdb.do_down(self, arg)
+    do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
+
+    def new_do_frame(self, arg):
+        OldPdb.do_frame(self, arg)
         __IPYTHON__.set_completer_frame(self.curframe)
-    do_d = do_down
+
+    def new_do_quit(self, arg):
+        __IPYTHON__.Completer.all_completions=self.old_all_completions
+        return OldPdb.do_quit(self, arg)
+
+    do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
+
+    def new_do_restart(self, arg):
+        """Restart command. In the context of ipython this is exactly the same
+        thing as 'quit'."""
+        self.msg("Restart doesn't make sense here. Using 'quit' instead.")
+        return self.do_quit(arg)
 
     def postloop(self):
         __IPYTHON__.set_completer_frame(None)
@@ -263,6 +331,39 @@ class Pdb(pdb.Pdb):
             
         return line
 
+    def list_command_pydb(self, arg):
+        """List command to use if we have a newer pydb installed"""
+        filename, first, last = OldPdb.parse_list_cmd(self, arg)
+        if filename is not None:
+            self.print_list_lines(filename, first, last)
+        
+    def print_list_lines(self, filename, first, last):
+        """The printing (as opposed to the parsing part of a 'list'
+        command."""
+        try:
+            Colors = self.color_scheme_table.active_colors
+            ColorsNormal = Colors.Normal
+            tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
+            tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
+            src = []
+            for lineno in range(first, last+1):
+                line = linecache.getline(filename, lineno)
+                if not line:
+                    break
+
+                if lineno == self.curframe.f_lineno:
+                    line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
+                else:
+                    line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
+
+                src.append(line)
+                self.lineno = lineno
+
+            print >>Term.cout, ''.join(src)
+
+        except KeyboardInterrupt:
+            pass
+
     def do_list(self, arg):
         self.lastcmd = 'list'
         last = None
@@ -287,29 +388,24 @@ class Pdb(pdb.Pdb):
             first = self.lineno + 1
         if last is None:
             last = first + 10
-        filename = self.curframe.f_code.co_filename
-        try:
-            Colors = self.color_scheme_table.active_colors
-            ColorsNormal = Colors.Normal
-            tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
-            tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
-            src = []
-            for lineno in range(first, last+1):
-                line = linecache.getline(filename, lineno)
-                if not line:
-                    break
-
-                if lineno == self.curframe.f_lineno:
-                    line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
-                else:
-                    line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
-
-                src.append(line)
-                self.lineno = lineno
-
-            print >>Term.cout, ''.join(src)
-
-        except KeyboardInterrupt:
-            pass
+        self.print_list_lines(self.curframe.f_code.co_filename, first, last)
 
     do_l = do_list
+
+    def do_pdef(self, arg):
+        """The debugger interface to magic_pdef"""
+        namespaces = [('Locals', self.curframe.f_locals),
+                      ('Globals', self.curframe.f_globals)]
+        __IPYTHON__.magic_pdef(arg, namespaces=namespaces)
+
+    def do_pdoc(self, arg):
+        """The debugger interface to magic_pdoc"""
+        namespaces = [('Locals', self.curframe.f_locals),
+                      ('Globals', self.curframe.f_globals)]
+        __IPYTHON__.magic_pdoc(arg, namespaces=namespaces)
+
+    def do_pinfo(self, arg):
+        """The debugger equivalant of ?obj"""
+        namespaces = [('Locals', self.curframe.f_locals),
+                      ('Globals', self.curframe.f_globals)]
+        __IPYTHON__.magic_pinfo("pinfo %s" % arg, namespaces=namespaces)
diff --git a/IPython/iplib.py b/IPython/iplib.py
index 7dc13df..1265422 100644
--- a/IPython/iplib.py
+++ b/IPython/iplib.py
@@ -6,7 +6,7 @@ Requires Python 2.3 or newer.
 
 This file contains all the classes and helper functions specific to IPython.
 
-$Id: iplib.py 1850 2006-10-28 19:48:13Z fptest $
+$Id: iplib.py 1853 2006-10-30 17:00:39Z vivainio $
 """
 
 #*****************************************************************************
@@ -47,7 +47,6 @@ import inspect
 import keyword
 import new
 import os
-import pdb
 import pydoc
 import re
 import shutil
@@ -1361,11 +1360,20 @@ want to merge them back into the new files.""" % locals()
         self.SyntaxTB(etype,value,[])
 
     def debugger(self):
-        """Call the pdb debugger."""
+        """Call the pydb/pdb debugger."""
 
         if not self.rc.pdb:
             return
-        pdb.pm()
+        have_pydb = False
+        if sys.version[:3] >= '2.5':
+            try:
+                from pydb import pm
+                have_pydb = True
+            except ImportError:
+                pass
+        if not have_pydb:
+            from pdb import pm
+        pm()
 
     def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None):
         """Display the exception that just occurred.
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 9222adf..6b531cf 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,9 @@
+2006-10-30  Ville Vainio  <vivainio@gmail.com>
+
+	* Debugger.py, iplib.py (debugger()): Add last set of Rocky 
+	Bernsteins's patches for pydb integration.
+	http://bashdb.sourceforge.net/pydb/
+
 2006-10-28  Fernando Perez  <Fernando.Perez@colorado.edu>
 
 	* IPython/UserConfig/ipythonrc-scipy: minor clenaups to remove old
@@ -22,7 +28,7 @@
 	file around %run commands to prevent side effects from 
 	%runned programs that might use readline (e.g. pydb).
 
-	* extensions/pydb_ipy.py: Adds %pydb magic when imported, for 
+	* extensions/ipy_pydb.py: Adds %pydb magic when imported, for 
 	invoking the pydb enhanced debugger.
 
 2006-10-23  Walter Doerwald  <walter@livinglogic.de>