diff options
Diffstat (limited to 'Modules/_io/textio.c')
| -rw-r--r-- | Modules/_io/textio.c | 94 |
1 files changed, 68 insertions, 26 deletions
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index b039c2f..73d83a1 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -658,6 +658,7 @@ typedef struct char writetranslate; char seekable; char telling; + char deallocating; /* Specialized encoding func (see below) */ encodefunc_t encodefunc; /* Whether or not it's the start of the stream */ @@ -905,8 +906,11 @@ textiowrapper_init(textio *self, PyObject *args, PyObject *kwds) Py_CLEAR(self->encoding); } } - if (self->encoding != NULL) + if (self->encoding != NULL) { encoding = _PyUnicode_AsString(self->encoding); + if (encoding == NULL) + goto error; + } else if (encoding != NULL) { self->encoding = PyUnicode_FromString(encoding); if (self->encoding == NULL) @@ -935,6 +939,8 @@ textiowrapper_init(textio *self, PyObject *args, PyObject *kwds) self->writetranslate = (newline == NULL || newline[0] != '\0'); if (!self->readuniversal && self->readnl) { self->writenl = _PyUnicode_AsString(self->readnl); + if (self->writenl == NULL) + goto error; if (!strcmp(self->writenl, "\n")) self->writenl = NULL; } @@ -1089,6 +1095,7 @@ _textiowrapper_clear(textio *self) static void textiowrapper_dealloc(textio *self) { + self->deallocating = 1; if (_textiowrapper_clear(self) < 0) return; _PyObject_GC_UNTRACK(self); @@ -1254,10 +1261,8 @@ textiowrapper_write(textio *self, PyObject *args) CHECK_CLOSED(self); - if (self->encoder == NULL) { - PyErr_SetString(PyExc_IOError, "not writable"); - return NULL; - } + if (self->encoder == NULL) + return _unsupported("not writable"); Py_INCREF(text); @@ -1394,7 +1399,7 @@ textiowrapper_read_chunk(textio *self) */ if (self->decoder == NULL) { - PyErr_SetString(PyExc_IOError, "not readable"); + _unsupported("not readable"); return -1; } @@ -1484,10 +1489,8 @@ textiowrapper_read(textio *self, PyObject *args) CHECK_CLOSED(self); - if (self->decoder == NULL) { - PyErr_SetString(PyExc_IOError, "not readable"); - return NULL; - } + if (self->decoder == NULL) + return _unsupported("not readable"); if (_textiowrapper_writeflush(self) < 0) return NULL; @@ -1978,8 +1981,7 @@ textiowrapper_seek(textio *self, PyObject *args) Py_INCREF(cookieObj); if (!self->seekable) { - PyErr_SetString(PyExc_IOError, - "underlying stream is not seekable"); + _unsupported("underlying stream is not seekable"); goto fail; } @@ -1990,8 +1992,7 @@ textiowrapper_seek(textio *self, PyObject *args) goto fail; if (cmp == 0) { - PyErr_SetString(PyExc_IOError, - "can't do nonzero cur-relative seeks"); + _unsupported("can't do nonzero cur-relative seeks"); goto fail; } @@ -2011,8 +2012,7 @@ textiowrapper_seek(textio *self, PyObject *args) goto fail; if (cmp == 0) { - PyErr_SetString(PyExc_IOError, - "can't do nonzero end-relative seeks"); + _unsupported("can't do nonzero end-relative seeks"); goto fail; } @@ -2146,8 +2146,7 @@ textiowrapper_tell(textio *self, PyObject *args) CHECK_CLOSED(self); if (!self->seekable) { - PyErr_SetString(PyExc_IOError, - "underlying stream is not seekable"); + _unsupported("underlying stream is not seekable"); goto fail; } if (!self->telling) { @@ -2324,25 +2323,52 @@ textiowrapper_truncate(textio *self, PyObject *args) static PyObject * textiowrapper_repr(textio *self) { - PyObject *nameobj, *res; + PyObject *nameobj, *modeobj, *res, *s; CHECK_INITIALIZED(self); + res = PyUnicode_FromString("<_io.TextIOWrapper"); + if (res == NULL) + return NULL; nameobj = PyObject_GetAttrString((PyObject *) self, "name"); if (nameobj == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) PyErr_Clear(); else - return NULL; - res = PyUnicode_FromFormat("<_io.TextIOWrapper encoding=%R>", - self->encoding); + goto error; } else { - res = PyUnicode_FromFormat("<_io.TextIOWrapper name=%R encoding=%R>", - nameobj, self->encoding); + s = PyUnicode_FromFormat(" name=%R", nameobj); Py_DECREF(nameobj); + if (s == NULL) + goto error; + PyUnicode_AppendAndDel(&res, s); + if (res == NULL) + return NULL; } - return res; + modeobj = PyObject_GetAttrString((PyObject *) self, "mode"); + if (modeobj == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) + PyErr_Clear(); + else + goto error; + } + else { + s = PyUnicode_FromFormat(" mode=%R", modeobj); + Py_DECREF(modeobj); + if (s == NULL) + goto error; + PyUnicode_AppendAndDel(&res, s); + if (res == NULL) + return NULL; + } + s = PyUnicode_FromFormat("%U encoding=%R>", + res, self->encoding); + Py_DECREF(res); + return s; +error: + Py_XDECREF(res); + return NULL; } @@ -2384,6 +2410,14 @@ textiowrapper_isatty(textio *self, PyObject *args) } static PyObject * +textiowrapper_getstate(textio *self, PyObject *args) +{ + PyErr_Format(PyExc_TypeError, + "cannot serialize '%s' object", Py_TYPE(self)->tp_name); + return NULL; +} + +static PyObject * textiowrapper_flush(textio *self, PyObject *args) { CHECK_INITIALIZED(self); @@ -2408,11 +2442,18 @@ textiowrapper_close(textio *self, PyObject *args) Py_DECREF(res); if (r < 0) return NULL; - + if (r > 0) { Py_RETURN_NONE; /* stream already closed */ } else { + if (self->deallocating) { + res = PyObject_CallMethod(self->buffer, "_dealloc_warn", "O", self); + if (res) + Py_DECREF(res); + else + PyErr_Clear(); + } res = PyObject_CallMethod((PyObject *)self, "flush", NULL); if (res == NULL) { return NULL; @@ -2540,6 +2581,7 @@ static PyMethodDef textiowrapper_methods[] = { {"readable", (PyCFunction)textiowrapper_readable, METH_NOARGS}, {"writable", (PyCFunction)textiowrapper_writable, METH_NOARGS}, {"isatty", (PyCFunction)textiowrapper_isatty, METH_NOARGS}, + {"__getstate__", (PyCFunction)textiowrapper_getstate, METH_NOARGS}, {"seek", (PyCFunction)textiowrapper_seek, METH_VARARGS}, {"tell", (PyCFunction)textiowrapper_tell, METH_NOARGS}, |
