Issue #20699: Document that “io” methods should accept memoryview

This matches the usage by BufferedReader, BufferedWriter, etc. Also document
and test that the write() methods should only access their argument before
they return.
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index b7f6046..e26ffba 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -54,6 +54,9 @@
 __metaclass__ = type
 bytes = support.py3k_bytes
 
+def byteslike(*pos, **kw):
+    return memoryview(bytearray(*pos, **kw))
+
 def _default_chunk_size():
     """Get the default TextIOWrapper chunk size"""
     with io.open(__file__, "r", encoding="latin1") as f:
@@ -273,7 +276,9 @@
         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)
@@ -286,20 +291,21 @@
     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(data.tobytes(), 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)
@@ -649,6 +655,16 @@
             support.gc_collect()
         self.assertEqual(recorded, [])
 
+    def test_buffered_readinto_mixin(self):
+        # Test the implementation provided by BufferedIOBase
+        class Stream(self.BufferedIOBase):
+            def read(self, size):
+                return b"12345"
+        stream = Stream()
+        buffer = byteslike(5)
+        self.assertEqual(stream.readinto(buffer), 5)
+        self.assertEqual(buffer.tobytes(), b"12345")
+
 
 class CIOTest(IOTest):
 
@@ -1111,6 +1127,11 @@
         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()
@@ -1440,9 +1461,9 @@
     def test_readinto(self):
         pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO())
 
-        data = bytearray(5)
+        data = byteslike(5)
         self.assertEqual(pair.readinto(data), 5)
-        self.assertEqual(data, b"abcde")
+        self.assertEqual(data.tobytes(), b"abcde")
 
     def test_write(self):
         w = self.MockRawIO()
@@ -1450,7 +1471,9 @@
 
         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"])