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/10 00:01:28 UTC
svn commit: r1155571 -
/subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c
Author: hwright
Date: Tue Aug 9 22:01:28 2011
New Revision: 1155571
URL: http://svn.apache.org/viewvc?rev=1155571&view=rev
Log:
On the fs-py branch:
Add a helper function which calls a given func/baton pair, and then wraps any
resulting Python exception in a Subversion error. We were already doing this
before for method calls, but this is a more generalized approach.
* subversion/libsvn_fs_py/py_util.c
(py_exc_func_t): New.
(catch_py_exception): New.
(call_method_baton, call_method): New.
(svn_fs_py__call_method): Use the helper function to do error handling.
Modified:
subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c
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=1155571&r1=1155570&r2=1155571&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 Tue Aug 9 22:01:28 2011
@@ -122,6 +122,49 @@ create_py_stack(PyObject *p_exception,
return err;
}
+typedef void (*py_exc_func_t)(void *baton, va_list argp);
+
+/* Call FUNC with BATON, and upon returning check to see if the Python
+ interpreter has a pending exception. If it does, convert that exception
+ to an svn_error_t and return it (or SVN_NO_ERROR if no error), resetting
+ the interpreter state and releasing the exception.
+
+ Note: This function assumes whatever locking we need for the interpreter
+ has already happened and will be released after it is done. */
+static svn_error_t *
+catch_py_exception(py_exc_func_t func,
+ void *baton,
+ va_list argp)
+{
+ PyObject *p_type;
+ PyObject *p_exception;
+ PyObject *p_traceback;
+ svn_error_t *err;
+
+ /* Call the handler. */
+ func(baton, argp);
+
+ /* Early out if we didn't have any errors. */
+ if (!PyErr_Occurred())
+ return SVN_NO_ERROR;
+
+ PyErr_Fetch(&p_type, &p_exception, &p_traceback);
+
+ if (p_exception && p_traceback)
+ err = create_py_stack(p_exception, p_traceback);
+ else
+ err = svn_error_create(SVN_ERR_BAD_PYTHON, NULL,
+ _("Python error."));
+
+ PyErr_Clear();
+
+ Py_DECREF(p_type);
+ Py_XDECREF(p_exception);
+ Py_XDECREF(p_traceback);
+
+ return err;
+}
+
static svn_error_t *
load_module(PyObject **p_module_out,
const char *module_name)
@@ -215,75 +258,77 @@ svn_fs_py__destroy_py_object(void *data)
}
-svn_error_t*
-svn_fs_py__call_method(PyObject **p_result,
- PyObject *p_obj,
- const char *name,
- const char *format,
- ...)
+struct call_method_baton
{
- PyObject *p_func = NULL;
- PyObject *p_value = NULL;
- PyObject *p_args = NULL;
- va_list argp;
+ PyObject **p_result;
+ PyObject *p_obj;
+ const char *name;
+ const char *format;
+};
- SVN_ERR_ASSERT(p_obj != NULL);
- va_start(argp, format);
+static void
+call_method(void *baton, va_list argp)
+{
+ struct call_method_baton *cmb = baton;
+ PyObject *p_args = NULL;
+ PyObject *p_func = NULL;
+ PyObject *p_value = NULL;
- p_args = Py_VaBuildValue(format, argp);
+ p_args = Py_VaBuildValue(cmb->format, argp);
if (PyErr_Occurred())
- goto create_error;
+ goto cm_free_objs;
- p_func = PyObject_GetAttrString(p_obj, name);
+ p_func = PyObject_GetAttrString(cmb->p_obj, cmb->name);
if (PyErr_Occurred())
- goto create_error;
-
- /* ### Need a callable check here? */
+ goto cm_free_objs;
p_value = PyObject_CallObject(p_func, p_args);
Py_DECREF(p_args);
p_args = NULL;
+ Py_DECREF(p_func);
+ p_func = NULL;
if (PyErr_Occurred())
- goto create_error;
+ goto cm_free_objs;
- if (p_result)
- *p_result = p_value;
+ if (cmb->p_result)
+ *cmb->p_result = p_value;
else
Py_DECREF(p_value);
- Py_DECREF(p_func);
+ return;
- va_end(argp);
- return SVN_NO_ERROR;
+cm_free_objs:
+ /* Error handler, decrefs all python objects we may have. */
+ Py_XDECREF(p_args);
+ Py_XDECREF(p_func);
+}
-create_error:
- {
- PyObject *p_type = NULL;
- PyObject *p_exception = NULL;
- PyObject *p_traceback = NULL;
- svn_error_t *err;
- va_end(argp);
- Py_XDECREF(p_args);
- Py_XDECREF(p_func);
+svn_error_t*
+svn_fs_py__call_method(PyObject **p_result,
+ PyObject *p_obj,
+ const char *name,
+ const char *format,
+ ...)
+{
+ svn_error_t *err;
+ va_list argp;
+ struct call_method_baton cmb;
- PyErr_Fetch(&p_type, &p_exception, &p_traceback);
+ SVN_ERR_ASSERT(p_obj != NULL);
- if (p_exception && p_traceback)
- err = create_py_stack(p_exception, p_traceback);
- else
- err = svn_error_create(SVN_ERR_BAD_PYTHON, NULL,
- _("Error calling method"));
+ va_start(argp, format);
- PyErr_Clear();
+ cmb.p_result = p_result;
+ cmb.p_obj = p_obj;
+ cmb.name = name;
+ cmb.format = format;
- Py_DECREF(p_type);
- Py_XDECREF(p_exception);
- Py_XDECREF(p_traceback);
+ err = catch_py_exception(call_method, &cmb, argp);
- return err;
- }
+ va_end(argp);
+ return err;
}
PyObject *