[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