diff --git a/CHANGELOG b/CHANGELOG index e135eb644..0c4303b45 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,10 +5,9 @@ Changes between 1.0.0 and 1.0.1 nose-style function/method/generator setup/teardown and tries to report functions correctly. -* unicode fixes: capturing and unicode writes to sys.stdout - (through e.g a print statement) now work within tests, - they are encoded as "utf8" by default, also terminalwriting - was adapted and somewhat unified between windows and linux +* capturing of unicode writes to sys.stdout/err work better within + encoded as "utf8" by default, also terminalwriting was adapted + and somewhat unified between windows and linux * improved documentation layout and content a lot diff --git a/py/test/plugin/pytest_capture.py b/py/test/plugin/pytest_capture.py index e43aa8559..2b985556e 100644 --- a/py/test/plugin/pytest_capture.py +++ b/py/test/plugin/pytest_capture.py @@ -110,8 +110,8 @@ class CaptureManager: def _maketempfile(self): f = py.std.tempfile.TemporaryFile() newf = py.io.dupfile(f) - f.close() - return ustream(newf) + encoding = getattr(newf, 'encoding', None) or "UTF-8" + return EncodedFile(newf, encoding) def _makestringio(self): return py.std.StringIO.StringIO() @@ -269,12 +269,21 @@ class CaptureFuncarg: self.capture.reset() del self.capture -def ustream(f): - import codecs - encoding = getattr(f, 'encoding', None) or "UTF-8" - reader = codecs.getreader(encoding) - writer = codecs.getwriter(encoding) - srw = codecs.StreamReaderWriter(f, reader, writer) - srw.encoding = encoding - return srw +class EncodedFile(object): + def __init__(self, _stream, encoding): + self._stream = _stream + self.encoding = encoding + + def write(self, obj): + if isinstance(obj, unicode): + self._stream.write(obj.encode(self.encoding)) + else: + self._stream.write(obj) + + def writelines(self, linelist): + data = ''.join(linelist) + self.write(data) + + def __getattr__(self, name): + return getattr(self._stream, name) diff --git a/py/test/plugin/test_pytest_capture.py b/py/test/plugin/test_pytest_capture.py index 298764963..4e07750ae 100644 --- a/py/test/plugin/test_pytest_capture.py +++ b/py/test/plugin/test_pytest_capture.py @@ -1,8 +1,7 @@ import py, os, sys -from py.__.test.plugin.pytest_capture import CaptureManager, ustream +from py.__.test.plugin.pytest_capture import CaptureManager, EncodedFile class TestCaptureManager: - def test_configure_per_fspath(self, testdir): config = testdir.parseconfig(testdir.tmpdir) assert config.getvalue("capture") is None @@ -57,7 +56,7 @@ class TestCaptureManager: @py.test.mark.multi(method=['fd', 'sys']) def test_capturing_unicode(testdir, method): testdir.makepyfile(""" - # taken from issue 227 from nosests + # taken from issue 227 from nosetests def test_unicode(): import sys print sys.stdout @@ -68,14 +67,27 @@ def test_capturing_unicode(testdir, method): "*1 passed*" ]) -def test_ustream_helper(testdir): +@py.test.mark.multi(method=['fd', 'sys']) +def test_capturing_bytes_in_utf8_encoding(testdir, method): + testdir.makepyfile(""" + def test_unicode(): + print '\\xe2' + """) + result = testdir.runpytest("--capture=%s" % method) + result.stdout.fnmatch_lines([ + "*1 passed*" + ]) + +def test_UnicodeFile(testdir): p = testdir.makepyfile("hello") f = p.open('w') - #f.encoding = "utf8" - x = ustream(f) - x.write(u'b\\00f6y') - x.close() - + pf = EncodedFile(f, "UTF-8") + pf.write(u'b\\00f6y\n') + pf.write('b\\00f6y\n') + pf.close() + assert f.closed + lines = p.readlines() + assert lines[0] == lines[1] def test_collect_capturing(testdir): p = testdir.makepyfile("""