home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 March / PCWK3A99.iso / Linux / DDD331 / DDD-3_1_.000 / DDD-3_1_ / ddd-3.1.1 / pydb / pydb.py < prev    next >
Encoding:
Python Source  |  1998-11-12  |  34.8 KB  |  1,071 lines

  1. #! /usr/bin/env python
  2. # $Id: pydb.py,v 1.2 1998/11/12 23:11:33 zeller Exp $
  3.  
  4. # pydb.py -- a Python debugger!
  5. # Modified original pdb.py
  6.  
  7. # (See pdb.doc for original documentation.)
  8.  
  9. import string
  10. import sys
  11. import linecache
  12. import cmd
  13. import bdb
  14. import repr
  15. import os
  16. import posix
  17.  
  18.  
  19. import pydbcmd
  20. from pydbsupt import Breakpoint, effective, Display, DisplayNode
  21.  
  22. # Interaction prompt line will separate file and call info from code
  23. # text using value of line_prefix string.  A newline and arrow may
  24. # be to your liking.  You can set it once pydb is imported using the
  25. # command "pydb.line_prefix = '\n% '".
  26. # line_prefix = ': '    # Use this to get the old situation back
  27. line_prefix = '\n-> '    # Probably a better default
  28.  
  29. class Pdb(bdb.Bdb, pydbcmd.Cmd):
  30.     
  31.     def __init__(self):
  32.         bdb.Bdb.__init__(self)
  33.         pydbcmd.Cmd.__init__(self)
  34.         self.prompt = '(Pdb) '
  35.         self.running = 0
  36.         self.filetodebug = ""
  37.         self.moduletodebug = ""
  38.         self.nextbpnumber = 1
  39.         self.latestbp = None     # for stack print routine
  40.         self.cmdqueue = []
  41.     
  42.     def reset(self):
  43.         bdb.Bdb.reset(self)
  44.         self.forget()
  45.     
  46.     def forget(self):
  47.         self.lineno = None
  48.         self.stack = []
  49.         self.curindex = 0
  50.         self.curframe = None
  51.     
  52.     def setup(self, f, t):
  53.         self.forget()
  54.         self.stack, self.curindex = self.get_stack(f, t)
  55.         self.curframe = self.stack[self.curindex][0]
  56.     
  57.     # Override Bdb methods (except user_call, for now)
  58.     
  59.     def user_line(self, frame):
  60.         # This function is called when we stop or break at this line
  61.         self.interaction(frame, None)
  62.     
  63.     def user_return(self, frame, return_value):
  64.         # This function is called when a return trap is set here
  65.         frame.f_locals['__return__'] = return_value
  66.         print '--Return--'
  67.         self.interaction(frame, None)
  68.     
  69.     def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
  70.         # This function is called if an exception occurs,
  71.         # but only if we are to stop at or just below this level
  72.         frame.f_locals['__exception__'] = exc_type, exc_value
  73.         if type(exc_type) == type(''):
  74.             exc_type_name = exc_type
  75.         else: exc_type_name = exc_type.__name__
  76.         print exc_type_name + ':', repr.repr(exc_value)
  77.         self.interaction(frame, exc_traceback)
  78.     
  79.     # General interaction function
  80.     
  81.     def interaction(self, frame, traceback):
  82.         if self.running != 0:
  83.             self.setup(frame, traceback)
  84.             self.print_stack_entry(self.stack[self.curindex])
  85.             self.display.displayAny(self.curframe)
  86.             try:
  87.                 self.cmdloop()
  88.             except KeyboardInterrupt:
  89.                 self.do_kill(None)
  90.         self.latestbp = None    # Can forget it now that we're moving on
  91.         self.forget()
  92.  
  93.     def default(self, line):
  94.         if line[:1] == '!': line = line[1:]
  95.         # Try both the local and "outer" environments.
  96.         both = 0
  97.         try:
  98.             locals = self.curframe.f_locals
  99.             globals = self.curframe.f_globals
  100.             both = 1
  101.         except:
  102.             locals = self.outerlocals
  103.             globals = self.outerglobals
  104.         globals['__privileged__'] = 1
  105.         try:
  106.             code = compile(line + '\n', '<stdin>', 'single')
  107.             exec code in globals, locals
  108.         except:
  109.             if both:
  110.                 # Failed with current frame, so try 'outer' world.
  111.                 locals = self.outerlocals
  112.                 globals = self.outerglobals
  113.                 globals['__privileged__'] = 1
  114.                 try:
  115.                     code = compile(line + '\n', '<stdin>', 'single')
  116.                     exec code in globals, locals
  117.                 except:
  118.                     t, v = sys.exc_info()[:2]
  119.                     if type(t) == type(''):
  120.                         exc_type_name = t
  121.                     else: exc_type_name = t.__name__
  122.                     print '***', exc_type_name + ':', v
  123.             else:
  124.                 t, v = sys.exc_info()[:2]
  125.                 if type(t) == type(''):
  126.                     exc_type_name = t
  127.                 else: exc_type_name = t.__name__
  128.                 print '***', exc_type_name + ':', v
  129.  
  130.     # Override Bdb (note number of args is different)
  131.     def set_break(self, filename, lineno, temporary=0):
  132.         import linecache # Import as late as possible
  133.         line = linecache.getline(filename, lineno)
  134.         if not line:
  135.             return 'That line does not exist!'
  136.         if not self.breaks.has_key(filename):
  137.             self.breaks[filename] = []
  138.         list = self.breaks[filename]
  139.         if not lineno in list:
  140.             list.append(lineno)
  141.         bp = Breakpoint(filename, lineno, temporary)
  142.         print 'Breakpoint %d, at %s:%d.' %(bp.number, filename, lineno)
  143.     
  144.     # Override Bdb
  145.     def break_here(self, frame):
  146.         filename=frame.f_code.co_filename
  147.         if not self.breaks.has_key(filename):
  148.             return 0
  149.         lineno=frame.f_lineno
  150.         if not lineno in self.breaks[filename]:
  151.             return 0
  152.         # flag says ok to delete temp. bp
  153.         (bp, flag) = effective(filename, lineno, frame)
  154.         if bp:
  155.             self.latestbp = bp.number
  156.             if (flag and bp.temporary):
  157.                 self.do_delete(str(bp.number))
  158.             return 1
  159.         else:
  160.             return 0
  161.  
  162.     # Command definitions, called by cmdloop()
  163.     # The argument is the remaining string on the command line
  164.     # Return true to exit from the command loop 
  165.     
  166.     do_h = pydbcmd.Cmd.do_help
  167.  
  168.     def do_break(self, arg, temporary = 0):
  169.         if not arg:
  170.             print self.get_all_breaks()
  171.             return
  172.         f_l = string.split(arg, ':')
  173.         # Setting a breakpoint at func:line
  174.         if len(f_l) == 2:
  175.             filename = f_l[0]
  176.             lineno = int(f_l[1])
  177.             line = self.checkline(filename, lineno)
  178.             if line:
  179.                 # now set the break point
  180.                 err = self.set_break(filename, lineno, temporary)
  181.                 if err: print '***', err
  182.             return
  183.  
  184.         try:    
  185.             lineno = int(arg)
  186.             try:
  187.                 filename = self.curframe.f_code.co_filename
  188.             except:
  189.                 filename = self.filetodebug # not tracing yet
  190.         except:
  191.             # Try function name as the argument
  192.             try:
  193.                 func = arg
  194.                 if hasattr(func, 'im_func'):
  195.                     func = func.im_func
  196.                 code = func.func_code
  197.                 lineno = code.co_firstlineno
  198.                 filename = code.co_filename
  199.             except:
  200.                 # One more thing to try:
  201.                 answer = self.lineinfo("'" + arg + "'")
  202.                 if not answer[0]:
  203.                     print '*** The specified object "', arg,
  204.                     print '" is not a function'
  205.                     return
  206.                 (junk, filename, l) = answer
  207.                 lineno = int(l)
  208.         line = self.checkline(filename, lineno)
  209.         if line:
  210.             # now set the break point
  211.             err = self.set_break(filename, line, temporary)
  212.             if err: print '***', err
  213.         return
  214.  
  215.     do_b = do_break
  216.     
  217.     def do_tbreak(self, arg):
  218.         self.do_break(arg, 1)
  219.  
  220.     def checkline(self, filename, lineno):
  221.         """Return line number of first line at or after input argument
  222.         such that if the input points to a 'def', the returned line number
  223.         is the first non-blank/non-comment line to follow.  If the input
  224.         points to a blank or comment line, return 0.  At end of file,
  225.         also return 0."""
  226.  
  227.         line = linecache.getline(filename, lineno)
  228.         if not line:
  229.             print 'End of file'
  230.             return 0
  231.         line = string.strip(line)
  232.         # Don't allow setting breakpoint at a blank line
  233.         if ( not line or (line[0] == '#') or
  234.          (line[:3] == '"""') or line[:3] == "'''" ):
  235.             print '*** Blank or comment'
  236.             return 0
  237.         # When a file is read in and a breakpoint is at
  238.         # the 'def' statement, the system stops there at
  239.         # code parse time.  We don't want that, so all breakpoints
  240.         # set at 'def' statements are moved one line onward
  241.         if line[:3] == 'def':
  242.             incomment = ''
  243.             while 1:
  244.                 lineno = lineno+1
  245.                 line = linecache.getline(filename, lineno)
  246.                 if not line:
  247.                     print 'end of file'
  248.                     return 0
  249.                 line = string.strip(line)
  250.                 if incomment:
  251.                     if len(line) < 3: continue
  252.                     if (line[-3:] == incomment):
  253.                         incomment = ''
  254.                     continue
  255.                 if not line: continue    # Blank line
  256.                 if len(line) >= 3:
  257.                     if ( line[:3] == '"""' or line[:3] == "'''" ):
  258.                         incomment = line[:3]
  259.                         continue
  260.                 if line[0] != '#': break
  261.         return lineno
  262.  
  263.     def do_enable(self, arg):
  264.         args = string.split(arg)
  265.         if args[0] == 'display':
  266.             self.display_enable(args[1:], 1)
  267.             return
  268.         for i in args:
  269.             bp = Breakpoint.bpbynumber[int(i)]
  270.             if bp:
  271.                 bp.enable()
  272.  
  273.     def do_disable(self, arg):
  274.         args = string.split(arg)
  275.         if args[0] == 'display':
  276.             self.display_enable(args[1:], 0)
  277.             return
  278.         for i in args:
  279.             bp = Breakpoint.bpbynumber[int(i)]
  280.             if bp:
  281.                 bp.disable()
  282.  
  283.     def display_enable(self, arg, flag):
  284.         # arg is list of display points
  285.         for i in arg:
  286.             self.display.enable(int(i), flag)
  287.  
  288.     def do_condition(self, arg):
  289.         # arg is breakpoint number and condition
  290.         args = string.split(arg, ' ', 1)
  291.         bpnum = int(string.strip(args[0]))
  292.         try:
  293.             cond = args[1]
  294.         except:
  295.             cond = None
  296.         bp = Breakpoint.bpbynumber[bpnum]
  297.         if bp:
  298.             bp.cond = cond
  299.             if not cond:
  300.                 print 'Breakpoint %d is now unconditional.' % (bpnum,)
  301.  
  302.     def do_ignore(self,arg):
  303.         # arg is bp number followed by ignore count
  304.         args = string.split(arg)
  305.         bpnum = int(string.strip(args[0]))
  306.         try:
  307.             count = int(string.strip(args[1]))
  308.         except:
  309.             count = 0
  310.         bp = Breakpoint.bpbynumber[bpnum]
  311.         if bp:
  312.             bp.ignore = count
  313.             if (count > 0):
  314.                 reply = 'Will ignore next '
  315.                 if (count > 1):
  316.                     reply = reply + '%d crossings' % (count,)
  317.                 else:
  318.                     reply = reply + '1 crossing'
  319.                 print reply + ' of breakpoint %d.' % (bpnum,)
  320.             else:
  321.                 print 'Will stop next time breakpoint %d is reached.' % (bpnum,)
  322.  
  323.     def do_delete(self, arg):
  324.         # Delete from a list, or delete all if no arg
  325.         numberlist = string.split(arg)
  326.         if numberlist:
  327.             for i in numberlist:
  328.                 number = int(i)
  329.                 bp = Breakpoint.bpbynumber[number]
  330.                 filename = bp.file
  331.                 lineno = bp.line
  332.                 if not self.breaks.has_key(filename):
  333.                     return 'There are no breakpoints in that file!'
  334.                 if lineno not in self.breaks[filename]:
  335.                     return 'There is no breakpoint there!'
  336.                 # If there's only one bp in the list for that file,line
  337.                 # pair, then remove the breaks entry
  338.                 if len(Breakpoint.bplist[filename, lineno]) == 1:
  339.                     self.breaks[filename].remove(lineno)
  340.                 if not self.breaks[filename]:
  341.                     del self.breaks[filename]
  342.                 bp.deleteMe()
  343.                 print 'Deleted breakpoint %d ' % (number,)
  344.         else:  # delete them all
  345.             for bp in Breakpoint.bpbynumber:
  346.                 if bp:
  347.                     bp.deleteMe()
  348.             self.breaks = {}
  349.     
  350.     def do_where(self, arg):
  351.         if arg:
  352.             count = int(string.strip(arg))
  353.             # neg count possible ?? XXX
  354.         else:
  355.             count = 10000   # 'huge' number
  356.         # Last two frames are internal to debugger and don't
  357.         # get printed
  358.         for j in range(len(self.stack)-1, 1, -1):
  359.             self.frame_print(j)
  360.             count = count -1
  361.             if count == 0:
  362.                 break
  363.     do_w = do_where
  364.  
  365.     def frame_print(self, j):
  366.         prefix = '#%d ' % (len(self.stack) -1 - j,)
  367.         res = self.format_stack_entry(self.stack[j], prefix)
  368.         print string.split(res, '\n', 1)[0]
  369.  
  370.     def do_frame(self, arg):
  371.         if not arg:
  372.             self.frame_print(self.curindex)
  373.         else:
  374.             goto = int(string.strip(arg))
  375.             # Should never happen, but if you want to be sure:
  376.             # Replace -1 with -3 if limited to frames of debugged program
  377.             if (goto < 0 or goto > len(self.stack)-1):
  378.                 return
  379.             self.curindex = len(self.stack) - 1 - goto
  380.             self.curframe = self.stack[self.curindex][0]
  381.             self.frame_print(self.curindex)
  382.             self.lineno = None
  383.         
  384.     
  385.     def do_up(self, arg):
  386.         # Replace 0 with 2 if up is limited to frames of debugged program
  387.         if self.curindex == 2:
  388.             print 'Initial frame selected; you cannot go up.'
  389.         else:
  390.             self.curindex = self.curindex - 1
  391.             self.curframe = self.stack[self.curindex][0]
  392.             self.frame_print(self.curindex)
  393.             self.lineno = None
  394.     do_u = do_up
  395.     
  396.     def do_down(self, arg):
  397.         if self.curindex + 1 == len(self.stack):
  398.             print 'Bottom (i.e., innermost) frame selected; you cannot go down.'
  399.         else:
  400.             self.curindex = self.curindex + 1
  401.             self.curframe = self.stack[self.curindex][0]
  402.             self.frame_print(self.curindex)
  403.             self.lineno = None
  404.     do_d = do_down
  405.     
  406.     def do_step(self, arg):
  407.         self.set_step()
  408.         return 1
  409.     do_s = do_step
  410.     
  411.     def do_next(self, arg):
  412.         self.set_next(self.curframe)
  413.         return 1
  414.     do_n = do_next
  415.     
  416.     def do_return(self, arg):
  417.         self.set_return(self.curframe)
  418.         return 1
  419.     do_r = do_return
  420.     
  421.     def do_continue(self, arg):
  422.         self.set_continue()
  423.         return 1
  424.     do_c = do_cont = do_continue
  425.     
  426.     def do_quit(self, arg):
  427.         if self.running:
  428.             self.set_quit()
  429.             self.running = 0
  430.         self.alldie = 1
  431.         return 1
  432.     do_q = do_quit
  433.  
  434.     def do_kill(self, arg):
  435.         self.set_quit()
  436.         self.running = 0
  437.         return 1
  438.     do_k = do_kill
  439.     
  440.     def do_args(self, arg):
  441.         f = self.curframe
  442.         co = f.f_code
  443.         dict = f.f_locals
  444.         n = co.co_argcount
  445.         if co.co_flags & 4: n = n+1
  446.         if co.co_flags & 8: n = n+1
  447.         for i in range(n):
  448.             name = co.co_varnames[i]
  449.             print name, '=',
  450.             if dict.has_key(name): print dict[name]
  451.             else: print "*** undefined ***"
  452.     do_a = do_args
  453.     
  454.     def do_retval(self, arg):
  455.         if self.curframe.f_locals.has_key('__return__'):
  456.             print self.curframe.f_locals['__return__']
  457.         else:
  458.             print '*** Not yet returned!'
  459.     do_rv = do_retval
  460.     
  461.     def do_p(self, arg):
  462.         try:
  463.            l = self.curframe.f_locals
  464.            g = self.curframe.f_globals
  465.         except:
  466.            l = self.outerlocals
  467.            g = self.outerglobals
  468.         g['__privileged__'] = 1
  469.         try:
  470.             value = eval(arg, g, l)
  471.         except:
  472.             return
  473.  
  474.         print `value`
  475.  
  476.     def do_list(self, arg):
  477.         if self.filetodebug == "":
  478.             print 'No symbol table is loaded.  Use the "file" command.'
  479.             return
  480.         self.lastcmd = 'list'
  481.         last = None
  482.         if arg:
  483.             try:
  484.                 x = eval(arg, {}, {})
  485.                 if type(x) == type(()):
  486.                     first, last = x
  487.                     first = int(first)
  488.                     last = int(last)
  489.                     if last < first:
  490.                         # Assume it's a count
  491.                         last = first + last
  492.                 else:
  493.                     first = max(1, int(x) - 5)
  494.             except:
  495.                 print '*** Error in argument:', `arg`
  496.                 return
  497.         elif self.lineno is None:
  498.             if self.running == 0:
  499.                 first = 1
  500.             else:
  501.                 first = max(1, self.curframe.f_lineno - 5)
  502.         else:
  503.             first = self.lineno + 1
  504.         if last == None:
  505.             last = first + 10
  506.         if self.running == 0:
  507.             filename = self.filetodebug
  508.         else:
  509.             filename = self.curframe.f_code.co_filename
  510.         try:
  511.             for lineno in range(first, last+1):
  512.                 line = linecache.getline(filename, lineno)
  513.                 if not line:
  514.                     print '[EOF]'
  515.                     break
  516.                 else:
  517.                     s = string.rjust(`lineno`, 3)
  518.                     if len(s) < 4: s = s + ' '
  519.                     print s + '\t' + line,
  520.                     self.lineno = lineno
  521.         except KeyboardInterrupt:
  522.             pass
  523.     do_l = do_list
  524.  
  525.     def do_whatis(self, arg):
  526.         try:
  527.             value = eval(arg, self.curframe.f_globals, \
  528.                     self.curframe.f_locals)
  529.         except:
  530.             print 'No symbol "%s" in current context.' % (arg,)
  531.             return
  532.         code = None
  533.         # Is it a function?
  534.         try: code = value.func_code
  535.         except: pass
  536.         if code:
  537.             print 'type = Function', code.co_name
  538.             return
  539.         # Is it an instance method?
  540.         try: code = value.im_func.func_code
  541.         except: pass
  542.         if code:
  543.             print 'type = Method', code.co_name
  544.             return
  545.         # None of the above...
  546.         print 'type = ' + type(value)
  547.     do_ptype = do_whatis
  548.     
  549.     # Print a traceback starting at the top stack frame.
  550.     # The most recently entered frame is printed last;
  551.     # this is different from dbx and gdb, but consistent with
  552.     # the Python interpreter's stack trace.
  553.     # It is also consistent with the up/down commands (which are
  554.     # compatible with dbx and gdb: up moves towards 'main()'
  555.     # and down moves towards the most recent stack frame).
  556.     
  557.     def print_stack_trace(self):
  558.         try:
  559.             for frame_lineno in self.stack:
  560.                 self.print_stack_entry(frame_lineno)
  561.         except KeyboardInterrupt:
  562.             pass
  563.     
  564.     def print_stack_entry(self, frame_lineno, prompt_prefix=line_prefix):
  565.         frame, lineno = frame_lineno
  566.         prefix = ""
  567.         if not self.stop_here(frame) and self.latestbp:
  568.             prefix = "Breakpoint %d, "% (self.latestbp,)
  569.         print self.format_stack_entry(frame_lineno, prefix)
  570.  
  571.     def format_stack_entry(self, frame_lineno, prefix=""):
  572.         import linecache, repr, string
  573.         frame, lineno = frame_lineno
  574.         filename = frame.f_code.co_filename
  575.         s = ' at ' + filename + ':' + `lineno`
  576.         if frame.f_code.co_name:
  577.             f = frame.f_code.co_name
  578.         else:
  579.             f = "<lambda>"
  580.         if frame.f_locals.has_key('__args__'):
  581.             args = frame.f_locals['__args__']
  582.         else:
  583.             args = None
  584.         if args:
  585.             a = '(' + repr.repr(args) + ')'
  586.         else:
  587.             a = '()'
  588.         first_line = prefix + f + a + s + '\n'
  589.         # Don't want the ?() at <string>:  line printed out; confuses ddd
  590.         if first_line[:15] == '?() at <string>':
  591.             return 'Issue "continue" command'
  592.         second_line = `lineno` + '    ' 
  593.         line = linecache.getline(filename, lineno)
  594.         if line: second_line = second_line + string.strip(line)
  595.         result = first_line + second_line
  596.         if frame.f_locals.has_key('__return__'):
  597.             rv = frame.f_locals['__return__']
  598.             third_line = 'Value returned is $1 = ' + repr.repr(rv)
  599.             result = result + '\n' + third_line
  600.         return result
  601.     
  602.     def do_info(self,args):
  603.         arglist = string.split(args)
  604.         arg = arglist[0]
  605.         if arg == 'program':
  606.             if not self.running:
  607.                 print 'The program being debugged is not being run.'
  608.             else:
  609.                 print 'Program stopped.\n'
  610.                 if self.latestbp:
  611.                     print 'It stopped at breakpoint %d.' % (self.latestbp,)
  612.             return
  613.         if arg == 'line':
  614.             #info line identifier
  615.             if len(arglist) == 2:
  616.                 # lineinfo returns (item, file, lineno) or (None,)
  617.                 answer = self.lineinfo(arglist[1])
  618.                 if answer[0]:
  619.                     print 'Lineinfo <%s> at %s:%s' % answer
  620.                 return
  621.             #info line
  622.             if self.lineno == None:
  623.                 try:
  624.                     file = self.curframe.f_code.co_filename
  625.                     line = self.curframe.f_lineno
  626.                     print 'Line %s of "%s"' % (line, file)
  627.                 except:
  628.                     print 'No line number information available.'
  629.             else:
  630.                 print 'Line %s of "%s"' %\
  631.                     (self.lineno, self.curframe.f_code.co_filename)
  632.             return
  633.         if arg == 'files':
  634.             if self.filetodebug == "":
  635.                 pass
  636.             else:
  637.                 print 'Symbols from "%s".' % (self.filetodebug,)
  638.             return
  639.         if arg == 'breakpoints':
  640.             any = 0
  641.             for b in Breakpoint.bpbynumber:
  642.                 if b:
  643.                     if not any:
  644.                         print "Num Type           Disp Enb Where"
  645.                     any = 1
  646.                     b.bpprint()
  647.             if not any:
  648.                 print 'No breakpoints or watchpoints.'
  649.             return
  650.         if arg == 'display':
  651.             if not self.display.displayAll():
  652.                 print 'There are no auto-display expressions now.'
  653.             return
  654.         print 'Undefined info command: "'+arg+'".  Try "help info".'
  655.  
  656.     def lineinfo(self, identifier):
  657.         # Input is identifier in single quotes
  658.         idstring = string.split(identifier, "'")
  659.         if len(idstring) == 1:
  660.             # not in single quotes
  661.             id = string.strip(idstring[0])
  662.         elif len(idstring) == 3:
  663.             # quoted
  664.             id = string.strip(idstring[1])
  665.         else:
  666.             return (None,)
  667.         if id == '': return (None,)
  668.         parts = string.split(id, '.')
  669.         if parts[0] == 'self':
  670.             # What could we do here?
  671.             return (None,)
  672.         # Best first guess at file to look at
  673.         try:
  674.             fname = self.curframe.f_code.co_filename
  675.         except:
  676.             fname = self.filetodebug # not tracing yet
  677.         if len(parts) == 1:
  678.             item = parts[0]
  679.         else:
  680.             # more than one part.  First is module, second is method/class
  681.             module = parts[0] + '.py'
  682.             item = parts[1]
  683.             for dirname in sys.path:
  684.                 while os.path.islink(dirname):
  685.                     dirname = os.readlink(dirname)
  686.                 fname = os.path.join(dirname, module)
  687.                 if os.path.exists(fname):
  688.                     break    # take the first
  689.         grepstring = 'egrep -n "(def|class) *%s *[(:]" %s /dev/null' % (item, fname)
  690.         answer = os.popen(grepstring, 'r').readline()
  691.         if answer:
  692.             f, line, junk = string.split(answer, ':', 2)
  693.             return(item, f,line)
  694.         else:
  695.             return (None,)
  696.  
  697.     def do_run(self, arg):
  698.         # if running, clean up by killing up to outer loop and then run
  699.         if self.running:
  700.            self.cmdqueue = ['k', 'k', 'run '+arg]
  701.            return
  702.         print 'Starting program:'
  703.         if self.filetodebug == "":
  704.            print 'No executable file specified.'
  705.            return
  706.         oldp = self.prompt
  707.         self.prompt = '(pydb) '
  708.         # Mark running, reset command count
  709.         self.running = 1
  710.         # Clear hit counts on breakpoints
  711.         for b in Breakpoint.bpbynumber:
  712.             if b:
  713.                 b.hits = 0
  714.         oldarg = sys.argv
  715.         argv = [self.filetodebug]
  716.         if arg:
  717.             args = string.split(arg)
  718.             argv = argv + args
  719.         sys.argv = argv
  720.         self.run('execfile(' + `self.filetodebug` + ')',
  721.                {'__name__': '__main__'})
  722.         sys.argv = oldarg
  723.         self.prompt = oldp
  724.  
  725.     def do_file(self, fname):
  726.         if fname == "":
  727.             if self.filetodebug == "":
  728.                 print 'No exec file now.\nNo symbol file now.'
  729.                 return
  730.             else:
  731.                 # should confirm this per
  732.                 #Discard symbol table from `/work/.../ddd/cxxtest'? (y or n) n
  733.                 # XXX 
  734.                 # del module
  735.                 sys.path = self.originalpath[:]
  736.                 self.filetodebug == ""
  737.         else:
  738.             path, module = os.path.split(fname)
  739.             module = string.split(module, '.')[0]
  740.             sys.path = self.originalpath[:]
  741.             sys.path.insert(0, path)
  742.             # XXX how to clean up name space ??
  743.             if self.moduletodebug:
  744.                 try:
  745.                     # del self.moduletodebug
  746.                     self.moduletodebug = ''
  747.                 except:
  748.                     pass
  749.             line = "import " + module + '\n'
  750.             code = compile(line, '<stdin>', 'single')
  751.             exec code in self.outerglobals, self.outerlocals
  752.             # Could print 'Reading symbols from fname...done.' for gdb conformance
  753.             self.filetodebug = fname
  754.             self.moduletodebug = module
  755.  
  756.     # Ultimately for interrogating settable attributes of the debugger
  757.     def do_show(self, arg):
  758.         if arg == 'language':
  759.             print 'The current source language is "auto; currently python".'
  760.  
  761.     def do_pwd(self, arg):
  762.         print 'Working directory ' + os.getcwd() + '.'
  763.  
  764.     def do_cd(self, arg):
  765.         if arg == '':
  766.            do_pwd(arg)
  767.         else:
  768.            os.chdir(arg)
  769.         return
  770.  
  771.     def do_display(self, arg):
  772.         if not arg:
  773.             # Display anything active
  774.             self.display.displayAny(self.curframe)
  775.         else:
  776.             # Set up a display
  777.             arglist = string.split(arg)
  778.             if len(arglist) == 2:
  779.                (format, variable) = tuple(arglist)
  780.             else:
  781.                format = ""
  782.                variable = arglist[0]
  783.             dp = DisplayNode(self.curframe, variable, format)
  784.             res = dp.checkValid(self.curframe)
  785.             print res
  786.         return
  787.     
  788.     def do_undisplay(self, arg):
  789.         args = string.split(arg)
  790.         for i in args:
  791.             self.display.deleteOne(int(i))
  792.  
  793.     # Help methods (originally derived from pdb.doc)
  794.  
  795.     def help_help(self):
  796.         self.help_h()
  797.  
  798.     def help_h(self):
  799.         print """h(elp)
  800.     Without argument, print the list of available commands.
  801.     With a command name as argument, print help about that command.
  802.     "help exec" gives help on the ! command"""
  803.  
  804.     def help_where(self):
  805.         self.help_w()
  806.  
  807.     def help_w(self):
  808.         print """w(here)
  809.     Print a stack trace, with the most recent frame at the bottom."""
  810.  
  811.     def help_down(self):
  812.         self.help_d()
  813.  
  814.     def help_d(self):
  815.         print """d(own)
  816.     Move the current frame one level down in the stack trace
  817.     (to an older frame)."""
  818.  
  819.     def help_up(self):
  820.         self.help_u()
  821.  
  822.     def help_u(self):
  823.         print """u(p)
  824.     Move the current frame one level up in the stack trace
  825.     (to a newer frame)."""
  826.  
  827.     def help_break(self):
  828.         self.help_b()
  829.  
  830.     def help_b(self):
  831.         print """b(reak) [file:lineno] [lineno | method]
  832.     With a line number argument, set a break there in the current
  833.     or specified file.  With a method name, set a break at the first
  834.     executable line after the 'def'.  Without argument, list all breaks."""
  835.  
  836.     def help_tbreak(self):
  837.         print """tbreak  same arguments as break, but breakpoint is
  838.     removed when first hit."""
  839.  
  840.     def help_delete(self):
  841.         print """delete [bpnumbers]
  842.     With a space separated list of breakpoint numbers, deletes
  843.     those breakpoints.  Without the argument, deletes all breakpoints."""
  844.  
  845.     def help_enable(self):
  846.         print """enable [display] bpnumber
  847.     Enables the breakpoints given as a space separated list of bp numbers.
  848.     If the word 'display' is present, the indicated display(s) is/are
  849.     enabled."""
  850.  
  851.     def help_disable(self):
  852.         print """disable [display] bpnumber
  853.     Disables the breakpoints given as a space separated list of bp numbers.
  854.     If the word 'display' is present, the indicated display(s) is/are
  855.     disabled."""
  856.  
  857.     def help_ignore(self):
  858.         print """ignore bpnumber count
  859.     Sets the ignore count for the given breakpoint number.  A breakpoint
  860.     becomes active when the ignore count is zero.  When non-zero, the
  861.     count is decremented each time the breakpoint is reached and the
  862.     breakpoint is not disabled and any associated condition evaluates
  863.     to true."""
  864.  
  865.     def help_condition(self):
  866.         print """condition bpnumber str_condition
  867.     str_condition is a string specifying an expression which
  868.     must evaluate to true before the breakpoint is honored.
  869.     If str_condition is absent, any existing condition is removed;
  870.     i.e., the breakpoint is made unconditional."""
  871.  
  872.     def help_step(self):
  873.         self.help_s()
  874.  
  875.     def help_s(self):
  876.         print """s(tep)
  877.     Execute the current line, stop at the first possible occasion
  878.     (either in a function that is called or in the current function)."""
  879.  
  880.     def help_next(self):
  881.         self.help_n()
  882.  
  883.     def help_n(self):
  884.         print """n(ext)
  885.     Continue execution until the next line in the current function
  886.     is reached or it returns."""
  887.  
  888.     def help_return(self):
  889.         self.help_r()
  890.  
  891.     def help_r(self):
  892.         print """r(eturn)
  893.     Continue execution until the current function returns."""
  894.  
  895.     def help_continue(self):
  896.         self.help_c()
  897.  
  898.     def help_cont(self):
  899.         self.help_c()
  900.  
  901.     def help_c(self):
  902.         print """c(ont(inue))
  903.     Continue execution, only stop when a breakpoint is encountered."""
  904.  
  905.     def help_list(self):
  906.         self.help_l()
  907.  
  908.     def help_l(self):
  909.         print """l(ist) [first [,last]]
  910.     List source code for the current file.
  911.     Without arguments, list 11 lines around the current line
  912.     or continue the previous listing.
  913.     With one argument, list 11 lines starting at that line.
  914.     With two arguments, list the given range;
  915.     if the second argument is less than the first, it is a count."""
  916.  
  917.     def help_args(self):
  918.         self.help_a()
  919.  
  920.     def help_a(self):
  921.         print """a(rgs)
  922.     Print the arguments of the current function."""
  923.  
  924.     def help_p(self):
  925.         print """p expression
  926.     Print the value of the expression."""
  927.  
  928.     def help_exec(self):
  929.         print """(!) statement
  930.     Execute the (one-line) statement in the context of
  931.     the current stack frame.
  932.     The exclamation point can be omitted unless the first word
  933.     of the statement resembles a debugger command.
  934.     To assign to a global variable you must always prefix the
  935.     command with a 'global' command, e.g.:
  936.     (Pdb) global list_options; list_options = ['-l']
  937.     (Pdb)"""
  938.  
  939.     def help_quit(self):
  940.         self.help_q()
  941.  
  942.     def help_q(self):
  943.         print """Quit from the debugger."""
  944.  
  945.     def help_kill(self):
  946.         self.help_k()
  947.  
  948.     def help_k(self):
  949.         print """Kill the program being debugged
  950.     The program being executed is aborted."""
  951.  
  952.     def help_info(self):
  953.         print """Generic command for showing things about the program being debugged.
  954.  
  955.         List of info subcommands:
  956.  
  957.         info program     -- Execution status of the program
  958.         info line        -- If "info line arg", line number and full path to file containing
  959.                             'def' for arg; if arg omitted, display where currently stopped.
  960.         info display     -- Expressions to display when program stops
  961.         info breakpoints -- Status of user-settable breakpoints
  962.         info files       -- Names of targets and files being debugged"""
  963.  
  964.     def help_show(self):
  965.         print """Generic command for showing things about the debugger.
  966.  
  967.         List of show subcommands:
  968.  
  969.         show language -- Show the current source language """
  970.  
  971.     def help_cd(self):
  972.         print 'Change to directory specified by argument.'
  973.  
  974.     def help_display(self):
  975.         print """display [format] expression
  976.         Displays the value of the expression whenever the program stops at
  977.         a breakpoint and the expression is valid in the current namespace
  978.         which must be the one in which the display command was issued.
  979.         Format is /a where a is one of[xotfcs] for hex, octal, binary (twos),
  980.         float, chr and string."""
  981.  
  982.     def help_undisplay(self):
  983.         print """undisplay dnumber
  984.         Delete the displays listed in the space separated list dnumber."""
  985.  
  986.     def help_file(self):
  987.         print """Use 'file' as the program to be debugged.  It is the
  988.         program executed when you use the 'run' command."""
  989.     
  990.     def help_frame(self):
  991.         print """frame [arg]
  992.         Prints the current frame location if no argument is given;
  993.         Changes to the frame 'arg' if 'arg' is present.  Frame 0 is
  994.         the newest one."""
  995.  
  996.     def help_pwd(self):
  997.         print 'Print working directory.'
  998.  
  999.     def help_run(self):
  1000.         print """run [arg1 [arg2 [...]]]
  1001.         Run the program to be debugged.  Arguments
  1002.         are space separated and are inserted into sys.argv
  1003.         following the file name from the 'file' command, all
  1004.         for the delectation of the program under study."""
  1005.     
  1006.     def help_whatis(self):
  1007.         print """whatis arg
  1008.         Prints the type of the argument."""
  1009.  
  1010.     def help_ptype(self):
  1011.         print """ptype arg
  1012.         Prints the type of the argument."""
  1013.  
  1014.     help_pydb = help_help
  1015.  
  1016. # Simplified interface
  1017.  
  1018. def run(statement, globals=None, locals=None):
  1019.     Pdb().run(statement, globals, locals)
  1020.  
  1021. def runeval(expression, globals=None, locals=None):
  1022.     return Pdb().runeval(expression, globals, locals)
  1023.  
  1024. def runctx(statement, globals, locals):
  1025.     # B/W compatibility
  1026.     run(statement, globals, locals)
  1027.  
  1028. def runcall(*args):
  1029.     return apply(Pdb().runcall, args)
  1030.  
  1031. def set_trace():
  1032.     Pdb().set_trace()
  1033.  
  1034. # Post-Mortem interface
  1035.  
  1036. def post_mortem(t):
  1037.     p = Pdb()
  1038.     p.reset()
  1039.     while t.tb_next <> None: t = t.tb_next
  1040.     p.interaction(t.tb_frame, t)
  1041.  
  1042. def pm():
  1043.     import sys
  1044.     post_mortem(sys.last_traceback)
  1045.  
  1046.  
  1047. # When invoked as main program, invoke the debugger on a script
  1048. if __name__=='__main__':
  1049.     import sys
  1050.     import os
  1051.  
  1052.     outer = Pdb()
  1053.     outer.prompt = "(Pdb) "
  1054.     outer.alldie = 0
  1055.     outer.display = Display()
  1056.     outer.reset()
  1057.     outer.originalpath = sys.path[:]
  1058.     while not outer.alldie:
  1059.         try:
  1060.           1 + ''
  1061.         except:
  1062.           frame = sys.exc_info()[2].tb_frame
  1063.           outer.outerlocals = frame.f_locals
  1064.           outer.outerglobals = frame.f_locals
  1065.         try:
  1066.             outer.cmdloop()
  1067.         except AttributeError, msg:
  1068.             print "Invalid command in outer loop: %s\n" % (msg,)
  1069.         except KeyboardInterrupt:
  1070.             pass
  1071.