Skip to content
2 changes: 1 addition & 1 deletion Lib/test/test_descr.py
Original file line number Diff line number Diff line change
Expand Up @@ -3405,7 +3405,7 @@ def test_descrdoc(self):
from _io import FileIO
def check(descr, what):
self.assertEqual(descr.__doc__, what)
check(FileIO.closed, "True if the file is closed") # getset descriptor
check(FileIO.closed, "True if the file is closed.") # getset descriptor
check(complex.real, "the real part of a complex number") # member descriptor

def test_doc_descriptor(self):
Expand Down
6 changes: 1 addition & 5 deletions Lib/test/test_inspect/test_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -6280,11 +6280,7 @@ def test_gc_module_has_signatures(self):
self._test_module_has_signatures(gc, no_signature)

def test_io_module_has_signatures(self):
methods_no_signature = {
'BufferedRWPair': {'read', 'peek', 'read1', 'readinto', 'readinto1', 'write'},
}
self._test_module_has_signatures(io,
methods_no_signature=methods_no_signature)
self._test_module_has_signatures(io)

def test_itertools_module_has_signatures(self):
import itertools
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:meth:`io.RawIOBase.readinto` and :meth:`io.RawIOBase.write` now raise
:exc:`TypeError` instead of :exc:`NotImplementedError`
if they are called without the required argument.
162 changes: 110 additions & 52 deletions Modules/_io/bufferedio.c
Original file line number Diff line number Diff line change
Expand Up @@ -2333,94 +2333,143 @@ bufferedrwpair_dealloc(PyObject *op)
Py_DECREF(tp);
}

/* Call the method of the underlying reader or writer. The argument is
only passed if it is not NULL, so that the default of that method is
used otherwise. */
static PyObject *
_forward_call(buffered *self, PyObject *name, PyObject *args)
_forward_call(buffered *self, PyObject *name, PyObject *arg)
{
PyObject *func, *ret;
if (self == NULL) {
PyErr_SetString(PyExc_ValueError,
"I/O operation on uninitialized object");
return NULL;
}

func = PyObject_GetAttr((PyObject *)self, name);
if (func == NULL) {
PyErr_SetObject(PyExc_AttributeError, name);
return NULL;
if (arg == NULL) {
return PyObject_CallMethodNoArgs((PyObject *)self, name);
}

ret = PyObject_CallObject(func, args);
Py_DECREF(func);
return ret;
return PyObject_CallMethodOneArg((PyObject *)self, name, arg);
}

/*[clinic input]
_io.BufferedRWPair.read
size: object(c_default="NULL") = -1
/
[clinic start generated code]*/

static PyObject *
bufferedrwpair_read(PyObject *op, PyObject *args)
_io_BufferedRWPair_read_impl(rwpair *self, PyObject *size)
/*[clinic end generated code: output=0668e3c5dbd3e93d input=eddb5e52aba9ebe5]*/
{
rwpair *self = rwpair_CAST(op);
return _forward_call(self->reader, &_Py_ID(read), args);
return _forward_call(self->reader, &_Py_ID(read), size);
}

/*[clinic input]
_io.BufferedRWPair.peek
size: object(c_default="NULL") = 0
/
[clinic start generated code]*/

static PyObject *
bufferedrwpair_peek(PyObject *op, PyObject *args)
_io_BufferedRWPair_peek_impl(rwpair *self, PyObject *size)
/*[clinic end generated code: output=190a267bd694efa0 input=36af95964bebe355]*/
{
rwpair *self = rwpair_CAST(op);
return _forward_call(self->reader, &_Py_ID(peek), args);
return _forward_call(self->reader, &_Py_ID(peek), size);
}

/*[clinic input]
_io.BufferedRWPair.read1
size: object(c_default="NULL") = -1
/
[clinic start generated code]*/

static PyObject *
bufferedrwpair_read1(PyObject *op, PyObject *args)
_io_BufferedRWPair_read1_impl(rwpair *self, PyObject *size)
/*[clinic end generated code: output=17ec19608f2bb825 input=9e94db423e490b58]*/
{
rwpair *self = rwpair_CAST(op);
return _forward_call(self->reader, &_Py_ID(read1), args);
return _forward_call(self->reader, &_Py_ID(read1), size);
}

/*[clinic input]
_io.BufferedRWPair.readinto
buffer: object
/
[clinic start generated code]*/

static PyObject *
bufferedrwpair_readinto(PyObject *op, PyObject *args)
_io_BufferedRWPair_readinto_impl(rwpair *self, PyObject *buffer)
/*[clinic end generated code: output=16c86b071015f7a4 input=ccd86ce2666261f7]*/
{
rwpair *self = rwpair_CAST(op);
return _forward_call(self->reader, &_Py_ID(readinto), args);
return _forward_call(self->reader, &_Py_ID(readinto), buffer);
}

/*[clinic input]
_io.BufferedRWPair.readinto1
buffer: object
/
[clinic start generated code]*/

static PyObject *
bufferedrwpair_readinto1(PyObject *op, PyObject *args)
_io_BufferedRWPair_readinto1_impl(rwpair *self, PyObject *buffer)
/*[clinic end generated code: output=f1577b6f54c2b02a input=613d9bf127f88a4a]*/
{
rwpair *self = rwpair_CAST(op);
return _forward_call(self->reader, &_Py_ID(readinto1), args);
return _forward_call(self->reader, &_Py_ID(readinto1), buffer);
}

/*[clinic input]
_io.BufferedRWPair.write
buffer: object
/
[clinic start generated code]*/

static PyObject *
bufferedrwpair_write(PyObject *op, PyObject *args)
_io_BufferedRWPair_write_impl(rwpair *self, PyObject *buffer)
/*[clinic end generated code: output=6f7509a747410c68 input=66c602422e3ec36f]*/
{
rwpair *self = rwpair_CAST(op);
return _forward_call(self->writer, &_Py_ID(write), args);
return _forward_call(self->writer, &_Py_ID(write), buffer);
}

/*[clinic input]
_io.BufferedRWPair.flush
[clinic start generated code]*/

static PyObject *
bufferedrwpair_flush(PyObject *op, PyObject *Py_UNUSED(dummy))
_io_BufferedRWPair_flush_impl(rwpair *self)
/*[clinic end generated code: output=0b2dcbe828718d6b input=e853da796ee61df1]*/
{
rwpair *self = rwpair_CAST(op);
return _forward_call(self->writer, &_Py_ID(flush), NULL);
}

/*[clinic input]
_io.BufferedRWPair.readable
[clinic start generated code]*/

static PyObject *
bufferedrwpair_readable(PyObject *op, PyObject *Py_UNUSED(dummy))
_io_BufferedRWPair_readable_impl(rwpair *self)
/*[clinic end generated code: output=615967d4aa58f122 input=0475ed73d0a3167f]*/
{
rwpair *self = rwpair_CAST(op);
return _forward_call(self->reader, &_Py_ID(readable), NULL);
}

/*[clinic input]
_io.BufferedRWPair.writable
[clinic start generated code]*/

static PyObject *
bufferedrwpair_writable(PyObject *op, PyObject *Py_UNUSED(dummy))
_io_BufferedRWPair_writable_impl(rwpair *self)
/*[clinic end generated code: output=c5a43c84e0195c11 input=3cfd44fb4757082f]*/
{
rwpair *self = rwpair_CAST(op);
return _forward_call(self->writer, &_Py_ID(writable), NULL);
}

/*[clinic input]
_io.BufferedRWPair.close
[clinic start generated code]*/

static PyObject *
bufferedrwpair_close(PyObject *op, PyObject *Py_UNUSED(dummy))
_io_BufferedRWPair_close_impl(rwpair *self)
/*[clinic end generated code: output=5924ba5ecc78752a input=4087d69f2d8fc368]*/
{
rwpair *self = rwpair_CAST(op);
PyObject *exc = NULL;
PyObject *ret = _forward_call(self->writer, &_Py_ID(close), NULL);
if (ret == NULL) {
Expand All @@ -2437,10 +2486,14 @@ bufferedrwpair_close(PyObject *op, PyObject *Py_UNUSED(dummy))
return ret;
}

/*[clinic input]
_io.BufferedRWPair.isatty
[clinic start generated code]*/

static PyObject *
bufferedrwpair_isatty(PyObject *op, PyObject *Py_UNUSED(dummy))
_io_BufferedRWPair_isatty_impl(rwpair *self)
/*[clinic end generated code: output=d017c621ed879cb7 input=92833e3d60586e14]*/
{
rwpair *self = rwpair_CAST(op);
PyObject *ret = _forward_call(self->writer, &_Py_ID(isatty), NULL);

if (ret != Py_False) {
Expand All @@ -2452,10 +2505,15 @@ bufferedrwpair_isatty(PyObject *op, PyObject *Py_UNUSED(dummy))
return _forward_call(self->reader, &_Py_ID(isatty), NULL);
}

/*[clinic input]
@getter
_io.BufferedRWPair.closed
[clinic start generated code]*/

static PyObject *
bufferedrwpair_closed_get(PyObject *op, void *Py_UNUSED(dummy))
_io_BufferedRWPair_closed_get_impl(rwpair *self)
/*[clinic end generated code: output=4117400c74766f21 input=8248430ac54e5b25]*/
{
rwpair *self = rwpair_CAST(op);
if (self->writer == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"the BufferedRWPair object is being garbage-collected");
Expand Down Expand Up @@ -2670,20 +2728,20 @@ PyType_Spec _Py_bufferedwriter_spec = {
};

static PyMethodDef bufferedrwpair_methods[] = {
{"read", bufferedrwpair_read, METH_VARARGS},
{"peek", bufferedrwpair_peek, METH_VARARGS},
{"read1", bufferedrwpair_read1, METH_VARARGS},
{"readinto", bufferedrwpair_readinto, METH_VARARGS},
{"readinto1", bufferedrwpair_readinto1, METH_VARARGS},
_IO_BUFFEREDRWPAIR_READ_METHODDEF
_IO_BUFFEREDRWPAIR_PEEK_METHODDEF
_IO_BUFFEREDRWPAIR_READ1_METHODDEF
_IO_BUFFEREDRWPAIR_READINTO_METHODDEF
_IO_BUFFEREDRWPAIR_READINTO1_METHODDEF

{"write", bufferedrwpair_write, METH_VARARGS},
{"flush", bufferedrwpair_flush, METH_NOARGS},
_IO_BUFFEREDRWPAIR_WRITE_METHODDEF
_IO_BUFFEREDRWPAIR_FLUSH_METHODDEF

{"readable", bufferedrwpair_readable, METH_NOARGS},
{"writable", bufferedrwpair_writable, METH_NOARGS},
_IO_BUFFEREDRWPAIR_READABLE_METHODDEF
_IO_BUFFEREDRWPAIR_WRITABLE_METHODDEF

{"close", bufferedrwpair_close, METH_NOARGS},
{"isatty", bufferedrwpair_isatty, METH_NOARGS},
_IO_BUFFEREDRWPAIR_CLOSE_METHODDEF
_IO_BUFFEREDRWPAIR_ISATTY_METHODDEF

{NULL, NULL}
};
Expand All @@ -2695,7 +2753,7 @@ static PyMemberDef bufferedrwpair_members[] = {
};

static PyGetSetDef bufferedrwpair_getset[] = {
{"closed", bufferedrwpair_closed_get, NULL, NULL},
_IO_BUFFEREDRWPAIR_CLOSED_GETSETDEF
{NULL}
};

Expand Down
Loading
Loading