github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/third_party/stdlib/traceback.py (about)

     1  """Extract, format and print information about Python stack traces."""
     2  
     3  import linecache
     4  import sys
     5  import types
     6  
     7  __all__ = ['extract_stack', 'extract_tb', 'format_exception',
     8             'format_exception_only', 'format_list', 'format_stack',
     9             'format_tb', 'print_exc', 'format_exc', 'print_exception',
    10             'print_last', 'print_stack', 'print_tb', 'tb_lineno']
    11  
    12  def _print(file, str='', terminator='\n'):
    13      file.write(str+terminator)
    14  
    15  
    16  def print_list(extracted_list, file=None):
    17      """Print the list of tuples as returned by extract_tb() or
    18      extract_stack() as a formatted stack trace to the given file."""
    19      if file is None:
    20          file = sys.stderr
    21      for filename, lineno, name, line in extracted_list:
    22          _print(file,
    23                 '  File "%s", line %d, in %s' % (filename,lineno,name))
    24          if line:
    25              _print(file, '    %s' % line.strip())
    26  
    27  def format_list(extracted_list):
    28      """Format a list of traceback entry tuples for printing.
    29  
    30      Given a list of tuples as returned by extract_tb() or
    31      extract_stack(), return a list of strings ready for printing.
    32      Each string in the resulting list corresponds to the item with the
    33      same index in the argument list.  Each string ends in a newline;
    34      the strings may contain internal newlines as well, for those items
    35      whose source text line is not None.
    36      """
    37      list = []
    38      for filename, lineno, name, line in extracted_list:
    39          item = '  File "%s", line %d, in %s\n' % (filename,lineno,name)
    40          if line:
    41              item = item + '    %s\n' % line.strip()
    42          list.append(item)
    43      return list
    44  
    45  
    46  def print_tb(tb, limit=None, file=None):
    47      """Print up to 'limit' stack trace entries from the traceback 'tb'.
    48  
    49      If 'limit' is omitted or None, all entries are printed.  If 'file'
    50      is omitted or None, the output goes to sys.stderr; otherwise
    51      'file' should be an open file or file-like object with a write()
    52      method.
    53      """
    54      if file is None:
    55          file = sys.stderr
    56      if limit is None:
    57          if hasattr(sys, 'tracebacklimit'):
    58              limit = sys.tracebacklimit
    59      n = 0
    60      while tb is not None and (limit is None or n < limit):
    61          f = tb.tb_frame
    62          lineno = tb.tb_lineno
    63          co = f.f_code
    64          filename = co.co_filename
    65          name = co.co_name
    66          _print(file,
    67                 '  File "%s", line %d, in %s' % (filename, lineno, name))
    68          linecache.checkcache(filename)
    69          line = linecache.getline(filename, lineno, f.f_globals)
    70          if line: _print(file, '    ' + line.strip())
    71          tb = tb.tb_next
    72          n = n+1
    73  
    74  def format_tb(tb, limit = None):
    75      """A shorthand for 'format_list(extract_tb(tb, limit))'."""
    76      return format_list(extract_tb(tb, limit))
    77  
    78  def extract_tb(tb, limit = None):
    79      """Return list of up to limit pre-processed entries from traceback.
    80  
    81      This is useful for alternate formatting of stack traces.  If
    82      'limit' is omitted or None, all entries are extracted.  A
    83      pre-processed stack trace entry is a quadruple (filename, line
    84      number, function name, text) representing the information that is
    85      usually printed for a stack trace.  The text is a string with
    86      leading and trailing whitespace stripped; if the source is not
    87      available it is None.
    88      """
    89      if limit is None:
    90          if hasattr(sys, 'tracebacklimit'):
    91              limit = sys.tracebacklimit
    92      list = []
    93      n = 0
    94      while tb is not None and (limit is None or n < limit):
    95          f = tb.tb_frame
    96          lineno = tb.tb_lineno
    97          co = f.f_code
    98          filename = co.co_filename
    99          name = co.co_name
   100          linecache.checkcache(filename)
   101          line = linecache.getline(filename, lineno, f.f_globals)
   102          if line: line = line.strip()
   103          else: line = None
   104          list.append((filename, lineno, name, line))
   105          tb = tb.tb_next
   106          n = n+1
   107      return list
   108  
   109  
   110  def print_exception(etype, value, tb, limit=None, file=None):
   111      """Print exception up to 'limit' stack trace entries from 'tb' to 'file'.
   112  
   113      This differs from print_tb() in the following ways: (1) if
   114      traceback is not None, it prints a header "Traceback (most recent
   115      call last):"; (2) it prints the exception type and value after the
   116      stack trace; (3) if type is SyntaxError and value has the
   117      appropriate format, it prints the line where the syntax error
   118      occurred with a caret on the next line indicating the approximate
   119      position of the error.
   120      """
   121      if file is None:
   122          # TODO: Use sys.stderr when that's implemented.
   123          file = open('/dev/stderr', 'w')
   124          #file = sys.stderr
   125      if tb:
   126          _print(file, 'Traceback (most recent call last):')
   127          print_tb(tb, limit, file)
   128      lines = format_exception_only(etype, value)
   129      for line in lines:
   130          _print(file, line, '')
   131  
   132  def format_exception(etype, value, tb, limit = None):
   133      """Format a stack trace and the exception information.
   134  
   135      The arguments have the same meaning as the corresponding arguments
   136      to print_exception().  The return value is a list of strings, each
   137      ending in a newline and some containing internal newlines.  When
   138      these lines are concatenated and printed, exactly the same text is
   139      printed as does print_exception().
   140      """
   141      if tb:
   142          list = ['Traceback (most recent call last):\n']
   143          list = list + format_tb(tb, limit)
   144      else:
   145          list = []
   146      list = list + format_exception_only(etype, value)
   147      return list
   148  
   149  def format_exception_only(etype, value):
   150      """Format the exception part of a traceback.
   151  
   152      The arguments are the exception type and value such as given by
   153      sys.last_type and sys.last_value. The return value is a list of
   154      strings, each ending in a newline.
   155  
   156      Normally, the list contains a single string; however, for
   157      SyntaxError exceptions, it contains several lines that (when
   158      printed) display detailed information about where the syntax
   159      error occurred.
   160  
   161      The message indicating which exception occurred is always the last
   162      string in the list.
   163  
   164      """
   165  
   166      # An instance should not have a meaningful value parameter, but
   167      # sometimes does, particularly for string exceptions, such as
   168      # >>> raise string1, string2  # deprecated
   169      #
   170      # Clear these out first because issubtype(string1, SyntaxError)
   171      # would raise another exception and mask the original problem.
   172      if (isinstance(etype, BaseException) or
   173  #        isinstance(etype, types.InstanceType) or
   174          etype is None or type(etype) is str):
   175          return [_format_final_exc_line(etype, value)]
   176  
   177      stype = etype.__name__
   178  
   179      if not issubclass(etype, SyntaxError):
   180          return [_format_final_exc_line(stype, value)]
   181  
   182      # It was a syntax error; show exactly where the problem was found.
   183      lines = []
   184      try:
   185          msg, (filename, lineno, offset, badline) = value.args
   186      except Exception:
   187          pass
   188      else:
   189          filename = filename or "<string>"
   190          lines.append('  File "%s", line %d\n' % (filename, lineno))
   191          if badline is not None:
   192              lines.append('    %s\n' % badline.strip())
   193              if offset is not None:
   194                  caretspace = badline.rstrip('\n')
   195                  offset = min(len(caretspace), offset) - 1
   196                  caretspace = caretspace[:offset].lstrip()
   197                  # non-space whitespace (likes tabs) must be kept for alignment
   198                  caretspace = ((c.isspace() and c or ' ') for c in caretspace)
   199                  lines.append('    %s^\n' % ''.join(caretspace))
   200          value = msg
   201  
   202      lines.append(_format_final_exc_line(stype, value))
   203      return lines
   204  
   205  def _format_final_exc_line(etype, value):
   206      """Return a list of a single line -- normal case for format_exception_only"""
   207      valuestr = _some_str(value)
   208      if value is None or not valuestr:
   209          line = "%s\n" % etype
   210      else:
   211          line = "%s: %s\n" % (etype, valuestr)
   212      return line
   213  
   214  def _some_str(value):
   215      try:
   216          return str(value)
   217      except Exception:
   218          pass
   219      try:
   220          value = unicode(value)
   221          return value.encode("ascii", "backslashreplace")
   222      except Exception:
   223          pass
   224      return '<unprintable %s object>' % type(value).__name__
   225  
   226  
   227  def print_exc(limit=None, file=None):
   228      """Shorthand for 'print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback, limit, file)'.
   229      (In fact, it uses sys.exc_info() to retrieve the same information
   230      in a thread-safe way.)"""
   231      if file is None:
   232          # TODO: Use sys.stderr when that's implemented.
   233          file = open('/dev/stderr', 'w')
   234          #file = sys.stderr
   235      try:
   236          etype, value, tb = sys.exc_info()
   237          print_exception(etype, value, tb, limit, file)
   238      finally:
   239          etype = value = tb = None
   240  
   241  
   242  def format_exc(limit=None):
   243      """Like print_exc() but return a string."""
   244      try:
   245          etype, value, tb = sys.exc_info()
   246          return ''.join(format_exception(etype, value, tb, limit))
   247      finally:
   248          etype = value = tb = None
   249  
   250  
   251  def print_last(limit=None, file=None):
   252      """This is a shorthand for 'print_exception(sys.last_type,
   253      sys.last_value, sys.last_traceback, limit, file)'."""
   254      if not hasattr(sys, "last_type"):
   255          raise ValueError("no last exception")
   256      if file is None:
   257          file = sys.stderr
   258      print_exception(sys.last_type, sys.last_value, sys.last_traceback,
   259                      limit, file)
   260  
   261  
   262  def print_stack(f=None, limit=None, file=None):
   263      """Print a stack trace from its invocation point.
   264  
   265      The optional 'f' argument can be used to specify an alternate
   266      stack frame at which to start. The optional 'limit' and 'file'
   267      arguments have the same meaning as for print_exception().
   268      """
   269      if f is None:
   270          try:
   271              raise ZeroDivisionError
   272          except ZeroDivisionError:
   273              f = sys.exc_info()[2].tb_frame.f_back
   274      print_list(extract_stack(f, limit), file)
   275  
   276  def format_stack(f=None, limit=None):
   277      """Shorthand for 'format_list(extract_stack(f, limit))'."""
   278      if f is None:
   279          try:
   280              raise ZeroDivisionError
   281          except ZeroDivisionError:
   282              f = sys.exc_info()[2].tb_frame.f_back
   283      return format_list(extract_stack(f, limit))
   284  
   285  def extract_stack(f=None, limit = None):
   286      """Extract the raw traceback from the current stack frame.
   287  
   288      The return value has the same format as for extract_tb().  The
   289      optional 'f' and 'limit' arguments have the same meaning as for
   290      print_stack().  Each item in the list is a quadruple (filename,
   291      line number, function name, text), and the entries are in order
   292      from oldest to newest stack frame.
   293      """
   294      if f is None:
   295          try:
   296              raise ZeroDivisionError
   297          except ZeroDivisionError:
   298              f = sys.exc_info()[2].tb_frame.f_back
   299      if limit is None:
   300          if hasattr(sys, 'tracebacklimit'):
   301              limit = sys.tracebacklimit
   302      list = []
   303      n = 0
   304      while f is not None and (limit is None or n < limit):
   305          lineno = f.f_lineno
   306          co = f.f_code
   307          filename = co.co_filename
   308          name = co.co_name
   309          linecache.checkcache(filename)
   310          line = linecache.getline(filename, lineno, f.f_globals)
   311          if line: line = line.strip()
   312          else: line = None
   313          list.append((filename, lineno, name, line))
   314          f = f.f_back
   315          n = n+1
   316      list.reverse()
   317      return list
   318  
   319  def tb_lineno(tb):
   320      """Calculate correct line number of traceback given in tb.
   321  
   322      Obsolete in 2.3.
   323      """
   324      return tb.tb_lineno