Merge pull request #2266 from asottile/capture_v2
Make capsys more like stdio streams in python3. Resolves #1407.
This commit is contained in:
commit
0f3d7acdc4
1
AUTHORS
1
AUTHORS
|
@ -13,6 +13,7 @@ Andrzej Ostrowski
|
|||
Andy Freeland
|
||||
Anthon van der Neut
|
||||
Antony Lee
|
||||
Anthony Sottile
|
||||
Armin Rigo
|
||||
Aron Curzon
|
||||
Aviv Palivoda
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue