@@ -73,6 +73,18 @@ BufferedIOBase_unsupported(const char *message)
7373 return NULL ;
7474}
7575
76+ PyDoc_STRVAR (BufferedIOBase_detach_doc ,
77+ "Disconnect this buffer from its underlying raw stream and return it.\n"
78+ "\n"
79+ "After the raw stream has been detached, the buffer is in an unusable\n"
80+ "state.\n" );
81+
82+ static PyObject *
83+ BufferedIOBase_detach (PyObject * self )
84+ {
85+ return BufferedIOBase_unsupported ("detach" );
86+ }
87+
7688PyDoc_STRVAR (BufferedIOBase_read_doc ,
7789 "Read and return up to n bytes.\n"
7890 "\n"
@@ -127,6 +139,7 @@ BufferedIOBase_write(PyObject *self, PyObject *args)
127139
128140
129141static PyMethodDef BufferedIOBase_methods [] = {
142+ {"detach" , (PyCFunction )BufferedIOBase_detach , METH_NOARGS , BufferedIOBase_detach_doc },
130143 {"read" , BufferedIOBase_read , METH_VARARGS , BufferedIOBase_read_doc },
131144 {"read1" , BufferedIOBase_read1 , METH_VARARGS , BufferedIOBase_read1_doc },
132145 {"readinto" , BufferedIOBase_readinto , METH_VARARGS , NULL },
@@ -181,6 +194,7 @@ typedef struct {
181194
182195 PyObject * raw ;
183196 int ok ; /* Initialized? */
197+ int detached ;
184198 int readable ;
185199 int writable ;
186200
@@ -260,15 +274,25 @@ typedef struct {
260274
261275#define CHECK_INITIALIZED (self ) \
262276 if (self->ok <= 0) { \
263- PyErr_SetString(PyExc_ValueError, \
264- "I/O operation on uninitialized object"); \
277+ if (self->detached) { \
278+ PyErr_SetString(PyExc_ValueError, \
279+ "raw stream has been detached"); \
280+ } else { \
281+ PyErr_SetString(PyExc_ValueError, \
282+ "I/O operation on uninitialized object"); \
283+ } \
265284 return NULL; \
266285 }
267286
268287#define CHECK_INITIALIZED_INT (self ) \
269288 if (self->ok <= 0) { \
270- PyErr_SetString(PyExc_ValueError, \
271- "I/O operation on uninitialized object"); \
289+ if (self->detached) { \
290+ PyErr_SetString(PyExc_ValueError, \
291+ "raw stream has been detached"); \
292+ } else { \
293+ PyErr_SetString(PyExc_ValueError, \
294+ "I/O operation on uninitialized object"); \
295+ } \
272296 return -1; \
273297 }
274298
@@ -430,6 +454,24 @@ BufferedIOMixin_close(BufferedObject *self, PyObject *args)
430454 return res ;
431455}
432456
457+ /* detach */
458+
459+ static PyObject *
460+ BufferedIOMixin_detach (BufferedObject * self , PyObject * args )
461+ {
462+ PyObject * raw , * res ;
463+ CHECK_INITIALIZED (self )
464+ res = PyObject_CallMethodObjArgs ((PyObject * )self , _PyIO_str_flush , NULL );
465+ if (res == NULL )
466+ return NULL ;
467+ Py_DECREF (res );
468+ raw = self -> raw ;
469+ self -> raw = NULL ;
470+ self -> detached = 1 ;
471+ self -> ok = 0 ;
472+ return raw ;
473+ }
474+
433475/* Inquiries */
434476
435477static PyObject *
@@ -1101,6 +1143,7 @@ BufferedReader_init(BufferedObject *self, PyObject *args, PyObject *kwds)
11011143 PyObject * raw ;
11021144
11031145 self -> ok = 0 ;
1146+ self -> detached = 0 ;
11041147
11051148 if (!PyArg_ParseTupleAndKeywords (args , kwds , "O|n:BufferedReader" , kwlist ,
11061149 & raw , & buffer_size )) {
@@ -1387,6 +1430,7 @@ _BufferedReader_peek_unlocked(BufferedObject *self, Py_ssize_t n)
13871430
13881431static PyMethodDef BufferedReader_methods [] = {
13891432 /* BufferedIOMixin methods */
1433+ {"detach" , (PyCFunction )BufferedIOMixin_detach , METH_NOARGS },
13901434 {"flush" , (PyCFunction )BufferedIOMixin_flush , METH_NOARGS },
13911435 {"close" , (PyCFunction )BufferedIOMixin_close , METH_NOARGS },
13921436 {"seekable" , (PyCFunction )BufferedIOMixin_seekable , METH_NOARGS },
@@ -1499,6 +1543,7 @@ BufferedWriter_init(BufferedObject *self, PyObject *args, PyObject *kwds)
14991543 PyObject * raw ;
15001544
15011545 self -> ok = 0 ;
1546+ self -> detached = 0 ;
15021547
15031548 if (!PyArg_ParseTupleAndKeywords (args , kwds , "O|nn:BufferedReader" , kwlist ,
15041549 & raw , & buffer_size , & max_buffer_size )) {
@@ -1745,6 +1790,7 @@ BufferedWriter_write(BufferedObject *self, PyObject *args)
17451790static PyMethodDef BufferedWriter_methods [] = {
17461791 /* BufferedIOMixin methods */
17471792 {"close" , (PyCFunction )BufferedIOMixin_close , METH_NOARGS },
1793+ {"detach" , (PyCFunction )BufferedIOMixin_detach , METH_NOARGS },
17481794 {"seekable" , (PyCFunction )BufferedIOMixin_seekable , METH_NOARGS },
17491795 {"readable" , (PyCFunction )BufferedIOMixin_readable , METH_NOARGS },
17501796 {"writable" , (PyCFunction )BufferedIOMixin_writable , METH_NOARGS },
@@ -2089,6 +2135,7 @@ BufferedRandom_init(BufferedObject *self, PyObject *args, PyObject *kwds)
20892135 PyObject * raw ;
20902136
20912137 self -> ok = 0 ;
2138+ self -> detached = 0 ;
20922139
20932140 if (!PyArg_ParseTupleAndKeywords (args , kwds , "O|nn:BufferedReader" , kwlist ,
20942141 & raw , & buffer_size , & max_buffer_size )) {
@@ -2128,6 +2175,7 @@ BufferedRandom_init(BufferedObject *self, PyObject *args, PyObject *kwds)
21282175static PyMethodDef BufferedRandom_methods [] = {
21292176 /* BufferedIOMixin methods */
21302177 {"close" , (PyCFunction )BufferedIOMixin_close , METH_NOARGS },
2178+ {"detach" , (PyCFunction )BufferedIOMixin_detach , METH_NOARGS },
21312179 {"seekable" , (PyCFunction )BufferedIOMixin_seekable , METH_NOARGS },
21322180 {"readable" , (PyCFunction )BufferedIOMixin_readable , METH_NOARGS },
21332181 {"writable" , (PyCFunction )BufferedIOMixin_writable , METH_NOARGS },
0 commit comments