plpython tracebacks - Mailing list pgsql-patches
From | P. Scott DeVos |
---|---|
Subject | plpython tracebacks |
Date | |
Msg-id | 43E7C831.3050207@countrysidetechnology.com Whole thread Raw |
Responses |
Re: plpython tracebacks
|
List | pgsql-patches |
I have been working with plpython for several months and have been hampered by the lack of a traceback being logged when a plpython function raises an error. I have written a patch causes the PLy_traceback function to fully log the traceback. The output looks just like the traceback output provided by the python interpreter. Feedback appreciated. Scott --- plpython-1.70.c.orig 2006-02-06 14:24:42.000000000 -0600 +++ plpython-1.70.c.patched 2006-02-06 15:34:05.000000000 -0600 @@ -2499,7 +2499,8 @@ *vob = NULL; char *vstr, *estr, - *xstr = NULL; + *xstr = NULL, + *tbstr; /* * get the current exception @@ -2523,6 +2524,82 @@ else vstr = "Unknown"; + /* If there is a traceback object, we build a string containing + the traceback information. */ + if (tb != NULL) + { + PyObject + *cur_tb, /* traceback (tb) item being handled */ + *old_tb, /* holds tb so we can decrement reference to it */ + *hdr, /* First line of logged output */ + *tmpl, /* PyString template for the logged tb item */ + *ftr, /* Last line of logged output */ + *tb_list, /* Each tb item create a PyString in this list */ + *ln, /* The line number of the item in the traceback */ + *frame, /* the tb_frame */ + *code, /* the f_code this guy has filename and method name*/ + *fn, /* the filename of the item in the tb */ + *nm, /* the function/method name of the item in the tb */ + *args, /* A tuple of the form (fn, ln, nm) */ + *logline, /* The assembled string with the logged message */ + *os, /* points to the os module */ + *sep, /* line separator */ + *tb_log; /* PyString with the assembled log msg */ + + hdr = PyString_FromString("Traceback (most recent call last):"); + tmpl = PyString_FromString(" File \"%s\", line %s, in %s"); + ftr = PyString_FromString(""); + + tb_list = PyList_New(0); /* create the list of strings */ + PyList_Append(tb_list, hdr); /* Append the header to the list */ + + /* 1st tb is useless; throw it away */ + cur_tb = PyObject_GetAttrString(tb, "tb_next"); + while (cur_tb != Py_None) + { + + ln = PyObject_GetAttrString(cur_tb, "tb_lineno"); + frame = PyObject_GetAttrString(cur_tb, "tb_frame"); + code = PyObject_GetAttrString(frame, "f_code"); + fn = PyObject_GetAttrString(code, "co_filename"); + nm = PyObject_GetAttrString(code, "co_name"); + + args = Py_BuildValue("(OOO)", fn, ln, nm); /* args tuple */ + logline = PyString_Format(tmpl, args); /* build logged string */ + PyList_Append(tb_list, logline); /* append string to list */ + + /* decrement references on all our objects */ + Py_DECREF(logline); + Py_DECREF(args); + Py_XDECREF(nm); + Py_XDECREF(fn); + Py_XDECREF(code); + Py_XDECREF(frame); + Py_XDECREF(ln); + + old_tb = cur_tb; + /* get the next traceback item */ + cur_tb = PyObject_GetAttrString(cur_tb, "tb_next"); + Py_DECREF(old_tb); /* we're done with old_tb so decref it */ + } + PyList_Append(tb_list, ftr); /* append the log msg footer */ + + os = PyImport_ImportModule("os"); + sep = PyObject_GetAttrString(os, "linesep"); /* get os EOL char */ + tb_log = _PyString_Join(sep, tb_list); /* create tb log msgs */ + tbstr = PyString_AsString(tb_log); + + Py_DECREF(tb_log); + Py_DECREF(sep); + Py_DECREF(os); + Py_DECREF(tb_list); + Py_DECREF(ftr); + Py_DECREF(tmpl); + Py_DECREF(hdr); + } + else + tbstr = "No Traceback"; + /* * 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 @@ -2530,7 +2607,7 @@ * Assert() be more appropriate? */ estr = eob ? PyString_AsString(eob) : "Unknown Exception"; - xstr = PLy_printf("%s: %s", estr, vstr); + xstr = PLy_printf("%s%s: %s", tbstr, estr, vstr); Py_DECREF(eob); Py_XDECREF(vob);
pgsql-patches by date: