diff options
author | Guido van Rossum <guido@python.org> | 2007-07-10 06:54:34 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2007-07-10 06:54:34 (GMT) |
commit | 7165cb1a485b1b5574785eac6e2edc8787e43c38 (patch) | |
tree | 1b8edb82abcc8ef143923a43366b6a90842b5692 /Modules/_fileio.c | |
parent | e8432ac42f9030bd75de03a07fd9059006292b7a (diff) | |
download | cpython-7165cb1a485b1b5574785eac6e2edc8787e43c38.zip cpython-7165cb1a485b1b5574785eac6e2edc8787e43c38.tar.gz cpython-7165cb1a485b1b5574785eac6e2edc8787e43c38.tar.bz2 |
Made test_file pass. This meant adding support for read(-1) and read()
to even the most basic file object (I also added readall() which may
be a better API). Also, not all the tests requiring specific failure
modes could be saved. And there were the usual str/bytes issues.
I made sure test_io.py still passes (io.py is now most thoroughly
tested by combining test_file.py and test_io.py).
Diffstat (limited to 'Modules/_fileio.c')
-rw-r--r-- | Modules/_fileio.c | 77 |
1 files changed, 70 insertions, 7 deletions
diff --git a/Modules/_fileio.c b/Modules/_fileio.c index 76b47e5..3ca3172 100644 --- a/Modules/_fileio.c +++ b/Modules/_fileio.c @@ -365,11 +365,69 @@ fileio_readinto(PyFileIOObject *self, PyObject *args) return PyInt_FromLong(n); } +#define DEFAULT_BUFFER_SIZE (8*1024) + +static PyObject * +fileio_readall(PyFileIOObject *self) +{ + PyObject *result; + Py_ssize_t total = 0; + int n; + + result = PyBytes_FromStringAndSize(NULL, DEFAULT_BUFFER_SIZE); + if (result == NULL) + return NULL; + + while (1) { + Py_ssize_t newsize = total + DEFAULT_BUFFER_SIZE; + if (PyBytes_GET_SIZE(result) < newsize) { + if (PyBytes_Resize(result, newsize) < 0) { + if (total == 0) { + Py_DECREF(result); + return NULL; + } + PyErr_Clear(); + break; + } + } + Py_BEGIN_ALLOW_THREADS + errno = 0; + n = read(self->fd, + PyBytes_AS_STRING(result) + total, + newsize - total); + Py_END_ALLOW_THREADS + if (n == 0) + break; + if (n < 0) { + if (total > 0) + break; + if (errno == EAGAIN) { + Py_DECREF(result); + Py_RETURN_NONE; + } + Py_DECREF(result); + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + total += n; + } + + if (PyBytes_GET_SIZE(result) > total) { + if (PyBytes_Resize(result, total) < 0) { + /* This should never happen, but just in case */ + Py_DECREF(result); + return NULL; + } + } + return result; +} + static PyObject * fileio_read(PyFileIOObject *self, PyObject *args) { char *ptr; - Py_ssize_t n, size; + Py_ssize_t n; + Py_ssize_t size = -1; PyObject *bytes; if (self->fd < 0) @@ -377,13 +435,11 @@ fileio_read(PyFileIOObject *self, PyObject *args) if (!self->readable) return err_mode("reading"); - if (!PyArg_ParseTuple(args, "i", &size)) + if (!PyArg_ParseTuple(args, "|i", &size)) return NULL; if (size < 0) { - PyErr_SetString(PyExc_ValueError, - "negative read count"); - return NULL; + return fileio_readall(self); } bytes = PyBytes_FromStringAndSize(NULL, size); @@ -624,8 +680,14 @@ PyDoc_STRVAR(read_doc, "read(size: int) -> bytes. read at most size bytes, returned as bytes.\n" "\n" "Only makes one system call, so less data may be returned than requested\n" -"In non-blocking mode, returns None if no data is available. On\n" -"end-of-file, returns 0."); +"In non-blocking mode, returns None if no data is available.\n" +"On end-of-file, returns ''."); + +PyDoc_STRVAR(readall_doc, +"readall() -> bytes. read all data from the file, returned as bytes.\n" +"\n" +"In non-blocking mode, returns as much as is immediately available,\n" +"or None if no data is available. On end-of-file, returns ''."); PyDoc_STRVAR(write_doc, "write(b: bytes) -> int. Write bytes b to file, return number written.\n" @@ -680,6 +742,7 @@ PyDoc_STRVAR(writable_doc, static PyMethodDef fileio_methods[] = { {"read", (PyCFunction)fileio_read, METH_VARARGS, read_doc}, + {"readall", (PyCFunction)fileio_readall, METH_NOARGS, readall_doc}, {"readinto", (PyCFunction)fileio_readinto, METH_VARARGS, readinto_doc}, {"write", (PyCFunction)fileio_write, METH_VARARGS, write_doc}, {"seek", (PyCFunction)fileio_seek, METH_VARARGS, seek_doc}, |