[5.4.x] Fix crash when printing while capsysbinary is active (#7002)

Backport of 1fda861190 from master.
This commit is contained in:
Ran Benita 2020-04-02 14:31:32 +03:00 committed by GitHub
parent f7327759e8
commit e3a3c90d94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 10 deletions

View File

@ -0,0 +1 @@
Fix crash with captured output when using the :fixture:`capsysbinary fixture <capsysbinary>`.

View File

@ -610,8 +610,6 @@ class FDCaptureBinary:
def writeorg(self, data):
""" write to original file descriptor. """
if isinstance(data, str):
data = data.encode("utf8") # XXX use encoding of original stream
os.write(self.targetfd_save, data)
@ -631,6 +629,11 @@ class FDCapture(FDCaptureBinary):
res = str(res, enc, "replace")
return res
def writeorg(self, data):
""" write to original file descriptor. """
data = data.encode("utf-8") # XXX use encoding of original stream
os.write(self.targetfd_save, data)
class SysCaptureBinary:
@ -682,8 +685,9 @@ class SysCaptureBinary:
self._state = "resumed"
def writeorg(self, data):
self._old.write(data)
self._old.flush()
self._old.buffer.write(data)
self._old.buffer.flush()
class SysCapture(SysCaptureBinary):
@ -695,6 +699,10 @@ class SysCapture(SysCaptureBinary):
self.tmpfile.truncate()
return res
def writeorg(self, data):
self._old.write(data)
self._old.flush()
class TeeSysCapture(SysCapture):
def __init__(self, fd, tmpfile=None):

View File

@ -542,18 +542,40 @@ class TestCaptureFixture:
reprec.assertoutcome(passed=1)
def test_capsysbinary(self, testdir):
reprec = testdir.inline_runsource(
"""\
p1 = testdir.makepyfile(
r"""
def test_hello(capsysbinary):
import sys
# some likely un-decodable bytes
sys.stdout.buffer.write(b'\\xfe\\x98\\x20')
sys.stdout.buffer.write(b'hello')
# Some likely un-decodable bytes.
sys.stdout.buffer.write(b'\xfe\x98\x20')
sys.stdout.buffer.flush()
# Ensure writing in text mode still works and is captured.
# https://github.com/pytest-dev/pytest/issues/6871
print("world", flush=True)
out, err = capsysbinary.readouterr()
assert out == b'\\xfe\\x98\\x20'
assert out == b'hello\xfe\x98\x20world\n'
assert err == b''
print("stdout after")
print("stderr after", file=sys.stderr)
"""
)
reprec.assertoutcome(passed=1)
result = testdir.runpytest(str(p1), "-rA")
result.stdout.fnmatch_lines(
[
"*- Captured stdout call -*",
"stdout after",
"*- Captured stderr call -*",
"stderr after",
"*= 1 passed in *",
]
)
def test_partial_setup_failure(self, testdir):
p = testdir.makepyfile(
@ -977,7 +999,7 @@ class TestFDCapture:
cap.start()
tmpfile.write(data1)
tmpfile.flush()
cap.writeorg(data2)
cap.writeorg(data2.decode("ascii"))
scap = cap.snap()
cap.done()
assert scap == data1.decode("ascii")