Re: plpython tracebacks - Mailing list pgsql-patches
From | Neil Conway |
---|---|
Subject | Re: plpython tracebacks |
Date | |
Msg-id | 43FCE9FE.9010106@samurai.com Whole thread Raw |
In response to | Re: plpython tracebacks ("P. Scott DeVos" <scott@countrysidetechnology.com>) |
Responses |
Re: plpython tracebacks
Re: plpython tracebacks Re: plpython tracebacks |
List | pgsql-patches |
P. Scott DeVos wrote: > I'm on it. Actually, don't worry about it -- I've made the corrections I had in mind myself. Attached is a revised patch. On looking closer, I didn't really like the way the patch accumulated the lines of the traceback: AFAICS _PyString_Join() is not an "official" Python C API function (it's not documented, at any rate), and besides it is cleaner and more efficient to build up the traceback string in a StringInfo rather than using Python lists and strings. The attached patch isn't quite finished: "No Traceback" when there is no traceback information doesn't seem like the best message, I need to update the regression tests and some comments, etc. But I plan to apply something similar in substance to the attached patch to HEAD in the next day or two, barring objections. -Neil Index: src/pl/plpython/plpython.c =================================================================== RCS file: /Users/neilc/postgres/cvs_root/pgsql/src/pl/plpython/plpython.c,v retrieving revision 1.71 diff -c -r1.71 plpython.c *** src/pl/plpython/plpython.c 20 Feb 2006 20:10:37 -0000 1.71 --- src/pl/plpython/plpython.c 22 Feb 2006 22:36:29 -0000 *************** *** 48,53 **** --- 48,54 ---- #include "commands/trigger.h" #include "executor/spi.h" #include "fmgr.h" + #include "lib/stringinfo.h" #include "nodes/makefuncs.h" #include "parser/parse_type.h" #include "tcop/tcopprot.h" *************** *** 2489,2494 **** --- 2490,2534 ---- } static char * + build_python_traceback(PyObject *tb) + { + PyObject *cur_tb; + StringInfoData buf; + + initStringInfo(&buf); + appendStringInfoString(&buf, "Traceback (most recent call last):\n"); + + /* skip the first element in the traceback list */ + cur_tb = PyObject_GetAttrString(tb, "tb_next"); + while (cur_tb != Py_None) + { + PyObject *lno = PyObject_GetAttrString(cur_tb, "tb_lineno"); + PyObject *frame = PyObject_GetAttrString(cur_tb, "tb_frame"); + PyObject *code = PyObject_GetAttrString(frame, "f_code"); + PyObject *file = PyObject_GetAttrString(code, "co_filename"); + PyObject *name = PyObject_GetAttrString(code, "co_name"); + PyObject *prev_tb; + + appendStringInfo(&buf, " File \"%s\", line %s, in %s\n", + PyString_AsString(file), + PyString_AsString(lno), + PyString_AsString(name)); + + Py_DECREF(lno); + Py_DECREF(frame); + Py_DECREF(code); + Py_DECREF(file); + Py_DECREF(name); + + prev_tb = cur_tb; + cur_tb = PyObject_GetAttrString(cur_tb, "tb_next"); + Py_DECREF(prev_tb); + } + + return buf.data; + } + + static char * PLy_traceback(int *xlevel) { PyObject *e, *************** *** 2498,2503 **** --- 2538,2544 ---- *vob = NULL; char *vstr, *estr, + *tbstr, *xstr = NULL; /* *************** *** 2515,2521 **** } PyErr_NormalizeException(&e, &v, &tb); - Py_XDECREF(tb); eob = PyObject_Str(e); if (v && ((vob = PyObject_Str(v)) != NULL)) --- 2556,2561 ---- *************** *** 2524,2540 **** vstr = "Unknown"; /* * I'm not sure what to do if eob is NULL here -- we can't call PLy_elog * because that function calls us, so we could end up with infinite * recursion. I'm not even sure if eob could be NULL here -- would an * Assert() be more appropriate? */ estr = eob ? PyString_AsString(eob) : "Unknown Exception"; ! xstr = PLy_printf("%s: %s", estr, vstr); Py_DECREF(eob); Py_XDECREF(vob); Py_XDECREF(v); /* * intuit an appropriate error level based on the exception type --- 2564,2594 ---- vstr = "Unknown"; /* + * If there is a traceback object, build a string containing a + * textual representation of the traceback. + */ + if (tb) + { + tbstr = build_python_traceback(tb); + /* we're done with the traceback object itself now */ + Py_DECREF(tb); + } + else + tbstr = pstrdup("No Traceback\n"); + + /* * I'm not sure what to do if eob is NULL here -- we can't call PLy_elog * because that function calls us, so we could end up with infinite * recursion. I'm not even sure if eob could be NULL here -- would an * Assert() be more appropriate? */ estr = eob ? PyString_AsString(eob) : "Unknown Exception"; ! xstr = PLy_printf("%s%s: %s", tbstr, estr, vstr); Py_DECREF(eob); Py_XDECREF(vob); Py_XDECREF(v); + pfree(tbstr); /* * intuit an appropriate error level based on the exception type
pgsql-patches by date: