system.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import traceback
  2. import sys
  3. from typing import List, Tuple
  4. from textwrap import dedent
  5. import html
  6. class Error:
  7. """Format class for errors including the exception
  8. and traceback.
  9. Parameters
  10. ----------
  11. contet_type : str
  12. Content type for which the error is meant to be rendered
  13. on.
  14. exception : Exception
  15. Exception object. If not passed, current stack trace is used.
  16. """
  17. def __init__(self, content_type="text", exception:Exception=None):
  18. self.content_type = content_type
  19. self.exception = exception
  20. def __str__(self):
  21. if self.content_type == "text":
  22. return self.as_text()
  23. elif self.content_type == "html-inline":
  24. return self.as_html_inline()
  25. elif self.content_type == "html":
  26. return self.as_html()
  27. def as_text(self):
  28. "Format traceback as text"
  29. exc_type, exc_text, tb_list = self.exc_format()
  30. tb_text = '\n'.join(tb_list)
  31. return f"""Traceback (most recent call last):\n{tb_text}\n{exc_type}: {exc_text}"""
  32. def as_html_inline(self):
  33. "Format traceback as HTML"
  34. exc_type, exc_text, tb_list = self.exc_format()
  35. tb_str = '\n'.join(tb_list)
  36. if tb_str.endswith('\n'):
  37. tb_str = tb_str[:-1]
  38. exc_type, exc_text, tb_str = (html.escape(val) for val in (exc_type, exc_text, tb_str))
  39. return dedent(
  40. f"""
  41. <div>
  42. <h4>Traceback (most recent call last):</h4>
  43. <pre><code>{tb_str}</code></pre>
  44. <span style="color: red; font-weight: bold">{exc_text}</span>: <span>{exc_type}</span>
  45. </div>"""
  46. )
  47. def as_html(self):
  48. "Format traceback as HTML"
  49. exc_type, exc_text, tb_list = self.exc_format()
  50. tb_str = '\n'.join(tb_list)
  51. if tb_str.endswith('\n'):
  52. tb_str = tb_str[:-1]
  53. exc_type, exc_text, tb_str = (html.escape(val) for val in (exc_type, exc_text, tb_str))
  54. return dedent(
  55. f"""<div class="error">
  56. <h4 class="header">Traceback (most recent call last):</h4>
  57. <pre class="traceback"><code>{tb_str}</code></pre>
  58. <div class="exception">
  59. <span class="exception-type">{exc_type}</span>: <span class="exception-value">{exc_text}</span>
  60. </div>
  61. </div>"""
  62. )
  63. @property
  64. def exception_type(self) -> str:
  65. "str: Type of the exception (as string)"
  66. type_, _, _ = self.exc_format()
  67. return type_
  68. @property
  69. def exception_value(self) -> str:
  70. "str: Exception value (as string)"
  71. _, value, _ = self.exc_format()
  72. return value
  73. @property
  74. def traceback(self) -> List[str]:
  75. "list str: Traceback (as list of str)"
  76. _, _, tb = self.exc_format()
  77. return tb
  78. def exc_format(self) -> Tuple[str, str, List[str]]:
  79. if self.exception is None:
  80. exc_type, exc_value, tb = sys.exc_info()
  81. else:
  82. exc_value = self.exception
  83. exc_type = type(self.exception)
  84. tb = self.exception.__traceback__
  85. tb_list = traceback.format_tb(tb)
  86. exc_str = str(exc_value)
  87. exc_type_str = exc_type.__name__
  88. return exc_type_str, exc_str, tb_list