Skip to content

Commit aac5d5d

Browse files
committed
faulthandler: avoid accessing sys.stderr.encoding
Fixes a pytest-xdist regression after 762bb61 (not yet released). pytest-xdist patches sys.stderr with an object which doesn't have `encoding`. Strictly speaking, this should be fixed there (or more precisely, in execnet), but it will drop support for older versions which don't want. But in any case, the fix turns out to simplify the code, using FD support added in Python 3.5, so it's good anyway! Refs: pytest-dev/pytest-xdist#900
1 parent a88ae82 commit aac5d5d

File tree

1 file changed

+8
-12
lines changed

1 file changed

+8
-12
lines changed

src/_pytest/faulthandler.py

+8-12
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import os
33
import sys
44
from typing import Generator
5-
from typing import TextIO
65

76
import pytest
87
from _pytest.config import Config
@@ -11,7 +10,7 @@
1110
from _pytest.stash import StashKey
1211

1312

14-
fault_handler_stderr_key = StashKey[TextIO]()
13+
fault_handler_stderr_fd_key = StashKey[int]()
1514
fault_handler_originally_enabled_key = StashKey[bool]()
1615

1716

@@ -26,22 +25,19 @@ def pytest_addoption(parser: Parser) -> None:
2625
def pytest_configure(config: Config) -> None:
2726
import faulthandler
2827

29-
stderr_fd_copy = os.dup(get_stderr_fileno())
30-
config.stash[fault_handler_stderr_key] = open(
31-
stderr_fd_copy, "w", encoding=sys.stderr.encoding
32-
)
28+
config.stash[fault_handler_stderr_fd_key] = os.dup(get_stderr_fileno())
3329
config.stash[fault_handler_originally_enabled_key] = faulthandler.is_enabled()
34-
faulthandler.enable(file=config.stash[fault_handler_stderr_key])
30+
faulthandler.enable(file=config.stash[fault_handler_stderr_fd_key])
3531

3632

3733
def pytest_unconfigure(config: Config) -> None:
3834
import faulthandler
3935

4036
faulthandler.disable()
4137
# Close the dup file installed during pytest_configure.
42-
if fault_handler_stderr_key in config.stash:
43-
config.stash[fault_handler_stderr_key].close()
44-
del config.stash[fault_handler_stderr_key]
38+
if fault_handler_stderr_fd_key in config.stash:
39+
os.close(config.stash[fault_handler_stderr_fd_key])
40+
del config.stash[fault_handler_stderr_fd_key]
4541
if config.stash.get(fault_handler_originally_enabled_key, False):
4642
# Re-enable the faulthandler if it was originally enabled.
4743
faulthandler.enable(file=get_stderr_fileno())
@@ -69,10 +65,10 @@ def get_timeout_config_value(config: Config) -> float:
6965
@pytest.hookimpl(hookwrapper=True, trylast=True)
7066
def pytest_runtest_protocol(item: Item) -> Generator[None, None, None]:
7167
timeout = get_timeout_config_value(item.config)
72-
stderr = item.config.stash[fault_handler_stderr_key]
73-
if timeout > 0 and stderr is not None:
68+
if timeout > 0:
7469
import faulthandler
7570

71+
stderr = item.config.stash[fault_handler_stderr_fd_key]
7672
faulthandler.dump_traceback_later(timeout, file=stderr)
7773
try:
7874
yield

0 commit comments

Comments
 (0)