symbian-qemu-0.9.1-12/python-win32-2.6.1/lib/bdb.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """Debugger basics"""
       
     2 
       
     3 import sys
       
     4 import os
       
     5 import types
       
     6 
       
     7 __all__ = ["BdbQuit","Bdb","Breakpoint"]
       
     8 
       
     9 class BdbQuit(Exception):
       
    10     """Exception to give up completely"""
       
    11 
       
    12 
       
    13 class Bdb:
       
    14 
       
    15     """Generic Python debugger base class.
       
    16 
       
    17     This class takes care of details of the trace facility;
       
    18     a derived class should implement user interaction.
       
    19     The standard debugger class (pdb.Pdb) is an example.
       
    20     """
       
    21 
       
    22     def __init__(self):
       
    23         self.breaks = {}
       
    24         self.fncache = {}
       
    25 
       
    26     def canonic(self, filename):
       
    27         if filename == "<" + filename[1:-1] + ">":
       
    28             return filename
       
    29         canonic = self.fncache.get(filename)
       
    30         if not canonic:
       
    31             canonic = os.path.abspath(filename)
       
    32             canonic = os.path.normcase(canonic)
       
    33             self.fncache[filename] = canonic
       
    34         return canonic
       
    35 
       
    36     def reset(self):
       
    37         import linecache
       
    38         linecache.checkcache()
       
    39         self.botframe = None
       
    40         self._set_stopinfo(None, None)
       
    41 
       
    42     def trace_dispatch(self, frame, event, arg):
       
    43         if self.quitting:
       
    44             return # None
       
    45         if event == 'line':
       
    46             return self.dispatch_line(frame)
       
    47         if event == 'call':
       
    48             return self.dispatch_call(frame, arg)
       
    49         if event == 'return':
       
    50             return self.dispatch_return(frame, arg)
       
    51         if event == 'exception':
       
    52             return self.dispatch_exception(frame, arg)
       
    53         if event == 'c_call':
       
    54             return self.trace_dispatch
       
    55         if event == 'c_exception':
       
    56             return self.trace_dispatch
       
    57         if event == 'c_return':
       
    58             return self.trace_dispatch
       
    59         print 'bdb.Bdb.dispatch: unknown debugging event:', repr(event)
       
    60         return self.trace_dispatch
       
    61 
       
    62     def dispatch_line(self, frame):
       
    63         if self.stop_here(frame) or self.break_here(frame):
       
    64             self.user_line(frame)
       
    65             if self.quitting: raise BdbQuit
       
    66         return self.trace_dispatch
       
    67 
       
    68     def dispatch_call(self, frame, arg):
       
    69         # XXX 'arg' is no longer used
       
    70         if self.botframe is None:
       
    71             # First call of dispatch since reset()
       
    72             self.botframe = frame.f_back # (CT) Note that this may also be None!
       
    73             return self.trace_dispatch
       
    74         if not (self.stop_here(frame) or self.break_anywhere(frame)):
       
    75             # No need to trace this function
       
    76             return # None
       
    77         self.user_call(frame, arg)
       
    78         if self.quitting: raise BdbQuit
       
    79         return self.trace_dispatch
       
    80 
       
    81     def dispatch_return(self, frame, arg):
       
    82         if self.stop_here(frame) or frame == self.returnframe:
       
    83             self.user_return(frame, arg)
       
    84             if self.quitting: raise BdbQuit
       
    85         return self.trace_dispatch
       
    86 
       
    87     def dispatch_exception(self, frame, arg):
       
    88         if self.stop_here(frame):
       
    89             self.user_exception(frame, arg)
       
    90             if self.quitting: raise BdbQuit
       
    91         return self.trace_dispatch
       
    92 
       
    93     # Normally derived classes don't override the following
       
    94     # methods, but they may if they want to redefine the
       
    95     # definition of stopping and breakpoints.
       
    96 
       
    97     def stop_here(self, frame):
       
    98         # (CT) stopframe may now also be None, see dispatch_call.
       
    99         # (CT) the former test for None is therefore removed from here.
       
   100         if frame is self.stopframe:
       
   101             return frame.f_lineno >= self.stoplineno
       
   102         while frame is not None and frame is not self.stopframe:
       
   103             if frame is self.botframe:
       
   104                 return True
       
   105             frame = frame.f_back
       
   106         return False
       
   107 
       
   108     def break_here(self, frame):
       
   109         filename = self.canonic(frame.f_code.co_filename)
       
   110         if not filename in self.breaks:
       
   111             return False
       
   112         lineno = frame.f_lineno
       
   113         if not lineno in self.breaks[filename]:
       
   114             # The line itself has no breakpoint, but maybe the line is the
       
   115             # first line of a function with breakpoint set by function name.
       
   116             lineno = frame.f_code.co_firstlineno
       
   117             if not lineno in self.breaks[filename]:
       
   118                 return False
       
   119 
       
   120         # flag says ok to delete temp. bp
       
   121         (bp, flag) = effective(filename, lineno, frame)
       
   122         if bp:
       
   123             self.currentbp = bp.number
       
   124             if (flag and bp.temporary):
       
   125                 self.do_clear(str(bp.number))
       
   126             return True
       
   127         else:
       
   128             return False
       
   129 
       
   130     def do_clear(self, arg):
       
   131         raise NotImplementedError, "subclass of bdb must implement do_clear()"
       
   132 
       
   133     def break_anywhere(self, frame):
       
   134         return self.canonic(frame.f_code.co_filename) in self.breaks
       
   135 
       
   136     # Derived classes should override the user_* methods
       
   137     # to gain control.
       
   138 
       
   139     def user_call(self, frame, argument_list):
       
   140         """This method is called when there is the remote possibility
       
   141         that we ever need to stop in this function."""
       
   142         pass
       
   143 
       
   144     def user_line(self, frame):
       
   145         """This method is called when we stop or break at this line."""
       
   146         pass
       
   147 
       
   148     def user_return(self, frame, return_value):
       
   149         """This method is called when a return trap is set here."""
       
   150         pass
       
   151 
       
   152     def user_exception(self, frame, exc_info):
       
   153         exc_type, exc_value, exc_traceback = exc_info
       
   154         """This method is called if an exception occurs,
       
   155         but only if we are to stop at or just below this level."""
       
   156         pass
       
   157 
       
   158     def _set_stopinfo(self, stopframe, returnframe, stoplineno=-1):
       
   159         self.stopframe = stopframe
       
   160         self.returnframe = returnframe
       
   161         self.quitting = 0
       
   162         self.stoplineno = stoplineno
       
   163 
       
   164     # Derived classes and clients can call the following methods
       
   165     # to affect the stepping state.
       
   166 
       
   167     def set_until(self, frame): #the name "until" is borrowed from gdb
       
   168         """Stop when the line with the line no greater than the current one is
       
   169         reached or when returning from current frame"""
       
   170         self._set_stopinfo(frame, frame, frame.f_lineno+1)
       
   171 
       
   172     def set_step(self):
       
   173         """Stop after one line of code."""
       
   174         self._set_stopinfo(None,None)
       
   175 
       
   176     def set_next(self, frame):
       
   177         """Stop on the next line in or below the given frame."""
       
   178         self._set_stopinfo(frame, None)
       
   179 
       
   180     def set_return(self, frame):
       
   181         """Stop when returning from the given frame."""
       
   182         self._set_stopinfo(frame.f_back, frame)
       
   183 
       
   184     def set_trace(self, frame=None):
       
   185         """Start debugging from `frame`.
       
   186 
       
   187         If frame is not specified, debugging starts from caller's frame.
       
   188         """
       
   189         if frame is None:
       
   190             frame = sys._getframe().f_back
       
   191         self.reset()
       
   192         while frame:
       
   193             frame.f_trace = self.trace_dispatch
       
   194             self.botframe = frame
       
   195             frame = frame.f_back
       
   196         self.set_step()
       
   197         sys.settrace(self.trace_dispatch)
       
   198 
       
   199     def set_continue(self):
       
   200         # Don't stop except at breakpoints or when finished
       
   201         self._set_stopinfo(self.botframe, None)
       
   202         if not self.breaks:
       
   203             # no breakpoints; run without debugger overhead
       
   204             sys.settrace(None)
       
   205             frame = sys._getframe().f_back
       
   206             while frame and frame is not self.botframe:
       
   207                 del frame.f_trace
       
   208                 frame = frame.f_back
       
   209 
       
   210     def set_quit(self):
       
   211         self.stopframe = self.botframe
       
   212         self.returnframe = None
       
   213         self.quitting = 1
       
   214         sys.settrace(None)
       
   215 
       
   216     # Derived classes and clients can call the following methods
       
   217     # to manipulate breakpoints.  These methods return an
       
   218     # error message is something went wrong, None if all is well.
       
   219     # Set_break prints out the breakpoint line and file:lineno.
       
   220     # Call self.get_*break*() to see the breakpoints or better
       
   221     # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().
       
   222 
       
   223     def set_break(self, filename, lineno, temporary=0, cond = None,
       
   224                   funcname=None):
       
   225         filename = self.canonic(filename)
       
   226         import linecache # Import as late as possible
       
   227         line = linecache.getline(filename, lineno)
       
   228         if not line:
       
   229             return 'Line %s:%d does not exist' % (filename,
       
   230                                    lineno)
       
   231         if not filename in self.breaks:
       
   232             self.breaks[filename] = []
       
   233         list = self.breaks[filename]
       
   234         if not lineno in list:
       
   235             list.append(lineno)
       
   236         bp = Breakpoint(filename, lineno, temporary, cond, funcname)
       
   237 
       
   238     def clear_break(self, filename, lineno):
       
   239         filename = self.canonic(filename)
       
   240         if not filename in self.breaks:
       
   241             return 'There are no breakpoints in %s' % filename
       
   242         if lineno not in self.breaks[filename]:
       
   243             return 'There is no breakpoint at %s:%d' % (filename,
       
   244                                     lineno)
       
   245         # If there's only one bp in the list for that file,line
       
   246         # pair, then remove the breaks entry
       
   247         for bp in Breakpoint.bplist[filename, lineno][:]:
       
   248             bp.deleteMe()
       
   249         if not Breakpoint.bplist.has_key((filename, lineno)):
       
   250             self.breaks[filename].remove(lineno)
       
   251         if not self.breaks[filename]:
       
   252             del self.breaks[filename]
       
   253 
       
   254     def clear_bpbynumber(self, arg):
       
   255         try:
       
   256             number = int(arg)
       
   257         except:
       
   258             return 'Non-numeric breakpoint number (%s)' % arg
       
   259         try:
       
   260             bp = Breakpoint.bpbynumber[number]
       
   261         except IndexError:
       
   262             return 'Breakpoint number (%d) out of range' % number
       
   263         if not bp:
       
   264             return 'Breakpoint (%d) already deleted' % number
       
   265         self.clear_break(bp.file, bp.line)
       
   266 
       
   267     def clear_all_file_breaks(self, filename):
       
   268         filename = self.canonic(filename)
       
   269         if not filename in self.breaks:
       
   270             return 'There are no breakpoints in %s' % filename
       
   271         for line in self.breaks[filename]:
       
   272             blist = Breakpoint.bplist[filename, line]
       
   273             for bp in blist:
       
   274                 bp.deleteMe()
       
   275         del self.breaks[filename]
       
   276 
       
   277     def clear_all_breaks(self):
       
   278         if not self.breaks:
       
   279             return 'There are no breakpoints'
       
   280         for bp in Breakpoint.bpbynumber:
       
   281             if bp:
       
   282                 bp.deleteMe()
       
   283         self.breaks = {}
       
   284 
       
   285     def get_break(self, filename, lineno):
       
   286         filename = self.canonic(filename)
       
   287         return filename in self.breaks and \
       
   288             lineno in self.breaks[filename]
       
   289 
       
   290     def get_breaks(self, filename, lineno):
       
   291         filename = self.canonic(filename)
       
   292         return filename in self.breaks and \
       
   293             lineno in self.breaks[filename] and \
       
   294             Breakpoint.bplist[filename, lineno] or []
       
   295 
       
   296     def get_file_breaks(self, filename):
       
   297         filename = self.canonic(filename)
       
   298         if filename in self.breaks:
       
   299             return self.breaks[filename]
       
   300         else:
       
   301             return []
       
   302 
       
   303     def get_all_breaks(self):
       
   304         return self.breaks
       
   305 
       
   306     # Derived classes and clients can call the following method
       
   307     # to get a data structure representing a stack trace.
       
   308 
       
   309     def get_stack(self, f, t):
       
   310         stack = []
       
   311         if t and t.tb_frame is f:
       
   312             t = t.tb_next
       
   313         while f is not None:
       
   314             stack.append((f, f.f_lineno))
       
   315             if f is self.botframe:
       
   316                 break
       
   317             f = f.f_back
       
   318         stack.reverse()
       
   319         i = max(0, len(stack) - 1)
       
   320         while t is not None:
       
   321             stack.append((t.tb_frame, t.tb_lineno))
       
   322             t = t.tb_next
       
   323         if f is None:
       
   324             i = max(0, len(stack) - 1)
       
   325         return stack, i
       
   326 
       
   327     #
       
   328 
       
   329     def format_stack_entry(self, frame_lineno, lprefix=': '):
       
   330         import linecache, repr
       
   331         frame, lineno = frame_lineno
       
   332         filename = self.canonic(frame.f_code.co_filename)
       
   333         s = '%s(%r)' % (filename, lineno)
       
   334         if frame.f_code.co_name:
       
   335             s = s + frame.f_code.co_name
       
   336         else:
       
   337             s = s + "<lambda>"
       
   338         if '__args__' in frame.f_locals:
       
   339             args = frame.f_locals['__args__']
       
   340         else:
       
   341             args = None
       
   342         if args:
       
   343             s = s + repr.repr(args)
       
   344         else:
       
   345             s = s + '()'
       
   346         if '__return__' in frame.f_locals:
       
   347             rv = frame.f_locals['__return__']
       
   348             s = s + '->'
       
   349             s = s + repr.repr(rv)
       
   350         line = linecache.getline(filename, lineno)
       
   351         if line: s = s + lprefix + line.strip()
       
   352         return s
       
   353 
       
   354     # The following two methods can be called by clients to use
       
   355     # a debugger to debug a statement, given as a string.
       
   356 
       
   357     def run(self, cmd, globals=None, locals=None):
       
   358         if globals is None:
       
   359             import __main__
       
   360             globals = __main__.__dict__
       
   361         if locals is None:
       
   362             locals = globals
       
   363         self.reset()
       
   364         sys.settrace(self.trace_dispatch)
       
   365         if not isinstance(cmd, types.CodeType):
       
   366             cmd = cmd+'\n'
       
   367         try:
       
   368             exec cmd in globals, locals
       
   369         except BdbQuit:
       
   370             pass
       
   371         finally:
       
   372             self.quitting = 1
       
   373             sys.settrace(None)
       
   374 
       
   375     def runeval(self, expr, globals=None, locals=None):
       
   376         if globals is None:
       
   377             import __main__
       
   378             globals = __main__.__dict__
       
   379         if locals is None:
       
   380             locals = globals
       
   381         self.reset()
       
   382         sys.settrace(self.trace_dispatch)
       
   383         if not isinstance(expr, types.CodeType):
       
   384             expr = expr+'\n'
       
   385         try:
       
   386             return eval(expr, globals, locals)
       
   387         except BdbQuit:
       
   388             pass
       
   389         finally:
       
   390             self.quitting = 1
       
   391             sys.settrace(None)
       
   392 
       
   393     def runctx(self, cmd, globals, locals):
       
   394         # B/W compatibility
       
   395         self.run(cmd, globals, locals)
       
   396 
       
   397     # This method is more useful to debug a single function call.
       
   398 
       
   399     def runcall(self, func, *args, **kwds):
       
   400         self.reset()
       
   401         sys.settrace(self.trace_dispatch)
       
   402         res = None
       
   403         try:
       
   404             res = func(*args, **kwds)
       
   405         except BdbQuit:
       
   406             pass
       
   407         finally:
       
   408             self.quitting = 1
       
   409             sys.settrace(None)
       
   410         return res
       
   411 
       
   412 
       
   413 def set_trace():
       
   414     Bdb().set_trace()
       
   415 
       
   416 
       
   417 class Breakpoint:
       
   418 
       
   419     """Breakpoint class
       
   420 
       
   421     Implements temporary breakpoints, ignore counts, disabling and
       
   422     (re)-enabling, and conditionals.
       
   423 
       
   424     Breakpoints are indexed by number through bpbynumber and by
       
   425     the file,line tuple using bplist.  The former points to a
       
   426     single instance of class Breakpoint.  The latter points to a
       
   427     list of such instances since there may be more than one
       
   428     breakpoint per line.
       
   429 
       
   430     """
       
   431 
       
   432     # XXX Keeping state in the class is a mistake -- this means
       
   433     # you cannot have more than one active Bdb instance.
       
   434 
       
   435     next = 1        # Next bp to be assigned
       
   436     bplist = {}     # indexed by (file, lineno) tuple
       
   437     bpbynumber = [None] # Each entry is None or an instance of Bpt
       
   438                 # index 0 is unused, except for marking an
       
   439                 # effective break .... see effective()
       
   440 
       
   441     def __init__(self, file, line, temporary=0, cond=None, funcname=None):
       
   442         self.funcname = funcname
       
   443         # Needed if funcname is not None.
       
   444         self.func_first_executable_line = None
       
   445         self.file = file    # This better be in canonical form!
       
   446         self.line = line
       
   447         self.temporary = temporary
       
   448         self.cond = cond
       
   449         self.enabled = 1
       
   450         self.ignore = 0
       
   451         self.hits = 0
       
   452         self.number = Breakpoint.next
       
   453         Breakpoint.next = Breakpoint.next + 1
       
   454         # Build the two lists
       
   455         self.bpbynumber.append(self)
       
   456         if self.bplist.has_key((file, line)):
       
   457             self.bplist[file, line].append(self)
       
   458         else:
       
   459             self.bplist[file, line] = [self]
       
   460 
       
   461 
       
   462     def deleteMe(self):
       
   463         index = (self.file, self.line)
       
   464         self.bpbynumber[self.number] = None   # No longer in list
       
   465         self.bplist[index].remove(self)
       
   466         if not self.bplist[index]:
       
   467             # No more bp for this f:l combo
       
   468             del self.bplist[index]
       
   469 
       
   470     def enable(self):
       
   471         self.enabled = 1
       
   472 
       
   473     def disable(self):
       
   474         self.enabled = 0
       
   475 
       
   476     def bpprint(self, out=None):
       
   477         if out is None:
       
   478             out = sys.stdout
       
   479         if self.temporary:
       
   480             disp = 'del  '
       
   481         else:
       
   482             disp = 'keep '
       
   483         if self.enabled:
       
   484             disp = disp + 'yes  '
       
   485         else:
       
   486             disp = disp + 'no   '
       
   487         print >>out, '%-4dbreakpoint   %s at %s:%d' % (self.number, disp,
       
   488                                                        self.file, self.line)
       
   489         if self.cond:
       
   490             print >>out, '\tstop only if %s' % (self.cond,)
       
   491         if self.ignore:
       
   492             print >>out, '\tignore next %d hits' % (self.ignore)
       
   493         if (self.hits):
       
   494             if (self.hits > 1): ss = 's'
       
   495             else: ss = ''
       
   496             print >>out, ('\tbreakpoint already hit %d time%s' %
       
   497                           (self.hits, ss))
       
   498 
       
   499 # -----------end of Breakpoint class----------
       
   500 
       
   501 def checkfuncname(b, frame):
       
   502     """Check whether we should break here because of `b.funcname`."""
       
   503     if not b.funcname:
       
   504         # Breakpoint was set via line number.
       
   505         if b.line != frame.f_lineno:
       
   506             # Breakpoint was set at a line with a def statement and the function
       
   507             # defined is called: don't break.
       
   508             return False
       
   509         return True
       
   510 
       
   511     # Breakpoint set via function name.
       
   512 
       
   513     if frame.f_code.co_name != b.funcname:
       
   514         # It's not a function call, but rather execution of def statement.
       
   515         return False
       
   516 
       
   517     # We are in the right frame.
       
   518     if not b.func_first_executable_line:
       
   519         # The function is entered for the 1st time.
       
   520         b.func_first_executable_line = frame.f_lineno
       
   521 
       
   522     if  b.func_first_executable_line != frame.f_lineno:
       
   523         # But we are not at the first line number: don't break.
       
   524         return False
       
   525     return True
       
   526 
       
   527 # Determines if there is an effective (active) breakpoint at this
       
   528 # line of code.  Returns breakpoint number or 0 if none
       
   529 def effective(file, line, frame):
       
   530     """Determine which breakpoint for this file:line is to be acted upon.
       
   531 
       
   532     Called only if we know there is a bpt at this
       
   533     location.  Returns breakpoint that was triggered and a flag
       
   534     that indicates if it is ok to delete a temporary bp.
       
   535 
       
   536     """
       
   537     possibles = Breakpoint.bplist[file,line]
       
   538     for i in range(0, len(possibles)):
       
   539         b = possibles[i]
       
   540         if b.enabled == 0:
       
   541             continue
       
   542         if not checkfuncname(b, frame):
       
   543             continue
       
   544         # Count every hit when bp is enabled
       
   545         b.hits = b.hits + 1
       
   546         if not b.cond:
       
   547             # If unconditional, and ignoring,
       
   548             # go on to next, else break
       
   549             if b.ignore > 0:
       
   550                 b.ignore = b.ignore -1
       
   551                 continue
       
   552             else:
       
   553                 # breakpoint and marker that's ok
       
   554                 # to delete if temporary
       
   555                 return (b,1)
       
   556         else:
       
   557             # Conditional bp.
       
   558             # Ignore count applies only to those bpt hits where the
       
   559             # condition evaluates to true.
       
   560             try:
       
   561                 val = eval(b.cond, frame.f_globals,
       
   562                        frame.f_locals)
       
   563                 if val:
       
   564                     if b.ignore > 0:
       
   565                         b.ignore = b.ignore -1
       
   566                         # continue
       
   567                     else:
       
   568                         return (b,1)
       
   569                 # else:
       
   570                 #   continue
       
   571             except:
       
   572                 # if eval fails, most conservative
       
   573                 # thing is to stop on breakpoint
       
   574                 # regardless of ignore count.
       
   575                 # Don't delete temporary,
       
   576                 # as another hint to user.
       
   577                 return (b,0)
       
   578     return (None, None)
       
   579 
       
   580 # -------------------- testing --------------------
       
   581 
       
   582 class Tdb(Bdb):
       
   583     def user_call(self, frame, args):
       
   584         name = frame.f_code.co_name
       
   585         if not name: name = '???'
       
   586         print '+++ call', name, args
       
   587     def user_line(self, frame):
       
   588         import linecache
       
   589         name = frame.f_code.co_name
       
   590         if not name: name = '???'
       
   591         fn = self.canonic(frame.f_code.co_filename)
       
   592         line = linecache.getline(fn, frame.f_lineno)
       
   593         print '+++', fn, frame.f_lineno, name, ':', line.strip()
       
   594     def user_return(self, frame, retval):
       
   595         print '+++ return', retval
       
   596     def user_exception(self, frame, exc_stuff):
       
   597         print '+++ exception', exc_stuff
       
   598         self.set_continue()
       
   599 
       
   600 def foo(n):
       
   601     print 'foo(', n, ')'
       
   602     x = bar(n*10)
       
   603     print 'bar returned', x
       
   604 
       
   605 def bar(a):
       
   606     print 'bar(', a, ')'
       
   607     return a/2
       
   608 
       
   609 def test():
       
   610     t = Tdb()
       
   611     t.run('import bdb; bdb.foo(10)')
       
   612 
       
   613 # end