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=1869354&r1=1869353&r2=1869354&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 
Mon Nov  4 05:59:36 2019
@@ -26,6 +26,7 @@
 
 #include <Python.h>
 
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -50,6 +51,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 +156,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 +193,25 @@ int svn_swig_py_get_pool_arg(PyObject *a
   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 +275,20 @@ static int proxy_set_pool(PyObject **pro
     {
       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 +346,45 @@ static PyObject *svn_swig_NewPointerObjS
   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 +399,8 @@ static int svn_swig_ConvertPtrString(PyO
 /** 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 +440,14 @@ void svn_swig_py_svn_exception(svn_error
           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 +506,36 @@ void svn_swig_py_svn_exception(svn_error
 
 /*** 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 +570,89 @@ static PyObject *make_ob_error(svn_error
 
 /***/
 
+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 +684,7 @@ static PyObject *convert_hash(apr_hash_t
             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 +709,10 @@ static PyObject *convert_svn_string_t(vo
 
   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 +722,7 @@ static PyObject *cstring_to_pystring(con
       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 +798,7 @@ PyObject *svn_swig_py_prophash_to_dict(a
 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 +880,7 @@ svn_swig_py_propinheriteditemarray_to_di
         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 +924,7 @@ PyObject *svn_swig_py_proparray_to_dict(
 
         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 +935,8 @@ PyObject *svn_swig_py_proparray_to_dict(
           }
         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 +986,7 @@ PyObject *svn_swig_py_locationhash_to_di
             Py_DECREF(dict);
             return NULL;
           }
-        value = PyString_FromString((char *)v);
+        value = PyBytes_FromString((const char *)v);
         if (value == NULL)
           {
             Py_DECREF(key);
@@ -881,6 +1036,7 @@ DECLARE_SWIG_CONSTRUCTOR(info, svn_info_
 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 +1051,7 @@ PyObject *svn_swig_py_c_strings_to_list(
 
     while ((s = *strings++) != NULL)
       {
-        PyObject *ob = PyString_FromString(s);
+        PyObject *ob = PyBytes_FromString(s);
 
         if (ob == NULL)
             goto error;
@@ -938,7 +1094,7 @@ PyObject *svn_swig_py_changed_path_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 +1130,7 @@ PyObject *svn_swig_py_changed_path2_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 +1142,9 @@ PyObject *svn_swig_py_changed_path2_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 +1169,18 @@ apr_hash_t *svn_swig_py_stringhash_from_
       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 +1213,15 @@ apr_hash_t *svn_swig_py_mergeinfo_from_d
       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 +1229,10 @@ apr_hash_t *svn_swig_py_mergeinfo_from_d
         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 +1267,18 @@ apr_array_header_t *svn_swig_py_proparra
       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 +1312,18 @@ apr_hash_t *svn_swig_py_prophash_from_di
       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 +1361,10 @@ apr_hash_t *svn_swig_py_path_revs_hash_f
 
       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 +1418,10 @@ apr_hash_t *svn_swig_py_struct_ptr_hash_
 
       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 +1445,21 @@ svn_swig_py_unwrap_string(PyObject *sour
                           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 +1577,7 @@ PyObject *svn_swig_py_array_to_list(cons
     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 +1631,7 @@ commit_item_array_to_list(const apr_arra
 }
 
 
- 
+
 /*** Errors ***/
 
 /* Convert a given SubversionException to an svn_error_t. On failure returns
@@ -1446,13 +1652,13 @@ static svn_error_t *exception_to_error(P
 
     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 +1885,8 @@ static svn_error_t *delete_entry(const c
 
   /* ### 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 +1917,12 @@ static svn_error_t *add_directory(const
 
   /* ### 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 +1953,8 @@ static svn_error_t *open_directory(const
 
   /* ### 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,7 +1983,12 @@ static svn_error_t *change_dir_prop(void
 
   /* ### 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,
                                     make_ob_pool, pool)) == NULL)
@@ -1810,7 +2027,12 @@ static svn_error_t *add_file(const char
 
   /* ### 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 +2064,8 @@ static svn_error_t *open_file(const char
 
   /* ### 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 +2138,12 @@ static svn_error_t *apply_textdelta(void
 
   /* ### 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,7 +2188,12 @@ static svn_error_t *change_file_prop(voi
 
   /* ### 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,
                                     make_ob_pool, pool)) == NULL)
@@ -1991,7 +2223,12 @@ static svn_error_t *close_file(void *fil
 
   /* ### 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 +2336,7 @@ static svn_error_t *parse_fn3_uuid_recor
 
   /* ### 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,7 +2425,12 @@ static svn_error_t *parse_fn3_set_revisi
 
   /* ### 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)
     {
@@ -2218,7 +2460,12 @@ static svn_error_t *parse_fn3_set_node_p
 
   /* ### 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)
     {
@@ -2247,7 +2494,8 @@ static svn_error_t *parse_fn3_delete_nod
 
   /* ### 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 +2683,23 @@ apr_file_t *svn_swig_py_make_file(PyObje
 {
   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 +2712,26 @@ apr_file_t *svn_swig_py_make_file(PyObje
           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 +2743,6 @@ read_handler_pyio(void *baton, char *buf
 {
   PyObject *result;
   PyObject *py_io = baton;
-  apr_size_t bytes;
   svn_error_t *err = SVN_NO_ERROR;
 
   if (py_io == Py_None)
@@ -2502,10 +2759,17 @@ read_handler_pyio(void *baton, char *buf
     {
       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 +2777,12 @@ read_handler_pyio(void *baton, char *buf
         {
           /* 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 +2801,8 @@ write_handler_pyio(void *baton, const ch
     {
       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, *len)) == NULL)
         {
           err = callback_exception_error();
         }
@@ -2644,13 +2909,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 +2945,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 +2959,18 @@ void svn_swig_py_notify_func2(void *bato
   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 +2989,9 @@ void svn_swig_py_notify_func2(void *bato
   /* 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 +3002,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,6 +3031,73 @@ 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();
+}
+
+void 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;
+
+  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 (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);
+    }
+
+  /* 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();
 }
 
@@ -2758,7 +3121,12 @@ svn_error_t *svn_swig_py_delta_path_driv
                                                  "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 +3161,20 @@ void svn_swig_py_status_func2(void *bato
   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 +3188,10 @@ void svn_swig_py_status_func2(void *bato
     }
 
   /* 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 +3280,7 @@ svn_error_t *svn_swig_py_fs_lock_callbac
   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 +3346,34 @@ svn_error_t *svn_swig_py_get_commit_log_
 
   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 +3412,11 @@ svn_error_t *svn_swig_py_repos_authz_fun
     }
 
   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 +3453,7 @@ svn_error_t *svn_swig_py_repos_history_f
 
   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 +3580,7 @@ svn_error_t *svn_swig_py_proplist_receiv
     }
 
   result = PyObject_CallFunction(receiver,
-                                 (char *)"sOOO",
+                                 (char *)SVN_SWIG_BYTES_FMT "OOO",
                                  path, py_props, py_iprops, py_pool);
   if (result == NULL)
     {
@@ -3247,7 +3640,11 @@ svn_error_t *svn_swig_py_log_receiver(vo
     }
 
   if ((result = PyObject_CallFunction(receiver,
+#if IS_PY3
+                                      (char *)"OlyyyO",
+#else
                                       (char *)"OlsssO",
+#endif
                                       chpaths, rev, author, date, msg,
                                       py_pool)) == NULL)
     {
@@ -3325,7 +3722,7 @@ svn_error_t *svn_swig_py_info_receiver_f
   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 +3791,12 @@ svn_error_t *svn_swig_py_client_blame_re
   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 +3828,11 @@ svn_error_t *svn_swig_py_changelist_rece
   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 +3867,7 @@ svn_swig_py_auth_gnome_keyring_unlock_pr
   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 +3875,11 @@ svn_swig_py_auth_gnome_keyring_unlock_pr
     }
   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 +3907,11 @@ svn_swig_py_auth_simple_prompt_func(svn_
   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 +3962,7 @@ svn_swig_py_auth_username_prompt_func(sv
   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 +4014,8 @@ svn_swig_py_auth_ssl_server_trust_prompt
 
   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 +4066,7 @@ svn_swig_py_auth_ssl_client_cert_prompt_
   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 +4117,7 @@ svn_swig_py_auth_ssl_client_cert_pw_prom
   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 +4184,12 @@ svn_swig_py_config_auth_walk_func(svn_bo
       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 +4288,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 +4345,19 @@ ra_callbacks_push_or_set_wc_prop(const c
       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 +4420,12 @@ ra_callbacks_invalidate_wc_props(void *b
     }
 
   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 +4447,17 @@ ra_callbacks_progress_func(apr_off_t pro
 {
   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 +4497,9 @@ ra_callbacks_progress_func(apr_off_t pro
 
   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 +4563,7 @@ ra_callbacks_get_client_string(void *bat
     }
   else if (result != Py_None)
     {
-      if ((*name = PyString_AsString(result)) == NULL)
+      if ((*name = PyBytes_AsString(result)) == NULL)
         {
           err = callback_exception_error();
         }
@@ -4222,7 +4666,11 @@ svn_error_t *svn_swig_py_commit_callback
   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 +4722,7 @@ svn_error_t *svn_swig_py_ra_file_rev_han
     }
 
   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 +4768,7 @@ svn_error_t *svn_swig_py_ra_lock_callbac
   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 +4805,11 @@ static svn_error_t *reporter_set_path(vo
 
   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 +4842,7 @@ static svn_error_t *reporter_delete_path
 
   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 +4878,11 @@ static svn_error_t *reporter_link_path(v
 
   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 +5013,11 @@ wc_diff_callbacks2_file_changed_or_added
     }
 
   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 +5140,11 @@ wc_diff_callbacks2_file_deleted(svn_wc_a
     }
 
   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 +5198,11 @@ wc_diff_callbacks2_dir_added(svn_wc_adm_
     }
 
   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 +5252,7 @@ wc_diff_callbacks2_dir_deleted(svn_wc_ad
     }
 
   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 +5304,11 @@ wc_diff_callbacks2_dir_props_changed(svn
     }
 
   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 +5360,21 @@ svn_swig_py_config_enumerator2(const cha
   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 +5390,7 @@ svn_swig_py_config_enumerator2(const cha
   /* 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 +5418,17 @@ svn_swig_py_config_section_enumerator2(c
   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 +5443,8 @@ svn_swig_py_config_section_enumerator2(c
   /* 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)
     {

Modified: 
subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- 
subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h 
(original)
+++ 
subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h 
Mon Nov  4 05:59:36 2019
@@ -50,6 +50,12 @@ extern "C" {
 apr_status_t svn_swig_py_initialize(void);
 
 
+/* Returns the provided python object as a FILE *object.
+ * Return the underlying FILE or NULL if the object is not a File instance.
+ */
+FILE *svn_swig_py_as_file(PyObject *pyfile);
+
+
 
 /* Functions to manage python's global interpreter lock */
 void svn_swig_py_release_py_lock(void);
@@ -101,6 +107,17 @@ void svn_swig_py_svn_exception(svn_error
 
 
 
+/* 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);
+
 /* helper function to convert an apr_hash_t* (char* -> svnstring_t*) to
    a Python dict */
 PyObject *svn_swig_py_prophash_to_dict(apr_hash_t *hash);
@@ -226,7 +243,10 @@ svn_swig_py_seq_to_array(PyObject *seq,
                          apr_pool_t *pool);
 
 /* An svn_swig_py_object_unwrap_t that extracts a char pointer from a Python
-   string. */
+   string.
+
+   Note the lifetime of the returned string is tied to the provided Python
+   object. */
 int
 svn_swig_py_unwrap_string(PyObject *source,
                           void *destination,
@@ -293,6 +313,13 @@ void svn_swig_py_status_func(void *baton
                              const char *path,
                              svn_wc_status_t *status);
 
+/* a client status function that executes a Python function that is passed in
+   via the baton argument */
+void svn_swig_py_client_status_func(void *baton,
+                                    const char *path,
+                                    const svn_client_status_t *status,
+                                    apr_pool_t *scratch_pool);
+
 /* a svn_delta_path_driver callback that executes a Python function
   that is passed in via the baton argument */
 svn_error_t *svn_swig_py_delta_path_driver_cb_func(void **dir_baton,

Modified: subversion/trunk/subversion/bindings/swig/python/svn/client.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/svn/client.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/svn/client.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/svn/client.py Mon Nov  4 
05:59:36 2019
@@ -24,8 +24,8 @@
 ######################################################################
 
 from libsvn.client import *
-from svn.core import _unprefix_names
+from svn.core import _unprefix_names, _as_list
 _unprefix_names(locals(), 'svn_client_')
 _unprefix_names(locals(), 'SVN_CLIENT_')
-__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
+__all__ = [x for x in _as_list(locals()) if x.lower().startswith('svn_')]
 del _unprefix_names

Modified: subversion/trunk/subversion/bindings/swig/python/svn/core.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/svn/core.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/svn/core.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/svn/core.py Mon Nov  4 
05:59:36 2019
@@ -27,8 +27,8 @@ from libsvn.core import *
 import libsvn.core as _libsvncore
 import atexit as _atexit
 import sys
-# __all__ is defined later, since some svn_* functions are implemented below.
 
+# __all__ is defined later, since some svn_* functions are implemented below.
 
 class SubversionException(Exception):
 
@@ -89,6 +89,20 @@ class SubversionException(Exception):
       child = cls(message, apr_err, child, file, line)
     return child
 
+# This function is useful for common Python 2/3 code. It prevents the double
+# memory hit of simply wrapping values/keys/items calls on dictionaries on
+# python 2, but ensuring an independent list is returned in Python 3.
+def _as_list(seq):
+  """Returns the given sequence or iterator as a list.
+
+  If already a list, simply returns the list, otherwise a list is constructed
+  using the given object.
+  """
+  if isinstance(seq, list):
+    return seq
+
+  return list(seq)
+
 def _cleanup_application_pool():
   """Cleanup the application pool before exiting"""
   if application_pool and application_pool.valid():
@@ -96,7 +110,7 @@ def _cleanup_application_pool():
 _atexit.register(_cleanup_application_pool)
 
 def _unprefix_names(symbol_dict, from_prefix, to_prefix = ''):
-  for name, value in symbol_dict.items():
+  for name, value in _as_list(symbol_dict.items()):
     if name.startswith(from_prefix):
       symbol_dict[to_prefix + name[len(from_prefix):]] = value
 
@@ -141,7 +155,7 @@ def svn_path_compare_paths(path1, path2)
 
   # Common prefix was skipped above, next character is compared to
   # determine order
-  return cmp(char1, char2)
+  return (char1 > char2) - (char1 < char2)
 
 def svn_mergeinfo_merge(mergeinfo, changes):
   return _libsvncore.svn_swig_mergeinfo_merge(mergeinfo, changes)
@@ -171,7 +185,7 @@ class Stream:
         if not data:
           break
         chunks.append(data)
-      return ''.join(chunks)
+      return b''.join(chunks)
 
     # read the amount specified
     return svn_stream_read(self._stream, int(amt))
@@ -194,7 +208,7 @@ def secs_from_timestr(svn_datetime, pool
   # ### convert to a time_t; this requires intimate knowledge of
   # ### the apr_time_t type
   # ### aprtime is microseconds; turn it into seconds
-  return aprtime / 1000000
+  return aprtime // 1000000
 
 
 # ============================================================================
@@ -319,10 +333,10 @@ def run_app(func, *args, **kw):
 # 'run_app'
 # 'svn_uri__is_ancestor'
 # 'svn_tristate__from_word' 'svn_tristate__to_word'
-__all__ = filter(lambda s: (s.startswith('svn_')
-                            or s.startswith('SVN_')
-                            or s.startswith('SVNSYNC_')
-                            or s in ('Pool', 'SubversionException'))
-                           and '__' not in s,
-                 locals())
+__all__ = [s for s in _as_list(locals())
+           if (s.startswith('svn_')
+               or s.startswith('SVN_')
+               or s.startswith('SVNSYNC_')
+               or s in ('Pool', 'SubversionException'))
+           and '__' not in s]
 

Modified: subversion/trunk/subversion/bindings/swig/python/svn/delta.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/svn/delta.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/svn/delta.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/svn/delta.py Mon Nov  4 
05:59:36 2019
@@ -24,10 +24,10 @@
 ######################################################################
 
 from libsvn.delta import *
-from svn.core import _unprefix_names
+from svn.core import _unprefix_names, _as_list
 _unprefix_names(locals(), 'svn_delta_')
 _unprefix_names(locals(), 'svn_txdelta_', 'tx_')
-__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
+__all__ = [x for x in _as_list(locals()) if x.lower().startswith('svn_')]
 del _unprefix_names
 
 class Editor:

Modified: subversion/trunk/subversion/bindings/swig/python/svn/diff.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/svn/diff.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/svn/diff.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/svn/diff.py Mon Nov  4 
05:59:36 2019
@@ -24,7 +24,7 @@
 ######################################################################
 
 from libsvn.diff import *
-from svn.core import _unprefix_names
+from svn.core import _unprefix_names, _as_list
 _unprefix_names(locals(), 'svn_diff_')
-__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
+__all__ = [x for x in _as_list(locals()) if x.lower().startswith('svn_')]
 del _unprefix_names

Modified: subversion/trunk/subversion/bindings/swig/python/svn/fs.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/svn/fs.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/svn/fs.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/svn/fs.py Mon Nov  4 
05:59:36 2019
@@ -24,10 +24,10 @@
 ######################################################################
 
 from libsvn.fs import *
-from svn.core import _unprefix_names, Pool
+from svn.core import _unprefix_names, Pool, _as_list
 _unprefix_names(locals(), 'svn_fs_')
 _unprefix_names(locals(), 'SVN_FS_')
-__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
+__all__ = [x for x in _as_list(locals()) if x.lower().startswith('svn_')]
 del _unprefix_names
 
 
@@ -48,10 +48,30 @@ import svn.diff as _svndiff
 def entries(root, path, pool=None):
   "Call dir_entries returning a dictionary mappings names to IDs."
   e = dir_entries(root, path, pool)
-  for name, entry in e.items():
+  for name, entry in _as_list(e.items()):
     e[name] = dirent_t_id_get(entry)
   return e
 
+class _PopenStdoutWrapper(object):
+  "Private wrapper object of _subprocess.Popen.stdout to clean up sub process"
+  def __init__(self, pobject):
+    self._pobject = pobject
+  def __getattr__(self, name):
+    return getattr(self._pobject.stdout, name)
+  def close(self):
+    self._pobject.stdout.close()
+    if self._pobject.poll() is None:
+        self._pobject.terminate()
+  def __del__(self):
+    if not self.closed:
+      self.close()
+    if self._pobject.poll() is None:
+        self._pobject.terminate()
+        if _sys.hexversion >= 0x030300F0:
+          try:
+            self._pobject.wait(10)
+          except _subprocess.TimeoutExpired:
+            self._pobject.kill() 
 
 class FileDiff:
   def __init__(self, root1, path1, root2, path2, pool=None, diffoptions=[]):
@@ -124,7 +144,7 @@ class FileDiff:
       # open the pipe, and return the file object for reading from the child.
       p = _subprocess.Popen(cmd, stdout=_subprocess.PIPE, bufsize=-1,
                             close_fds=_sys.platform != "win32")
-      return p.stdout
+      return _PopenStdoutWrapper(p)
 
     else:
       if self.difftemp is None:
@@ -132,16 +152,16 @@ class FileDiff:
 
         with builtins.open(self.difftemp, "wb") as fp:
           diffopt = _svndiff.file_options_create()
-          diffobj = _svndiff.file_diff_2(self.tempfile1,
-                                         self.tempfile2,
+          diffobj = _svndiff.file_diff_2(self.tempfile1.encode('UTF-8'),
+                                         self.tempfile2.encode('UTF-8'),
                                          diffopt)
 
           _svndiff.file_output_unified4(fp,
                                         diffobj,
-                                        self.tempfile1,
-                                        self.tempfile2,
+                                        self.tempfile1.encode('UTF-8'),
+                                        self.tempfile2.encode('UTF-8'),
                                         None, None,
-                                        "utf8",
+                                        b"utf8",
                                         None,
                                         diffopt.show_c_function,
                                         diffopt.context_size,

Modified: subversion/trunk/subversion/bindings/swig/python/svn/ra.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/svn/ra.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/svn/ra.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/svn/ra.py Mon Nov  4 
05:59:36 2019
@@ -24,10 +24,10 @@
 ######################################################################
 
 from libsvn.ra import *
-from svn.core import _unprefix_names
+from svn.core import _unprefix_names, _as_list
 _unprefix_names(locals(), 'svn_ra_')
 _unprefix_names(locals(), 'SVN_RA_')
-__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
+__all__ = [x for x in _as_list(locals()) if x.lower().startswith('svn_')]
 del _unprefix_names
 
 class Callbacks:
@@ -58,7 +58,7 @@ class Callbacks:
                                       svn.core.SVN_AUTH_PARAM_DEFAULT_PASSWORD,
                                       password)
     def open_tmp_file(self, pool):
-      path = '/'.join([self.wc, svn.wc.get_adm_dir(pool), 'tmp'])
+      path = b'/'.join([self.wc, svn.wc.get_adm_dir(pool), b'tmp'])
       (fd, fn) = tempfile.mkstemp(dir=path)
       os.close(fd)
       return fn

Modified: subversion/trunk/subversion/bindings/swig/python/svn/repos.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/svn/repos.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/svn/repos.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/svn/repos.py Mon Nov  4 
05:59:36 2019
@@ -24,10 +24,10 @@
 ######################################################################
 
 from libsvn.repos import *
-from svn.core import _unprefix_names, Pool
+from svn.core import _unprefix_names, Pool, _as_list
 _unprefix_names(locals(), 'svn_repos_')
 _unprefix_names(locals(), 'SVN_REPOS_')
-__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
+__all__ = [x for x in _as_list(locals()) if x.lower().startswith('svn_')]
 del _unprefix_names
 
 
@@ -126,9 +126,9 @@ class ChangeCollector(_svndelta.Editor):
         self.notify_cb(change)
 
   def _make_base_path(self, parent_path, path):
-    idx = path.rfind('/')
+    idx = path.rfind(b'/')
     if parent_path:
-      parent_path = parent_path + '/'
+      parent_path = parent_path + b'/'
     if idx == -1:
       return parent_path + path
     return parent_path + path[idx+1:]
@@ -142,7 +142,7 @@ class ChangeCollector(_svndelta.Editor):
     return root
 
   def open_root(self, base_revision, dir_pool=None):
-    return ('', '', self.base_rev)  # dir_baton
+    return (b'', b'', self.base_rev)  # dir_baton
 
   def delete_entry(self, path, revision, parent_baton, pool=None):
     base_path = self._make_base_path(parent_baton[1], path)
@@ -281,9 +281,9 @@ class RevisionChangeCollector(ChangeColl
     ChangeCollector.__init__(self, fs_ptr, root, pool, notify_cb)
 
   def _make_base_path(self, parent_path, path):
-    idx = path.rfind('/')
+    idx = path.rfind(b'/')
     if idx == -1:
-      return parent_path + '/' + path
+      return parent_path + b'/' + path
     return parent_path + path[idx:]
 
 

Modified: subversion/trunk/subversion/bindings/swig/python/svn/wc.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/svn/wc.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/svn/wc.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/svn/wc.py Mon Nov  4 
05:59:36 2019
@@ -24,10 +24,10 @@
 ######################################################################
 
 from libsvn.wc import *
-from svn.core import _unprefix_names
+from svn.core import _unprefix_names, _as_list
 _unprefix_names(locals(), 'svn_wc_')
 _unprefix_names(locals(), 'SVN_WC_')
-__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
+__all__ = [x for x in _as_list(locals()) if x.lower().startswith('svn_')]
 del _unprefix_names
 
 

Modified: subversion/trunk/subversion/bindings/swig/python/tests/auth.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/tests/auth.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/tests/auth.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/tests/auth.py Mon Nov  4 
05:59:36 2019
@@ -27,87 +27,87 @@ class SubversionAuthTestCase(unittest.Te
 
   def test_open(self):
     baton = core.svn_auth_open([])
-    self.assert_(baton is not None)
+    self.assertTrue(baton is not None)
 
   def test_set_parameter(self):
     baton = core.svn_auth_open([])
-    core.svn_auth_set_parameter(baton, "name", "somedata")
-    core.svn_auth_set_parameter(baton, "name", None)
-    core.svn_auth_set_parameter(baton, "name", 2)
-    core.svn_auth_set_parameter(baton, "name",
+    core.svn_auth_set_parameter(baton, b"name", b"somedata")
+    core.svn_auth_set_parameter(baton, b"name", None)
+    core.svn_auth_set_parameter(baton, b"name", 2)
+    core.svn_auth_set_parameter(baton, b"name",
                                 core.svn_auth_ssl_server_cert_info_t())
 
   def test_invalid_cred_kind(self):
     baton = core.svn_auth_open([])
     self.assertRaises(core.SubversionException,
             lambda: core.svn_auth_first_credentials(
-                "unknown", "somerealm", baton))
+                b"unknown", b"somerealm", baton))
 
   def test_credentials_get_username(self):
     def myfunc(realm, maysave, pool):
-      self.assertEquals("somerealm", realm)
+      self.assertEqual(b"somerealm", realm)
       username_cred = core.svn_auth_cred_username_t()
-      username_cred.username = "bar"
+      username_cred.username = b"bar"
       username_cred.may_save = False
       return username_cred
     baton = 
core.svn_auth_open([core.svn_auth_get_username_prompt_provider(myfunc, 1)])
     creds = core.svn_auth_first_credentials(
-                core.SVN_AUTH_CRED_USERNAME, "somerealm", baton)
-    self.assert_(creds is not None)
+                core.SVN_AUTH_CRED_USERNAME, b"somerealm", baton)
+    self.assertTrue(creds is not None)
 
   def test_credentials_get_simple(self):
     def myfunc(realm, username, may_save, pool):
-      self.assertEquals("somerealm", realm)
+      self.assertEqual(b"somerealm", realm)
       simple_cred = core.svn_auth_cred_simple_t()
-      simple_cred.username = "mijnnaam"
-      simple_cred.password = "geheim"
+      simple_cred.username = b"mijnnaam"
+      simple_cred.password = b"geheim"
       simple_cred.may_save = False
       return simple_cred
     baton = 
core.svn_auth_open([core.svn_auth_get_simple_prompt_provider(myfunc, 1)])
     creds = core.svn_auth_first_credentials(
-                core.SVN_AUTH_CRED_SIMPLE, "somerealm", baton)
-    self.assert_(creds is not None)
+                core.SVN_AUTH_CRED_SIMPLE, b"somerealm", baton)
+    self.assertTrue(creds is not None)
 
   def test_credentials_get_ssl_client_cert(self):
     def myfunc(realm, may_save, pool):
-      self.assertEquals("somerealm", realm)
+      self.assertEqual(b"somerealm", realm)
       ssl_cred = core.svn_auth_cred_ssl_client_cert_t()
-      ssl_cred.cert_file = "my-certs-file"
+      ssl_cred.cert_file = b"my-certs-file"
       ssl_cred.may_save = False
       return ssl_cred
     baton = 
core.svn_auth_open([core.svn_auth_get_ssl_client_cert_prompt_provider(myfunc, 
1)])
     creds = core.svn_auth_first_credentials(
-                core.SVN_AUTH_CRED_SSL_CLIENT_CERT, "somerealm", baton)
-    self.assert_(creds is not None)
+                core.SVN_AUTH_CRED_SSL_CLIENT_CERT, b"somerealm", baton)
+    self.assertTrue(creds is not None)
 
   def test_credentials_get_ssl_client_cert_pw(self):
     def myfunc(realm, may_save, pool):
-      self.assertEquals("somerealm", realm)
+      self.assertEqual(b"somerealm", realm)
       ssl_cred_pw = core.svn_auth_cred_ssl_client_cert_pw_t()
-      ssl_cred_pw.password = "supergeheim"
+      ssl_cred_pw.password = b"supergeheim"
       ssl_cred_pw.may_save = False
       return ssl_cred_pw
     baton = 
core.svn_auth_open([core.svn_auth_get_ssl_client_cert_pw_prompt_provider(myfunc,
 1)])
     creds = core.svn_auth_first_credentials(
-                core.SVN_AUTH_CRED_SSL_CLIENT_CERT_PW, "somerealm", baton)
-    self.assert_(creds is not None)
+                core.SVN_AUTH_CRED_SSL_CLIENT_CERT_PW, b"somerealm", baton)
+    self.assertTrue(creds is not None)
 
   def test_credentials_get_ssl_server_trust(self):
     def myfunc(realm, failures, cert_info, may_save, pool):
-      self.assertEquals("somerealm", realm)
+      self.assertEqual(b"somerealm", realm)
       ssl_trust = core.svn_auth_cred_ssl_server_trust_t()
       ssl_trust.accepted_failures = 0
       ssl_trust.may_save = False
       return ssl_trust
     baton = 
core.svn_auth_open([core.svn_auth_get_ssl_server_trust_prompt_provider(myfunc)])
     core.svn_auth_set_parameter(baton, core.SVN_AUTH_PARAM_SSL_SERVER_FAILURES,
-                                "2")
+                                b"2")
     cert_info = core.svn_auth_ssl_server_cert_info_t()
     core.svn_auth_set_parameter(baton, 
core.SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO,
                 cert_info)
     creds = core.svn_auth_first_credentials(
-                core.SVN_AUTH_CRED_SSL_SERVER_TRUST, "somerealm", baton)
-    self.assert_(creds is not None)
+                core.SVN_AUTH_CRED_SSL_SERVER_TRUST, b"somerealm", baton)
+    self.assertTrue(creds is not None)
 
 def suite():
     return unittest.defaultTestLoader.loadTestsFromTestCase(

Modified: subversion/trunk/subversion/bindings/swig/python/tests/checksum.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/tests/checksum.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/tests/checksum.py 
(original)
+++ subversion/trunk/subversion/bindings/swig/python/tests/checksum.py Mon Nov  
4 05:59:36 2019
@@ -29,7 +29,7 @@ class ChecksumTestCases(unittest.TestCas
         val = svn.core.svn_checksum_create(kind)
         check_val = svn.core.svn_checksum_to_cstring_display(val)
 
-        self.assertTrue(isinstance(check_val, str),
+        self.assertTrue(isinstance(check_val, bytes),
                               "Type of digest not string")
         self.assertEqual(len(check_val), 2*expected_length,
                          "Length of digest does not match kind")


Reply via email to