You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2011/08/05 22:53:44 UTC

svn commit: r1154378 - in /subversion/branches/fs-py/subversion: include/svn_error_codes.h libsvn_fs_py/py_util.c

Author: hwright
Date: Fri Aug  5 20:53:44 2011
New Revision: 1154378

URL: http://svn.apache.org/viewvc?rev=1154378&view=rev
Log:
On the fs-py branch:
When handling exceptions raised in Python code, insert the python stack trace
into our own error tracing.

* subversion/libsvn_fs_py/py_util.c
  (create_py_stack): New.
  (load_module): Use create_py_stack() to build the appropriate error, and
    fix up a couple of cleanup stuffs.
  (svn_fs_py__init_python): Don't search for the exception type if the module
    didn't load.

* subversion/include/svn_error_codes.h
  (SVN_ERR_BAD_PYTHON): New.

Modified:
    subversion/branches/fs-py/subversion/include/svn_error_codes.h
    subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c

Modified: subversion/branches/fs-py/subversion/include/svn_error_codes.h
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/include/svn_error_codes.h?rev=1154378&r1=1154377&r2=1154378&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/include/svn_error_codes.h (original)
+++ subversion/branches/fs-py/subversion/include/svn_error_codes.h Fri Aug  5 20:53:44 2011
@@ -224,6 +224,11 @@ SVN_ERROR_START
              SVN_ERR_BAD_CATEGORY_START + 14,
              "Invalid changelist name")
 
+  /** @since New in ??. */
+  SVN_ERRDEF(SVN_ERR_BAD_PYTHON,
+             SVN_ERR_BAD_CATEGORY_START + 15,
+             "Embedded Python exception")
+
   /* xml errors */
 
   SVN_ERRDEF(SVN_ERR_XML_ATTRIB_NOT_FOUND,

Modified: subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c?rev=1154378&r1=1154377&r2=1154378&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c Fri Aug  5 20:53:44 2011
@@ -34,6 +34,89 @@ static PyObject *p_exception_type;
 static PyObject *p_root_module;
 
 static svn_error_t *
+create_py_stack(PyObject *p_exception,
+                PyObject *p_traceback)
+{
+  svn_error_t *err;
+  PyObject *p_reason;
+  char *reason;
+
+  p_reason = PyObject_Str(p_exception);
+  reason = PyString_AsString(p_reason);
+
+#ifdef SVN_ERR__TRACING
+  {
+    PyObject *p_module_name;
+    PyObject *p_traceback_mod;
+    PyObject *p_func;
+    PyObject *p_args;
+    PyObject *p_stack;
+    PyObject *p_frame;
+    PyObject *p_filename;
+    PyObject *p_lineno;
+    Py_ssize_t i;
+
+    /* We don't use load_module() here to avoid an infinite recursion. */
+    /* ### This could use more python error checking. */
+    p_module_name = PyString_FromString("traceback");
+    p_traceback_mod = PyImport_Import(p_module_name);
+    Py_DECREF(p_module_name);
+
+    p_func = PyObject_GetAttrString(p_traceback_mod, "extract_tb");
+    Py_DECREF(p_traceback_mod);
+
+    p_args = Py_BuildValue("(O)", p_traceback);
+    p_stack = PyObject_CallObject(p_func, p_args);
+    Py_DECREF(p_func);
+    Py_DECREF(p_args);
+
+    i = PySequence_Length(p_stack);
+
+    /* Build the "root error" for the chain. */
+    p_frame = PySequence_GetItem(p_stack, i-1);
+    p_filename = PySequence_GetItem(p_frame, 0);
+    p_lineno = PySequence_GetItem(p_frame, 1);
+    Py_DECREF(p_frame);
+
+    err = svn_error_createf(SVN_ERR_BAD_PYTHON, NULL,
+                          _("Exception while executing Python; cause: '%s'"),
+                          reason);
+
+    err->file = apr_pstrdup(err->pool, PyString_AsString(p_filename));
+    err->line = PyInt_AsLong(p_lineno);
+
+    Py_DECREF(p_filename);
+    Py_DECREF(p_lineno);
+
+    for (i = i-2; i >=0; i--)
+      {
+        p_frame = PySequence_GetItem(p_stack, i);
+        p_filename = PySequence_GetItem(p_frame, 0);
+        p_lineno = PySequence_GetItem(p_frame, 1);
+        Py_DECREF(p_frame);
+
+        err = svn_error_quick_wrap(err, SVN_ERR__TRACED);
+        err->file = apr_pstrdup(err->pool, PyString_AsString(p_filename));
+        err->line = PyInt_AsLong(p_lineno);
+        
+        Py_DECREF(p_filename);
+        Py_DECREF(p_lineno);
+      }
+
+    Py_DECREF(p_stack);
+  }
+#else
+  err = svn_error_createf(SVN_ERR_BAD_PYTHON, NULL,
+                          _("Exception while executing Python; cause: '%s'"),
+                          reason);
+#endif
+
+  Py_DECREF(p_reason);
+
+  return err;
+}
+
+static svn_error_t *
 load_module(PyObject **p_module_out,
             const char *module_name)
 {
@@ -56,8 +139,6 @@ load_module(PyObject **p_module_out,
 load_error:
   {
     PyObject *p_type, *p_exception, *p_traceback;
-    PyObject *p_reason;
-    const char *reason;
     svn_error_t *err;
 
     /* Release the values above. */
@@ -66,23 +147,18 @@ load_error:
 
     PyErr_Fetch(&p_type, &p_exception, &p_traceback);
 
-    if (p_exception)
-      {
-        p_reason = PyObject_Str(p_exception);
-        reason = PyString_AsString(p_reason);
-
-        err = svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
-                                _("Cannot load Python module, cause: %s"),
-                                reason);
-      }
+    if (p_exception && p_traceback)
+      err = create_py_stack(p_exception, p_traceback);
     else
-      err = svn_error_create(SVN_ERR_FS_GENERAL, NULL, NULL);
+      err = svn_error_create(SVN_ERR_BAD_PYTHON, NULL,
+                             _("Cannot load Python module"));
+
+    PyErr_Clear();
 
+    Py_DECREF(p_type);
     Py_XDECREF(p_exception);
-    Py_XDECREF(p_type);
     Py_XDECREF(p_traceback);
 
-    Py_XDECREF(p_reason);
     return err;
   }
 }
@@ -114,8 +190,6 @@ svn_fs_py__init_python(apr_pool_t *pool)
 
   SVN_ERR(load_module(&p_root_module, ROOT_MODULE_NAME));
   
-  p_exception_type = PyObject_GetAttrString(p_root_module,
-                                            "SubversionException");
   if (PyErr_Occurred())
     {
       PyErr_Clear();
@@ -123,6 +197,8 @@ svn_fs_py__init_python(apr_pool_t *pool)
                               _("Cannot load Python module"));
     }
 
+  p_exception_type = PyObject_GetAttrString(p_root_module,
+                                            "SubversionException");
 
   return SVN_NO_ERROR;
 }