]> granicus.if.org Git - python/commitdiff
Issue #12175: BufferedReader.read(-1) now calls raw.readall() if available.
authorVictor Stinner <victor.stinner@haypocalc.com>
Wed, 25 May 2011 22:19:38 +0000 (00:19 +0200)
committerVictor Stinner <victor.stinner@haypocalc.com>
Wed, 25 May 2011 22:19:38 +0000 (00:19 +0200)
Lib/_pyio.py
Misc/NEWS
Modules/_io/_iomodule.c
Modules/_io/_iomodule.h
Modules/_io/bufferedio.c

index 74047bf475be277c7f53fdcf763396e847fb1840..265edab1134548c33589112c071beda38b7384c0 100644 (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:
index d1db0ab73842ba0ace1b0af64a1dd24b8b5ceb56..b7f39077f472af82bb564d6053360a85de5a5c5d 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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.
 
index 44bdac6b5cf41126a99936cdcad7f11b71967fff..6f5bd48780c02cddcd34c1600e493d6c9d86c773 100644 (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")))
index 925e4f2cc72a11ef5502472d49b74b274e5be22a..9174bdd1c8c9bc9ea32b48db9f9a541968eef73d 100644 (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;
index 3b8b7e97ecc256fd7ef0c30070155aebfbdc1610..63ae1cbd1d8da48536ef7b64859613e23c777dda 100644 (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) {