home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / palmos / pippy-0.6beta-src.tar.gz / pippy-0.6beta-src.tar / pippy-0.6beta-src / src / Lib / traceback.py < prev    next >
Text File  |  2000-12-21  |  9KB  |  269 lines

  1. """Extract, format and print information about Python stack traces."""
  2.  
  3. import linecache
  4. import string
  5. import sys
  6. import types
  7.  
  8. def _print(file, str='', terminator='\n'):
  9.     file.write(str+terminator)
  10.  
  11.  
  12. def print_list(extracted_list, file=None):
  13.     """Print the list of tuples as returned by extract_tb() or
  14.     extract_stack() as a formatted stack trace to the given file."""
  15.     if not file:
  16.         file = sys.stderr
  17.     for filename, lineno, name, line in extracted_list:
  18.         _print(file,
  19.                '  File "%s", line %d, in %s' % (filename,lineno,name))
  20.         if line:
  21.             _print(file, '    %s' % string.strip(line))
  22.  
  23. def format_list(extracted_list):
  24.     """Given a list of tuples as returned by extract_tb() or
  25.     extract_stack(), return a list of strings ready for printing.
  26.     Each string in the resulting list corresponds to the item with
  27.     the same index in the argument list.  Each string ends in a
  28.     newline; the strings may contain internal newlines as well, for
  29.     those items whose source text line is not None."""
  30.     list = []
  31.     for filename, lineno, name, line in extracted_list:
  32.         item = '  File "%s", line %d, in %s\n' % (filename,lineno,name)
  33.         if line:
  34.             item = item + '    %s\n' % string.strip(line)
  35.         list.append(item)
  36.     return list
  37.     
  38.  
  39. def print_tb(tb, limit=None, file=None):
  40.     """Print up to 'limit' stack trace entries from the traceback 'tb'.
  41.     If 'limit' is omitted or None, all entries are printed.  If 'file' is
  42.     omitted or None, the output goes to sys.stderr; otherwise 'file'
  43.     should be an open file or file-like object with a write() method."""
  44.     if not file:
  45.         file = sys.stderr
  46.     if limit is None:
  47.         if hasattr(sys, 'tracebacklimit'):
  48.             limit = sys.tracebacklimit
  49.     n = 0
  50.     while tb is not None and (limit is None or n < limit):
  51.         f = tb.tb_frame
  52.         lineno = tb_lineno(tb)
  53.         co = f.f_code
  54.         filename = co.co_filename
  55.         name = co.co_name
  56.         _print(file,
  57.                '  File "%s", line %d, in %s' % (filename,lineno,name))
  58.         line = linecache.getline(filename, lineno)
  59.         if line: _print(file, '    ' + string.strip(line))
  60.         tb = tb.tb_next
  61.         n = n+1
  62.  
  63. def format_tb(tb, limit = None):
  64.     """A shorthand for 'format_list(extract_stack(f, limit))."""
  65.     return format_list(extract_tb(tb, limit))
  66.  
  67. def extract_tb(tb, limit = None):
  68.     """Return a list of up to 'limit' pre-processed stack trace entries
  69.     extracted from the traceback object 'traceback'.  This is useful for
  70.     alternate formatting of stack traces.  If 'limit' is omitted or None,
  71.     all entries are extracted.  A pre-processed stack trace entry is a
  72.     quadruple (filename, line number, function name, text) representing
  73.     the information that is usually printed for a stack trace.  The text
  74.     is a string with leading and trailing whitespace stripped; if the
  75.     source is not available it is None."""
  76.     if limit is None:
  77.         if hasattr(sys, 'tracebacklimit'):
  78.             limit = sys.tracebacklimit
  79.     list = []
  80.     n = 0
  81.     while tb is not None and (limit is None or n < limit):
  82.         f = tb.tb_frame
  83.         lineno = tb_lineno(tb)
  84.         co = f.f_code
  85.         filename = co.co_filename
  86.         name = co.co_name
  87.         line = linecache.getline(filename, lineno)
  88.         if line: line = string.strip(line)
  89.         else: line = None
  90.         list.append((filename, lineno, name, line))
  91.         tb = tb.tb_next
  92.         n = n+1
  93.     return list
  94.  
  95.  
  96. def print_exception(etype, value, tb, limit=None, file=None):
  97.     """Print exception information and up to 'limit' stack trace entries
  98.     from the traceback 'tb' to 'file'.  This differs from print_tb() in
  99.     the following ways: (1) if traceback is not None, it prints a header
  100.     "Traceback (innermost last):"; (2) it prints the exception type and
  101.     value after the stack trace; (3) if type is SyntaxError and value has
  102.     the appropriate format, it prints the line where the syntax error
  103.     occurred with a caret on the next line indicating the approximate
  104.     position of the error."""
  105.     if not file:
  106.         file = sys.stderr
  107.     if tb:
  108.         _print(file, 'Traceback (innermost last):')
  109.         print_tb(tb, limit, file)
  110.     lines = format_exception_only(etype, value)
  111.     for line in lines[:-1]:
  112.         _print(file, line, ' ')
  113.     _print(file, lines[-1], '')
  114.  
  115. def format_exception(etype, value, tb, limit = None):
  116.     """Format a stack trace and the exception information.  The arguments
  117.     have the same meaning as the corresponding arguments to
  118.     print_exception().  The return value is a list of strings, each
  119.     ending in a newline and some containing internal newlines.  When 
  120.     these lines are contatenated and printed, exactly the same text is
  121.     printed as does print_exception()."""
  122.     if tb:
  123.         list = ['Traceback (innermost last):\n']
  124.         list = list + format_tb(tb, limit)
  125.     else:
  126.         list = []
  127.     list = list + format_exception_only(etype, value)
  128.     return list
  129.  
  130. def format_exception_only(etype, value):
  131.     """Format the exception part of a traceback.  The arguments are the
  132.     exception type and value such as given by sys.last_type and
  133.     sys.last_value. The return value is a list of strings, each ending
  134.     in a newline.  Normally, the list contains a single string;
  135.     however, for SyntaxError exceptions, it contains several lines that
  136.     (when printed) display detailed information about where the syntax
  137.     error occurred.  The message indicating which exception occurred is
  138.     the always last string in the list."""
  139.     list = []
  140.     if type(etype) == types.ClassType:
  141.         stype = etype.__name__
  142.     else:
  143.         stype = etype
  144.     if value is None:
  145.         list.append(str(stype) + '\n')
  146.     else:
  147.         if etype is SyntaxError:
  148.             try:
  149.                 msg, (filename, lineno, offset, line) = value
  150.             except:
  151.                 pass
  152.             else:
  153.                 if not filename: filename = "<string>"
  154.                 list.append('  File "%s", line %d\n' %
  155.                         (filename, lineno))
  156.                 i = 0
  157.                 while i < len(line) and \
  158.                       line[i] in string.whitespace:
  159.                     i = i+1
  160.                 list.append('    %s\n' % string.strip(line))
  161.                 s = '    '
  162.                 for c in line[i:offset-1]:
  163.                     if c in string.whitespace:
  164.                         s = s + c
  165.                     else:
  166.                         s = s + ' '
  167.                 list.append('%s^\n' % s)
  168.                 value = msg
  169.         list.append('%s: %s\n' % (str(stype), str(value)))
  170.     return list
  171.  
  172.  
  173. def print_exc(limit=None, file=None):
  174.     """This is a shorthand for 'print_exception(sys.exc_type,
  175.     sys.exc_value, sys.exc_traceback, limit, file)'.
  176.     (In fact, it uses sys.exc_info() to retrieve the same information
  177.     in a thread-safe way.)"""
  178.     if not file:
  179.         file = sys.stderr
  180.     try:
  181.         etype, value, tb = sys.exc_info()
  182.         print_exception(etype, value, tb, limit, file)
  183.     finally:
  184.         etype = value = tb = None
  185.  
  186. def print_last(limit=None, file=None):
  187.     """This is a shorthand for 'print_exception(sys.last_type,
  188.     sys.last_value, sys.last_traceback, limit, file)'."""
  189.     if not file:
  190.         file = sys.stderr
  191.     print_exception(sys.last_type, sys.last_value, sys.last_traceback,
  192.             limit, file)
  193.  
  194.  
  195. def print_stack(f=None, limit=None, file=None):
  196.     """This function prints a stack trace from its invocation point.
  197.     The optional 'f' argument can be used to specify an alternate stack
  198.     frame at which to start. The optional 'limit' and 'file' arguments
  199.     have the same meaning as for print_exception()."""
  200.     if f is None:
  201.         try:
  202.             raise ZeroDivisionError
  203.         except ZeroDivisionError:
  204.             f = sys.exc_info()[2].tb_frame.f_back
  205.     print_list(extract_stack(f, limit), file)
  206.  
  207. def format_stack(f=None, limit=None):
  208.     """A shorthand for 'format_list(extract_stack(f, limit))'."""
  209.     if f is None:
  210.         try:
  211.             raise ZeroDivisionError
  212.         except ZeroDivisionError:
  213.             f = sys.exc_info()[2].tb_frame.f_back
  214.     return format_list(extract_stack(f, limit))
  215.  
  216. def extract_stack(f=None, limit = None):
  217.     """Extract the raw traceback from the current stack frame.  The
  218.     return value has the same format as for extract_tb().  The optional
  219.     'f' and 'limit' arguments have the same meaning as for print_stack(). 
  220.     Each item in the list is a quadruple (filename, line number,
  221.     function name, text), and the entries are in order from outermost
  222.     to innermost stack frame."""
  223.     if f is None:
  224.         try:
  225.             raise ZeroDivisionError
  226.         except ZeroDivisionError:
  227.             f = sys.exc_info()[2].tb_frame.f_back
  228.     if limit is None:
  229.         if hasattr(sys, 'tracebacklimit'):
  230.             limit = sys.tracebacklimit
  231.     list = []
  232.     n = 0
  233.     while f is not None and (limit is None or n < limit):
  234.         lineno = f.f_lineno    # XXX Too bad if -O is used
  235.         co = f.f_code
  236.         filename = co.co_filename
  237.         name = co.co_name
  238.         line = linecache.getline(filename, lineno)
  239.         if line: line = string.strip(line)
  240.         else: line = None
  241.         list.append((filename, lineno, name, line))
  242.         f = f.f_back
  243.         n = n+1
  244.     list.reverse()
  245.     return list
  246.  
  247. def tb_lineno(tb):
  248.     """Calculate the correct line number of the traceback given in tb
  249.     (even with -O on)."""
  250.  
  251.     # Coded by Marc-Andre Lemburg from the example of PyCode_Addr2Line()
  252.     # in compile.c.
  253.     # Revised version by Jim Hugunin to work with JPython too.
  254.  
  255.     c = tb.tb_frame.f_code
  256.     if not hasattr(c, 'co_lnotab'):
  257.         return tb.tb_lineno
  258.  
  259.     tab = c.co_lnotab
  260.     line = c.co_firstlineno
  261.     stopat = tb.tb_lasti
  262.     addr = 0
  263.     for i in range(0, len(tab), 2):
  264.         addr = addr + ord(tab[i])
  265.         if addr > stopat:
  266.             break
  267.         line = line + ord(tab[i+1])
  268.     return line
  269.