[Python-checkins] cpython (merge 3.4 -> default): merge 3.4 (#23093)

benjamin.peterson python-checkins at python.org
Mon Dec 22 04:01:33 CET 2014


https://hg.python.org/cpython/rev/f2cfa8a348dd
changeset:   93946:f2cfa8a348dd
parent:      93943:75ede5bec8db
parent:      93944:f3ff3e424b6f
user:        Benjamin Peterson <benjamin at python.org>
date:        Sun Dec 21 21:00:51 2014 -0600
summary:
  merge 3.4 (#23093)

files:
  Lib/_pyio.py             |   6 +-
  Lib/test/test_io.py      |  14 +++++
  Misc/NEWS                |   3 +
  Modules/_io/bufferedio.c |   2 +-
  Modules/_io/textio.c     |  78 ++++++++++++++-------------
  5 files changed, 61 insertions(+), 42 deletions(-)


diff --git a/Lib/_pyio.py b/Lib/_pyio.py
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -812,7 +812,7 @@
         clsname = self.__class__.__qualname__
         try:
             name = self.name
-        except AttributeError:
+        except Exception:
             return "<{}.{}>".format(modname, clsname)
         else:
             return "<{}.{} name={!r}>".format(modname, clsname, name)
@@ -1640,13 +1640,13 @@
                                  self.__class__.__qualname__)
         try:
             name = self.name
-        except AttributeError:
+        except Exception:
             pass
         else:
             result += " name={0!r}".format(name)
         try:
             mode = self.mode
-        except AttributeError:
+        except Exception:
             pass
         else:
             result += " mode={0!r}".format(mode)
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -697,6 +697,8 @@
         self.assertIs(buf.detach(), raw)
         self.assertRaises(ValueError, buf.detach)
 
+        repr(buf)  # Should still work
+
     def test_fileno(self):
         rawio = self.MockRawIO()
         bufio = self.tp(rawio)
@@ -2087,6 +2089,12 @@
         self.assertEqual(r.getvalue(), b"howdy")
         self.assertRaises(ValueError, t.detach)
 
+        # Operations independent of the detached stream should still work
+        repr(t)
+        self.assertEqual(t.encoding, "ascii")
+        self.assertEqual(t.errors, "strict")
+        self.assertFalse(t.line_buffering)
+
     def test_repr(self):
         raw = self.BytesIO("hello".encode("utf-8"))
         b = self.BufferedReader(raw)
@@ -2104,6 +2112,9 @@
         self.assertEqual(repr(t),
                          "<%s.TextIOWrapper name=b'dummy' mode='r' encoding='utf-8'>" % modname)
 
+        t.buffer.detach()
+        repr(t)  # Should not raise an exception
+
     def test_line_buffering(self):
         r = self.BytesIO()
         b = self.BufferedWriter(r, 1000)
@@ -2904,6 +2915,9 @@
         self.assertRaises(ValueError, t.__init__, b, newline='xyzzy')
         self.assertRaises(ValueError, t.read)
 
+        t = self.TextIOWrapper.__new__(self.TextIOWrapper)
+        self.assertRaises(Exception, repr, t)
+
     def test_garbage_collection(self):
         # C TextIOWrapper objects are collected, and collecting them flushes
         # all data to disk.
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -196,6 +196,9 @@
 Library
 -------
 
+- Issue #23093: In the io, module allow more operations to work on detached
+  streams.
+
 - Issue #22585: On OpenBSD 5.6 and newer, os.urandom() now calls getentropy(),
   instead of reading /dev/urandom, to get pseudo-random bytes.
 
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -1404,7 +1404,7 @@
 
     nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name);
     if (nameobj == NULL) {
-        if (PyErr_ExceptionMatches(PyExc_AttributeError))
+        if (PyErr_ExceptionMatches(PyExc_Exception))
             PyErr_Clear();
         else
             return NULL;
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -1219,25 +1219,27 @@
 
 #define CHECK_INITIALIZED(self) \
     if (self->ok <= 0) { \
-        if (self->detached) { \
-            PyErr_SetString(PyExc_ValueError, \
-                 "underlying buffer has been detached"); \
-        } else {                                   \
-            PyErr_SetString(PyExc_ValueError, \
-                "I/O operation on uninitialized object"); \
-        } \
+        PyErr_SetString(PyExc_ValueError, \
+            "I/O operation on uninitialized object"); \
         return NULL; \
     }
 
-#define CHECK_INITIALIZED_INT(self) \
+#define CHECK_ATTACHED(self) \
+    CHECK_INITIALIZED(self); \
+    if (self->detached) { \
+        PyErr_SetString(PyExc_ValueError, \
+             "underlying buffer has been detached"); \
+        return NULL; \
+    }
+
+#define CHECK_ATTACHED_INT(self) \
     if (self->ok <= 0) { \
-        if (self->detached) { \
-            PyErr_SetString(PyExc_ValueError, \
-                 "underlying buffer has been detached"); \
-        } else {                                   \
-            PyErr_SetString(PyExc_ValueError, \
-                "I/O operation on uninitialized object"); \
-        } \
+        PyErr_SetString(PyExc_ValueError, \
+            "I/O operation on uninitialized object"); \
+        return -1; \
+    } else if (self->detached) { \
+        PyErr_SetString(PyExc_ValueError, \
+             "underlying buffer has been detached"); \
         return -1; \
     }
 
@@ -1246,7 +1248,7 @@
 textiowrapper_detach(textio *self)
 {
     PyObject *buffer, *res;
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
     res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
     if (res == NULL)
         return NULL;
@@ -1254,7 +1256,6 @@
     buffer = self->buffer;
     self->buffer = NULL;
     self->detached = 1;
-    self->ok = 0;
     return buffer;
 }
 
@@ -1299,7 +1300,7 @@
     int haslf = 0;
     int needflush = 0, text_needflush = 0;
 
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
 
     if (!PyArg_ParseTuple(args, "U:write", &text)) {
         return NULL;
@@ -1562,7 +1563,7 @@
     Py_ssize_t n = -1;
     PyObject *result = NULL, *chunks = NULL;
 
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
 
     if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n))
         return NULL;
@@ -1937,7 +1938,7 @@
 {
     Py_ssize_t limit = -1;
 
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
     if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
         return NULL;
     }
@@ -2075,7 +2076,7 @@
     PyObject *res;
     int cmp;
 
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
 
     if (!PyArg_ParseTuple(args, "O|i:seek", &cookieObj, &whence))
         return NULL;
@@ -2255,7 +2256,7 @@
     Py_ssize_t dec_buffer_len;
     int dec_flags;
 
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
     CHECK_CLOSED(self);
 
     if (!self->seekable) {
@@ -2458,7 +2459,7 @@
     PyObject *pos = Py_None;
     PyObject *res;
 
-    CHECK_INITIALIZED(self)
+    CHECK_ATTACHED(self)
     if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
         return NULL;
     }
@@ -2481,9 +2482,10 @@
     res = PyUnicode_FromString("<_io.TextIOWrapper");
     if (res == NULL)
         return NULL;
+
     nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name);
     if (nameobj == NULL) {
-        if (PyErr_ExceptionMatches(PyExc_AttributeError))
+        if (PyErr_ExceptionMatches(PyExc_Exception))
             PyErr_Clear();
         else
             goto error;
@@ -2499,7 +2501,7 @@
     }
     modeobj = _PyObject_GetAttrId((PyObject *) self, &PyId_mode);
     if (modeobj == NULL) {
-        if (PyErr_ExceptionMatches(PyExc_AttributeError))
+        if (PyErr_ExceptionMatches(PyExc_Exception))
             PyErr_Clear();
         else
             goto error;
@@ -2528,35 +2530,35 @@
 static PyObject *
 textiowrapper_fileno(textio *self, PyObject *args)
 {
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
     return _PyObject_CallMethodId(self->buffer, &PyId_fileno, NULL);
 }
 
 static PyObject *
 textiowrapper_seekable(textio *self, PyObject *args)
 {
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
     return _PyObject_CallMethodId(self->buffer, &PyId_seekable, NULL);
 }
 
 static PyObject *
 textiowrapper_readable(textio *self, PyObject *args)
 {
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
     return _PyObject_CallMethodId(self->buffer, &PyId_readable, NULL);
 }
 
 static PyObject *
 textiowrapper_writable(textio *self, PyObject *args)
 {
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
     return _PyObject_CallMethodId(self->buffer, &PyId_writable, NULL);
 }
 
 static PyObject *
 textiowrapper_isatty(textio *self, PyObject *args)
 {
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
     return _PyObject_CallMethodId(self->buffer, &PyId_isatty, NULL);
 }
 
@@ -2571,7 +2573,7 @@
 static PyObject *
 textiowrapper_flush(textio *self, PyObject *args)
 {
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
     CHECK_CLOSED(self);
     self->telling = self->seekable;
     if (_textiowrapper_writeflush(self) < 0)
@@ -2584,7 +2586,7 @@
 {
     PyObject *res;
     int r;
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
 
     res = textiowrapper_closed_get(self, NULL);
     if (res == NULL)
@@ -2626,7 +2628,7 @@
 {
     PyObject *line;
 
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
 
     self->telling = 0;
     if (Py_TYPE(self) == &PyTextIOWrapper_Type) {
@@ -2662,14 +2664,14 @@
 static PyObject *
 textiowrapper_name_get(textio *self, void *context)
 {
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
     return _PyObject_GetAttrId(self->buffer, &PyId_name);
 }
 
 static PyObject *
 textiowrapper_closed_get(textio *self, void *context)
 {
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
     return PyObject_GetAttr(self->buffer, _PyIO_str_closed);
 }
 
@@ -2677,7 +2679,7 @@
 textiowrapper_newlines_get(textio *self, void *context)
 {
     PyObject *res;
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
     if (self->decoder == NULL)
         Py_RETURN_NONE;
     res = PyObject_GetAttr(self->decoder, _PyIO_str_newlines);
@@ -2703,7 +2705,7 @@
 static PyObject *
 textiowrapper_chunk_size_get(textio *self, void *context)
 {
-    CHECK_INITIALIZED(self);
+    CHECK_ATTACHED(self);
     return PyLong_FromSsize_t(self->chunk_size);
 }
 
@@ -2711,7 +2713,7 @@
 textiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context)
 {
     Py_ssize_t n;
-    CHECK_INITIALIZED_INT(self);
+    CHECK_ATTACHED_INT(self);
     n = PyNumber_AsSsize_t(arg, PyExc_ValueError);
     if (n == -1 && PyErr_Occurred())
         return -1;

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list