From af935e3bc46dde5c32a3d23173e2a8f6ec9a8792 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 12 Nov 2007 16:05:45 +0000 Subject: Stop Python code from instantiating a new stdprinter with sys.stderr.__class__() Added some more methods and attributes to stdprinter to ease up debugging #1415 on Windows. It also makes the object more file like. Now it can be used as a working replacement for an io instance. --- Objects/fileobject.c | 101 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 90 insertions(+), 11 deletions(-) diff --git a/Objects/fileobject.c b/Objects/fileobject.c index c4feed1..ecf6762 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -325,7 +325,10 @@ Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj) return buf; } -/* **************************** std printer **************************** */ +/* **************************** std printer **************************** + * The stdprinter is used during the boot strapping phase as a preliminary + * file like object for sys.stderr. + */ typedef struct { PyObject_HEAD @@ -347,6 +350,14 @@ stdprinter_new(PyTypeObject *type, PyObject *args, PyObject *kews) return (PyObject *) self; } +static int +fileio_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyErr_SetString(PyExc_TypeError, + "cannot create 'stderrprinter' instances"); + return -1; +} + PyObject * PyFile_NewStdPrinter(int fd) { @@ -372,14 +383,17 @@ stdprinter_write(PyStdPrinter_Object *self, PyObject *args) Py_ssize_t n; if (self->fd < 0) { - PyErr_SetString(PyExc_ValueError, - "I/O operation on closed file"); - return NULL; + /* fd might be invalid on Windows + * I can't raise an exception here. It may lead to an + * unlimited recursion in the case stderr is invalid. + */ + return PyLong_FromLong((long)-1); } - if (!PyArg_ParseTuple(args, "s#", &c, &n)) { + if (!PyArg_ParseTuple(args, "s", &c)) { return NULL; } + n = strlen(c); Py_BEGIN_ALLOW_THREADS errno = 0; @@ -393,12 +407,77 @@ stdprinter_write(PyStdPrinter_Object *self, PyObject *args) return NULL; } - return PyInt_FromSsize_t(n); + return PyLong_FromSsize_t(n); +} + +static PyObject * +stdprinter_fileno(PyStdPrinter_Object *self) +{ + return PyInt_FromLong((long) self->fd); +} + +static PyObject * +stdprinter_repr(PyStdPrinter_Object *self) +{ + return PyUnicode_FromFormat("", + self->fd, self); +} + +static PyObject * +stdprinter_noop(PyStdPrinter_Object *self) +{ + Py_RETURN_NONE; +} + +static PyObject * +stdprinter_isatty(PyStdPrinter_Object *self) +{ + long res; + if (self->fd < 0) { + Py_INCREF(Py_False); + return Py_False; + } + + Py_BEGIN_ALLOW_THREADS + res = isatty(self->fd); + Py_END_ALLOW_THREADS + + return PyBool_FromLong(res); } static PyMethodDef stdprinter_methods[] = { - {"write", (PyCFunction)stdprinter_write, METH_VARARGS, ""}, - {NULL, NULL} /* sentinel */ + {"close", (PyCFunction)stdprinter_noop, METH_NOARGS, ""}, + {"flush", (PyCFunction)stdprinter_noop, METH_NOARGS, ""}, + {"fileno", (PyCFunction)stdprinter_fileno, METH_NOARGS, ""}, + {"isatty", (PyCFunction)stdprinter_isatty, METH_NOARGS, ""}, + {"write", (PyCFunction)stdprinter_write, METH_VARARGS, ""}, + {NULL, NULL} /*sentinel */ +}; + +static PyObject * +get_closed(PyStdPrinter_Object *self, void *closure) +{ + Py_INCREF(Py_False); + return Py_False; +} + +static PyObject * +get_mode(PyStdPrinter_Object *self, void *closure) +{ + return PyUnicode_FromString("w"); +} + +static PyObject * +get_encoding(PyStdPrinter_Object *self, void *closure) +{ + Py_RETURN_NONE; +} + +static PyGetSetDef stdprinter_getsetlist[] = { + {"closed", (getter)get_closed, NULL, "True if the file is closed"}, + {"encoding", (getter)get_encoding, NULL, "Encoding of the file"}, + {"mode", (getter)get_mode, NULL, "String giving the file mode"}, + {0}, }; PyTypeObject PyStdPrinter_Type = { @@ -412,7 +491,7 @@ PyTypeObject PyStdPrinter_Type = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ - 0, /* tp_repr */ + (reprfunc)stdprinter_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -432,13 +511,13 @@ PyTypeObject PyStdPrinter_Type = { 0, /* tp_iternext */ stdprinter_methods, /* tp_methods */ 0, /* tp_members */ - 0, /* tp_getset */ + stdprinter_getsetlist, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - 0, /* tp_init */ + fileio_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ stdprinter_new, /* tp_new */ PyObject_Del, /* tp_free */ -- cgit v0.12