Issue #12175: BufferedReader.read(-1) now calls raw.readall() if available.

This commit is contained in:
Victor Stinner 2011-05-26 00:19:38 +02:00
parent e9d44ccb22
commit b57f108b03
5 changed files with 48 additions and 11 deletions

View File

@ -944,6 +944,12 @@ class BufferedReader(_BufferedIOMixin):
# Special case for when the number of bytes to read is unspecified.
if n is None or n == -1:
self._reset_read_buf()
if hasattr(self.raw, 'readall'):
chunk = self.raw.readall()
if chunk is None:
return buf[pos:] or None
else:
return buf[pos:] + chunk
chunks = [buf[pos:]] # Strip the consumed bytes.
current_size = 0
while True:

View File

@ -161,6 +161,8 @@ Core and Builtins
Library
-------
- Issue #12175: BufferedReader.read(-1) now calls raw.readall() if available.
- Issue #12175: FileIO.readall() now only reads the file position and size
once.

View File

@ -36,6 +36,7 @@ PyObject *_PyIO_str_nl;
PyObject *_PyIO_str_read;
PyObject *_PyIO_str_read1;
PyObject *_PyIO_str_readable;
PyObject *_PyIO_str_readall;
PyObject *_PyIO_str_readinto;
PyObject *_PyIO_str_readline;
PyObject *_PyIO_str_reset;
@ -767,6 +768,8 @@ PyInit__io(void)
goto fail;
if (!(_PyIO_str_readable = PyUnicode_InternFromString("readable")))
goto fail;
if (!(_PyIO_str_readall = PyUnicode_InternFromString("readall")))
goto fail;
if (!(_PyIO_str_readinto = PyUnicode_InternFromString("readinto")))
goto fail;
if (!(_PyIO_str_readline = PyUnicode_InternFromString("readline")))

View File

@ -155,6 +155,7 @@ extern PyObject *_PyIO_str_nl;
extern PyObject *_PyIO_str_read;
extern PyObject *_PyIO_str_read1;
extern PyObject *_PyIO_str_readable;
extern PyObject *_PyIO_str_readall;
extern PyObject *_PyIO_str_readinto;
extern PyObject *_PyIO_str_readline;
extern PyObject *_PyIO_str_reset;

View File

@ -1407,32 +1407,57 @@ static PyObject *
_bufferedreader_read_all(buffered *self)
{
Py_ssize_t current_size;
PyObject *res, *data = NULL;
PyObject *chunks = PyList_New(0);
if (chunks == NULL)
return NULL;
PyObject *res, *data = NULL, *chunk, *chunks;
/* First copy what we have in the current buffer. */
current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
if (current_size) {
data = PyBytes_FromStringAndSize(
self->buffer + self->pos, current_size);
if (data == NULL) {
Py_DECREF(chunks);
if (data == NULL)
return NULL;
}
}
_bufferedreader_reset_buf(self);
/* We're going past the buffer's bounds, flush it */
if (self->writable) {
res = _bufferedwriter_flush_unlocked(self, 1);
if (res == NULL) {
Py_DECREF(chunks);
if (res == NULL)
return NULL;
}
Py_CLEAR(res);
}
if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) {
chunk = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL);
if (chunk == NULL)
return NULL;
if (chunk != Py_None && !PyBytes_Check(chunk)) {
Py_XDECREF(data);
Py_DECREF(chunk);
PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
return NULL;
}
if (chunk == Py_None) {
if (current_size == 0)
return chunk;
else {
Py_DECREF(chunk);
return data;
}
}
else if (current_size) {
PyBytes_Concat(&data, chunk);
Py_DECREF(chunk);
if (data == NULL)
return NULL;
return data;
} else
return chunk;
}
chunks = PyList_New(0);
if (chunks == NULL)
return NULL;
while (1) {
if (data) {
if (PyList_Append(chunks, data) < 0) {