Skip to content

Commit df4e3a6

Browse files
committed
capture: do not close tmpfile buffer, but redirect
Fixes #5502
1 parent 978c7ae commit df4e3a6

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

src/_pytest/capture.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,10 @@ def _done(self):
594594
os.dup2(targetfd_save, self.targetfd)
595595
os.close(targetfd_save)
596596
self.syscapture.done()
597-
self.tmpfile.close()
597+
# Redirect any remaining output.
598+
os.dup2(self.targetfd, self.tmpfile.buffer.fileno())
599+
# TODO: atexit?
600+
# self.tmpfile.close()
598601
self._state = "done"
599602

600603
def suspend(self):
@@ -665,7 +668,8 @@ def snap(self):
665668
def done(self):
666669
setattr(sys, self.name, self._old)
667670
del self._old
668-
self.tmpfile.close()
671+
# TODO: atexit?
672+
# self.tmpfile.close()
669673
self._state = "done"
670674

671675
def suspend(self):

testing/test_capture.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,3 +1510,47 @@ def test_fails():
15101510
result_with_capture.stdout.fnmatch_lines(
15111511
["E TypeError: write() argument must be str, not bytes"]
15121512
)
1513+
1514+
1515+
def test_logging_in_atexit(testdir):
1516+
p = testdir.makepyfile(
1517+
"""
1518+
import atexit
1519+
import logging
1520+
import sys
1521+
1522+
cur_stdout = sys.stdout
1523+
LOGGER = logging.getLogger(__name__)
1524+
1525+
def test_fail():
1526+
assert 0
1527+
1528+
def _atexit():
1529+
print("test-print in atexit", cur_stdout)
1530+
LOGGER.error("test-log in atexit")
1531+
1532+
print()
1533+
print("test-register")
1534+
print()
1535+
atexit.register(_atexit)
1536+
logging.basicConfig()
1537+
1538+
LOGGER.error("log_setup_not_shown_from_collection")
1539+
1540+
print(sys.stderr, id(sys.stderr))
1541+
"""
1542+
)
1543+
result = testdir.runpytest_subprocess(str(p))
1544+
result.stdout.fnmatch_lines(
1545+
[
1546+
"*= 1 failed in *",
1547+
"test-print in atexit <_pytest.capture.EncodedFile object *",
1548+
]
1549+
)
1550+
assert result.stderr.lines == ["ERROR:test_logging_in_atexit:test-log in atexit"]
1551+
assert result.ret == 1
1552+
1553+
output = str(result.stdout) + str(result.stderr)
1554+
assert "test-register" not in output
1555+
assert "*- Captured stderr call -*" not in output
1556+
assert "log_setup_not_shown_from_collection" not in output

0 commit comments

Comments
 (0)