Issue #12175: BufferedReader.read(-1) now calls raw.readall() if available.
This commit is contained in:
parent
e9d44ccb22
commit
b57f108b03
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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")))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue