summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorMartin Panter <vadmium+py@gmail.com>2016-05-28 00:41:57 (GMT)
committerMartin Panter <vadmium+py@gmail.com>2016-05-28 00:41:57 (GMT)
commit6bb91f3b6e51352f91bcf785d3f6fe160ed2cd85 (patch)
tree0f97c3f8b3fac65680e880ec870796138af78faf /Lib/test
parentfc36e66af46957a65b12ab0087027727f8555aed (diff)
downloadcpython-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.py78
-rw-r--r--Lib/test/test_memoryio.py23
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)