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);

---------------------------(end of broadcast)---------------------------
TIP 1: if posting/reading through Usenet, please send an appropriate
      subscribe-nomail command to [EMAIL PROTECTED] so that your
      message can get through to the mailing list cleanly

Reply via email to