[Python-checkins] r66495 - in sandbox/trunk/io-c: io.c io.py
amaury.forgeotdarc
python-checkins at python.org
Thu Sep 18 01:31:44 CEST 2008
Author: amaury.forgeotdarc
Date: Thu Sep 18 01:31:43 2008
New Revision: 66495
Log:
Implement RawIOBase.
Creation of a type (in C) that inherits a python class is fun.
Allowing the result to be part of multiple inheritance is even more fun.
This hack should be temporary.
Modified:
sandbox/trunk/io-c/io.c
sandbox/trunk/io-c/io.py
Modified: sandbox/trunk/io-c/io.c
==============================================================================
--- sandbox/trunk/io-c/io.c (original)
+++ sandbox/trunk/io-c/io.c Thu Sep 18 01:31:43 2008
@@ -6,6 +6,7 @@
/* open() uses st_blksize whenever we can */
#define DEFAULT_BUFFER_SIZE (8 * 1024) /* bytes */
+
PyDoc_STRVAR(module_doc,
"The io module provides the Python interfaces to stream handling. The\n"
"builtin open function is defined in this module.\n"
@@ -41,6 +42,7 @@
" I/O classes. open() uses the file's blksize (as obtained by os.stat) if\n"
" possible.\n"
);
+
/*
* BlockingIOError extends IOError
@@ -135,6 +137,7 @@
0, /* tp_new */
};
PyObject *PyExc_BlockingIOError = (PyObject *)&_PyExc_BlockingIOError;
+
/*
* The main open() function
@@ -504,8 +507,154 @@
Py_XDECREF(wrapper);
return NULL;
}
+
+/*
+ * RawIOBase class, Inherits from IOBase.
+ */
+PyDoc_STRVAR(RawIOBase_doc,
+ "Base class for raw binary I/O.");
+
+/*
+ * The read() method is implemented by calling readinto(); derived classes
+ * that want to support read() only need to implement readinto() as a
+ * primitive operation. In general, readinto() can be more efficient than
+ * read().
+ *
+ * (It would be tempting to also provide an implementation of readinto() in
+ * terms of read(), in case the latter is a more suitable primitive operation,
+ * but that would lead to nasty recursion in case a subclass doesn't implement
+ * either.)
+*/
+
+static PyObject *
+RawIOBase_read(PyObject *self, PyObject *args)
+{
+ Py_ssize_t n = -1;
+ PyObject *b, *res;
+
+ if (!PyArg_ParseTuple(args, "|n:read", &n)) {
+ return NULL;
+ }
+
+ if (n < 0)
+ return PyObject_CallMethod(self, "readall", NULL);
+
+ b = PyByteArray_FromStringAndSize(NULL, n);
+ if (b == NULL)
+ return NULL;
+
+ res = PyObject_CallMethod(self, "readinto", "O", b);
+ if (res == NULL) {
+ Py_DECREF(b);
+ return NULL;
+ }
+
+ n = PyNumber_AsSsize_t(res, PyExc_ValueError);
+ Py_DECREF(res);
+ if (n == -1 && PyErr_Occurred()) {
+ Py_DECREF(b);
+ return NULL;
+ }
+
+ res = PyBytes_FromStringAndSize(PyByteArray_AsString(b), n);
+ Py_DECREF(b);
+ return res;
+}
+
+
+PyDoc_STRVAR(RawIOBase_readall_doc,
+ "Read until EOF, using multiple read() call.");
+
+static PyObject *
+RawIOBase_readall(PyObject *self, PyObject *args)
+{
+ PyObject *b, *res;
+ Py_ssize_t cursize = 0;
+
+ b = PyBytes_FromStringAndSize(NULL, 0);
+ if (b == NULL)
+ return NULL;
+
+ while (1) {
+ Py_ssize_t length;
+ PyObject *data = PyObject_CallMethod(self, "read",
+ "i", DEFAULT_BUFFER_SIZE);
+
+ if (!data) {
+ Py_DECREF(b);
+ return NULL;
+ }
+
+ if (!PyBytes_Check(b)) {
+ Py_DECREF(b);
+ Py_DECREF(data);
+ PyErr_SetString(PyExc_TypeError, "read() should return bytes");
+ return NULL;
+ }
+
+ length = Py_SIZE(data);
+
+ if (length == 0)
+ break;
+
+ _PyBytes_Resize(&b, cursize + length);
+ memcpy(PyBytes_AS_STRING(b) + cursize,
+ PyBytes_AS_STRING(data), length);
+ Py_DECREF(data);
+ }
+
+ return res;
+}
+
+static PyMethodDef RawIOBase_methods[] = {
+ {"read", RawIOBase_read, METH_VARARGS},
+ {"readall", RawIOBase_readall, METH_NOARGS, RawIOBase_readall_doc},
+ {NULL, NULL}
+};
+
+static PyTypeObject RawIOBase_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "RawIOBase", /*tp_name*/
+ 0, /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare */
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+ RawIOBase_readall_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ RawIOBase_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
/*
* Module definition
@@ -532,6 +681,7 @@
PyInit__io()
{
PyObject *m = PyModule_Create(&iomodule);
+ PyTypeObject *base;
if (m == NULL)
goto fail;
@@ -539,13 +689,30 @@
if (io_py_module == NULL)
goto fail;
- _PyExc_BlockingIOError.tp_base = (PyTypeObject*)PyExc_IOError;
+ /* BlockingIOError */
+ base = (PyTypeObject*)PyExc_IOError;
+ _PyExc_BlockingIOError.tp_base = base;
if (PyType_Ready(&_PyExc_BlockingIOError) < 0)
goto fail;
Py_INCREF(&_PyExc_BlockingIOError);
PyModule_AddObject(m, "BlockingIOError",
(PyObject *)&_PyExc_BlockingIOError);
+ /* RawIOBase */
+ base = (PyTypeObject*)PyObject_GetAttrString(io_py_module, "IOBase");
+ if (base == NULL)
+ return NULL;
+ RawIOBase_Type.tp_base = base;
+ RawIOBase_Type.tp_basicsize = base->tp_basicsize;
+ /* XXX next line is needed for multiple derivation */
+ /* XXX try to remove it when FileIO is fully ported */
+ RawIOBase_Type.tp_flags |= Py_TPFLAGS_HEAPTYPE;
+ if (PyType_Ready(&RawIOBase_Type) < 0)
+ goto fail;
+ Py_INCREF(&RawIOBase_Type);
+ PyModule_AddObject(m, "RawIOBase",
+ (PyObject *)&RawIOBase_Type);
+
return m;
fail:
Modified: sandbox/trunk/io-c/io.py
==============================================================================
--- sandbox/trunk/io-c/io.py (original)
+++ sandbox/trunk/io-c/io.py Thu Sep 18 01:31:43 2008
@@ -59,7 +59,6 @@
import abc
import codecs
import _fileio
-import _io
# Import _thread instead of threading to reduce startup cost
try:
from _thread import allocate_lock as Lock
@@ -78,7 +77,6 @@
def __init__(self, errno, strerror, characters_written=0):
IOError.__init__(self, errno, strerror)
self.characters_written = characters_written
-BlockingIOError = _io.BlockingIOError
def open(file, mode="r", buffering=None, encoding=None, errors=None,
@@ -271,7 +269,6 @@
"open(file, mode='r', buffering=None, encoding=None, "
"errors=None, newline=None, closefd=True)\n\n" +
open.__doc__)
-open = _io.open
class OpenWrapper:
"""Wrapper for builtins.open
@@ -555,6 +552,10 @@
for line in lines:
self.write(line)
+import _io
+BlockingIOError = _io.BlockingIOError
+open = _io.open
+
class RawIOBase(IOBase):
@@ -609,6 +610,7 @@
Returns the number of bytes written, which may be less than len(b).
"""
self._unsupported("write")
+RawIOBase = _io.RawIOBase
class FileIO(_fileio._FileIO, RawIOBase):
More information about the Python-checkins
mailing list