diff options
author | Guido van Rossum <guido@python.org> | 2007-10-30 18:34:07 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2007-10-30 18:34:07 (GMT) |
commit | 826d8973ac52a0a8155ef857c8a9bf18a90b11ac (patch) | |
tree | 228f7830ba30118bed52db846a39b2ef1f9c0fda | |
parent | 1cd5bd2a2e600d0f29f9dcfbb9ea922cb1cd006f (diff) | |
download | cpython-826d8973ac52a0a8155ef857c8a9bf18a90b11ac.zip cpython-826d8973ac52a0a8155ef857c8a9bf18a90b11ac.tar.gz cpython-826d8973ac52a0a8155ef857c8a9bf18a90b11ac.tar.bz2 |
Patch 1352 (continued in issue 1329) by Christian Heimes.
Before sys.stderr is set to the proper thing, set it to a really simple
file-like object that can print tracebacks using direct file descriptor I/O.
This is handy for debugging.
-rw-r--r-- | Include/fileobject.h | 7 | ||||
-rw-r--r-- | Objects/fileobject.c | 118 | ||||
-rw-r--r-- | Objects/object.c | 3 | ||||
-rw-r--r-- | Python/pythonrun.c | 9 |
4 files changed, 136 insertions, 1 deletions
diff --git a/Include/fileobject.h b/Include/fileobject.h index ae127da..40d871a 100644 --- a/Include/fileobject.h +++ b/Include/fileobject.h @@ -21,6 +21,13 @@ PyAPI_FUNC(char *) Py_UniversalNewlineFgets(char *, int, FILE*, PyObject *); */ PyAPI_DATA(const char *) Py_FileSystemDefaultEncoding; +/* Internal API + + The std printer acts as a preliminary sys.stderr until the new io + infrastructure is in place. */ +PyAPI_FUNC(PyObject *) PyFile_NewStdPrinter(int); +PyAPI_DATA(PyTypeObject) PyStdPrinter_Type; + #ifdef __cplusplus } #endif diff --git a/Objects/fileobject.c b/Objects/fileobject.c index 4e18480..dc0f1fd 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -325,6 +325,124 @@ Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj) return buf; } +/* **************************** std printer **************************** */ + +typedef struct { + PyObject_HEAD + int fd; +} PyStdPrinter_Object; + +static PyObject * +stdprinter_new(PyTypeObject *type, PyObject *args, PyObject *kews) +{ + PyStdPrinter_Object *self; + + assert(type != NULL && type->tp_alloc != NULL); + + self = (PyStdPrinter_Object *) type->tp_alloc(type, 0); + if (self != NULL) { + self->fd = -1; + } + + return (PyObject *) self; +} + +PyObject * +PyFile_NewStdPrinter(int fd) +{ + PyStdPrinter_Object *self; + + if (fd != 1 && fd != 2) { + PyErr_BadInternalCall(); + return NULL; + } + + self = PyObject_New(PyStdPrinter_Object, + &PyStdPrinter_Type); + self->fd = fd; + return (PyObject*)self; +} + +PyObject * +stdprinter_write(PyStdPrinter_Object *self, PyObject *args) +{ + char *c; + Py_ssize_t n; + + if (self->fd < 0) { + PyErr_SetString(PyExc_ValueError, + "I/O operation on closed file"); + return NULL; + } + + if (!PyArg_ParseTuple(args, "s#", &c, &n)) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + errno = 0; + n = write(self->fd, c, n); + Py_END_ALLOW_THREADS + + if (n < 0) { + if (errno == EAGAIN) + Py_RETURN_NONE; + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + + return PyInt_FromSsize_t(n); +} + +static PyMethodDef stdprinter_methods[] = { + {"write", (PyCFunction)stdprinter_write, METH_VARARGS, ""}, + {NULL, NULL} /* sentinel */ +}; + +PyTypeObject PyStdPrinter_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "stderrprinter", /* tp_name */ + sizeof(PyStdPrinter_Object), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + 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 */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + stdprinter_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 */ + PyType_GenericAlloc, /* tp_alloc */ + stdprinter_new, /* tp_new */ + PyObject_Del, /* tp_free */ +}; + + #ifdef __cplusplus } #endif diff --git a/Objects/object.c b/Objects/object.c index f6d125f..77ddb1d 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1595,6 +1595,9 @@ _Py_ReadyTypes(void) if (PyType_Ready(&PyCode_Type) < 0) Py_FatalError("Can't initialize 'code'"); + + if (PyType_Ready(&PyStdPrinter_Type) < 0) + Py_FatalError("Can't initialize StdPrinter"); } diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 76da8fb..ec9ed02 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -151,7 +151,7 @@ Py_InitializeEx(int install_sigs) { PyInterpreterState *interp; PyThreadState *tstate; - PyObject *bimod, *sysmod; + PyObject *bimod, *sysmod, *pstderr; char *p; #if defined(HAVE_LANGINFO_H) && defined(CODESET) char *codeset; @@ -228,6 +228,13 @@ Py_InitializeEx(int install_sigs) PyDict_SetItemString(interp->sysdict, "modules", interp->modules); + /* Set up a preliminary stderr printer until we have enough + infrastructure for the io module in place. */ + pstderr = PyFile_NewStdPrinter(fileno(stderr)); + if (pstderr == NULL) + Py_FatalError("Py_Initialize: can't set preliminary stderr"); + PySys_SetObject("stderr", pstderr); + _PyImport_Init(); /* initialize builtin exceptions */ |