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"""