]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Stop Python code from instantiating a new stdprinter with sys.stderr.__class__()
authorChristian Heimes <christian@cheimes.de>
Mon, 12 Nov 2007 16:05:45 +0000 (16:05 +0000)
committerChristian Heimes <christian@cheimes.de>
Mon, 12 Nov 2007 16:05:45 +0000 (16:05 +0000)
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

index c4feed1304e01f61bb7ccf7a0192b6c7ff90cfb5..ecf67621f32f160d6496475a23cd00830b32e5a4 100644 (file)
@@ -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("<stdprinter(fd=%d) object at 0x%x>",
+                                   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 */