Source

py-patches / capture-bytes

# HG changeset patch
# Parent 0e9b0af624e13e1cbb3cd7a058a20722c6c89cdc
use the replace handler for stray bytes on stdout/err capture

diff --git a/py/_io/capture.py b/py/_io/capture.py
--- a/py/_io/capture.py
+++ b/py/_io/capture.py
@@ -12,7 +12,7 @@ if sys.version_info < (3,0):
     class TextIO(StringIO):
         def write(self, data):
             if not isinstance(data, unicode):
-                data = unicode(data, getattr(self, '_encoding', 'UTF-8'))
+                data = unicode(data, getattr(self, '_encoding', 'UTF-8'), 'replace')
             StringIO.write(self, data)
 else:
     TextIO = StringIO
@@ -260,7 +260,7 @@ class StdCaptureFD(Capture):
                 res = f.read()
                 enc = getattr(f, 'encoding', None)
                 if enc:
-                    res = py.builtin._totext(res, enc)
+                    res = py.builtin._totext(res, enc, 'replace')
                 f.truncate(0)
                 f.seek(0)
             l.append(res)
diff --git a/testing/io_/test_capture.py b/testing/io_/test_capture.py
--- a/testing/io_/test_capture.py
+++ b/testing/io_/test_capture.py
@@ -219,6 +219,15 @@ class TestStdCapture:
         out, err = cap.readouterr()
         assert out == py.builtin._totext("hx\xc4\x85\xc4\x87\n", "utf8")
 
+    @py.test.mark.skipif('sys.version_info >= (3,)',
+                      reason='text output different for bytes on python3')
+    def test_capturing_readouterr_decode_error_handling(self):
+        cap = self.getcapture()
+        # triggered a internal error in pytest
+        print('\xa6')
+        out, err = cap.readouterr()
+        assert out == py.builtin._totext('\ufffd\n', 'unicode-escape')
+
     def test_capturing_mixed(self):
         cap = self.getcapture(mixed=True)
         sys.stdout.write("hello ")