# HG changeset patch
# Parent 154ae3af03173ce0f735b6dd47a37da97910f0b9
Document that âioâ methods should accept bytes-like objects as arguments
This matches the usage of ZipFile and BufferedWriter. This still requires
return values to be bytes() objects.
diff -r 154ae3af0317 Doc/library/io.rst
--- a/Doc/library/io.rst Fri Jan 09 16:40:38 2015 -0600
+++ b/Doc/library/io.rst Sat Jan 10 07:33:24 2015 +0000
@@ -66,7 +66,8 @@
Binary I/O
^^^^^^^^^^
-Binary I/O (also called *buffered I/O*) expects and produces :class:`bytes`
+Binary I/O (also called *buffered I/O*) expects
+:term:`bytes-like objects ` and produces :class:`bytes`
objects. No encoding, decoding, or newline translation is performed. This
category of streams can be used for all kinds of non-text data, and also when
manual control over the handling of text data is desired.
@@ -227,8 +228,9 @@
when operations they do not support are called.
The basic type used for binary data read from or written to a file is
- :class:`bytes`. :class:`bytearray`\s are accepted too, and in some cases
- (such as :meth:`readinto`) required. Text I/O classes work with
+ :class:`bytes`. Other :term:`bytes-like objects ` are
+ accepted too. In some cases, such as :meth:`~RawIOBase.readinto`,
+ :class:`bytearray` is required. Text I/O classes work with
:class:`str` data.
Note that calling any method (even inquiries) on a closed stream is
@@ -396,7 +398,7 @@
.. method:: write(b)
- Write the given :class:`bytes` or :class:`bytearray` object, *b*, to the
+ Write the given :term:`bytes-like object`, *b*, to the
underlying raw stream and return the number of bytes written. This can
be less than ``len(b)``, depending on specifics of the underlying raw
stream, and especially if it is in non-blocking mode. ``None`` is
@@ -495,7 +497,7 @@
.. method:: write(b)
- Write the given :class:`bytes` or :class:`bytearray` object, *b* and
+ Write the given :term:`bytes-like object`, *b*, and
return the number of bytes written (never less than ``len(b)``, since if
the write fails an :exc:`OSError` will be raised). Depending on the
actual implementation, these bytes may be readily written to the
@@ -580,7 +582,8 @@
A stream implementation using an in-memory bytes buffer. It inherits
:class:`BufferedIOBase`.
- The argument *initial_bytes* contains optional initial :class:`bytes` data.
+ The argument *initial_bytes* contains
+ optional initial :term:`bytes-like object` data.
:class:`BytesIO` provides or overrides these methods in addition to those
from :class:`BufferedIOBase` and :class:`IOBase`:
@@ -677,7 +680,7 @@
.. method:: write(b)
- Write the :class:`bytes` or :class:`bytearray` object, *b* and return the
+ Write the :term:`bytes-like object` object, *b*, and return the
number of bytes written. When in non-blocking mode, a
:exc:`BlockingIOError` is raised if the buffer needs to be written out but
the raw stream blocks.
diff -r 154ae3af0317 Lib/_pyio.py
--- a/Lib/_pyio.py Fri Jan 09 16:40:38 2015 -0600
+++ b/Lib/_pyio.py Sat Jan 10 07:33:24 2015 +0000
@@ -290,8 +290,8 @@
called.
The basic type used for binary data read from or written to a file is
- bytes. bytearrays are accepted too, and in some cases (such as
- readinto) needed. Text I/O classes work with str data.
+ bytes. Other bytes-like objects are accepted too. In some cases (such as
+ readinto), bytearray is required. Text I/O classes work with str data.
Note that calling any method (even inquiries) on a closed stream is
undefined. Implementations may raise OSError in this case.
@@ -878,7 +878,8 @@
raise ValueError("write to closed file")
if isinstance(b, str):
raise TypeError("can't write str to binary stream")
- n = len(b)
+ with memoryview(b) as view:
+ n = view.nbytes # Size of any bytes-like object
if n == 0:
return 0
pos = self._pos
diff -r 154ae3af0317 Lib/test/test_io.py
--- a/Lib/test/test_io.py Fri Jan 09 16:40:38 2015 -0600
+++ b/Lib/test/test_io.py Sat Jan 10 07:33:24 2015 +0000
@@ -528,10 +528,22 @@
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 make_file_writer():
+ return self.FileIO(support.TESTFN, "w")
+ def make_buffered_writer():
+ return self.BufferedWriter(self.MockRawIO())
+ def make_buffered_random():
+ return self.BufferedRandom(self.MockRawIO())
+ def make_buffered_rw_pair():
+ return self.BufferedRWPair(self.MockRawIO(), self.MockRawIO())
+ writer_factories = (
+ self.BytesIO, make_file_writer, make_buffered_writer,
+ make_buffered_random, make_buffered_rw_pair,
+ )
+ for factory in writer_factories:
+ with self.subTest(factory), factory() as f:
+ self.assertEqual(f.write(a), n)
+ f.writelines((a,))
def test_closefd(self):
self.assertRaises(ValueError, self.open, support.TESTFN, 'w',
diff -r 154ae3af0317 Lib/test/test_memoryio.py
--- a/Lib/test/test_memoryio.py Fri Jan 09 16:40:38 2015 -0600
+++ b/Lib/test/test_memoryio.py Sat Jan 10 07:33:24 2015 +0000
@@ -408,6 +408,15 @@
support.gc_collect()
memio.truncate()
+ def test_bytes_array(self):
+ buf = b"1234567890"
+ import array
+ a = array.array('b', list(buf))
+ memio = self.ioclass(a)
+ self.assertEqual(memio.getvalue(), buf)
+ self.assertEqual(memio.write(a), 10)
+ self.assertEqual(memio.getvalue(), buf)
+
class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin,
BytesIOMixin, unittest.TestCase):
@@ -483,15 +492,6 @@
self.assertRaises(TypeError, memio.write, "1234567890")
self.assertRaises(TypeError, memio.writelines, ["1234567890"])
- def test_bytes_array(self):
- buf = b"1234567890"
- import array
- a = array.array('b', list(buf))
- memio = self.ioclass(a)
- self.assertEqual(memio.getvalue(), buf)
- self.assertEqual(memio.write(a), 10)
- self.assertEqual(memio.getvalue(), buf)
-
def test_issue5449(self):
buf = self.buftype("1234567890")
self.ioclass(initial_bytes=buf)
diff -r 154ae3af0317 Modules/_io/fileio.c
--- a/Modules/_io/fileio.c Fri Jan 09 16:40:38 2015 -0600
+++ b/Modules/_io/fileio.c Sat Jan 10 07:33:24 2015 +0000
@@ -1118,7 +1118,8 @@
"or None if no data is available. On end-of-file, returns ''.");
PyDoc_STRVAR(write_doc,
-"write(b: bytes) -> int. Write bytes b to file, return number written.\n"
+"write(b) -> int. Write bytes-like object b to file; return number of bytes\n"
+"written.\n"
"\n"
"Only makes one system call, so not all of the data may be written.\n"
"The number of bytes actually written is returned.");