[Python-checkins] r45955 - in python/trunk: Lib/bdb.py Lib/doctest.py Lib/pdb.py Misc/NEWS

georg.brandl python-checkins at python.org
Wed May 10 19:13:22 CEST 2006


Author: georg.brandl
Date: Wed May 10 19:13:20 2006
New Revision: 45955

Modified:
   python/trunk/Lib/bdb.py
   python/trunk/Lib/doctest.py
   python/trunk/Lib/pdb.py
   python/trunk/Misc/NEWS
Log:
Patch #721464: pdb.Pdb instances can now be given explicit stdin and
stdout arguments, making it possible to redirect input and output
for remote debugging.


Modified: python/trunk/Lib/bdb.py
==============================================================================
--- python/trunk/Lib/bdb.py	(original)
+++ python/trunk/Lib/bdb.py	Wed May 10 19:13:20 2006
@@ -473,7 +473,9 @@
     def disable(self):
         self.enabled = 0
 
-    def bpprint(self):
+    def bpprint(self, out=None):
+        if out is None:
+            out = sys.stdout
         if self.temporary:
             disp = 'del  '
         else:
@@ -482,17 +484,17 @@
             disp = disp + 'yes  '
         else:
             disp = disp + 'no   '
-        print '%-4dbreakpoint   %s at %s:%d' % (self.number, disp,
-                             self.file, self.line)
+        print >>out, '%-4dbreakpoint   %s at %s:%d' % (self.number, disp,
+                                                       self.file, self.line)
         if self.cond:
-            print '\tstop only if %s' % (self.cond,)
+            print >>out, '\tstop only if %s' % (self.cond,)
         if self.ignore:
-            print '\tignore next %d hits' % (self.ignore)
+            print >>out, '\tignore next %d hits' % (self.ignore)
         if (self.hits):
             if (self.hits > 1): ss = 's'
             else: ss = ''
-            print ('\tbreakpoint already hit %d time%s' %
-                   (self.hits, ss))
+            print >>out, ('\tbreakpoint already hit %d time%s' %
+                          (self.hits, ss))
 
 # -----------end of Breakpoint class----------
 

Modified: python/trunk/Lib/doctest.py
==============================================================================
--- python/trunk/Lib/doctest.py	(original)
+++ python/trunk/Lib/doctest.py	Wed May 10 19:13:20 2006
@@ -352,7 +352,7 @@
     """
     def __init__(self, out):
         self.__out = out
-        pdb.Pdb.__init__(self)
+        pdb.Pdb.__init__(self, stdout=out)
 
     def trace_dispatch(self, *args):
         # Redirect stdout to the given stream.

Modified: python/trunk/Lib/pdb.py
==============================================================================
--- python/trunk/Lib/pdb.py	(original)
+++ python/trunk/Lib/pdb.py	Wed May 10 19:13:20 2006
@@ -52,9 +52,11 @@
 
 class Pdb(bdb.Bdb, cmd.Cmd):
 
-    def __init__(self):
+    def __init__(self, completekey='tab', stdin=None, stdout=None):
         bdb.Bdb.__init__(self)
-        cmd.Cmd.__init__(self)
+        cmd.Cmd.__init__(self, completekey, stdin, stdout)
+        if stdout:
+            self.use_rawinput = 0
         self.prompt = '(Pdb) '
         self.aliases = {}
         self.mainpyfile = ''
@@ -128,7 +130,7 @@
         if self._wait_for_mainpyfile:
             return
         if self.stop_here(frame):
-            print '--Call--'
+            print >>self.stdout, '--Call--'
             self.interaction(frame, None)
 
     def user_line(self, frame):
@@ -164,7 +166,7 @@
     def user_return(self, frame, return_value):
         """This function is called when a return trap is set here."""
         frame.f_locals['__return__'] = return_value
-        print '--Return--'
+        print >>self.stdout, '--Return--'
         self.interaction(frame, None)
 
     def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
@@ -174,7 +176,7 @@
         if type(exc_type) == type(''):
             exc_type_name = exc_type
         else: exc_type_name = exc_type.__name__
-        print exc_type_name + ':', _saferepr(exc_value)
+        print >>self.stdout, exc_type_name + ':', _saferepr(exc_value)
         self.interaction(frame, exc_traceback)
 
     # General interaction function
@@ -197,7 +199,7 @@
             if type(t) == type(''):
                 exc_type_name = t
             else: exc_type_name = t.__name__
-            print '***', exc_type_name + ':', v
+            print >>self.stdout, '***', exc_type_name + ':', v
 
     def precmd(self, line):
         """Handle alias expansion and ';;' separator."""
@@ -275,7 +277,7 @@
             try:
                 bnum = int(arg)
             except:
-                print "Usage : commands [bnum]\n        ...\n        end"
+                print >>self.stdout, "Usage : commands [bnum]\n        ...\n        end"
                 return
         self.commands_bnum = bnum
         self.commands[bnum] = []
@@ -292,10 +294,10 @@
         # break [ ([filename:]lineno | function) [, "condition"] ]
         if not arg:
             if self.breaks:  # There's at least one
-                print "Num Type         Disp Enb   Where"
+                print >>self.stdout, "Num Type         Disp Enb   Where"
                 for bp in bdb.Breakpoint.bpbynumber:
                     if bp:
-                        bp.bpprint()
+                        bp.bpprint(self.stdout)
             return
         # parse arguments; comma has lowest precedence
         # and cannot occur in filename
@@ -314,8 +316,8 @@
             filename = arg[:colon].rstrip()
             f = self.lookupmodule(filename)
             if not f:
-                print '*** ', repr(filename),
-                print 'not found from sys.path'
+                print >>self.stdout, '*** ', repr(filename),
+                print >>self.stdout, 'not found from sys.path'
                 return
             else:
                 filename = f
@@ -323,7 +325,7 @@
             try:
                 lineno = int(arg)
             except ValueError, msg:
-                print '*** Bad lineno:', arg
+                print >>self.stdout, '*** Bad lineno:', arg
                 return
         else:
             # no colon; can be lineno or function
@@ -349,11 +351,10 @@
                     # last thing to try
                     (ok, filename, ln) = self.lineinfo(arg)
                     if not ok:
-                        print '*** The specified object',
-                        print repr(arg),
-                        print 'is not a function'
-                        print ('or was not found '
-                               'along sys.path.')
+                        print >>self.stdout, '*** The specified object',
+                        print >>self.stdout, repr(arg),
+                        print >>self.stdout, 'is not a function'
+                        print >>self.stdout, 'or was not found along sys.path.'
                         return
                     funcname = ok # ok contains a function name
                     lineno = int(ln)
@@ -364,12 +365,12 @@
         if line:
             # now set the break point
             err = self.set_break(filename, line, temporary, cond, funcname)
-            if err: print '***', err
+            if err: print >>self.stdout, '***', err
             else:
                 bp = self.get_breaks(filename, line)[-1]
-                print "Breakpoint %d at %s:%d" % (bp.number,
-                                                  bp.file,
-                                                  bp.line)
+                print >>self.stdout, "Breakpoint %d at %s:%d" % (bp.number,
+                                                                 bp.file,
+                                                                 bp.line)
 
     # To be overridden in derived debuggers
     def defaultFile(self):
@@ -425,13 +426,13 @@
         """
         line = linecache.getline(filename, lineno)
         if not line:
-            print 'End of file'
+            print >>self.stdout, 'End of file'
             return 0
         line = line.strip()
         # Don't allow setting breakpoint at a blank line
         if (not line or (line[0] == '#') or
              (line[:3] == '"""') or line[:3] == "'''"):
-            print '*** Blank or comment'
+            print >>self.stdout, '*** Blank or comment'
             return 0
         return lineno
 
@@ -441,11 +442,11 @@
             try:
                 i = int(i)
             except ValueError:
-                print 'Breakpoint index %r is not a number' % i
+                print >>self.stdout, 'Breakpoint index %r is not a number' % i
                 continue
 
             if not (0 <= i < len(bdb.Breakpoint.bpbynumber)):
-                print 'No breakpoint numbered', i
+                print >>self.stdout, 'No breakpoint numbered', i
                 continue
 
             bp = bdb.Breakpoint.bpbynumber[i]
@@ -458,11 +459,11 @@
             try:
                 i = int(i)
             except ValueError:
-                print 'Breakpoint index %r is not a number' % i
+                print >>self.stdout, 'Breakpoint index %r is not a number' % i
                 continue
 
             if not (0 <= i < len(bdb.Breakpoint.bpbynumber)):
-                print 'No breakpoint numbered', i
+                print >>self.stdout, 'No breakpoint numbered', i
                 continue
 
             bp = bdb.Breakpoint.bpbynumber[i]
@@ -481,8 +482,8 @@
         if bp:
             bp.cond = cond
             if not cond:
-                print 'Breakpoint', bpnum,
-                print 'is now unconditional.'
+                print >>self.stdout, 'Breakpoint', bpnum,
+                print >>self.stdout, 'is now unconditional.'
 
     def do_ignore(self,arg):
         """arg is bp number followed by ignore count."""
@@ -501,10 +502,10 @@
                     reply = reply + '%d crossings' % count
                 else:
                     reply = reply + '1 crossing'
-                print reply + ' of breakpoint %d.' % bpnum
+                print >>self.stdout, reply + ' of breakpoint %d.' % bpnum
             else:
-                print 'Will stop next time breakpoint',
-                print bpnum, 'is reached.'
+                print >>self.stdout, 'Will stop next time breakpoint',
+                print >>self.stdout, bpnum, 'is reached.'
 
     def do_clear(self, arg):
         """Three possibilities, tried in this order:
@@ -531,24 +532,24 @@
                 err = "Invalid line number (%s)" % arg
             else:
                 err = self.clear_break(filename, lineno)
-            if err: print '***', err
+            if err: print >>self.stdout, '***', err
             return
         numberlist = arg.split()
         for i in numberlist:
             try:
                 i = int(i)
             except ValueError:
-                print 'Breakpoint index %r is not a number' % i
+                print >>self.stdout, 'Breakpoint index %r is not a number' % i
                 continue
 
             if not (0 <= i < len(bdb.Breakpoint.bpbynumber)):
-                print 'No breakpoint numbered', i
+                print >>self.stdout, 'No breakpoint numbered', i
                 continue
             err = self.clear_bpbynumber(i)
             if err:
-                print '***', err
+                print >>self.stdout, '***', err
             else:
-                print 'Deleted breakpoint', i
+                print >>self.stdout, 'Deleted breakpoint', i
     do_cl = do_clear # 'c' is already an abbreviation for 'continue'
 
     def do_where(self, arg):
@@ -558,7 +559,7 @@
 
     def do_up(self, arg):
         if self.curindex == 0:
-            print '*** Oldest frame'
+            print >>self.stdout, '*** Oldest frame'
         else:
             self.curindex = self.curindex - 1
             self.curframe = self.stack[self.curindex][0]
@@ -568,7 +569,7 @@
 
     def do_down(self, arg):
         if self.curindex + 1 == len(self.stack):
-            print '*** Newest frame'
+            print >>self.stdout, '*** Newest frame'
         else:
             self.curindex = self.curindex + 1
             self.curframe = self.stack[self.curindex][0]
@@ -598,12 +599,12 @@
 
     def do_jump(self, arg):
         if self.curindex + 1 != len(self.stack):
-            print "*** You can only jump within the bottom frame"
+            print >>self.stdout, "*** You can only jump within the bottom frame"
             return
         try:
             arg = int(arg)
         except ValueError:
-            print "*** The 'jump' command requires a line number."
+            print >>self.stdout, "*** The 'jump' command requires a line number."
         else:
             try:
                 # Do the jump, fix up our copy of the stack, and display the
@@ -612,7 +613,7 @@
                 self.stack[self.curindex] = self.stack[self.curindex][0], arg
                 self.print_stack_entry(self.stack[self.curindex])
             except ValueError, e:
-                print '*** Jump failed:', e
+                print >>self.stdout, '*** Jump failed:', e
     do_j = do_jump
 
     def do_debug(self, arg):
@@ -621,9 +622,9 @@
         locals = self.curframe.f_locals
         p = Pdb()
         p.prompt = "(%s) " % self.prompt.strip()
-        print "ENTERING RECURSIVE DEBUGGER"
+        print >>self.stdout, "ENTERING RECURSIVE DEBUGGER"
         sys.call_tracing(p.run, (arg, globals, locals))
-        print "LEAVING RECURSIVE DEBUGGER"
+        print >>self.stdout, "LEAVING RECURSIVE DEBUGGER"
         sys.settrace(self.trace_dispatch)
         self.lastcmd = p.lastcmd
 
@@ -636,7 +637,7 @@
     do_exit = do_quit
 
     def do_EOF(self, arg):
-        print
+        print >>self.stdout
         self._user_requested_quit = 1
         self.set_quit()
         return 1
@@ -650,16 +651,16 @@
         if co.co_flags & 8: n = n+1
         for i in range(n):
             name = co.co_varnames[i]
-            print name, '=',
-            if name in dict: print dict[name]
-            else: print "*** undefined ***"
+            print >>self.stdout, name, '=',
+            if name in dict: print >>self.stdout, dict[name]
+            else: print >>self.stdout, "*** undefined ***"
     do_a = do_args
 
     def do_retval(self, arg):
         if '__return__' in self.curframe.f_locals:
-            print self.curframe.f_locals['__return__']
+            print >>self.stdout, self.curframe.f_locals['__return__']
         else:
-            print '*** Not yet returned!'
+            print >>self.stdout, '*** Not yet returned!'
     do_rv = do_retval
 
     def _getval(self, arg):
@@ -671,18 +672,18 @@
             if isinstance(t, str):
                 exc_type_name = t
             else: exc_type_name = t.__name__
-            print '***', exc_type_name + ':', repr(v)
+            print >>self.stdout, '***', exc_type_name + ':', repr(v)
             raise
 
     def do_p(self, arg):
         try:
-            print repr(self._getval(arg))
+            print >>self.stdout, repr(self._getval(arg))
         except:
             pass
 
     def do_pp(self, arg):
         try:
-            pprint.pprint(self._getval(arg))
+            pprint.pprint(self._getval(arg), self.stdout)
         except:
             pass
 
@@ -702,7 +703,7 @@
                 else:
                     first = max(1, int(x) - 5)
             except:
-                print '*** Error in argument:', repr(arg)
+                print >>self.stdout, '*** Error in argument:', repr(arg)
                 return
         elif self.lineno is None:
             first = max(1, self.curframe.f_lineno - 5)
@@ -716,7 +717,7 @@
             for lineno in range(first, last+1):
                 line = linecache.getline(filename, lineno)
                 if not line:
-                    print '[EOF]'
+                    print >>self.stdout, '[EOF]'
                     break
                 else:
                     s = repr(lineno).rjust(3)
@@ -725,7 +726,7 @@
                     else: s = s + ' '
                     if lineno == self.curframe.f_lineno:
                         s = s + '->'
-                    print s + '\t' + line,
+                    print >>self.stdout, s + '\t' + line,
                     self.lineno = lineno
         except KeyboardInterrupt:
             pass
@@ -740,23 +741,23 @@
             if type(t) == type(''):
                 exc_type_name = t
             else: exc_type_name = t.__name__
-            print '***', exc_type_name + ':', repr(v)
+            print >>self.stdout, '***', exc_type_name + ':', repr(v)
             return
         code = None
         # Is it a function?
         try: code = value.func_code
         except: pass
         if code:
-            print 'Function', code.co_name
+            print >>self.stdout, 'Function', code.co_name
             return
         # Is it an instance method?
         try: code = value.im_func.func_code
         except: pass
         if code:
-            print 'Method', code.co_name
+            print >>self.stdout, 'Method', code.co_name
             return
         # None of the above...
-        print type(value)
+        print >>self.stdout, type(value)
 
     def do_alias(self, arg):
         args = arg.split()
@@ -764,10 +765,10 @@
             keys = self.aliases.keys()
             keys.sort()
             for alias in keys:
-                print "%s = %s" % (alias, self.aliases[alias])
+                print >>self.stdout, "%s = %s" % (alias, self.aliases[alias])
             return
         if args[0] in self.aliases and len(args) == 1:
-            print "%s = %s" % (args[0], self.aliases[args[0]])
+            print >>self.stdout, "%s = %s" % (args[0], self.aliases[args[0]])
         else:
             self.aliases[args[0]] = ' '.join(args[1:])
 
@@ -778,7 +779,8 @@
             del self.aliases[args[0]]
 
     #list of all the commands making the program resume execution.
-    commands_resuming = ['do_continue', 'do_step', 'do_next', 'do_return', 'do_quit', 'do_jump']
+    commands_resuming = ['do_continue', 'do_step', 'do_next', 'do_return',
+                         'do_quit', 'do_jump']
 
     # Print a traceback starting at the top stack frame.
     # The most recently entered frame is printed last;
@@ -798,10 +800,11 @@
     def print_stack_entry(self, frame_lineno, prompt_prefix=line_prefix):
         frame, lineno = frame_lineno
         if frame is self.curframe:
-            print '>',
+            print >>self.stdout, '>',
         else:
-            print ' ',
-        print self.format_stack_entry(frame_lineno, prompt_prefix)
+            print >>self.stdout, ' ',
+        print >>self.stdout, self.format_stack_entry(frame_lineno,
+                                                     prompt_prefix)
 
 
     # Help methods (derived from pdb.doc)
@@ -810,7 +813,7 @@
         self.help_h()
 
     def help_h(self):
-        print """h(elp)
+        print >>self.stdout, """h(elp)
 Without argument, print the list of available commands.
 With a command name as argument, print help about that command
 "help pdb" pipes the full documentation file to the $PAGER
@@ -820,7 +823,7 @@
         self.help_w()
 
     def help_w(self):
-        print """w(here)
+        print >>self.stdout, """w(here)
 Print a stack trace, with the most recent frame at the bottom.
 An arrow indicates the "current frame", which determines the
 context of most commands.  'bt' is an alias for this command."""
@@ -831,7 +834,7 @@
         self.help_d()
 
     def help_d(self):
-        print """d(own)
+        print >>self.stdout, """d(own)
 Move the current frame one level down in the stack trace
 (to a newer frame)."""
 
@@ -839,7 +842,7 @@
         self.help_u()
 
     def help_u(self):
-        print """u(p)
+        print >>self.stdout, """u(p)
 Move the current frame one level up in the stack trace
 (to an older frame)."""
 
@@ -847,7 +850,7 @@
         self.help_b()
 
     def help_b(self):
-        print """b(reak) ([file:]lineno | function) [, condition]
+        print >>self.stdout, """b(reak) ([file:]lineno | function) [, condition]
 With a line number argument, set a break there in the current
 file.  With a function name, set a break at first executable line
 of that function.  Without argument, list all breaks.  If a second
@@ -863,8 +866,8 @@
         self.help_cl()
 
     def help_cl(self):
-        print "cl(ear) filename:lineno"
-        print """cl(ear) [bpnumber [bpnumber...]]
+        print >>self.stdout, "cl(ear) filename:lineno"
+        print >>self.stdout, """cl(ear) [bpnumber [bpnumber...]]
 With a space separated list of breakpoint numbers, clear
 those breakpoints.  Without argument, clear all breaks (but
 first ask confirmation).  With a filename:lineno argument,
@@ -876,21 +879,21 @@
 breakpoint numbers."""
 
     def help_tbreak(self):
-        print """tbreak  same arguments as break, but breakpoint is
+        print >>self.stdout, """tbreak  same arguments as break, but breakpoint is
 removed when first hit."""
 
     def help_enable(self):
-        print """enable bpnumber [bpnumber ...]
+        print >>self.stdout, """enable bpnumber [bpnumber ...]
 Enables the breakpoints given as a space separated list of
 bp numbers."""
 
     def help_disable(self):
-        print """disable bpnumber [bpnumber ...]
+        print >>self.stdout, """disable bpnumber [bpnumber ...]
 Disables the breakpoints given as a space separated list of
 bp numbers."""
 
     def help_ignore(self):
-        print """ignore bpnumber count
+        print >>self.stdout, """ignore bpnumber count
 Sets the ignore count for the given breakpoint number.  A breakpoint
 becomes active when the ignore count is zero.  When non-zero, the
 count is decremented each time the breakpoint is reached and the
@@ -898,7 +901,7 @@
 to true."""
 
     def help_condition(self):
-        print """condition bpnumber str_condition
+        print >>self.stdout, """condition bpnumber str_condition
 str_condition is a string specifying an expression which
 must evaluate to true before the breakpoint is honored.
 If str_condition is absent, any existing condition is removed;
@@ -908,7 +911,7 @@
         self.help_s()
 
     def help_s(self):
-        print """s(tep)
+        print >>self.stdout, """s(tep)
 Execute the current line, stop at the first possible occasion
 (either in a function that is called or in the current function)."""
 
@@ -916,7 +919,7 @@
         self.help_n()
 
     def help_n(self):
-        print """n(ext)
+        print >>self.stdout, """n(ext)
 Continue execution until the next line in the current function
 is reached or it returns."""
 
@@ -924,7 +927,7 @@
         self.help_r()
 
     def help_r(self):
-        print """r(eturn)
+        print >>self.stdout, """r(eturn)
 Continue execution until the current function returns."""
 
     def help_continue(self):
@@ -934,18 +937,18 @@
         self.help_c()
 
     def help_c(self):
-        print """c(ont(inue))
+        print >>self.stdout, """c(ont(inue))
 Continue execution, only stop when a breakpoint is encountered."""
 
     def help_jump(self):
         self.help_j()
 
     def help_j(self):
-        print """j(ump) lineno
+        print >>self.stdout, """j(ump) lineno
 Set the next line that will be executed."""
 
     def help_debug(self):
-        print """debug code
+        print >>self.stdout, """debug code
 Enter a recursive debugger that steps through the code argument
 (which is an arbitrary expression or statement to be executed
 in the current environment)."""
@@ -954,7 +957,7 @@
         self.help_l()
 
     def help_l(self):
-        print """l(ist) [first [,last]]
+        print >>self.stdout, """l(ist) [first [,last]]
 List source code for the current file.
 Without arguments, list 11 lines around the current line
 or continue the previous listing.
@@ -966,19 +969,19 @@
         self.help_a()
 
     def help_a(self):
-        print """a(rgs)
+        print >>self.stdout, """a(rgs)
 Print the arguments of the current function."""
 
     def help_p(self):
-        print """p expression
+        print >>self.stdout, """p expression
 Print the value of the expression."""
 
     def help_pp(self):
-        print """pp expression
+        print >>self.stdout, """pp expression
 Pretty-print the value of the expression."""
 
     def help_exec(self):
-        print """(!) statement
+        print >>self.stdout, """(!) statement
 Execute the (one-line) statement in the context of
 the current stack frame.
 The exclamation point can be omitted unless the first word
@@ -992,21 +995,21 @@
         self.help_q()
 
     def help_q(self):
-        print """q(uit) or exit - Quit from the debugger.
+        print >>self.stdout, """q(uit) or exit - Quit from the debugger.
 The program being executed is aborted."""
 
     help_exit = help_q
 
     def help_whatis(self):
-        print """whatis arg
+        print >>self.stdout, """whatis arg
 Prints the type of the argument."""
 
     def help_EOF(self):
-        print """EOF
+        print >>self.stdout, """EOF
 Handles the receipt of EOF as a command."""
 
     def help_alias(self):
-        print """alias [name [command [parameter parameter ...] ]]
+        print >>self.stdout, """alias [name [command [parameter parameter ...] ]]
 Creates an alias called 'name' the executes 'command'.  The command
 must *not* be enclosed in quotes.  Replaceable parameters are
 indicated by %1, %2, and so on, while %* is replaced by all the
@@ -1030,11 +1033,11 @@
 """
 
     def help_unalias(self):
-        print """unalias name
+        print >>self.stdout, """unalias name
 Deletes the specified alias."""
 
     def help_commands(self):
-        print """commands [bpnumber]
+        print >>self.stdout, """commands [bpnumber]
 (com) ...
 (com) end
 (Pdb)

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Wed May 10 19:13:20 2006
@@ -96,6 +96,10 @@
 Library
 -------
 
+- Patch #721464: pdb.Pdb instances can now be given explicit stdin and
+  stdout arguments, making it possible to redirect input and output
+  for remote debugging.
+
 - Patch #1484695: Update the tarfile module to version 0.8. This fixes
   a couple of issues, notably handling of long file names using the
   GNU LONGNAME extension.


More information about the Python-checkins mailing list