[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