forked from pytest-dev/pytest-faulthandler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pytest_faulthandler.py
81 lines (65 loc) · 2.55 KB
/
pytest_faulthandler.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import sys
import os
import pytest
def pytest_addoption(parser):
group = parser.getgroup('terminal reporting')
group.addoption(
'--no-faulthandler', action='store_false', dest='fault_handler',
default=True, help='Disable faulthandler module.')
group.addoption(
'--faulthandler-timeout', type=int, dest='fault_handler_timeout',
metavar='TIMEOUT', default=0,
help='Dump the traceback of all threads if a test takes '
'more than TIMEOUT seconds to finish.\n'
'Not available on Windows.')
def pytest_configure(config):
if config.getoption('fault_handler'):
import faulthandler
stderr_fd_copy = os.dup(sys.stderr.fileno())
config.fault_handler_stderr = os.fdopen(stderr_fd_copy, 'w')
faulthandler.enable(config.fault_handler_stderr)
# we never disable faulthandler after it was enabled, see #3
if config.getoption('fault_handler_timeout') > 0:
if not timeout_support_available():
message = 'faulthandler timeout support not available on ' \
'this platform'
config.warn(code='C1', message=message)
def timeout_support_available():
"""Returns True if the current platform/python support faulthandler
timeout.
"""
import faulthandler
return hasattr(faulthandler, 'dump_traceback_later') and \
hasattr(faulthandler, 'cancel_dump_traceback_later')
@pytest.mark.hookwrapper
def pytest_runtest_protocol(item):
enabled = item.config.getoption('fault_handler')
timeout = item.config.getoption('fault_handler_timeout')
timeout_supported = timeout_support_available()
if enabled and timeout > 0 and timeout_supported:
import faulthandler
stderr = item.config.fault_handler_stderr
faulthandler.dump_traceback_later(timeout, file=stderr)
try:
yield
finally:
faulthandler.cancel_dump_traceback_later()
else:
yield
def _cancel_traceback_dump():
"""Cancel traceback dumping if timeout support is available.
"""
if timeout_support_available():
import faulthandler
faulthandler.cancel_dump_traceback_later()
@pytest.hookimpl(tryfirst=True)
def pytest_enter_pdb():
"""Cancel any traceback dumping due to timeout before entering pdb.
"""
_cancel_traceback_dump()
@pytest.hookimpl(tryfirst=True)
def pytest_exception_interact():
"""Cancel any traceback dumping due to an interactive exception being
raised.
"""
_cancel_traceback_dump()