You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rd...@apache.org on 2010/03/25 00:29:20 UTC

svn commit: r927222 - in /subversion/trunk/subversion/bindings/swig/python: libsvn_swig_py/swigutil_py.c tests/repository.py

Author: rdonch
Date: Wed Mar 24 23:29:20 2010
New Revision: 927222

URL: http://svn.apache.org/viewvc?rev=927222&view=rev
Log:
SWIG/Python: enable callback functions to return Subversion errors (by
throwing a SubversionException).

* subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c:
  (callback_exception_error): Extend to check for a SubversionException
   and attempt to translate it into an svn_error_t*.

* subversion/bindings/swig/python/tests/repository.py:
  (SubversionRepositoryTestCase.test_cease_invocation): New test for
   the above functionality.


Modified:
    subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c
    subversion/trunk/subversion/bindings/swig/python/tests/repository.py

Modified: subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c?rev=927222&r1=927221&r2=927222&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c (original)
+++ subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c Wed Mar 24 23:29:20 2010
@@ -1320,11 +1320,57 @@ commit_item_array_to_list(const apr_arra
 
 /*** Errors ***/
 
-/* Return a Subversion error about a failed callback. */
+/* If the currently set Python exception is a valid SubversionException,
+   clear exception state and transform it into a Subversion error.
+   Otherwise, return a Subversion error about an exception in a callback. */
 static svn_error_t *callback_exception_error(void)
 {
-  return svn_error_create(SVN_ERR_SWIG_PY_EXCEPTION_SET, NULL,
-                          "Python callback raised an exception");
+  PyObject *svn_module = NULL, *svn_exc = NULL;
+  PyObject *exc, *exc_type, *exc_traceback;
+  PyObject *message_ob = NULL, *apr_err_ob = NULL;
+  const char *message;
+  int apr_err;
+  svn_error_t *rv = NULL;
+
+  PyErr_Fetch(&exc_type, &exc, &exc_traceback);
+
+  if ((svn_module = PyImport_ImportModule("svn.core")) == NULL)
+    goto finished;
+  if ((svn_exc = PyObject_GetAttrString(svn_module, "SubversionException"))
+      == NULL)
+    goto finished;
+
+  if (!PyErr_GivenExceptionMatches(exc_type, svn_exc))
+    {
+      PyErr_Restore(exc_type, exc, exc_traceback);
+      exc = exc_type = exc_traceback = NULL;
+      goto finished;
+    }
+
+  if ((apr_err_ob = PyObject_GetAttrString(exc, "apr_err")) == NULL)
+    goto finished;
+  apr_err = PyInt_AsLong(apr_err_ob);
+  if (PyErr_Occurred()) goto finished;
+
+  if ((message_ob = PyObject_GetAttrString(exc, "message")) == NULL)
+    goto finished;
+  message = PyString_AsString(message_ob);
+  if (PyErr_Occurred()) goto finished;
+
+  /* A possible improvement here would be to convert the whole
+     SubversionException chain. */
+  rv = svn_error_create(apr_err, NULL, message);
+
+finished:
+  Py_XDECREF(exc);
+  Py_XDECREF(exc_type);
+  Py_XDECREF(exc_traceback);
+  Py_XDECREF(svn_module);
+  Py_XDECREF(svn_exc);
+  Py_XDECREF(apr_err_ob);
+  Py_XDECREF(message_ob);
+  return rv ? rv : svn_error_create(SVN_ERR_SWIG_PY_EXCEPTION_SET, NULL,
+                                    "Python callback raised an exception");
 }
 
 /* Raise a TypeError exception with MESSAGE, and return a Subversion

Modified: subversion/trunk/subversion/bindings/swig/python/tests/repository.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/tests/repository.py?rev=927222&r1=927221&r2=927222&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/tests/repository.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/tests/repository.py Wed Mar 24 23:29:20 2010
@@ -63,6 +63,19 @@ class SubversionRepositoryTestCase(unitt
     self.fs = None
     self.repos = None
 
+  def test_cease_invocation(self):
+    """Test returning SVN_ERR_CEASE_INVOCATION from a callback"""
+
+    revs = []
+    def history_lookup(path, rev, pool):
+      revs.append(rev)
+      raise core.SubversionException(apr_err=core.SVN_ERR_CEASE_INVOCATION,
+                                     message="Hi from history_lookup")
+    
+    repos.history2(self.fs, '/trunk/README2.txt', history_lookup, None, 0,
+                   self.rev, True)
+    self.assertEqual(len(revs), 1)
+
   def test_create(self):
     """Make sure that repos.create doesn't segfault when we set fs-type
        using a config hash"""