summaryrefslogtreecommitdiffstats
path: root/Modules/_io/textio.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_io/textio.c')
-rw-r--r--Modules/_io/textio.c94
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},