On Tuesday 23 March 2010 03:38:06 pm Роман Донченко wrote: > Alexey Neyman <sti...@att.net> писал в своём письме Fri, 19 Mar 2010 > > 02:26:28 +0300: > > ... > > > > With stock 1.6.6, it produces the following traceback: > > > > --------------------------------------------------------------------- > >---- svn: Commit blocked by pre-commit hook (exit code 1) with output: > > Traceback (most recent call last): > > File "/tmp/c.repo/hooks/pre-commit", line 35, in <module> > > core.run_app(verify, sys.argv[1], sys.argv[2]) > > File "/usr/local/lib/svn-python/svn/core.py", line 281, in run_app > > return func(application_pool, *args, **kw) > > File "/tmp/c.repo/hooks/pre-commit", line 31, in verify > > repos.svn_repos_replay2(txn_root, "", -1, True, e_ptr, e_baton, > > None, pool) > > File "/usr/local/lib/svn-python/libsvn/repos.py", line 311, in > > svn_repos_replay2 > > return apply(_repos.svn_repos_replay2, args) > > File "/tmp/c.repo/hooks/pre-commit", line 22, in open_directory > > repos.svn_repos_history2(self.fs_ptr, path, history_lookup, None, > > 0, self.base_rev, True, self.pool) > > File "/usr/local/lib/svn-python/libsvn/repos.py", line 407, in > > svn_repos_history2 > > return apply(_repos.svn_repos_history2, args) > > File "/tmp/c.repo/hooks/pre-commit", line 21, in history_lookup > > raise > > core.SubversionException(apr_err=core.SVN_ERR_CEASE_INVOCATION, > > message="Hi from history_lookup") > > svn.core.SubversionException: ('Hi from history_lookup', 200021) > > --------------------------------------------------------------------- > >---- > > > > Changed to the following code (difference from previous version is > > that it > > Py_DECREF's everything): > > > > --------------------------------------------------------------------- > >---- static svn_error_t *callback_exception_error(void) > > { > > PyObject *err = PyErr_Occurred(); > > PyObject *svn_module = NULL, *exc_class = NULL; > > PyObject *message = NULL, *apr_err = NULL; > > svn_error_t *rv = NULL; > > > > if ((svn_module = PyImport_ImportModule((char *)"svn.core")) == > > NULL) goto finished; > > if ((exc_class = PyObject_GetAttrString(svn_module, > > (char *)"SubversionException")) == NULL) > > goto finished; > > if (PyErr_GivenExceptionMatches(exc_class, err)) > > { > > apr_err = PyObject_GetAttrString(err, (char *)"apr_err"); > > message = PyObject_GetAttrString(err, (char *)"message"); > > if (message && apr_err && PyString_Check(message) && > > PyInt_Check(apr_err)) > > rv = svn_error_create(PyInt_AsLong(apr_err), NULL, > > PyString_AsString(message)); > > } > > finished: > > Py_XDECREF(svn_module); > > Py_XDECREF(exc_class); > > Py_XDECREF(apr_err); > > Py_XDECREF(message); > > return rv ? rv : svn_error_create(SVN_ERR_SWIG_PY_EXCEPTION_SET, > > NULL, "Python callback raised an exception"); } > > --------------------------------------------------------------------- > >---- > > > > With this, pre-commit produces this traceback: > > > > --------------------------------------------------------------------- > >---- svn: Commit blocked by pre-commit hook (exit code 1) with output: > > Traceback (most recent call last): > > File "/tmp/c.repo/hooks/pre-commit", line 35, in <module> > > core.run_app(verify, sys.argv[1], sys.argv[2]) > > File "/usr/local/lib/svn-python/svn/core.py", line 281, in run_app > > return func(application_pool, *args, **kw) > > File "/tmp/c.repo/hooks/pre-commit", line 31, in verify > > repos.svn_repos_replay2(txn_root, "", -1, True, e_ptr, e_baton, > > None, pool) > > File "/usr/local/lib/svn-python/libsvn/repos.py", line 311, in > > svn_repos_replay2 > > return apply(_repos.svn_repos_replay2, args) > > SystemError: NULL result without error in PyObject_Call > > --------------------------------------------------------------------- > >---- > > OK, I think I got it. It couldn't find "apr_err", because > PyErr_Occurred returns the exception _type_, and I'm pretty sure that > the SystemError is due to not clearing the exception (although I don't > know for sure, since I switched to PyErr_Fetch, and that automatically > clears it). Please test with this version, which works for me: > > static svn_error_t *callback_exception_error(void) > { > PyObject *svn_module = NULL, *svn_exc = NULL; > PyObject *message = NULL, *apr_err = NULL; > PyObject *exc, *exc_type, *exc_traceback; > 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)) > { > Py_DECREF(exc_type); > Py_DECREF(exc_traceback); > } > else > { > PyErr_Restore(exc_type, exc, exc_traceback); > goto finished; > } > > if ((apr_err = PyObject_GetAttrString(exc, "apr_err")) == NULL) > goto finished; > if ((message = PyObject_GetAttrString(exc, "message")) == NULL) > goto finished; > > Py_DECREF(exc); > > /* A possible improvement here would be to convert the whole > SubversionException chain. */ > if (PyString_Check(message) && PyInt_Check(apr_err)) > rv = svn_error_create(PyInt_AsLong(apr_err), NULL, > PyString_AsString(message)); > > finished: > Py_XDECREF(svn_module); > Py_XDECREF(svn_exc); > Py_XDECREF(apr_err); > Py_XDECREF(message); > return rv ? rv : svn_error_create(SVN_ERR_SWIG_PY_EXCEPTION_SET, > NULL, "Python callback raised an exception"); } > }
Works for me, thanks! I'll try to write a test case for 'make check-swig-py'. Is this going to be checked to trunk only, or could it be checked in to upcoming 1.6.10 as well? I tried the same code with SVN I am currently using (1.6.6), it works as well. Regards, Alexey.