[Python-checkins] cpython (3.4): allow more operations to work on detached streams (closes #23093)

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


https://hg.python.org/cpython/rev/f3ff3e424b6f
changeset: 93944:f3ff3e424b6f
branch: 3.4
parent: 93940:872f048f0403
user: Benjamin Peterson <benjamin at python.org>
date: Sun Dec 21 20:51:50 2014 -0600
summary:
 allow more operations to work on detached streams (closes #23093)
Patch by Martin Panter.
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
@@ -793,7 +793,7 @@
 clsname = self.__class__.__name__
 try:
 name = self.name
- except AttributeError:
+ except Exception:
 return "<_pyio.{0}>".format(clsname)
 else:
 return "<_pyio.{0} name={1!r}>".format(clsname, name)
@@ -1561,13 +1561,13 @@
 result = "<_pyio.TextIOWrapper"
 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
@@ -701,6 +701,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)
@@ -2026,6 +2028,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)
@@ -2043,6 +2051,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)
@@ -2813,6 +2824,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
@@ -41,6 +41,9 @@
 Library
 -------
 
+- Issue #23093: In the io, module allow more operations to work on detached
+ streams.
+
 - Issue #19104: pprint now produces evaluable output for wrapped strings.
 
 - Issue #23071: Added missing names to codecs.__all__. Patch by Martin Panter.
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -1359,7 +1359,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;
@@ -1556,7 +1557,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;
@@ -1931,7 +1932,7 @@
 {
 Py_ssize_t limit = -1;
 
- CHECK_INITIALIZED(self);
+ CHECK_ATTACHED(self);
 if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
 return NULL;
 }
@@ -2069,7 +2070,7 @@
 PyObject *res;
 int cmp;
 
- CHECK_INITIALIZED(self);
+ CHECK_ATTACHED(self);
 
 if (!PyArg_ParseTuple(args, "O|i:seek", &cookieObj, &whence))
 return NULL;
@@ -2249,7 +2250,7 @@
 Py_ssize_t dec_buffer_len;
 int dec_flags;
 
- CHECK_INITIALIZED(self);
+ CHECK_ATTACHED(self);
 CHECK_CLOSED(self);
 
 if (!self->seekable) {
@@ -2452,7 +2453,7 @@
 PyObject *pos = Py_None;
 PyObject *res;
 
- CHECK_INITIALIZED(self)
+ CHECK_ATTACHED(self)
 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
 return NULL;
 }
@@ -2475,9 +2476,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;
@@ -2493,7 +2495,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;
@@ -2522,35 +2524,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);
 }
 
@@ -2565,7 +2567,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)
@@ -2578,7 +2580,7 @@
 {
 PyObject *res;
 int r;
- CHECK_INITIALIZED(self);
+ CHECK_ATTACHED(self);
 
 res = textiowrapper_closed_get(self, NULL);
 if (res == NULL)
@@ -2620,7 +2622,7 @@
 {
 PyObject *line;
 
- CHECK_INITIALIZED(self);
+ CHECK_ATTACHED(self);
 
 self->telling = 0;
 if (Py_TYPE(self) == &PyTextIOWrapper_Type) {
@@ -2656,14 +2658,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);
 }
 
@@ -2671,7 +2673,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);
@@ -2697,7 +2699,7 @@
 static PyObject *
 textiowrapper_chunk_size_get(textio *self, void *context)
 {
- CHECK_INITIALIZED(self);
+ CHECK_ATTACHED(self);
 return PyLong_FromSsize_t(self->chunk_size);
 }
 
@@ -2705,7 +2707,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

AltStyle によって変換されたページ (->オリジナル) /