test_tbutils.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. # -*- coding: utf-8 -*-
  2. import json
  3. import sys
  4. try:
  5. from cStringIO import StringIO
  6. except:
  7. from io import StringIO
  8. from boltons.tbutils import (TracebackInfo,
  9. ExceptionInfo,
  10. print_exception,
  11. fix_print_exception,
  12. ContextualCallpoint,
  13. ContextualExceptionInfo)
  14. def test_exception_info():
  15. # test ExceptionInfo and TracebackInfo and hooks, via StringIOs
  16. builtin_exc_hook = sys.excepthook
  17. fix_print_exception()
  18. tbi_str = ''
  19. def test():
  20. raise ValueError('yay fun')
  21. fake_stderr1 = StringIO()
  22. fake_stderr2 = StringIO()
  23. sys.stderr = fake_stderr1
  24. try:
  25. test()
  26. except:
  27. _, _, exc_traceback = sys.exc_info()
  28. tbi = TracebackInfo.from_traceback(exc_traceback)
  29. exc_info = ExceptionInfo.from_exc_info(*sys.exc_info())
  30. exc_info2 = ExceptionInfo.from_current()
  31. tbi_str = str(tbi)
  32. print_exception(*sys.exc_info(), file=fake_stderr2)
  33. new_exc_hook_res = fake_stderr2.getvalue()
  34. builtin_exc_hook(*sys.exc_info())
  35. builtin_exc_hook_res = fake_stderr1.getvalue()
  36. finally:
  37. sys.stderr = sys.__stderr__
  38. # Single frame
  39. single_frame_str = tbi.frames[-1].tb_frame_str()
  40. assert 'in test' in single_frame_str
  41. assert 'yay fun' in single_frame_str
  42. # Traceback info
  43. assert len(tbi_str.splitlines()) == 5
  44. assert 'yay fun' in tbi_str
  45. # Full except hook output
  46. assert 'ValueError: yay fun' in new_exc_hook_res
  47. assert "ValueError('yay fun')" in new_exc_hook_res
  48. assert len(new_exc_hook_res) > len(tbi_str)
  49. assert new_exc_hook_res == builtin_exc_hook_res
  50. def test_contextual():
  51. def func1():
  52. return func2()
  53. def func2():
  54. x = 5
  55. return func3()
  56. def func3():
  57. return ContextualCallpoint.from_current(level=2)
  58. callpoint = func1()
  59. assert callpoint.func_name == 'func2'
  60. line = str(callpoint.line)
  61. assert line.startswith(' ')
  62. assert line.strip() == 'return func3()'
  63. assert 'func2' in repr(callpoint)
  64. try:
  65. json.dumps(callpoint.to_dict())
  66. except TypeError:
  67. raise AssertionError("to_dict result is not JSON serializable")
  68. def func_a():
  69. a = 1
  70. raise Exception('func_a exception')
  71. def func_b():
  72. b = 2
  73. return func_a()
  74. def func_c():
  75. c = 3
  76. return func_b()
  77. try:
  78. func_c()
  79. except Exception as e:
  80. ctx_ei = ContextualExceptionInfo.from_current()
  81. ctx_ei_str = ctx_ei.get_formatted()
  82. ctx_ei_lines = ctx_ei_str.splitlines()
  83. assert ctx_ei_lines[-1] == 'Exception: func_a exception'
  84. assert ctx_ei_lines[0] == 'Traceback (most recent call last):'
  85. assert len(ctx_ei_lines) == 10
  86. assert "Exception('func_a exception')" in ctx_ei_str
  87. assert ctx_ei.tb_info.frames[2].local_reprs['b'] == '2'