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