diff options
Diffstat (limited to 'Modules/_io')
-rw-r--r-- | Modules/_io/bufferedio.c | 56 | ||||
-rw-r--r-- | Modules/_io/textio.c | 51 |
2 files changed, 99 insertions, 8 deletions
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 3d175c7..2c65207 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -73,6 +73,18 @@ BufferedIOBase_unsupported(const char *message) return NULL; } +PyDoc_STRVAR(BufferedIOBase_detach_doc, + "Disconnect this buffer from its underlying raw stream and return it.\n" + "\n" + "After the raw stream has been detached, the buffer is in an unusable\n" + "state.\n"); + +static PyObject * +BufferedIOBase_detach(PyObject *self) +{ + return BufferedIOBase_unsupported("detach"); +} + PyDoc_STRVAR(BufferedIOBase_read_doc, "Read and return up to n bytes.\n" "\n" @@ -127,6 +139,7 @@ BufferedIOBase_write(PyObject *self, PyObject *args) static PyMethodDef BufferedIOBase_methods[] = { + {"detach", (PyCFunction)BufferedIOBase_detach, METH_NOARGS, BufferedIOBase_detach_doc}, {"read", BufferedIOBase_read, METH_VARARGS, BufferedIOBase_read_doc}, {"read1", BufferedIOBase_read1, METH_VARARGS, BufferedIOBase_read1_doc}, {"readinto", BufferedIOBase_readinto, METH_VARARGS, NULL}, @@ -181,6 +194,7 @@ typedef struct { PyObject *raw; int ok; /* Initialized? */ + int detached; int readable; int writable; @@ -260,15 +274,25 @@ typedef struct { #define CHECK_INITIALIZED(self) \ if (self->ok <= 0) { \ - PyErr_SetString(PyExc_ValueError, \ - "I/O operation on uninitialized object"); \ + if (self->detached) { \ + PyErr_SetString(PyExc_ValueError, \ + "raw stream has been detached"); \ + } else { \ + PyErr_SetString(PyExc_ValueError, \ + "I/O operation on uninitialized object"); \ + } \ return NULL; \ } #define CHECK_INITIALIZED_INT(self) \ if (self->ok <= 0) { \ - PyErr_SetString(PyExc_ValueError, \ - "I/O operation on uninitialized object"); \ + if (self->detached) { \ + PyErr_SetString(PyExc_ValueError, \ + "raw stream has been detached"); \ + } else { \ + PyErr_SetString(PyExc_ValueError, \ + "I/O operation on uninitialized object"); \ + } \ return -1; \ } @@ -430,6 +454,24 @@ end: return res; } +/* detach */ + +static PyObject * +BufferedIOMixin_detach(BufferedObject *self, PyObject *args) +{ + PyObject *raw, *res; + CHECK_INITIALIZED(self) + res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL); + if (res == NULL) + return NULL; + Py_DECREF(res); + raw = self->raw; + self->raw = NULL; + self->detached = 1; + self->ok = 0; + return raw; +} + /* Inquiries */ static PyObject * @@ -1101,6 +1143,7 @@ BufferedReader_init(BufferedObject *self, PyObject *args, PyObject *kwds) PyObject *raw; self->ok = 0; + self->detached = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist, &raw, &buffer_size)) { @@ -1387,6 +1430,7 @@ _BufferedReader_peek_unlocked(BufferedObject *self, Py_ssize_t n) static PyMethodDef BufferedReader_methods[] = { /* BufferedIOMixin methods */ + {"detach", (PyCFunction)BufferedIOMixin_detach, METH_NOARGS}, {"flush", (PyCFunction)BufferedIOMixin_flush, METH_NOARGS}, {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS}, {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS}, @@ -1499,6 +1543,7 @@ BufferedWriter_init(BufferedObject *self, PyObject *args, PyObject *kwds) PyObject *raw; self->ok = 0; + self->detached = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist, &raw, &buffer_size, &max_buffer_size)) { @@ -1745,6 +1790,7 @@ error: static PyMethodDef BufferedWriter_methods[] = { /* BufferedIOMixin methods */ {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS}, + {"detach", (PyCFunction)BufferedIOMixin_detach, METH_NOARGS}, {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS}, {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS}, {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS}, @@ -2089,6 +2135,7 @@ BufferedRandom_init(BufferedObject *self, PyObject *args, PyObject *kwds) PyObject *raw; self->ok = 0; + self->detached = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist, &raw, &buffer_size, &max_buffer_size)) { @@ -2128,6 +2175,7 @@ BufferedRandom_init(BufferedObject *self, PyObject *args, PyObject *kwds) static PyMethodDef BufferedRandom_methods[] = { /* BufferedIOMixin methods */ {"close", (PyCFunction)BufferedIOMixin_close, METH_NOARGS}, + {"detach", (PyCFunction)BufferedIOMixin_detach, METH_NOARGS}, {"seekable", (PyCFunction)BufferedIOMixin_seekable, METH_NOARGS}, {"readable", (PyCFunction)BufferedIOMixin_readable, METH_NOARGS}, {"writable", (PyCFunction)BufferedIOMixin_writable, METH_NOARGS}, diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 26fc68d..f201ba7 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -28,6 +28,19 @@ _unsupported(const char *message) return NULL; } +PyDoc_STRVAR(TextIOBase_detach_doc, + "Separate the underlying buffer from the TextIOBase and return it.\n" + "\n" + "After the underlying buffer has been detached, the TextIO is in an\n" + "unusable state.\n" + ); + +static PyObject * +TextIOBase_detach(PyObject *self) +{ + return _unsupported("detach"); +} + PyDoc_STRVAR(TextIOBase_read_doc, "Read at most n characters from stream.\n" "\n" @@ -93,6 +106,7 @@ TextIOBase_newlines_get(PyObject *self, void *context) static PyMethodDef TextIOBase_methods[] = { + {"detach", (PyCFunction)TextIOBase_detach, METH_NOARGS, TextIOBase_detach_doc}, {"read", TextIOBase_read, METH_VARARGS, TextIOBase_read_doc}, {"readline", TextIOBase_readline, METH_VARARGS, TextIOBase_readline_doc}, {"write", TextIOBase_write, METH_VARARGS, TextIOBase_write_doc}, @@ -616,6 +630,7 @@ typedef struct { PyObject_HEAD int ok; /* initialized? */ + int detached; Py_ssize_t chunk_size; PyObject *buffer; PyObject *encoding; @@ -759,6 +774,7 @@ TextIOWrapper_init(PyTextIOWrapperObject *self, PyObject *args, PyObject *kwds) int r; self->ok = 0; + self->detached = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|zzzi:fileio", kwlist, &buffer, &encoding, &errors, &newline, &line_buffering)) @@ -1059,19 +1075,45 @@ TextIOWrapper_closed_get(PyTextIOWrapperObject *self, void *context); #define CHECK_INITIALIZED(self) \ if (self->ok <= 0) { \ - PyErr_SetString(PyExc_ValueError, \ - "I/O operation on uninitialized object"); \ + if (self->detached) { \ + PyErr_SetString(PyExc_ValueError, \ + "underlying buffer has been detached"); \ + } else { \ + PyErr_SetString(PyExc_ValueError, \ + "I/O operation on uninitialized object"); \ + } \ return NULL; \ } #define CHECK_INITIALIZED_INT(self) \ if (self->ok <= 0) { \ - PyErr_SetString(PyExc_ValueError, \ - "I/O operation on uninitialized object"); \ + if (self->detached) { \ + PyErr_SetString(PyExc_ValueError, \ + "underlying buffer has been detached"); \ + } else { \ + PyErr_SetString(PyExc_ValueError, \ + "I/O operation on uninitialized object"); \ + } \ return -1; \ } +static PyObject * +TextIOWrapper_detach(PyTextIOWrapperObject *self) +{ + PyObject *buffer, *res; + CHECK_INITIALIZED(self); + res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL); + if (res == NULL) + return NULL; + Py_DECREF(res); + buffer = self->buffer; + self->buffer = NULL; + self->detached = 1; + self->ok = 0; + return buffer; +} + Py_LOCAL_INLINE(const Py_UNICODE *) findchar(const Py_UNICODE *s, Py_ssize_t size, Py_UNICODE ch) { @@ -2341,6 +2383,7 @@ TextIOWrapper_chunk_size_set(PyTextIOWrapperObject *self, } static PyMethodDef TextIOWrapper_methods[] = { + {"detach", (PyCFunction)TextIOWrapper_detach, METH_NOARGS}, {"write", (PyCFunction)TextIOWrapper_write, METH_VARARGS}, {"read", (PyCFunction)TextIOWrapper_read, METH_VARARGS}, {"readline", (PyCFunction)TextIOWrapper_readline, METH_VARARGS}, |