| # Format and print Python stack traces |
| |
| import linecache |
| import string |
| import sys |
| import types |
| |
| def _print(file, str='', terminator='\n'): |
| file.write(str+terminator) |
| |
| |
| def print_list(extracted_list, file=None): |
| if not file: |
| file = sys.stderr |
| for filename, lineno, name, line in extracted_list: |
| _print(file, |
| ' File "%s", line %d, in %s' % (filename,lineno,name)) |
| if line: |
| _print(file, ' %s' % string.strip(line)) |
| |
| def format_list(extracted_list): |
| list = [] |
| for filename, lineno, name, line in extracted_list: |
| item = ' File "%s", line %d, in %s\n' % (filename,lineno,name) |
| if line: |
| item = item + ' %s\n' % string.strip(line) |
| list.append(item) |
| return list |
| |
| |
| def print_tb(tb, limit=None, file=None): |
| if not file: |
| file = sys.stderr |
| if limit is None: |
| if hasattr(sys, 'tracebacklimit'): |
| limit = sys.tracebacklimit |
| n = 0 |
| while tb is not None and (limit is None or n < limit): |
| f = tb.tb_frame |
| lineno = tb_lineno(tb) |
| co = f.f_code |
| filename = co.co_filename |
| name = co.co_name |
| _print(file, |
| ' File "%s", line %d, in %s' % (filename,lineno,name)) |
| line = linecache.getline(filename, lineno) |
| if line: _print(file, ' ' + string.strip(line)) |
| tb = tb.tb_next |
| n = n+1 |
| |
| def format_tb(tb, limit = None): |
| return format_list(extract_tb(tb, limit)) |
| |
| def extract_tb(tb, limit = None): |
| if limit is None: |
| if hasattr(sys, 'tracebacklimit'): |
| limit = sys.tracebacklimit |
| list = [] |
| n = 0 |
| while tb is not None and (limit is None or n < limit): |
| f = tb.tb_frame |
| lineno = tb_lineno(tb) |
| co = f.f_code |
| filename = co.co_filename |
| name = co.co_name |
| line = linecache.getline(filename, lineno) |
| if line: line = string.strip(line) |
| else: line = None |
| list.append((filename, lineno, name, line)) |
| tb = tb.tb_next |
| n = n+1 |
| return list |
| |
| |
| def print_exception(etype, value, tb, limit=None, file=None): |
| if not file: |
| file = sys.stderr |
| if tb: |
| _print(file, 'Traceback (innermost last):') |
| print_tb(tb, limit, file) |
| lines = format_exception_only(etype, value) |
| for line in lines[:-1]: |
| _print(file, line, ' ') |
| _print(file, lines[-1], '') |
| |
| def format_exception(etype, value, tb, limit = None): |
| if tb: |
| list = ['Traceback (innermost last):\n'] |
| list = list + format_tb(tb, limit) |
| else: |
| list = [] |
| list = list + format_exception_only(etype, value) |
| return list |
| |
| def format_exception_only(etype, value): |
| list = [] |
| if type(etype) == types.ClassType: |
| stype = etype.__name__ |
| else: |
| stype = etype |
| if value is None: |
| list.append(str(stype) + '\n') |
| else: |
| if etype is SyntaxError: |
| try: |
| msg, (filename, lineno, offset, line) = value |
| except: |
| pass |
| else: |
| if not filename: filename = "<string>" |
| list.append(' File "%s", line %d\n' % |
| (filename, lineno)) |
| i = 0 |
| while i < len(line) and \ |
| line[i] in string.whitespace: |
| i = i+1 |
| list.append(' %s\n' % string.strip(line)) |
| s = ' ' |
| for c in line[i:offset-1]: |
| if c in string.whitespace: |
| s = s + c |
| else: |
| s = s + ' ' |
| list.append('%s^\n' % s) |
| value = msg |
| list.append('%s: %s\n' % (str(stype), str(value))) |
| return list |
| |
| |
| def print_exc(limit=None, file=None): |
| if not file: |
| file = sys.stderr |
| try: |
| etype, value, tb = sys.exc_info() |
| print_exception(etype, value, tb, limit, file) |
| finally: |
| etype = value = tb = None |
| |
| def print_last(limit=None, file=None): |
| if not file: |
| file = sys.stderr |
| print_exception(sys.last_type, sys.last_value, sys.last_traceback, |
| limit, file) |
| |
| |
| def print_stack(f=None, limit=None, file=None): |
| if f is None: |
| try: |
| raise ZeroDivisionError |
| except ZeroDivisionError: |
| f = sys.exc_info()[2].tb_frame.f_back |
| print_list(extract_stack(f, limit), file) |
| |
| def format_stack(f=None, limit=None): |
| if f is None: |
| try: |
| raise ZeroDivisionError |
| except ZeroDivisionError: |
| f = sys.exc_info()[2].tb_frame.f_back |
| return format_list(extract_stack(f, limit)) |
| |
| def extract_stack(f=None, limit = None): |
| if f is None: |
| try: |
| raise ZeroDivisionError |
| except ZeroDivisionError: |
| f = sys.exc_info()[2].tb_frame.f_back |
| if limit is None: |
| if hasattr(sys, 'tracebacklimit'): |
| limit = sys.tracebacklimit |
| list = [] |
| n = 0 |
| while f is not None and (limit is None or n < limit): |
| lineno = f.f_lineno # XXX Too bad if -O is used |
| co = f.f_code |
| filename = co.co_filename |
| name = co.co_name |
| line = linecache.getline(filename, lineno) |
| if line: line = string.strip(line) |
| else: line = None |
| list.append((filename, lineno, name, line)) |
| f = f.f_back |
| n = n+1 |
| list.reverse() |
| return list |
| |
| # Calculate the correct line number of the traceback given in tb (even |
| # with -O on). |
| # Coded by Marc-Andre Lemburg from the example of PyCode_Addr2Line() |
| # in compile.c. |
| # Revised version by Jim Hugunin to work with JPython too. |
| |
| def tb_lineno(tb): |
| c = tb.tb_frame.f_code |
| if not hasattr(c, 'co_lnotab'): |
| return tb.tb_lineno |
| |
| tab = c.co_lnotab |
| line = c.co_firstlineno |
| stopat = tb.tb_lasti |
| addr = 0 |
| for i in range(0, len(tab), 2): |
| addr = addr + ord(tab[i]) |
| if addr > stopat: |
| break |
| line = line + ord(tab[i+1]) |
| return line |