diff options
author | Martin Panter <vadmium+py@gmail.com> | 2016-05-28 00:41:57 (GMT) |
---|---|---|
committer | Martin Panter <vadmium+py@gmail.com> | 2016-05-28 00:41:57 (GMT) |
commit | 6bb91f3b6e51352f91bcf785d3f6fe160ed2cd85 (patch) | |
tree | 0f97c3f8b3fac65680e880ec870796138af78faf /Lib/test | |
parent | fc36e66af46957a65b12ab0087027727f8555aed (diff) | |
download | cpython-6bb91f3b6e51352f91bcf785d3f6fe160ed2cd85.zip cpython-6bb91f3b6e51352f91bcf785d3f6fe160ed2cd85.tar.gz cpython-6bb91f3b6e51352f91bcf785d3f6fe160ed2cd85.tar.bz2 |
Issue #20699: Document that “io” methods accept bytes-like objects
This matches the usage of ZipFile and BufferedWriter. This still requires
return values to be bytes() objects.
Also document and test that the write() methods should only access their
argument before they return.
Diffstat (limited to 'Lib/test')
-rw-r--r-- | Lib/test/test_io.py | 78 | ||||
-rw-r--r-- | Lib/test/test_memoryio.py | 23 |
2 files changed, 74 insertions, 27 deletions
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index a7bb95b..7323198 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -45,6 +45,22 @@ try: except ImportError: threading = None +try: + import ctypes +except ImportError: + def byteslike(*pos, **kw): + return array.array("b", bytes(*pos, **kw)) +else: + def byteslike(*pos, **kw): + """Create a bytes-like object having no string or sequence methods""" + data = bytes(*pos, **kw) + obj = EmptyStruct() + ctypes.resize(obj, len(data)) + memoryview(obj).cast("B")[:] = data + return obj + class EmptyStruct(ctypes.Structure): + pass + def _default_chunk_size(): """Get the default TextIOWrapper chunk size""" with open(__file__, "r", encoding="latin-1") as f: @@ -284,7 +300,9 @@ class IOTest(unittest.TestCase): self.assertEqual(f.tell(), 6) self.assertEqual(f.seek(-1, 1), 5) self.assertEqual(f.tell(), 5) - self.assertEqual(f.write(bytearray(b" world\n\n\n")), 9) + buffer = bytearray(b" world\n\n\n") + self.assertEqual(f.write(buffer), 9) + buffer[:] = b"*" * 9 # Overwrite our copy of the data self.assertEqual(f.seek(0), 0) self.assertEqual(f.write(b"h"), 1) self.assertEqual(f.seek(-1, 2), 13) @@ -297,20 +315,21 @@ class IOTest(unittest.TestCase): def read_ops(self, f, buffered=False): data = f.read(5) self.assertEqual(data, b"hello") - data = bytearray(data) + data = byteslike(data) self.assertEqual(f.readinto(data), 5) - self.assertEqual(data, b" worl") + self.assertEqual(bytes(data), b" worl") + data = bytearray(5) self.assertEqual(f.readinto(data), 2) self.assertEqual(len(data), 5) self.assertEqual(data[:2], b"d\n") self.assertEqual(f.seek(0), 0) self.assertEqual(f.read(20), b"hello world\n") self.assertEqual(f.read(1), b"") - self.assertEqual(f.readinto(bytearray(b"x")), 0) + self.assertEqual(f.readinto(byteslike(b"x")), 0) self.assertEqual(f.seek(-6, 2), 6) self.assertEqual(f.read(5), b"world") self.assertEqual(f.read(0), b"") - self.assertEqual(f.readinto(bytearray()), 0) + self.assertEqual(f.readinto(byteslike()), 0) self.assertEqual(f.seek(-6, 1), 5) self.assertEqual(f.read(5), b" worl") self.assertEqual(f.tell(), 10) @@ -321,6 +340,10 @@ class IOTest(unittest.TestCase): f.seek(6) self.assertEqual(f.read(), b"world\n") self.assertEqual(f.read(), b"") + f.seek(0) + data = byteslike(5) + self.assertEqual(f.readinto1(data), 5) + self.assertEqual(bytes(data), b"hello") LARGE = 2**31 @@ -637,10 +660,15 @@ class IOTest(unittest.TestCase): def test_array_writes(self): a = array.array('i', range(10)) n = len(a.tobytes()) - with self.open(support.TESTFN, "wb", 0) as f: - self.assertEqual(f.write(a), n) - with self.open(support.TESTFN, "wb") as f: - self.assertEqual(f.write(a), n) + def check(f): + with f: + self.assertEqual(f.write(a), n) + f.writelines((a,)) + check(self.BytesIO()) + check(self.FileIO(support.TESTFN, "w")) + check(self.BufferedWriter(self.MockRawIO())) + check(self.BufferedRandom(self.MockRawIO())) + check(self.BufferedRWPair(self.MockRawIO(), self.MockRawIO())) def test_closefd(self): self.assertRaises(ValueError, self.open, support.TESTFN, 'w', @@ -799,6 +827,19 @@ class IOTest(unittest.TestCase): with self.assertRaises(ValueError): self.open(support.TESTFN, 'w', newline='invalid') + def test_buffered_readinto_mixin(self): + # Test the implementation provided by BufferedIOBase + class Stream(self.BufferedIOBase): + def read(self, size): + return b"12345" + read1 = read + stream = Stream() + for method in ("readinto", "readinto1"): + with self.subTest(method): + buffer = byteslike(5) + self.assertEqual(getattr(stream, method)(buffer), 5) + self.assertEqual(bytes(buffer), b"12345") + class CIOTest(IOTest): @@ -1390,6 +1431,11 @@ class BufferedWriterTest(unittest.TestCase, CommonBufferedTests): bufio = self.tp(writer, 8) bufio.write(b"abc") self.assertFalse(writer._write_stack) + buffer = bytearray(b"def") + bufio.write(buffer) + buffer[:] = b"***" # Overwrite our copy of the data + bufio.flush() + self.assertEqual(b"".join(writer._write_stack), b"abcdef") def test_write_overflow(self): writer = self.MockRawIO() @@ -1716,11 +1762,13 @@ class BufferedRWPairTest(unittest.TestCase): self.assertEqual(pair.read1(3), b"abc") def test_readinto(self): - pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO()) + for method in ("readinto", "readinto1"): + with self.subTest(method): + pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO()) - data = bytearray(5) - self.assertEqual(pair.readinto(data), 5) - self.assertEqual(data, b"abcde") + data = byteslike(5) + self.assertEqual(getattr(pair, method)(data), 5) + self.assertEqual(bytes(data), b"abcde") def test_write(self): w = self.MockRawIO() @@ -1728,7 +1776,9 @@ class BufferedRWPairTest(unittest.TestCase): pair.write(b"abc") pair.flush() - pair.write(b"def") + buffer = bytearray(b"def") + pair.write(buffer) + buffer[:] = b"***" # Overwrite our copy of the data pair.flush() self.assertEqual(w._write_stack, [b"abc", b"def"]) diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py index 812db4c..55b693e 100644 --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -399,7 +399,16 @@ class MemoryTestMixin: del __main__.PickleTestMemIO -class BytesIOMixin: +class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase): + # Test _pyio.BytesIO; class also inherited for testing C implementation + + UnsupportedOperation = pyio.UnsupportedOperation + + @staticmethod + def buftype(s): + return s.encode("ascii") + ioclass = pyio.BytesIO + EOF = b"" def test_getbuffer(self): memio = self.ioclass(b"1234567890") @@ -426,18 +435,6 @@ class BytesIOMixin: memio.close() self.assertRaises(ValueError, memio.getbuffer) - -class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, - BytesIOMixin, unittest.TestCase): - - UnsupportedOperation = pyio.UnsupportedOperation - - @staticmethod - def buftype(s): - return s.encode("ascii") - ioclass = pyio.BytesIO - EOF = b"" - def test_read1(self): buf = self.buftype("1234567890") memio = self.ioclass(buf) |