diff options
Diffstat (limited to 'subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c')
-rw-r--r-- | subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c | 801 |
1 files changed, 642 insertions, 159 deletions
diff --git a/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c b/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c index abe5a2a..346041f 100644 --- a/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c +++ b/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c @@ -23,9 +23,12 @@ /* Tell swigutil_py.h that we're inside the implementation */ #define SVN_SWIG_SWIGUTIL_PY_C +/* Avoid deprecation warnings about PY_SSIZE_T_CLEAN since Python 3.8 */ +#define PY_SSIZE_T_CLEAN #include <Python.h> + #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -50,6 +53,19 @@ #include "swig_python_external_runtime.swg" #include "swigutil_py.h" +#include "swigutil_py3c.h" + +#if IS_PY3 + +/* In Python 3 use the bytes format character for raw data */ +#define SVN_SWIG_BYTES_FMT "y" + +#else + +/* In Python 2 use the string format character for raw data */ +#define SVN_SWIG_BYTES_FMT "s" + +#endif /* Py_ssize_t for old Pythons */ /* This code is as recommended by: */ @@ -142,6 +158,35 @@ apr_status_t svn_swig_py_initialize(void) return APR_SUCCESS; } +FILE *svn_swig_py_as_file(PyObject *pyfile) +{ +#if IS_PY3 + FILE *fp = NULL; + int fd = PyObject_AsFileDescriptor(pyfile); + if (fd >= 0) + { + PyObject *mode_obj; + PyObject *mode_byte_obj = NULL; + char *mode = NULL; + + /* If any Python API returns NULL, then the Python exception is set and + this function will return NULL signifying to the caller that an error + occurred. */ + if ( NULL != (mode_obj = PyObject_GetAttrString(pyfile, "mode")) + && NULL != (mode_byte_obj = PyUnicode_AsUTF8String(mode_obj)) + && NULL != (mode = PyBytes_AsString(mode_byte_obj))) + fp = fdopen(fd, mode); + + Py_XDECREF(mode_obj); + Py_XDECREF(mode_byte_obj); + } + + return fp; +#else + return PyFile_AsFile(pyfile); +#endif +} + int svn_swig_py_get_pool_arg(PyObject *args, swig_type_info *type, PyObject **py_pool, apr_pool_t **pool) { @@ -150,14 +195,25 @@ int svn_swig_py_get_pool_arg(PyObject *args, swig_type_info *type, if (argnum >= 0) { PyObject *input = PyTuple_GET_ITEM(args, argnum); - if (input != Py_None && PyObject_HasAttrString(input, markValid)) + if (input != Py_None) { - *pool = svn_swig_py_must_get_ptr(input, type, argnum+1); - if (*pool == NULL) - return 1; - *py_pool = input; - Py_INCREF(input); - return 0; + PyObject *fn; + if (NULL != (fn = PyObject_GetAttrString(input, markValid))) + { + Py_DECREF(fn); + + *pool = svn_swig_py_must_get_ptr(input, type, argnum+1); + if (*pool == NULL) + return 1; + *py_pool = input; + Py_INCREF(input); + return 0; + } + else + { + /* Clear any getattr() error, it isn't needed. */ + PyErr_Clear(); + } } } @@ -221,13 +277,20 @@ static int proxy_set_pool(PyObject **proxy, PyObject *pool) { if (pool == NULL) { - if (PyObject_HasAttrString(*proxy, setParentPool)) + PyObject *setFn; + if (NULL != (setFn = PyObject_GetAttrString(*proxy, setParentPool))) { - result = PyObject_CallMethod(*proxy, setParentPool, emptyTuple); + result = PyObject_CallObject(setFn, NULL); + Py_DECREF(setFn); if (result == NULL) return 1; Py_DECREF(result); } + else + { + /* Clear any getattr() error, it isn't needed. */ + PyErr_Clear(); + } } else { @@ -285,23 +348,45 @@ static PyObject *svn_swig_NewPointerObjString(void *ptr, const char *type, return svn_swig_py_new_pointer_obj(ptr, typeinfo, py_pool, NULL); } -/** Wrapper for SWIG_ConvertPtr */ -int svn_swig_py_convert_ptr(PyObject *input, void **obj, swig_type_info *type) +static int svn_swig_ensure_valid_swig_wrapper(PyObject *input) { - if (PyObject_HasAttrString(input, assertValid)) + PyObject *assertFn; + PyObject *unwrapFn; + if (NULL != (assertFn = PyObject_GetAttrString(input, assertValid))) { - PyObject *result = PyObject_CallMethod(input, assertValid, emptyTuple); + PyObject *result = PyObject_CallObject(assertFn, NULL); + Py_DECREF(assertFn); if (result == NULL) return 1; Py_DECREF(result); } - if (PyObject_HasAttrString(input, unwrap)) + else { - input = PyObject_CallMethod(input, unwrap, emptyTuple); + /* Clear any getattr() error, it isn't needed. */ + PyErr_Clear(); + } + if (NULL != (unwrapFn = PyObject_GetAttrString(input, unwrap))) + { + input = PyObject_CallObject(unwrapFn, NULL); + Py_DECREF(unwrapFn); if (input == NULL) return 1; Py_DECREF(input); } + else + { + /* Clear any getattr() error, it isn't needed. */ + PyErr_Clear(); + } + + return 0; +} + +/** Wrapper for SWIG_ConvertPtr */ +int svn_swig_py_convert_ptr(PyObject *input, void **obj, swig_type_info *type) +{ + if (svn_swig_ensure_valid_swig_wrapper(input)) + return 1; return SWIG_ConvertPtr(input, obj, type, SWIG_POINTER_EXCEPTION | 0); } @@ -316,21 +401,8 @@ static int svn_swig_ConvertPtrString(PyObject *input, /** Wrapper for SWIG_MustGetPtr */ void *svn_swig_py_must_get_ptr(void *input, swig_type_info *type, int argnum) { - if (PyObject_HasAttrString(input, assertValid)) - { - PyObject *result = PyObject_CallMethod(input, assertValid, emptyTuple); - if (result == NULL) - return NULL; - Py_DECREF(result); - } - - if (PyObject_HasAttrString(input, unwrap)) - { - input = PyObject_CallMethod(input, unwrap, emptyTuple); - if (input == NULL) - return NULL; - Py_DECREF((PyObject *) input); - } + if (svn_swig_ensure_valid_swig_wrapper(input)) + return NULL; return SWIG_MustGetPtr(input, type, argnum, SWIG_POINTER_EXCEPTION | 0); } @@ -370,14 +442,14 @@ void svn_swig_py_svn_exception(svn_error_t *error_chain) Py_INCREF(Py_None); message_ob = Py_None; } - else if ((message_ob = PyString_FromString(err->message)) == NULL) + else if ((message_ob = PyStr_FromString(err->message)) == NULL) goto finished; if (err->file == NULL) { Py_INCREF(Py_None); file_ob = Py_None; } - else if ((file_ob = PyString_FromString(err->file)) == NULL) + else if ((file_ob = PyStr_FromString(err->file)) == NULL) goto finished; if ((line_ob = PyInt_FromLong(err->line)) == NULL) goto finished; @@ -436,6 +508,36 @@ void svn_swig_py_svn_exception(svn_error_t *error_chain) /*** Helper/Conversion Routines ***/ +/* Function to get char * representation of bytes/str object. This is + the replacement of typemap(in, parse="s") and typemap(in, parse="z") + to accept both of bytes object and str object, and it assumes to be + used from those typemaps only. + Note: type of return value should be char const *, however, as SWIG + produces variables for C function without 'const' modifier, to avoid + ton of cast in SWIG produced C code we drop it from return value + types as well */ +char *svn_swig_py_string_to_cstring(PyObject *input, int maybe_null, + const char * funcsym, const char * argsym) +{ + char *retval = NULL; + if (PyBytes_Check(input)) + { + retval = PyBytes_AsString(input); + } + else if (PyUnicode_Check(input)) + { + retval = (char *)PyStr_AsUTF8(input); + } + else if (input != Py_None || ! maybe_null) + { + PyErr_Format(PyExc_TypeError, + "%s() argument %s must be bytes or str%s, not %s", + funcsym, argsym, maybe_null?" or None":"", + Py_TYPE(input)->tp_name); + } + return retval; +} + /* Functions for making Python wrappers around Subversion structs */ static PyObject *make_ob_pool(void *pool) { @@ -470,32 +572,89 @@ static PyObject *make_ob_error(svn_error_t *err) /***/ +static void svn_swig_py_string_type_exception(int maybe_null) +{ + PyErr_Format(PyExc_TypeError, "not a bytes or a str%s", + maybe_null?" or None":""); +} + /* Conversion from Python single objects (not hashes/lists/etc.) to Subversion types. */ static char *make_string_from_ob(PyObject *ob, apr_pool_t *pool) { + /* caller should not expect to raise TypeError: check return value + whether it is NULL or not, if needed */ + if (PyBytes_Check(ob)) + { + return apr_pstrdup(pool, PyBytes_AsString(ob)); + } + if (PyUnicode_Check(ob)) + { + /* PyStr_AsUTF8() may cause UnicodeEncodeError, + but apr_pstrdup() allows NULL for s */ + return apr_pstrdup(pool, PyStr_AsUTF8(ob)); + } + return NULL; +} + +static char *make_string_from_ob_maybe_null(PyObject *ob, apr_pool_t *pool) +{ + char * retval; if (ob == Py_None) - return NULL; - if (! PyString_Check(ob)) { - PyErr_SetString(PyExc_TypeError, "not a string"); return NULL; } - return apr_pstrdup(pool, PyString_AS_STRING(ob)); + retval = make_string_from_ob(ob, pool); + if (!retval) + { + if (!PyErr_Occurred()) + { + svn_swig_py_string_type_exception(TRUE); + } + } + return retval; } + static svn_string_t *make_svn_string_from_ob(PyObject *ob, apr_pool_t *pool) { + /* caller should not expect to raise TypeError: check return value + whether it is NULL or not, if needed */ + if (PyBytes_Check(ob)) + { + return svn_string_create(PyBytes_AsString(ob), pool); + } + if (PyUnicode_Check(ob)) + { + /* PyStr_AsUTF8() may cause UnicodeEncodeError, + and svn_string_create() does not allows NULL for cstring */ + const char *obstr = PyStr_AsUTF8(ob); + if (obstr) + { + return svn_string_create(obstr, pool); + } + } + return NULL; +} + +static svn_string_t *make_svn_string_from_ob_maybe_null(PyObject *ob, + apr_pool_t *pool) +{ + svn_string_t * retval; if (ob == Py_None) - return NULL; - if (! PyString_Check(ob)) { - PyErr_SetString(PyExc_TypeError, "not a string"); return NULL; } - return svn_string_create(PyString_AS_STRING(ob), pool); + retval = make_svn_string_from_ob(ob, pool); + if (!retval) + { + if (!PyErr_Occurred()) + { + svn_swig_py_string_type_exception(TRUE); + } + } + return retval; } - /***/ static PyObject *convert_hash(apr_hash_t *hash, @@ -527,7 +686,7 @@ static PyObject *convert_hash(apr_hash_t *hash, return NULL; } /* ### gotta cast this thing cuz Python doesn't use "const" */ - if (PyDict_SetItemString(dict, (char *)key, value) == -1) + if (PyDict_SetItem(dict, PyBytes_FromString((char *)key), value) == -1) { Py_DECREF(value); Py_DECREF(dict); @@ -552,11 +711,10 @@ static PyObject *convert_svn_string_t(void *value, void *ctx, const svn_string_t *s = value; - /* ### gotta cast this thing cuz Python doesn't use "const" */ - return PyString_FromStringAndSize((void *)s->data, s->len); + return PyBytes_FromStringAndSize(s->data, s->len); } -/* Convert a C string into a Python String object (or a reference to +/* Convert a C string into a Python Bytes object (or a reference to Py_None if CSTRING is NULL). */ static PyObject *cstring_to_pystring(const char *cstring) { @@ -566,7 +724,7 @@ static PyObject *cstring_to_pystring(const char *cstring) Py_INCREF(Py_None); return retval; } - return PyString_FromString(cstring); + return PyBytes_FromString(cstring); } static PyObject *convert_svn_client_commit_item3_t(void *value, void *ctx) @@ -642,8 +800,7 @@ PyObject *svn_swig_py_prophash_to_dict(apr_hash_t *hash) static PyObject *convert_string(void *value, void *ctx, PyObject *py_pool) { - /* ### gotta cast this thing cuz Python doesn't use "const" */ - return PyString_FromString((const char *)value); + return PyBytes_FromString((const char *)value); } PyObject *svn_swig_py_stringhash_to_dict(apr_hash_t *hash) @@ -725,7 +882,7 @@ svn_swig_py_propinheriteditemarray_to_dict(const apr_array_header_t *array) apr_hash_t *prop_hash = prop_inherited_item->prop_hash; PyObject *py_key, *py_value; - py_key = PyString_FromString(prop_inherited_item->path_or_url); + py_key = PyBytes_FromString(prop_inherited_item->path_or_url); if (py_key == NULL) goto error; @@ -769,7 +926,7 @@ PyObject *svn_swig_py_proparray_to_dict(const apr_array_header_t *array) prop = APR_ARRAY_IDX(array, i, svn_prop_t); - py_key = PyString_FromString(prop.name); + py_key = PyBytes_FromString(prop.name); if (py_key == NULL) goto error; @@ -780,8 +937,8 @@ PyObject *svn_swig_py_proparray_to_dict(const apr_array_header_t *array) } else { - py_value = PyString_FromStringAndSize((void *)prop.value->data, - prop.value->len); + py_value = PyBytes_FromStringAndSize(prop.value->data, + prop.value->len); if (py_value == NULL) { Py_DECREF(py_key); @@ -831,7 +988,7 @@ PyObject *svn_swig_py_locationhash_to_dict(apr_hash_t *hash) Py_DECREF(dict); return NULL; } - value = PyString_FromString((char *)v); + value = PyBytes_FromString((const char *)v); if (value == NULL) { Py_DECREF(key); @@ -881,6 +1038,7 @@ DECLARE_SWIG_CONSTRUCTOR(info, svn_info_dup) DECLARE_SWIG_CONSTRUCTOR(location_segment, svn_location_segment_dup) DECLARE_SWIG_CONSTRUCTOR(commit_info, svn_commit_info_dup) DECLARE_SWIG_CONSTRUCTOR(wc_notify, svn_wc_dup_notify) +DECLARE_SWIG_CONSTRUCTOR(client_status, svn_client_status_dup) static PyObject *convert_log_changed_path(void *value, void *ctx, PyObject *py_pool) @@ -895,7 +1053,7 @@ PyObject *svn_swig_py_c_strings_to_list(char **strings) while ((s = *strings++) != NULL) { - PyObject *ob = PyString_FromString(s); + PyObject *ob = PyBytes_FromString(s); if (ob == NULL) goto error; @@ -938,7 +1096,7 @@ PyObject *svn_swig_py_changed_path_hash_to_dict(apr_hash_t *hash) Py_DECREF(dict); return NULL; } - if (PyDict_SetItemString(dict, (char *)key, value) == -1) + if (PyDict_SetItem(dict, PyBytes_FromString((char *)key), value) == -1) { Py_DECREF(value); Py_DECREF(dict); @@ -974,7 +1132,7 @@ PyObject *svn_swig_py_changed_path2_hash_to_dict(apr_hash_t *hash) Py_DECREF(dict); return NULL; } - if (PyDict_SetItemString(dict, (char *)key, value) == -1) + if (PyDict_SetItem(dict, PyBytes_FromString((char *)key), value) == -1) { Py_DECREF(value); Py_DECREF(dict); @@ -986,6 +1144,9 @@ PyObject *svn_swig_py_changed_path2_hash_to_dict(apr_hash_t *hash) return dict; } +#define TYPE_ERROR_DICT_STRING_KEY \ + "dictionary keys aren't bytes or str objects" + apr_hash_t *svn_swig_py_stringhash_from_dict(PyObject *dict, apr_pool_t *pool) { @@ -1010,11 +1171,18 @@ apr_hash_t *svn_swig_py_stringhash_from_dict(PyObject *dict, PyObject *key = PyList_GetItem(keys, i); PyObject *value = PyDict_GetItem(dict, key); const char *propname = make_string_from_ob(key, pool); - const char *propval = make_string_from_ob(value, pool); - if (! (propname && propval)) + if (!propname) + { + if (!PyErr_Occurred()) + { + PyErr_SetString(PyExc_TypeError, TYPE_ERROR_DICT_STRING_KEY); + } + Py_DECREF(keys); + return NULL; + } + const char *propval = make_string_from_ob_maybe_null(value, pool); + if (PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "dictionary keys/values aren't strings"); Py_DECREF(keys); return NULL; } @@ -1047,6 +1215,15 @@ apr_hash_t *svn_swig_py_mergeinfo_from_dict(PyObject *dict, PyObject *key = PyList_GetItem(keys, i); PyObject *value = PyDict_GetItem(dict, key); const char *pathname = make_string_from_ob(key, pool); + if (!pathname) + { + if (!PyErr_Occurred()) + { + PyErr_SetString(PyExc_TypeError, TYPE_ERROR_DICT_STRING_KEY); + } + Py_DECREF(keys); + return NULL; + } const svn_rangelist_t *ranges = svn_swig_py_seq_to_array(value, sizeof(const svn_merge_range_t *), svn_swig_py_unwrap_struct_ptr, @@ -1054,10 +1231,10 @@ apr_hash_t *svn_swig_py_mergeinfo_from_dict(PyObject *dict, pool ); - if (! (pathname && ranges)) + if (!ranges) { PyErr_SetString(PyExc_TypeError, - "dictionary keys aren't strings or values aren't svn_merge_range_t *'s"); + "dictionary values aren't svn_merge_range_t *'s"); Py_DECREF(keys); return NULL; } @@ -1092,11 +1269,18 @@ apr_array_header_t *svn_swig_py_proparray_from_dict(PyObject *dict, PyObject *value = PyDict_GetItem(dict, key); svn_prop_t *prop = apr_palloc(pool, sizeof(*prop)); prop->name = make_string_from_ob(key, pool); - prop->value = make_svn_string_from_ob(value, pool); - if (! (prop->name && prop->value)) + if (! prop->name) + { + if (!PyErr_Occurred()) + { + PyErr_SetString(PyExc_TypeError, TYPE_ERROR_DICT_STRING_KEY); + } + Py_DECREF(keys); + return NULL; + } + prop->value = make_svn_string_from_ob_maybe_null(value, pool); + if (PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "dictionary keys/values aren't strings"); Py_DECREF(keys); return NULL; } @@ -1130,11 +1314,18 @@ apr_hash_t *svn_swig_py_prophash_from_dict(PyObject *dict, PyObject *key = PyList_GetItem(keys, i); PyObject *value = PyDict_GetItem(dict, key); const char *propname = make_string_from_ob(key, pool); - svn_string_t *propval = make_svn_string_from_ob(value, pool); - if (! (propname && propval)) + if (!propname) + { + if (!PyErr_Occurred()) + { + PyErr_SetString(PyExc_TypeError, TYPE_ERROR_DICT_STRING_KEY); + } + Py_DECREF(keys); + return NULL; + } + svn_string_t *propval = make_svn_string_from_ob_maybe_null(value, pool); + if (PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "dictionary keys/values aren't strings"); Py_DECREF(keys); return NULL; } @@ -1172,8 +1363,10 @@ apr_hash_t *svn_swig_py_path_revs_hash_from_dict(PyObject *dict, if (!(path)) { - PyErr_SetString(PyExc_TypeError, - "dictionary keys aren't strings"); + if (!PyErr_Occurred()) + { + PyErr_SetString(PyExc_TypeError, TYPE_ERROR_DICT_STRING_KEY); + } Py_DECREF(keys); return NULL; } @@ -1227,8 +1420,10 @@ apr_hash_t *svn_swig_py_struct_ptr_hash_from_dict(PyObject *dict, if (!c_key) { - PyErr_SetString(PyExc_TypeError, - "dictionary keys aren't strings"); + if (!PyErr_Occurred()) + { + PyErr_SetString(PyExc_TypeError, TYPE_ERROR_DICT_STRING_KEY); + } Py_DECREF(keys); return NULL; } @@ -1252,8 +1447,21 @@ svn_swig_py_unwrap_string(PyObject *source, void *baton) { const char **ptr_dest = destination; - *ptr_dest = PyString_AsString(source); - + if (PyBytes_Check(source)) + { + *ptr_dest = PyBytes_AsString(source); + } + else if (PyUnicode_Check(source)) + { + *ptr_dest = PyStr_AsUTF8(source); + } + else + { + PyErr_Format(PyExc_TypeError, + "Expected bytes or str object, %s found", + Py_TYPE(source)->tp_name); + *ptr_dest = NULL; + } if (*ptr_dest != NULL) return 0; else @@ -1371,7 +1579,7 @@ PyObject *svn_swig_py_array_to_list(const apr_array_header_t *array) for (i = 0; i < array->nelts; ++i) { PyObject *ob = - PyString_FromString(APR_ARRAY_IDX(array, i, const char *)); + PyBytes_FromString(APR_ARRAY_IDX(array, i, const char *)); if (ob == NULL) goto error; PyList_SET_ITEM(list, i, ob); @@ -1425,7 +1633,7 @@ commit_item_array_to_list(const apr_array_header_t *array) } - + /*** Errors ***/ /* Convert a given SubversionException to an svn_error_t. On failure returns @@ -1446,13 +1654,13 @@ static svn_error_t *exception_to_error(PyObject * exc) if ((message_ob = PyObject_GetAttrString(exc, "message")) == NULL) goto finished; - message = PyString_AsString(message_ob); + message = PyStr_AsString(message_ob); if (PyErr_Occurred()) goto finished; if ((file_ob = PyObject_GetAttrString(exc, "file")) == NULL) goto finished; if (file_ob != Py_None) - file = PyString_AsString(file_ob); + file = PyStr_AsString(file_ob); if (PyErr_Occurred()) goto finished; if ((line_ob = PyObject_GetAttrString(exc, "line")) == NULL) @@ -1679,7 +1887,8 @@ static svn_error_t *delete_entry(const char *path, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"delete_entry", - (char *)"slOO&", path, revision, ib->baton, + (char *)SVN_SWIG_BYTES_FMT "lOO&", + path, revision, ib->baton, make_ob_pool, pool)) == NULL) { err = callback_exception_error(); @@ -1710,7 +1919,12 @@ static svn_error_t *add_directory(const char *path, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"add_directory", - (char *)"sOslO&", path, ib->baton, +#if IS_PY3 + (char *)"yOylO&", +#else + (char *)"sOslO&", +#endif + path, ib->baton, copyfrom_path, copyfrom_revision, make_ob_pool, dir_pool)) == NULL) { @@ -1741,8 +1955,8 @@ static svn_error_t *open_directory(const char *path, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"open_directory", - (char *)"sOlO&", path, ib->baton, - base_revision, + (char *)SVN_SWIG_BYTES_FMT "OlO&", + path, ib->baton, base_revision, make_ob_pool, dir_pool)) == NULL) { err = callback_exception_error(); @@ -1771,9 +1985,14 @@ static svn_error_t *change_dir_prop(void *dir_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"change_dir_prop", - (char *)"Oss#O&", ib->baton, name, +#if IS_PY3 + (char *)"Oyy#O&", +#else + (char *)"Oss#O&", +#endif + ib->baton, name, value ? value->data : NULL, - value ? value->len : 0, + (Py_ssize_t) (value ? value->len : 0), make_ob_pool, pool)) == NULL) { err = callback_exception_error(); @@ -1810,7 +2029,12 @@ static svn_error_t *add_file(const char *path, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"add_file", - (char *)"sOslO&", path, ib->baton, +#if IS_PY3 + (char *)"yOylO&", +#else + (char *)"sOslO&", +#endif + path, ib->baton, copyfrom_path, copyfrom_revision, make_ob_pool, file_pool)) == NULL) { @@ -1842,8 +2066,8 @@ static svn_error_t *open_file(const char *path, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"open_file", - (char *)"sOlO&", path, ib->baton, - base_revision, + (char *)SVN_SWIG_BYTES_FMT "OlO&", + path, ib->baton, base_revision, make_ob_pool, file_pool)) == NULL) { err = callback_exception_error(); @@ -1916,7 +2140,12 @@ static svn_error_t *apply_textdelta(void *file_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"apply_textdelta", - (char *)"(Os)", ib->baton, +#if IS_PY3 + (char *)"(Oy)", +#else + (char *)"(Os)", +#endif + ib->baton, base_checksum)) == NULL) { err = callback_exception_error(); @@ -1961,9 +2190,14 @@ static svn_error_t *change_file_prop(void *file_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"change_file_prop", - (char *)"Oss#O&", ib->baton, name, +#if IS_PY3 + (char *)"Oyy#O&", +#else + (char *)"Oss#O&", +#endif + ib->baton, name, value ? value->data : NULL, - value ? value->len : 0, + (Py_ssize_t) (value ? value->len : 0), make_ob_pool, pool)) == NULL) { err = callback_exception_error(); @@ -1991,7 +2225,12 @@ static svn_error_t *close_file(void *file_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"close_file", - (char *)"(Os)", ib->baton, +#if IS_PY3 + (char *)"(Oy)", +#else + (char *)"(Os)", +#endif + ib->baton, text_checksum)) == NULL) { err = callback_exception_error(); @@ -2099,7 +2338,7 @@ static svn_error_t *parse_fn3_uuid_record(const char *uuid, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"uuid_record", - (char *)"sO&", uuid, + (char *)SVN_SWIG_BYTES_FMT "O&", uuid, make_ob_pool, pool)) == NULL) { err = callback_exception_error(); @@ -2188,9 +2427,15 @@ static svn_error_t *parse_fn3_set_revision_property(void *revision_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"set_revision_property", - (char *)"Oss#", ib->baton, name, +#if IS_PY3 + (char *)"Oyy#", +#else + (char *)"Oss#", +#endif + ib->baton, name, value ? value->data : NULL, - value ? value->len : 0)) == NULL) + (Py_ssize_t) (value ? value->len : 0))) + == NULL) { err = callback_exception_error(); goto finished; @@ -2218,9 +2463,15 @@ static svn_error_t *parse_fn3_set_node_property(void *node_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"set_node_property", - (char *)"Oss#", ib->baton, name, +#if IS_PY3 + (char *)"Oyy#", +#else + (char *)"Oss#", +#endif + ib->baton, name, value ? value->data : NULL, - value ? value->len : 0)) == NULL) + (Py_ssize_t) (value ? value->len : 0))) + == NULL) { err = callback_exception_error(); goto finished; @@ -2247,7 +2498,8 @@ static svn_error_t *parse_fn3_delete_node_property(void *node_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"delete_node_property", - (char *)"Os", ib->baton, name)) == NULL) + (char *)"O" SVN_SWIG_BYTES_FMT, + ib->baton, name)) == NULL) { err = callback_exception_error(); goto finished; @@ -2435,14 +2687,23 @@ apr_file_t *svn_swig_py_make_file(PyObject *py_file, { apr_file_t *apr_file = NULL; apr_status_t apr_err; + const char* fname = NULL; if (py_file == NULL || py_file == Py_None) return NULL; - if (PyString_Check(py_file)) + /* check if input is a path */ + if (PyBytes_Check(py_file)) + { + fname = PyBytes_AsString(py_file); + } + else if (PyUnicode_Check(py_file)) + { + fname = PyStr_AsUTF8(py_file); + } + if (fname) { /* input is a path -- just open an apr_file_t */ - char* fname = PyString_AS_STRING(py_file); apr_err = apr_file_open(&apr_file, fname, APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, pool); @@ -2455,25 +2716,26 @@ apr_file_t *svn_swig_py_make_file(PyObject *py_file, return NULL; } } - else if (PyFile_Check(py_file)) + else { - FILE *file; - apr_os_file_t osfile; + FILE *file = svn_swig_py_as_file(py_file); /* input is a file object -- convert to apr_file_t */ - file = PyFile_AsFile(py_file); + if (file != NULL) + { #ifdef WIN32 - osfile = (apr_os_file_t)_get_osfhandle(_fileno(file)); + apr_os_file_t osfile = (apr_os_file_t)_get_osfhandle(_fileno(file)); #else - osfile = (apr_os_file_t)fileno(file); + apr_os_file_t osfile = (apr_os_file_t)fileno(file); #endif - apr_err = apr_os_file_put(&apr_file, &osfile, O_CREAT | O_WRONLY, pool); - if (apr_err) - { - char buf[256]; - apr_strerror(apr_err, buf, sizeof(buf)); - PyErr_Format(PyExc_IOError, "apr_os_file_put failed: %s", buf); - return NULL; + apr_err = apr_os_file_put(&apr_file, &osfile, O_CREAT | O_WRONLY, pool); + if (apr_err) + { + char buf[256]; + apr_strerror(apr_err, buf, sizeof(buf)); + PyErr_Format(PyExc_IOError, "apr_os_file_put failed: %s", buf); + return NULL; + } } } return apr_file; @@ -2485,7 +2747,6 @@ read_handler_pyio(void *baton, char *buffer, apr_size_t *len) { PyObject *result; PyObject *py_io = baton; - apr_size_t bytes; svn_error_t *err = SVN_NO_ERROR; if (py_io == Py_None) @@ -2502,10 +2763,17 @@ read_handler_pyio(void *baton, char *buffer, apr_size_t *len) { err = callback_exception_error(); } - else if (PyString_Check(result)) + else if (PyBytes_Check(result)) { - bytes = PyString_GET_SIZE(result); - if (bytes > *len) + Py_ssize_t bytes; + char *result_str; + + if ( -1 == PyBytes_AsStringAndSize(result, &result_str, &bytes) + || result_str == NULL) + { + err = callback_exception_error(); + } + else if (bytes > *len) { err = callback_bad_return_error("Too many bytes"); } @@ -2513,12 +2781,12 @@ read_handler_pyio(void *baton, char *buffer, apr_size_t *len) { /* Writeback, in case this was a short read, indicating EOF */ *len = bytes; - memcpy(buffer, PyString_AS_STRING(result), *len); + memcpy(buffer, result_str, *len); } } else { - err = callback_bad_return_error("Not a string"); + err = callback_bad_return_error("Not a bytes object"); } Py_XDECREF(result); svn_swig_py_release_py_lock(); @@ -2537,7 +2805,8 @@ write_handler_pyio(void *baton, const char *data, apr_size_t *len) { svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallMethod(py_io, (char *)"write", - (char *)"s#", data, *len)) == NULL) + (char *) SVN_SWIG_BYTES_FMT "#", + data, (Py_ssize_t) *len)) == NULL) { err = callback_exception_error(); } @@ -2644,13 +2913,24 @@ void svn_swig_py_notify_func(void *baton, PyObject *function = baton; PyObject *result; svn_error_t *err = SVN_NO_ERROR; + PyObject *exc, *exc_type, *exc_traceback; if (function == NULL || function == Py_None) return; svn_swig_py_acquire_py_lock(); + + /* As caller can't understand Python context and we can't notify if + Python call back function raise exception to caller, we must catch it + if it is occurred, and restore error indicator */ + PyErr_Fetch(&exc_type, &exc, &exc_traceback); + if ((result = PyObject_CallFunction(function, +#if IS_PY3 + (char *)"(yiiyiii)", +#else (char *)"(siisiii)", +#endif path, action, kind, mime_type, content_state, prop_state, @@ -2669,6 +2949,9 @@ void svn_swig_py_notify_func(void *baton, /* Our error has no place to go. :-( */ svn_error_clear(err); + /* Also, restore error indicator */ + PyErr_Restore(exc_type, exc, exc_traceback); + svn_swig_py_release_py_lock(); } @@ -2680,12 +2963,18 @@ void svn_swig_py_notify_func2(void *baton, PyObject *function = baton; PyObject *result; svn_error_t *err = SVN_NO_ERROR; + PyObject *exc, *exc_type, *exc_traceback; if (function == NULL || function == Py_None) return; svn_swig_py_acquire_py_lock(); + /* As caller can't understand Python context and we can't notify if + Python call back function raise exception to caller, we must catch it + if it is occurred, and restore error indicator */ + PyErr_Fetch(&exc_type, &exc, &exc_traceback); + if ((result = PyObject_CallFunction(function, (char *)"(O&O&)", make_ob_wc_notify, notify, @@ -2704,6 +2993,9 @@ void svn_swig_py_notify_func2(void *baton, /* Our error has no place to go. :-( */ svn_error_clear(err); + /* Also, restore error indicator */ + PyErr_Restore(exc_type, exc, exc_traceback); + svn_swig_py_release_py_lock(); } @@ -2714,12 +3006,20 @@ void svn_swig_py_status_func(void *baton, PyObject *function = baton; PyObject *result; svn_error_t *err = SVN_NO_ERROR; + PyObject *exc, *exc_type, *exc_traceback; if (function == NULL || function == Py_None) return; svn_swig_py_acquire_py_lock(); - if ((result = PyObject_CallFunction(function, (char *)"sO&", path, + + /* As caller can't understand Python context and we can't notify if + Python call back function raise exception to caller, we must catch it + if it is occurred, and restore error indicator */ + PyErr_Fetch(&exc_type, &exc, &exc_traceback); + + if ((result = PyObject_CallFunction(function, + (char *)SVN_SWIG_BYTES_FMT "O&", path, make_ob_wc_status, status)) == NULL) { err = callback_exception_error(); @@ -2735,9 +3035,66 @@ void svn_swig_py_status_func(void *baton, /* Our error has no place to go. :-( */ svn_error_clear(err); + /* Also, restore error indicator */ + PyErr_Restore(exc_type, exc, exc_traceback); + svn_swig_py_release_py_lock(); } +svn_error_t *svn_swig_py_client_status_func(void *baton, + const char *path, + const svn_client_status_t *status, + apr_pool_t *scratch_pool) +{ + PyObject *function = baton; + PyObject *result; + svn_error_t *err = SVN_NO_ERROR; + PyObject *exc, *exc_type, *exc_traceback; + + if (function == NULL || function == Py_None) + return err; + + svn_swig_py_acquire_py_lock(); + + if (status == NULL) + { + result = PyObject_CallFunction(function, +#if IS_PY3 + (char *)"yOO&", +#else + (char *)"sOO&", +#endif + path, Py_None, + make_ob_pool, scratch_pool); + } + else + { + result = PyObject_CallFunction(function, +#if IS_PY3 + (char *)"yO&O&", +#else + (char *)"sO&O&", +#endif + path, + make_ob_client_status, status, + make_ob_pool, scratch_pool); + } + if (result == NULL) + { + err = callback_exception_error(); + } + else + { + /* The callback shouldn't be returning anything. */ + if (result != Py_None) + err = callback_bad_return_error("Not None"); + Py_DECREF(result); + } + + svn_swig_py_release_py_lock(); + return err; +} + svn_error_t *svn_swig_py_delta_path_driver_cb_func(void **dir_baton, void *parent_baton, @@ -2758,7 +3115,12 @@ svn_error_t *svn_swig_py_delta_path_driver_cb_func(void **dir_baton, "void *", NULL); - result = PyObject_CallFunction(function, (char *)"OsO&", + result = PyObject_CallFunction(function, +#if IS_PY3 + (char *)"OyO&", +#else + (char *)"OsO&", +#endif py_parent_baton, path, make_ob_pool, pool); @@ -2793,12 +3155,20 @@ void svn_swig_py_status_func2(void *baton, PyObject *function = baton; PyObject *result; svn_error_t *err = SVN_NO_ERROR; + PyObject *exc, *exc_type, *exc_traceback; if (function == NULL || function == Py_None) return; svn_swig_py_acquire_py_lock(); - if ((result = PyObject_CallFunction(function, (char *)"sO&", path, + + /* As caller can't understand Python context and we can't notify if + Python call back function raise exception to caller, we must catch it + if it is occurred, and restore error indicator */ + PyErr_Fetch(&exc_type, &exc, &exc_traceback); + + if ((result = PyObject_CallFunction(function, + (char *)SVN_SWIG_BYTES_FMT "O&", path, make_ob_wc_status, status)) == NULL) { err = callback_exception_error(); @@ -2812,8 +3182,10 @@ void svn_swig_py_status_func2(void *baton, } /* Our error has no place to go. :-( */ - if (err) - svn_error_clear(err); + svn_error_clear(err); + + /* Also, restore error indicator */ + PyErr_Restore(exc_type, exc, exc_traceback); svn_swig_py_release_py_lock(); } @@ -2902,7 +3274,7 @@ svn_error_t *svn_swig_py_fs_lock_callback( svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(py_callback, - (char *)"sO&O&O&", + (char *)SVN_SWIG_BYTES_FMT "O&O&O&", path, make_ob_lock, lock, make_ob_error, fs_err, @@ -2968,23 +3340,34 @@ svn_error_t *svn_swig_py_get_commit_log_func(const char **log_msg, if (result == Py_None) { - Py_DECREF(result); *log_msg = NULL; err = SVN_NO_ERROR; } - else if (PyString_Check(result)) + else if (PyBytes_Check(result)) { - *log_msg = apr_pstrdup(pool, PyString_AS_STRING(result)); - Py_DECREF(result); + *log_msg = apr_pstrdup(pool, PyBytes_AsString(result)); err = SVN_NO_ERROR; } + else if (PyUnicode_Check(result)) + { + /* PyStr_AsUTF8() may cause UnicodeEncodeError, + but apr_pstrdup() allows NULL for s */ + if ((*log_msg = apr_pstrdup(pool, PyStr_AsUTF8(result))) == NULL) + { + err = callback_exception_error(); + } + else + { + err = SVN_NO_ERROR; + } + } else { - Py_DECREF(result); - err = callback_bad_return_error("Not a string"); + err = callback_bad_return_error("Not a bytes or str object"); } + Py_DECREF(result); - finished: +finished: svn_swig_py_release_py_lock(); return err; } @@ -3023,7 +3406,11 @@ svn_error_t *svn_swig_py_repos_authz_func(svn_boolean_t *allowed, } if ((result = PyObject_CallFunction(function, +#if IS_PY3 + (char *)"OyO", +#else (char *)"OsO", +#endif py_root, path, py_pool)) == NULL) { err = callback_exception_error(); @@ -3060,7 +3447,7 @@ svn_error_t *svn_swig_py_repos_history_func(void *baton, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, - (char *)"slO&", + (char *)SVN_SWIG_BYTES_FMT "lO&", path, revision, make_ob_pool, pool)) == NULL) { @@ -3187,7 +3574,7 @@ svn_error_t *svn_swig_py_proplist_receiver2(void *baton, } result = PyObject_CallFunction(receiver, - (char *)"sOOO", + (char *)SVN_SWIG_BYTES_FMT "OOO", path, py_props, py_iprops, py_pool); if (result == NULL) { @@ -3247,7 +3634,11 @@ svn_error_t *svn_swig_py_log_receiver(void *baton, } if ((result = PyObject_CallFunction(receiver, +#if IS_PY3 + (char *)"OlyyyO", +#else (char *)"OlsssO", +#endif chpaths, rev, author, date, msg, py_pool)) == NULL) { @@ -3325,7 +3716,7 @@ svn_error_t *svn_swig_py_info_receiver_func(void *baton, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(receiver, - (char *)"sO&O&", + (char *)SVN_SWIG_BYTES_FMT "O&O&", path, make_ob_info, info, make_ob_pool, pool)) == NULL) { @@ -3394,7 +3785,12 @@ svn_error_t *svn_swig_py_client_blame_receiver_func(void *baton, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(receiver, - (char *)"LlsssO&", + (char *) +#if IS_PY3 + "LlyyyO&", +#else + "LlsssO&", +#endif (PY_LONG_LONG)line_no, revision, author, date, line, make_ob_pool, pool)) == NULL) { @@ -3426,7 +3822,11 @@ svn_error_t *svn_swig_py_changelist_receiver_func(void *baton, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(receiver, +#if IS_PY3 + (char *)"yyO&", +#else (char *)"ssO&", +#endif path, changelist, make_ob_pool, pool)) == NULL) { @@ -3461,7 +3861,7 @@ svn_swig_py_auth_gnome_keyring_unlock_prompt_func(char **keyring_passwd, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, - (char *)"sO&", + (char *)SVN_SWIG_BYTES_FMT "O&", keyring_name, make_ob_pool, pool)) == NULL) { @@ -3469,7 +3869,11 @@ svn_swig_py_auth_gnome_keyring_unlock_prompt_func(char **keyring_passwd, } else { - *keyring_passwd = make_string_from_ob(result, pool); + *keyring_passwd = make_string_from_ob_maybe_null(result, pool); + if (PyErr_Occurred()) + { + err = callback_exception_error(); + } Py_DECREF(result); } @@ -3497,7 +3901,11 @@ svn_swig_py_auth_simple_prompt_func(svn_auth_cred_simple_t **cred, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, +#if IS_PY3 + (char *)"yylO&", +#else (char *)"sslO&", +#endif realm, username, may_save, make_ob_pool, pool)) == NULL) { @@ -3548,7 +3956,7 @@ svn_swig_py_auth_username_prompt_func(svn_auth_cred_username_t **cred, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, - (char *)"slO&", + (char *)SVN_SWIG_BYTES_FMT "lO&", realm, may_save, make_ob_pool, pool)) == NULL) { @@ -3600,7 +4008,8 @@ svn_swig_py_auth_ssl_server_trust_prompt_func( svn_swig_py_acquire_py_lock(); - if ((result = PyObject_CallFunction(function, (char *)"slO&lO&", + if ((result = PyObject_CallFunction(function, + (char *)SVN_SWIG_BYTES_FMT "lO&lO&", realm, failures, make_ob_auth_ssl_server_cert_info, cert_info, may_save, make_ob_pool, pool)) == NULL) { @@ -3651,7 +4060,7 @@ svn_swig_py_auth_ssl_client_cert_prompt_func( svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, - (char *)"slO&", + (char *)SVN_SWIG_BYTES_FMT "lO&", realm, may_save, make_ob_pool, pool)) == NULL) { @@ -3702,7 +4111,7 @@ svn_swig_py_auth_ssl_client_cert_pw_prompt_func( svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, - (char *)"slO&", + (char *)SVN_SWIG_BYTES_FMT "lO&", realm, may_save, make_ob_pool, pool)) == NULL) { @@ -3769,7 +4178,12 @@ svn_swig_py_config_auth_walk_func(svn_boolean_t *delete_cred, goto finished; } - if ((result = PyObject_CallFunction(function, (char *)"ssOO", + if ((result = PyObject_CallFunction(function, +#if IS_PY3 + (char *)"yyOO", +#else + (char *)"ssOO", +#endif cred_kind, realmstring, py_hash, py_scratch_pool)) == NULL) { @@ -3868,16 +4282,21 @@ ra_callbacks_get_wc_prop(void *baton, } if ((result = PyObject_CallFunction(py_callback, - (char *)"ssO&", path, name, +#if IS_PY3 + (char *)"yyO&", +#else + (char *)"ssO&", +#endif + path, name, make_ob_pool, pool)) == NULL) { err = callback_exception_error(); } else if (result != Py_None) { - char *buf; Py_ssize_t len; - if (PyString_AsStringAndSize(result, &buf, &len) == -1) + char *buf; + if (PyBytes_AsStringAndSize(result, &buf, &len) == -1) { err = callback_exception_error(); } @@ -3920,14 +4339,19 @@ ra_callbacks_push_or_set_wc_prop(const char *callback, goto finished; } - if ((py_value = PyString_FromStringAndSize(value->data, value->len)) == NULL) + if ((py_value = PyBytes_FromStringAndSize(value->data, value->len)) == NULL) { err = callback_exception_error(); goto finished; } if ((result = PyObject_CallFunction(py_callback, - (char *)"ssOO&", path, name, py_value, +#if IS_PY3 + (char *)"yyOO&", +#else + (char *)"ssOO&", +#endif + path, name, py_value, make_ob_pool, pool)) == NULL) { err = callback_exception_error(); @@ -3990,7 +4414,12 @@ ra_callbacks_invalidate_wc_props(void *baton, } if ((result = PyObject_CallFunction(py_callback, - (char *)"ssO&", path, name, +#if IS_PY3 + (char *)"yyO&", +#else + (char *)"ssO&", +#endif + path, name, make_ob_pool, pool)) == NULL) { err = callback_exception_error(); @@ -4012,11 +4441,17 @@ ra_callbacks_progress_func(apr_off_t progress, { PyObject *callbacks = (PyObject *)baton; PyObject *py_callback, *py_progress, *py_total, *result; + PyObject *exc, *exc_type, *exc_traceback; py_progress = py_total = NULL; svn_swig_py_acquire_py_lock(); + /* As caller can't understand Python context and we can't notify if + Python call back function raise exception to caller, we must catch it + if it is occurred, and restore error indicator */ + PyErr_Fetch(&exc_type, &exc, &exc_traceback); + py_callback = PyObject_GetAttrString(callbacks, (char *)"progress_func"); if (py_callback == NULL) @@ -4056,6 +4491,9 @@ ra_callbacks_progress_func(apr_off_t progress, Py_XDECREF(result); finished: + /* Restore error indicator */ + PyErr_Restore(exc_type, exc, exc_traceback); + Py_XDECREF(py_callback); Py_XDECREF(py_progress); Py_XDECREF(py_total); @@ -4119,7 +4557,7 @@ ra_callbacks_get_client_string(void *baton, } else if (result != Py_None) { - if ((*name = PyString_AsString(result)) == NULL) + if ((*name = PyBytes_AsString(result)) == NULL) { err = callback_exception_error(); } @@ -4222,7 +4660,11 @@ svn_error_t *svn_swig_py_commit_callback(svn_revnum_t new_revision, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(receiver, +#if IS_PY3 + (char *)"lyy", +#else (char *)"lss", +#endif new_revision, date, author)) == NULL) { err = callback_exception_error(); @@ -4274,7 +4716,7 @@ svn_error_t *svn_swig_py_ra_file_rev_handler_func( } if ((result = PyObject_CallFunction(handler, - (char *)"slOOO&", + (char *)SVN_SWIG_BYTES_FMT "lOOO&", path, rev, py_rev_props, py_prop_diffs, make_ob_pool, pool)) == NULL) { @@ -4320,7 +4762,7 @@ svn_error_t *svn_swig_py_ra_lock_callback( svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(py_callback, - (char *)"sbO&O&O&", + (char *)SVN_SWIG_BYTES_FMT "bO&O&O&", path, do_lock, make_ob_lock, lock, make_ob_error, ra_err, @@ -4357,7 +4799,11 @@ static svn_error_t *reporter_set_path(void *report_baton, if ((result = PyObject_CallMethod(py_reporter, (char *)"set_path", +#if IS_PY3 + (char *)"ylbyO&", +#else (char *)"slbsO&", +#endif path, revision, start_empty, lock_token, make_ob_pool, pool)) == NULL) @@ -4390,7 +4836,7 @@ static svn_error_t *reporter_delete_path(void *report_baton, if ((result = PyObject_CallMethod(py_reporter, (char *)"delete_path", - (char *)"sO&", + (char *)SVN_SWIG_BYTES_FMT "O&", path, make_ob_pool, pool)) == NULL) { @@ -4426,7 +4872,11 @@ static svn_error_t *reporter_link_path(void *report_baton, if ((result = PyObject_CallMethod(py_reporter, (char *)"link_path", +#if IS_PY3 + (char *)"yylbsO&", +#else (char *)"sslbsO&", +#endif path, url, revision, start_empty, lock_token, make_ob_pool, pool)) == NULL) @@ -4557,7 +5007,11 @@ wc_diff_callbacks2_file_changed_or_added(const char *callback, } result = PyObject_CallFunction(py_callback, +#if IS_PY3 + (char *)"O&yyyllyyO&O&", +#else (char *)"O&sssllssO&O&", +#endif make_ob_wc_adm_access, adm_access, path, tmpfile1, tmpfile2, @@ -4680,7 +5134,11 @@ wc_diff_callbacks2_file_deleted(svn_wc_adm_access_t *adm_access, } result = PyObject_CallFunction(py_callback, +#if IS_PY3 + (char *)"O&yyyyyO&", +#else (char *)"O&sssssO&", +#endif make_ob_wc_adm_access, adm_access, path, tmpfile1, tmpfile2, @@ -4734,7 +5192,11 @@ wc_diff_callbacks2_dir_added(svn_wc_adm_access_t *adm_access, } result = PyObject_CallFunction(py_callback, +#if IS_PY3 + (char *)"O&yl", +#else (char *)"O&sl", +#endif make_ob_wc_adm_access, adm_access, path, rev); if (result == NULL) @@ -4784,7 +5246,7 @@ wc_diff_callbacks2_dir_deleted(svn_wc_adm_access_t *adm_access, } result = PyObject_CallFunction(py_callback, - (char *)"O&s", + (char *)"O&" SVN_SWIG_BYTES_FMT, make_ob_wc_adm_access, adm_access, path); if (result == NULL) { @@ -4836,7 +5298,11 @@ wc_diff_callbacks2_dir_props_changed(svn_wc_adm_access_t *adm_access, } result = PyObject_CallFunction(py_callback, +#if IS_PY3 + (char *)"O&yO&O&", +#else (char *)"O&sO&O&", +#endif make_ob_wc_adm_access, adm_access, path, svn_swig_py_proparray_to_dict, propchanges, @@ -4888,11 +5354,21 @@ svn_swig_py_config_enumerator2(const char *name, PyObject *result; svn_error_t *err = SVN_NO_ERROR; svn_boolean_t c_result; + PyObject *exc, *exc_type, *exc_traceback; svn_swig_py_acquire_py_lock(); + /* As caller can't understand Python context and we can't notify if + Python call back function raise exception to caller, we must catch it + if it is occurred, and restore error indicator */ + PyErr_Fetch(&exc_type, &exc, &exc_traceback); + if ((result = PyObject_CallFunction(function, +#if IS_PY3 + (char *)"yyO&", +#else (char *)"ssO&", +#endif name, value, make_ob_pool, pool)) == NULL) @@ -4908,7 +5384,7 @@ svn_swig_py_config_enumerator2(const char *name, /* Any Python exception we might have pending must be cleared, because the SWIG wrapper will not check for it, and return a value with the exception still set. */ - PyErr_Clear(); + PyErr_Restore(exc_type, exc, exc_traceback); if (err) { @@ -4936,11 +5412,17 @@ svn_swig_py_config_section_enumerator2(const char *name, PyObject *result; svn_error_t *err = SVN_NO_ERROR; svn_boolean_t c_result; + PyObject *exc, *exc_type, *exc_traceback; svn_swig_py_acquire_py_lock(); + /* As caller can't understand Python context and we can't notify if + Python call back function raise exception to caller, we must catch it + if it is occurred, and restore error indicator */ + PyErr_Fetch(&exc_type, &exc, &exc_traceback); + if ((result = PyObject_CallFunction(function, - (char *)"sO&", + (char *)SVN_SWIG_BYTES_FMT "O&", name, make_ob_pool, pool)) == NULL) { @@ -4955,7 +5437,8 @@ svn_swig_py_config_section_enumerator2(const char *name, /* Any Python exception we might have pending must be cleared, because the SWIG wrapper will not check for it, and return a value with the exception still set. */ - PyErr_Clear(); + PyErr_Restore(exc_type, exc, exc_traceback); + if (err) { |