[Python-checkins] r67819 - in sandbox/trunk/io-c: _fileio.c _iobase.c _iomodule.h _textio.c io.c

amaury.forgeotdarc python-checkins at python.org
Wed Dec 17 02:12:16 CET 2008


Author: amaury.forgeotdarc
Date: Wed Dec 17 02:12:15 2008
New Revision: 67819

Log:
io-c: TextIOWrapper works for basic usage, stdin/stdout can use it.

Still missing: seek() and tell(),
and the IncrementalNewlineDecoder.

probably tons of bugs and memory leaks.


Modified:
   sandbox/trunk/io-c/_fileio.c
   sandbox/trunk/io-c/_iobase.c
   sandbox/trunk/io-c/_iomodule.h
   sandbox/trunk/io-c/_textio.c
   sandbox/trunk/io-c/io.c

Modified: sandbox/trunk/io-c/_fileio.c
==============================================================================
--- sandbox/trunk/io-c/_fileio.c	(original)
+++ sandbox/trunk/io-c/_fileio.c	Wed Dec 17 02:12:15 2008
@@ -91,7 +91,7 @@
 }
 
 static PyObject *
-fileio_new(PyTypeObject *type, PyObject *args, PyObject *kews)
+fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
 	PyFileIOObject *self;
 

Modified: sandbox/trunk/io-c/_iobase.c
==============================================================================
--- sandbox/trunk/io-c/_iobase.c	(original)
+++ sandbox/trunk/io-c/_iobase.c	Wed Dec 17 02:12:15 2008
@@ -71,7 +71,7 @@
 static PyObject *
 IOBase_tell(PyObject *self, PyObject *args)
 {
-    return PyObject_CallMethod(self, "tell", "ii", 0, 1);
+    return PyObject_CallMethod(self, "seek", "ii", 0, 1);
 }
 
 PyDoc_STRVAR(IOBase_truncate_doc,

Modified: sandbox/trunk/io-c/_iomodule.h
==============================================================================
--- sandbox/trunk/io-c/_iomodule.h	(original)
+++ sandbox/trunk/io-c/_iomodule.h	Wed Dec 17 02:12:15 2008
@@ -11,6 +11,7 @@
 extern PyTypeObject PyBufferedWriter_Type;
 extern PyTypeObject PyBufferedRWPair_Type;
 extern PyTypeObject PyBufferedRandom_Type;
+extern PyTypeObject PyTextIOWrapper_Type;
 
 extern PyObject* _PyIOBase_checkReadable(PyObject *self, PyObject *unused);
 extern PyObject* _PyIOBase_checkWritable(PyObject *self, PyObject *unused);

Modified: sandbox/trunk/io-c/_textio.c
==============================================================================
--- sandbox/trunk/io-c/_textio.c	(original)
+++ sandbox/trunk/io-c/_textio.c	Wed Dec 17 02:12:15 2008
@@ -1,4 +1,5 @@
 #include "Python.h"
+#include "structmember.h"
 #include "_iomodule.h"
 
 extern PyObject *
@@ -72,8 +73,7 @@
     PyObject_HEAD
     Py_ssize_t chunk_size;
     PyObject *buffer;
-    const char *encoding;
-    const char *errors;
+    PyObject *encoding;
     PyObject *encoder;
     PyObject *decoder;
     PyObject *readnl;
@@ -93,8 +93,140 @@
      * next_input is the chunk of input bytes that comes next after the
      * snapshot point.  We use this to reconstruct decoder states in tell().
      */
+
+    PyObject *weakreflist;
+    PyObject *dict;
 } PyTextIOWrapperObject;
 
+static int
+TextIOWrapper_init(PyTextIOWrapperObject *self, PyObject *args, PyObject *kwds)
+{
+    char *kwlist[] = {"buffer", "encoding", "errors",
+                      "newline", "line_buffering",
+		      NULL};
+    PyObject *buffer;
+    char *encoding = NULL;
+    char *errors = NULL;
+    char *newline = NULL;
+    int line_buffering = 0;
+
+    PyObject *res;
+    int r;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|zzzi:fileio",
+				     kwlist, &buffer, &encoding, &errors,
+				     &newline, &line_buffering))
+	return -1;
+
+    if (newline && newline[0] != '\0'
+	&& !(newline[0] == '\n' && newline[1] == '\0')
+	&& !(newline[0] == '\r' && newline[1] == '\0')
+	&& !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
+	PyErr_Format(PyExc_ValueError,
+		     "illegal newline value: %s", newline);
+	return -1;
+    }
+
+    if (encoding == NULL) {
+	/* Try os.device_encoding(fileno) */
+	PyObject *os = PyImport_ImportModule("os");
+	if (os == NULL)
+	    return -1;
+	self->encoding = PyObject_CallMethod(
+	    os, "device_encoding", "N",
+	    PyObject_CallMethod(buffer, "fileno", NULL));
+	Py_DECREF(os);
+	/* Ignore any error */
+	/* XXX only AttributeError and UnsupportedOperation */
+	if (self->encoding == NULL)
+	    PyErr_Clear();
+	if (!PyUnicode_Check(self->encoding))
+	    Py_CLEAR(self->encoding);
+    }
+    if (encoding == NULL && self->encoding == NULL) {
+	/* try locale.getpreferredencoding() */
+	PyObject *locale = PyImport_ImportModule("locale");
+	if (locale == NULL) {
+	    self->encoding = PyUnicode_FromString("ascii");
+	}
+	else {
+	    self->encoding = PyObject_CallMethod(
+		locale, "getpreferredencoding", NULL);
+	    Py_DECREF(locale);
+	    if (self->encoding == NULL)
+		return -1;
+	    if (!PyUnicode_Check(self->encoding))
+		Py_CLEAR(self->encoding);
+	}
+    }
+    if (self->encoding != NULL)
+	encoding = _PyUnicode_AsString(self->encoding);
+
+    if (errors == NULL)
+	errors = "strict";
+
+    self->chunk_size = 8192;
+    self->readuniversal = (newline == NULL || newline[0] == '\0');
+    self->line_buffering = line_buffering;
+    self->readtranslate = (newline == NULL);
+    if (newline)
+	self->readnl = PyUnicode_FromString(newline);
+    self->writetranslate = (newline == NULL || newline[0] != '\0');
+    if (self->readuniversal) {
+	if (self->readnl)
+	    self->writenl = _PyUnicode_AsString(self->readnl);
+    }
+#ifdef MS_WINDOWS
+    else
+        self->writenl = "\r\n";
+#endif
+
+    /* Build the decoder object */
+    res = PyObject_CallMethod(buffer, "readable", NULL);
+    if (res == NULL)
+	goto error;
+    r = PyObject_IsTrue(res);
+    Py_DECREF(res);
+    if (r == -1)
+	goto error;
+    if (r == 1) {
+	self->decoder = PyCodec_IncrementalDecoder(
+            encoding, errors);
+	if (self->decoder == NULL)
+	    goto error;
+
+        if (self->readuniversal) {
+            /* XXX
+             * decoder = IncrementalNewlineDecoder(decoder, self._readtranslate)
+             */
+        }
+    }
+
+    /* Build the encoder object */
+    res = PyObject_CallMethod(buffer, "writable", NULL);
+    if (res == NULL)
+	goto error;
+    r = PyObject_IsTrue(res);
+    Py_DECREF(res);
+    if (r == -1)
+	goto error;
+    if (r == 1) {
+	self->encoder = PyCodec_IncrementalEncoder(
+            encoding, errors);
+	if (self->encoder == NULL)
+	    goto error;
+    }
+
+    self->buffer = buffer;
+    Py_INCREF(buffer);
+
+    /* self._seekable = self._telling = self.buffer.seekable(); */
+    return 0;
+
+  error:
+    return -1;
+}
+
 Py_LOCAL_INLINE(const Py_UNICODE *)
 findchar(const Py_UNICODE *s, Py_ssize_t size, Py_UNICODE ch)
 {
@@ -108,47 +240,11 @@
 }
 
 static PyObject *
-TextIOWrapper_encoder_get(PyTextIOWrapperObject *self)
-{
-    if (self->encoder == NULL) {
-        self->encoder = PyCodec_IncrementalEncoder(
-            self->encoding, self->errors);
-
-        if (self->encoder == NULL)
-            return NULL;
-    }
-
-    Py_INCREF(self->encoder);
-    return self->encoder;
-}
-
-static PyObject *
-TextIOWrapper_decoder_get(PyTextIOWrapperObject *self)
-{
-    if (self->decoder == NULL) {
-        PyObject *decoder = PyCodec_IncrementalDecoder(
-            self->encoding, self->errors);
-
-        if (decoder == NULL)
-            return NULL;
-
-        if (self->readuniversal) {
-            /* XXX
-             * decoder = IncrementalNewlineDecoder(decoder, self._readtranslate)
-             */
-        }
-    }
-
-    Py_INCREF(self->decoder);
-    return self->decoder;
-}
-
-static PyObject *
 TextIOWrapper_write(PyTextIOWrapperObject *self, PyObject *args)
 {
     PyObject *ret;
     PyObject *text; /* owned reference */
-    PyObject *encoder, *b;
+    PyObject *b;
     Py_ssize_t textlen;
     int haslf = 0;
     int needflush = 0;
@@ -184,15 +280,9 @@
                   PyUnicode_GET_SIZE(text), '\r')))
         needflush = 1;
 
-    encoder = TextIOWrapper_encoder_get(self);
-    if (!encoder) {
-        Py_DECREF(text);
-        return NULL;
-    }
     /* XXX What if we were just reading? */
-    b = PyObject_CallMethod(encoder, "encode", "O", text);
+    b = PyObject_CallMethod(self->encoder, "encode", "O", text);
     Py_DECREF(text);
-    Py_DECREF(encoder);
     if (b == NULL)
         return NULL;
 
@@ -235,18 +325,20 @@
 TextIOWrapper_get_decoded_chars(PyTextIOWrapperObject *self, Py_ssize_t n)
 {
     PyObject *chars;
-    Py_ssize_t avail = (PyBytes_GET_SIZE(self->decoded_chars)
-                        - self->decoded_chars_used);
+    Py_ssize_t avail;
 
     if (self->decoded_chars == NULL)
         return PyUnicode_FromStringAndSize(NULL, 0);
 
+    avail = (PyUnicode_GET_SIZE(self->decoded_chars)
+	     - self->decoded_chars_used);
+
     if (n < 0 || n > avail)
         n = avail;
 
-    chars = PyBytes_FromStringAndSize(
-        PyBytes_AS_STRING(self->decoded_chars) + self->decoded_chars_used,
-        n);
+    chars = PyUnicode_FromUnicode(
+        PyUnicode_AS_UNICODE(self->decoded_chars)
+	+ self->decoded_chars_used, n);
     if (chars == NULL)
         return NULL;
 
@@ -357,23 +449,19 @@
 TextIOWrapper_read(PyTextIOWrapperObject *self, PyObject *args)
 {
     Py_ssize_t n = -1;
-    PyObject *decoder;
     PyObject *result;
 
     if (!PyArg_ParseTuple(args, "|n:read", &n))
         return NULL;
 
-    decoder = TextIOWrapper_decoder_get(self);
-    if (decoder == NULL)
-        return NULL;
-
     if (n < 0) {
         /* Read everything */
         PyObject *bytes = PyObject_CallMethod(self->buffer, "read", NULL);
         PyObject *decoded;
         if (bytes == NULL)
             goto fail;
-        decoded = PyObject_CallMethod(decoder, "decode", "Oi", bytes, /*final=*/1);
+        decoded = PyObject_CallMethod(self->decoder, "decode",
+				      "Oi", bytes, /*final=*/1);
 
         if (self->decoded_chars) {
             result = PyNumber_Add(self->decoded_chars, decoded);
@@ -386,7 +474,6 @@
             result = decoded;
         }
         Py_CLEAR(self->snapshot);
-        Py_DECREF(decoder);
         return result;
     }
     else {
@@ -410,11 +497,9 @@
             if (result == NULL)
                 goto fail;
         }
-        Py_DECREF(decoder);
         return result;
     }
   fail:
-    Py_DECREF(decoder);
     return NULL;
 }
 
@@ -442,11 +527,11 @@
 TextIOWrapper_readline(PyTextIOWrapperObject *self, PyObject *args)
 {
     Py_ssize_t limit = -1;
-    PyObject *line, *decoder;
+    PyObject *line;
     Py_ssize_t start, endpos;
     int res;
 
-    if (!PyArg_ParseTuple(args, "n:readline", &limit)) {
+    if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
         return NULL;
     }
 
@@ -460,10 +545,6 @@
 
     start = 0;
 
-    decoder = TextIOWrapper_decoder_get(self);
-    if (decoder == NULL)
-        goto error;
-
     endpos = -1;
 
     while (1) {
@@ -576,3 +657,79 @@
     Py_DECREF(line);
     return NULL;
 }
+
+static PyMethodDef TextIOWrapper_methods[] = {
+/*    {"seekable", (PyCFunction)TextIOWrapper_seekable, METH_NOARGS},
+    {"readable", (PyCFunction)TextIOWrapper_readable, METH_NOARGS},
+    {"writable", (PyCFunction)TextIOWrapper_writable, METH_NOARGS},
+    {"fileno", (PyCFunction)TextIOWrapper_fileno, METH_NOARGS},
+    {"isatty", (PyCFunction)TextIOWrapper_isatty, METH_NOARGS},
+    {"flush", (PyCFunction)BufferedWriter_flush, METH_NOARGS},
+*/
+
+    {"write", (PyCFunction)TextIOWrapper_write, METH_VARARGS},
+    {"read", (PyCFunction)TextIOWrapper_read, METH_VARARGS},
+    {"readline", (PyCFunction)TextIOWrapper_readline, METH_VARARGS},
+/*    {"seek", (PyCFunction)TextIOWrapper_seek, METH_VARARGS},
+    {"tell", (PyCFunction)TextIOWrapper_tell, METH_NOARGS},
+    {"truncate", (PyCFunction)TextIOWrapper_truncate, METH_VARARGS},
+    {"readinto", (PyCFunction)TextIOWrapper_readinto, METH_VARARGS},
+    {"peek", (PyCFunction)TextIOWrapper_peek, METH_VARARGS},
+    {"read1", (PyCFunction)TextIOWrapper_read1, METH_VARARGS},
+*/
+    {NULL, NULL}
+};
+
+static PyMemberDef TextIOWrapper_members[] = {
+    {"encoding", T_OBJECT, offsetof(PyTextIOWrapperObject, encoding), READONLY},
+    {NULL}
+};
+
+static PyGetSetDef TextIOWrapper_getset[] = {
+/*    {"closed", (getter)TextIOWrapper_closed_get, NULL, NULL},
+    {"name", (getter)TextIOWrapper_name_get, NULL, NULL},
+    {"mode", (getter)TextIOWrapper_mode_get, NULL, NULL},
+*/
+    {0}
+};
+
+PyTypeObject PyTextIOWrapper_Type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "TextIOWrapper",            /*tp_name*/
+    sizeof(PyTextIOWrapperObject), /*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,  /*tp_flags*/
+    TextIOWrapper_doc,          /* tp_doc */
+    0,                          /* tp_traverse */
+    0,                          /* tp_clear */
+    0,                          /* tp_richcompare */
+    offsetof(PyTextIOWrapperObject, weakreflist), /*tp_weaklistoffset*/
+    0,                          /* tp_iter */
+    0,                          /* tp_iternext */
+    TextIOWrapper_methods,      /* tp_methods */
+    TextIOWrapper_members,      /* tp_members */
+    TextIOWrapper_getset,       /* tp_getset */
+    0,                          /* tp_base */
+    0,                          /* tp_dict */
+    0,                          /* tp_descr_get */
+    0,                          /* tp_descr_set */
+    offsetof(PyTextIOWrapperObject, dict), /*tp_dictoffset*/
+    (initproc)TextIOWrapper_init, /* tp_init */
+    0,                          /* tp_alloc */
+    PyType_GenericNew,          /* tp_new */
+};

Modified: sandbox/trunk/io-c/io.c
==============================================================================
--- sandbox/trunk/io-c/io.c	(original)
+++ sandbox/trunk/io-c/io.c	Wed Dec 17 02:12:15 2008
@@ -3,9 +3,6 @@
 #include "_iomodule.h"
 
 PyObject *PyIOExc_UnsupportedOperation;
-
-
-static PyObject *io_py_module;
 
 
 PyDoc_STRVAR(module_doc,
@@ -434,7 +431,7 @@
         PyObject *Buffered_class;
 
         if (updating)
-	    Buffered_class = (PyObject *)&PyBufferedRandom_Type;
+            Buffered_class = (PyObject *)&PyBufferedRandom_Type;
         else if (writing || appending)
             Buffered_class = (PyObject *)&PyBufferedWriter_Type;
         else if (reading)
@@ -459,19 +456,11 @@
     }
 
     /* wraps into a TextIOWrapper */
-    {
-        PyObject *TextIOWrapper_class;
-        TextIOWrapper_class = PyObject_GetAttrString(io_py_module,
-                                                     "TextIOWrapper");
-        if (TextIOWrapper_class == NULL)
-            goto error;
-
-        wrapper = PyObject_CallFunction(TextIOWrapper_class, "Osssi",
-                                        buffer,
-                                        encoding, errors, newline,
-                                        line_buffering);
-        Py_DECREF(TextIOWrapper_class);
-    }
+    wrapper = PyObject_CallFunction((PyObject *)&PyTextIOWrapper_Type,
+				    "Osssi",
+				    buffer,
+				    encoding, errors, newline,
+				    line_buffering);
     Py_CLEAR(buffer);
     if (wrapper == NULL)
         goto error;
@@ -519,10 +508,6 @@
     if (m == NULL)
         goto fail;
 
-    io_py_module = PyImport_ImportModule("io");
-    if (io_py_module == NULL)
-        goto fail;
-
     /* UnsupportedOperation inherits from ValueError and IOError */
     PyIOExc_UnsupportedOperation = PyObject_CallFunction(
         (PyObject *)&PyType_Type, "s(OO){}",
@@ -601,6 +586,13 @@
     Py_INCREF(&PyBufferedRandom_Type);
     PyModule_AddObject(m, "BufferedRandom", (PyObject *) &PyBufferedRandom_Type);
 
+    /* TextIOWrapper */
+    PyTextIOWrapper_Type.tp_base = &PyIOBase_Type;
+    if (PyType_Ready(&PyTextIOWrapper_Type) < 0)
+        goto fail;
+    Py_INCREF(&PyTextIOWrapper_Type);
+    PyModule_AddObject(m, "TextIOWrapper", (PyObject *) &PyTextIOWrapper_Type);
+
     return m;
 
   fail:


More information about the Python-checkins mailing list