|
12 | 12 | import io |
13 | 13 | import json |
14 | 14 | import logging |
| 15 | +import sys |
| 16 | +import types |
15 | 17 | import typing |
16 | 18 | import unittest |
17 | 19 | import warnings |
18 | 20 |
|
19 | 21 | import daiquiri |
20 | 22 |
|
| 23 | +real_excepthook = sys.excepthook |
| 24 | + |
21 | 25 |
|
22 | 26 | class TestDaiquiri(unittest.TestCase): |
23 | 27 | def tearDown(self) -> None: |
24 | 28 | # Be sure to reset the warning capture |
25 | 29 | logging.captureWarnings(False) |
| 30 | + # Reset exception hook |
| 31 | + sys.excepthook = real_excepthook |
26 | 32 | super(TestDaiquiri, self).tearDown() |
27 | 33 |
|
28 | 34 | def test_setup(self) -> None: |
29 | 35 | daiquiri.setup() |
30 | 36 | daiquiri.setup(level=logging.DEBUG) |
31 | 37 | daiquiri.setup(program_name="foobar") |
32 | 38 |
|
| 39 | + def test_excepthook(self) -> None: |
| 40 | + hook_ran = False |
| 41 | + |
| 42 | + def catcher( |
| 43 | + exctype: type[BaseException], |
| 44 | + value: BaseException, |
| 45 | + traceback: types.TracebackType | None, |
| 46 | + ) -> None: |
| 47 | + nonlocal hook_ran |
| 48 | + hook_ran = True |
| 49 | + real_excepthook(exctype, value, traceback) |
| 50 | + |
| 51 | + sys.excepthook = catcher |
| 52 | + |
| 53 | + sys.excepthook(Exception, Exception("boom"), None) |
| 54 | + assert hook_ran |
| 55 | + |
| 56 | + daiquiri.setup() |
| 57 | + |
| 58 | + hook_ran = False |
| 59 | + sys.excepthook(Exception, Exception("boom"), None) |
| 60 | + assert hook_ran |
| 61 | + |
33 | 62 | def test_setup_json_formatter(self) -> None: |
34 | 63 | stream = io.StringIO() |
35 | 64 | daiquiri.setup( |
@@ -67,7 +96,7 @@ def test_capture_warnings(self) -> None: |
67 | 96 | line = stream.getvalue() |
68 | 97 | self.assertIn("WARNING py.warnings: ", line) |
69 | 98 | self.assertIn( |
70 | | - "daiquiri/tests/test_daiquiri.py:66: " |
| 99 | + "daiquiri/tests/test_daiquiri.py:95: " |
71 | 100 | 'UserWarning: omg!\n warnings.warn("omg!")\n', |
72 | 101 | line, |
73 | 102 | ) |
|
0 commit comments