_py2traceback.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. # -*- coding: utf-8 -*-
  2. # copied from python-2.7.3's traceback.py
  3. # CHANGES:
  4. # - some_str is replaced, trying to create unicode strings
  5. #
  6. from __future__ import absolute_import
  7. from __future__ import division
  8. from __future__ import print_function
  9. from __future__ import unicode_literals
  10. import types
  11. from six import text_type
  12. def format_exception_only(etype, value):
  13. """Format the exception part of a traceback.
  14. The arguments are the exception type and value such as given by
  15. sys.last_type and sys.last_value. The return value is a list of
  16. strings, each ending in a newline.
  17. Normally, the list contains a single string; however, for
  18. SyntaxError exceptions, it contains several lines that (when
  19. printed) display detailed information about where the syntax
  20. error occurred.
  21. The message indicating which exception occurred is always the last
  22. string in the list.
  23. """
  24. # An instance should not have a meaningful value parameter, but
  25. # sometimes does, particularly for string exceptions, such as
  26. # >>> raise string1, string2 # deprecated
  27. #
  28. # Clear these out first because issubtype(string1, SyntaxError)
  29. # would throw another exception and mask the original problem.
  30. if (
  31. isinstance(etype, BaseException)
  32. or isinstance(etype, types.InstanceType)
  33. or etype is None
  34. or type(etype) is str
  35. ):
  36. return [_format_final_exc_line(etype, value)]
  37. stype = etype.__name__
  38. if not issubclass(etype, SyntaxError):
  39. return [_format_final_exc_line(stype, value)]
  40. # It was a syntax error; show exactly where the problem was found.
  41. lines = []
  42. try:
  43. msg, (filename, lineno, offset, badline) = value.args
  44. except Exception:
  45. pass
  46. else:
  47. filename = filename or "<string>"
  48. lines.append(' File "{}", line {}\n'.format(filename, lineno))
  49. if badline is not None:
  50. if isinstance(badline, bytes): # python 2 only
  51. badline = badline.decode("utf-8", "replace")
  52. lines.append(" {}\n".format(badline.strip()))
  53. if offset is not None:
  54. caretspace = badline.rstrip("\n")[:offset].lstrip()
  55. # non-space whitespace (likes tabs) must be kept for alignment
  56. caretspace = ((c.isspace() and c or " ") for c in caretspace)
  57. # only three spaces to account for offset1 == pos 0
  58. lines.append(" {}^\n".format("".join(caretspace)))
  59. value = msg
  60. lines.append(_format_final_exc_line(stype, value))
  61. return lines
  62. def _format_final_exc_line(etype, value):
  63. """Return a list of a single line -- normal case for format_exception_only"""
  64. valuestr = _some_str(value)
  65. if value is None or not valuestr:
  66. line = "{}\n".format(etype)
  67. else:
  68. line = "{}: {}\n".format(etype, valuestr)
  69. return line
  70. def _some_str(value):
  71. try:
  72. return text_type(value)
  73. except Exception:
  74. try:
  75. return bytes(value).decode("UTF-8", "replace")
  76. except Exception:
  77. pass
  78. return "<unprintable {} object>".format(type(value).__name__)