[Jython-checkins] jython: Check buffer and decoder types in _jyio.TextIOWrapper

jeff.allen jython-checkins at python.org
Fri Mar 22 23:59:29 CET 2013


http://hg.python.org/jython/rev/7eab1d85d3c7
changeset:   7102:7eab1d85d3c7
user:        Jeff Allen <ja...py at farowl.co.uk>
date:        Thu Mar 21 07:55:57 2013 +0000
summary:
  Check buffer and decoder types in _jyio.TextIOWrapper
We now pass the tests in test.test_io that require TextIOWrapper to verify
that the buffer returns bytes, and the decoder returns unicode.
We go one beyond CPython in requiring this of the unbounded read(),
as not doing so appears to have been an oversight in textio.c.

files:
  Lib/_jyio.py        |  35 ++++++++++++++++++++++++++++----
  Lib/test/test_io.py |   8 +++---
  2 files changed, 34 insertions(+), 9 deletions(-)


diff --git a/Lib/_jyio.py b/Lib/_jyio.py
--- a/Lib/_jyio.py
+++ b/Lib/_jyio.py
@@ -971,6 +971,20 @@
                )[self.seennl]
 
 
+def _check_decoded_chars(chars):
+    """Check decoder output is unicode"""
+    if not isinstance(chars, unicode):
+        raise TypeError("decoder should return a string result, not '%s'" %
+                        type(chars))
+
+def _check_buffered_bytes(b, context="read"):
+    """Check buffer has returned bytes"""
+    if not isinstance(b, str):
+        raise TypeError("underlying %s() should have returned a bytes object, not '%s'" %
+                        (context, type(b)))
+
+
+
 class TextIOWrapper(_TextIOBase):
 
     r"""Character and line based layer over a _BufferedIOBase object, buffer.
@@ -1216,8 +1230,12 @@
 
         # Read a chunk, decode it, and put the result in self._decoded_chars.
         input_chunk = self.buffer.read1(self._CHUNK_SIZE)
+        _check_buffered_bytes(input_chunk, "read1")
+
         eof = not input_chunk
-        self._set_decoded_chars(self._decoder.decode(input_chunk, eof))
+        decoded_chunk = self._decoder.decode(input_chunk, eof)
+        _check_decoded_chars(decoded_chunk)
+        self._set_decoded_chars(decoded_chunk)
 
         if self._telling:
             # At the snapshot point, len(dec_buffer) bytes before the read,
@@ -1370,8 +1388,11 @@
         if chars_to_skip:
             # Just like _read_chunk, feed the decoder and save a snapshot.
             input_chunk = self.buffer.read(bytes_to_feed)
-            self._set_decoded_chars(
-                self._decoder.decode(input_chunk, need_eof))
+            _check_buffered_bytes(input_chunk)
+            decoded_chunk = self._decoder.decode(input_chunk, need_eof)
+            _check_decoded_chars(decoded_chunk)
+            self._set_decoded_chars(decoded_chunk)
+
             self._snapshot = (dec_flags, input_chunk)
 
             # Skip chars_to_skip of the decoded characters.
@@ -1403,8 +1424,12 @@
             raise TypeError("an integer is required")
         if n < 0:
             # Read everything.
-            result = (self._get_decoded_chars() +
-                      decoder.decode(self.buffer.read(), final=True))
+            input_chunk = self.buffer.read()
+            # Jython difference: CPython textio.c omits:
+            _check_buffered_bytes(input_chunk)
+            decoded_chunk = decoder.decode(input_chunk, final=True)
+            _check_decoded_chars(decoded_chunk)
+            result = self._get_decoded_chars() + decoded_chunk
             self._set_decoded_chars('')
             self._snapshot = None
             return result
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -2491,7 +2491,6 @@
         with self.assertRaises((AttributeError, TypeError)):
             txt.buffer = buf
 
-    @unittest.skipIf(support.is_jython, "FIXME: missing check?")
     def test_read_nonbytes(self):
         # Issue #17106
         # Crash when underlying read() returns non-bytes
@@ -2506,9 +2505,10 @@
         with self.maybeRaises(TypeError):
             t.readline()
         t = self.TextIOWrapper(NonbytesStream('a'))
-        self.assertEqual(t.read(), u'a')
-
-    @unittest.skipIf(support.is_jython, "FIXME: missing check?")
+        with self.maybeRaises(TypeError):
+            # Jython difference: also detect the error in
+            t.read()
+
     def test_illegal_decoder(self):
         # Issue #17106
         # Crash when decoder returns non-string

-- 
Repository URL: http://hg.python.org/jython


More information about the Jython-checkins mailing list