Merge pull request #2266 from asottile/capture_v2

Make capsys more like stdio streams in python3. Resolves #1407.
This commit is contained in:
Bruno Oliveira 2017-02-24 20:18:55 -03:00 committed by GitHub
commit 0f3d7acdc4
6 changed files with 51 additions and 10 deletions

View File

@ -13,6 +13,7 @@ Andrzej Ostrowski
Andy Freeland
Anthon van der Neut
Antony Lee
Anthony Sottile
Armin Rigo
Aron Curzon
Aviv Palivoda

View File

@ -55,6 +55,14 @@ Changes
Thanks `@The-Compiler`_ for the PR.
Bug Fixes
---------
* Fix ``AttributeError`` on ``sys.stdout.buffer`` / ``sys.stderr.buffer``
while using ``capsys`` fixture in python 3. (`#1407`_).
Thanks to `@asottile`_.
.. _@davidszotten: https://github.com/davidszotten
.. _@fushi: https://github.com/fushi
.. _@mattduck: https://github.com/mattduck
@ -65,6 +73,7 @@ Changes
.. _@unsignedint: https://github.com/unsignedint
.. _@Kriechi: https://github.com/Kriechi
.. _#1407: https://github.com/pytest-dev/pytest/issues/1407
.. _#1512: https://github.com/pytest-dev/pytest/issues/1512
.. _#1874: https://github.com/pytest-dev/pytest/pull/1874
.. _#1952: https://github.com/pytest-dev/pytest/pull/1952

View File

@ -12,8 +12,8 @@ from tempfile import TemporaryFile
import py
import pytest
from _pytest.compat import CaptureIO
from py.io import TextIO
unicode = py.builtin.text
patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'}
@ -403,7 +403,7 @@ class SysCapture(object):
if name == "stdin":
tmpfile = DontReadFromInput()
else:
tmpfile = TextIO()
tmpfile = CaptureIO()
self.tmpfile = tmpfile
def start(self):

View File

@ -251,3 +251,19 @@ else:
except UnicodeError:
errors = 'replace'
return v.encode('ascii', errors)
if _PY2:
from py.io import TextIO as CaptureIO
else:
import io
class CaptureIO(io.TextIOWrapper):
def __init__(self):
super(CaptureIO, self).__init__(
io.BytesIO(),
encoding='UTF-8', newline='', write_through=True,
)
def getvalue(self):
return self.buffer.getvalue().decode('UTF-8')

View File

@ -14,6 +14,7 @@ from weakref import WeakKeyDictionary
from py.builtin import print_
from _pytest.capture import MultiCapture, SysCapture
from _pytest._code import Source
import py
import pytest
@ -737,7 +738,8 @@ class Testdir(object):
if kwargs.get("syspathinsert"):
self.syspathinsert()
now = time.time()
capture = py.io.StdCapture()
capture = MultiCapture(Capture=SysCapture)
capture.start_capturing()
try:
try:
reprec = self.inline_run(*args, **kwargs)
@ -752,7 +754,8 @@ class Testdir(object):
class reprec(object):
ret = 3
finally:
out, err = capture.reset()
out, err = capture.readouterr()
capture.stop_capturing()
sys.stdout.write(out)
sys.stderr.write(err)

View File

@ -281,7 +281,7 @@ class TestLoggingInteraction(object):
def test_logging():
import logging
import pytest
stream = capture.TextIO()
stream = capture.CaptureIO()
logging.basicConfig(stream=stream)
stream.close() # to free memory/release resources
""")
@ -622,16 +622,16 @@ def test_error_during_readouterr(testdir):
])
class TestTextIO(object):
class TestCaptureIO(object):
def test_text(self):
f = capture.TextIO()
f = capture.CaptureIO()
f.write("hello")
s = f.getvalue()
assert s == "hello"
f.close()
def test_unicode_and_str_mixture(self):
f = capture.TextIO()
f = capture.CaptureIO()
if sys.version_info >= (3, 0):
f.write("\u00f6")
pytest.raises(TypeError, "f.write(bytes('hello', 'UTF-8'))")
@ -642,6 +642,18 @@ class TestTextIO(object):
f.close()
assert isinstance(s, unicode)
@pytest.mark.skipif(
sys.version_info[0] == 2,
reason='python 3 only behaviour',
)
def test_write_bytes_to_buffer(self):
"""In python3, stdout / stderr are text io wrappers (exposing a buffer
property of the underlying bytestream). See issue #1407
"""
f = capture.CaptureIO()
f.buffer.write(b'foo\r\n')
assert f.getvalue() == 'foo\r\n'
def test_bytes_io():
f = py.io.BytesIO()
@ -900,8 +912,8 @@ class TestStdCapture(object):
with self.getcapture() as cap:
sys.stdout.write("hello")
sys.stderr.write("world")
sys.stdout = capture.TextIO()
sys.stderr = capture.TextIO()
sys.stdout = capture.CaptureIO()
sys.stderr = capture.CaptureIO()
print ("not seen")
sys.stderr.write("not seen\n")
out, err = cap.readouterr()