Add (mostly) Python3 support.
authorJelmer Vernooij <jelmer@jelmer.uk>
Sun, 24 Jul 2016 18:04:16 +0000 (18:04 +0000)
committerJelmer Vernooij <jelmer@jelmer.uk>
Sun, 24 Jul 2016 18:04:16 +0000 (18:04 +0000)
NEWS
subvertpy/_ra.c
subvertpy/client.c
subvertpy/repos.c
subvertpy/tests/test_client.py
subvertpy/tests/test_ra.py
subvertpy/tests/test_wc.py
subvertpy/util.c
subvertpy/wc.c

diff --git a/NEWS b/NEWS
index e2d7281..b745dc5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,9 +5,13 @@
    * Drop support for Python versions before 2.7, in preparation of Python3 support.
      (Jelmer Vernooij)
 
+   * subvertpy.client methods no longer canonicalize paths and URLs, instead
+     requiring the caller to do so. If uncanonicalized paths/URLs are passed in,
+     a ValueError will be raised. (Jelmer Vernooij)
+
   IMPROVEMENTS
 
-   * Add Python3 support (Martin Panter, Yonggang Luo).
+   * Add Python3 support. (Martin Panter, Yonggang Luo, Jelmer Vernooij).
 
    * Add constant ERR_RA_CANNOT_CREATE_SESSION. (Jelmer Vernooij)
 
index 90ee6b2..061d597 100644 (file)
@@ -1281,8 +1281,6 @@ static PyObject *ra_replay_range(PyObject *self, PyObject *args)
 #endif
 }
 
-
-
 static PyObject *ra_rev_proplist(PyObject *self, PyObject *args)
 {
        apr_pool_t *temp_pool;
@@ -1568,6 +1566,7 @@ static PyObject *ra_get_file(PyObject *self, PyObject *args)
        svn_revnum_t fetch_rev;
        PyObject *py_stream, *py_props;
        apr_pool_t *temp_pool;
+       svn_stream_t *stream;
 
        if (!PyArg_ParseTuple(args, "OO|l:get_file", &py_path, &py_stream, &revision))
                return NULL;
@@ -1583,14 +1582,19 @@ static PyObject *ra_get_file(PyObject *self, PyObject *args)
                fetch_rev = revision;
 
        path = py_object_to_svn_relpath(py_path, temp_pool);
-       if (path == NULL)
+       if (path == NULL) {
+               apr_pool_destroy(temp_pool);
                return NULL;
+       }
 
-       /* Yuck. Subversion doesn't like leading slashes.. */
-       while (*path == '/') path++;
+       stream = new_py_stream(temp_pool, py_stream);
+       if (stream == NULL) {
+               apr_pool_destroy(temp_pool);
+               return NULL;
+       }
 
        RUN_RA_WITH_POOL(temp_pool, ra, svn_ra_get_file(ra->ra, path, revision,
-                                                                                                       new_py_stream(temp_pool, py_stream),
+                                                                                                       stream,
                                                                                                        &fetch_rev, &props, temp_pool));
 
        py_props = prop_hash_to_dict(props);
index 26f96d0..788d186 100644 (file)
@@ -73,25 +73,40 @@ typedef struct {
 static int client_set_auth(PyObject *self, PyObject *auth, void *closure);
 static int client_set_config(PyObject *self, PyObject *auth, void *closure);
 
+static bool client_check_path(const char *path, apr_pool_t *scratch_pool)
+{
+       return svn_path_is_canonical(path, scratch_pool);
+}
+
 static bool client_path_list_to_apr_array(apr_pool_t *pool, PyObject *l, apr_array_header_t **ret)
 {
        int i;
+       const char *path;
        if (l == Py_None) {
                *ret = NULL;
                return true;
        }
-       if (PyString_Check(l)) {
+       if (PyUnicode_Check(l) || PyBytes_Check(l)) {
                *ret = apr_array_make(pool, 1, sizeof(char *));
-               APR_ARRAY_PUSH(*ret, const char *) = svn_path_canonicalize(PyString_AsString(l), pool);
+               path = py_object_to_svn_string(l, pool);
+               if (path == NULL) {
+                       return false;
+               }
+               if (!client_check_path(path, pool)) {
+                       PyErr_SetString(PyExc_ValueError, "Expected canonical path or URL");
+                       return false;
+               }
+               APR_ARRAY_PUSH(*ret, const char *) = path;
        } else if (PyList_Check(l)) {
                *ret = apr_array_make(pool, PyList_Size(l), sizeof(char *));
                for (i = 0; i < PyList_GET_SIZE(l); i++) {
                        PyObject *item = PyList_GET_ITEM(l, i);
-                       if (!PyString_Check(item)) {
-                               PyErr_Format(PyExc_TypeError, "Expected list of strings, item was %s", item->ob_type->tp_name);
+                       path = py_object_to_svn_string(item, pool);
+                       if (!client_check_path(path, pool)) {
+                               PyErr_SetString(PyExc_ValueError, "Expected canonical path or URL");
                                return false;
                        }
-                       APR_ARRAY_PUSH(*ret, const char *) = svn_path_canonicalize(PyString_AsString(item), pool);
+                       APR_ARRAY_PUSH(*ret, const char *) = path;
                }
        } else {
                PyErr_Format(PyExc_TypeError, "Expected list of strings, got: %s",
@@ -820,34 +835,45 @@ static PyObject *client_export(PyObject *self, PyObject *args, PyObject *kwargs)
 
 static PyObject *client_cat(PyObject *self, PyObject *args, PyObject *kwargs)
 {
-    ClientObject *client = (ClientObject *)self;
-    char *kwnames[] = { "path", "output_stream", "revision", "peg_revision", NULL };
-    char *path;
-    PyObject *peg_rev=Py_None, *rev=Py_None;
-    svn_opt_revision_t c_peg_rev, c_rev;
-    apr_pool_t *temp_pool;
-    svn_stream_t *stream;
-    PyObject *py_stream;
+       ClientObject *client = (ClientObject *)self;
+       char *kwnames[] = { "path", "output_stream", "revision", "peg_revision", NULL };
+       char *path;
+       PyObject *peg_rev=Py_None, *rev=Py_None;
+       svn_opt_revision_t c_peg_rev, c_rev;
+       apr_pool_t *temp_pool;
+       svn_stream_t *stream;
+       PyObject *py_stream, *py_path;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|OO", kwnames, &path, &py_stream, &rev, &peg_rev))
-        return NULL;
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|OO", kwnames, &py_path, &py_stream, &rev, &peg_rev))
+               return NULL;
 
-    if (!to_opt_revision(rev, &c_rev))
-        return NULL;
-    if (!to_opt_revision(peg_rev, &c_peg_rev))
-        return NULL;
+       if (!to_opt_revision(rev, &c_rev))
+               return NULL;
+       if (!to_opt_revision(peg_rev, &c_peg_rev))
+               return NULL;
 
-    temp_pool = Pool(NULL);
-    if (temp_pool == NULL)
-        return NULL;
+       temp_pool = Pool(NULL);
+       if (temp_pool == NULL) {
+               return NULL;
+       }
 
-    stream = new_py_stream(temp_pool, py_stream);
+       path = py_object_to_svn_string(py_path, temp_pool);
+       if (path == NULL) {
+               apr_pool_destroy(temp_pool);
+               return NULL;
+       }
+
+       stream = new_py_stream(temp_pool, py_stream);
+       if (stream == NULL) {
+               apr_pool_destroy(temp_pool);
+               return NULL;
+       }
 
-    RUN_SVN_WITH_POOL(temp_pool, svn_client_cat2(stream, path,
-        &c_peg_rev, &c_rev, client->client, temp_pool));
+       RUN_SVN_WITH_POOL(temp_pool, svn_client_cat2(stream, path,
+                                                                                                &c_peg_rev, &c_rev, client->client, temp_pool));
 
-    apr_pool_destroy(temp_pool);
-    Py_RETURN_NONE;
+       apr_pool_destroy(temp_pool);
+       Py_RETURN_NONE;
 }
 
 static PyObject *client_delete(PyObject *self, PyObject *args)
index eb40d75..e501588 100644 (file)
@@ -463,14 +463,21 @@ static PyObject *repos_verify(RepositoryObject *self, PyObject *args)
        apr_pool_t *temp_pool;
        PyObject *py_feedback_stream;
        svn_revnum_t start_rev, end_rev;
+       svn_stream_t *stream;
        if (!PyArg_ParseTuple(args, "Oll", &py_feedback_stream, &start_rev, &end_rev))
                return NULL;
        temp_pool = Pool(NULL);
-       if (temp_pool == NULL)
+       if (temp_pool == NULL) {
+               return NULL;
+       }
+       stream = new_py_stream(temp_pool, py_feedback_stream);
+       if (stream == NULL) {
+               apr_pool_destroy(temp_pool);
                return NULL;
+       }
        RUN_SVN_WITH_POOL(temp_pool,
                svn_repos_verify_fs(self->repos,
-                       new_py_stream(temp_pool, py_feedback_stream), start_rev, end_rev,
+                       stream, start_rev, end_rev,
                        py_cancel_check, NULL, temp_pool));
        apr_pool_destroy(temp_pool);
 
index b72ba54..f756642 100644 (file)
@@ -1,5 +1,5 @@
 # Copyright (C) 2005-2007 Jelmer Vernooij <jelmer@jelmer.uk>
+
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License as published by
 # the Free Software Foundation; either version 2.1 of the License, or
@@ -70,7 +70,7 @@ class TestClient(SubversionTestCase):
         self.client.commit(["dc"])
         r = ra.RemoteAccess(self.repos_url)
         revprops = r.rev_proplist(1)
-        self.assertEqual("Amessage", revprops["svn:log"])
+        self.assertEqual(b"Amessage", revprops["svn:log"])
 
     def test_commit_start(self):
         self.build_tree({"dc/foo": None})
@@ -80,7 +80,7 @@ class TestClient(SubversionTestCase):
         self.client.commit(["dc"])
         r = ra.RemoteAccess(self.repos_url)
         revprops = r.rev_proplist(1)
-        self.assertEqual("Bmessage", revprops["svn:log"])
+        self.assertEqual(b"Bmessage", revprops["svn:log"])
 
     def test_mkdir(self):
         self.client.mkdir(["dc/foo"])
@@ -128,19 +128,21 @@ class TestClient(SubversionTestCase):
             config = client.get_config(svn_cfg_dir)
             self.assertIsInstance(config, client.Config)
             ignores = config.get_default_ignores()
-            self.assertTrue(base_dir_basename in ignores)
+            self.assertTrue(
+                base_dir_basename.encode('utf-8') in ignores,
+                "no %r in %r" % (base_dir_basename, ignores))
         finally:
             shutil.rmtree(base_dir)
 
     def test_diff(self):
         r = ra.RemoteAccess(self.repos_url,
                 auth=ra.Auth([ra.get_username_provider()]))
-        dc = self.get_commit_editor(self.repos_url) 
+        dc = self.get_commit_editor(self.repos_url)
         f = dc.add_file("foo")
         f.modify(b"foo1")
         dc.close()
 
-        dc = self.get_commit_editor(self.repos_url) 
+        dc = self.get_commit_editor(self.repos_url)
         f = dc.open_file("foo")
         f.modify(b"foo2")
         dc.close()
@@ -191,13 +193,15 @@ class TestClient(SubversionTestCase):
         self.assertEqual(expected, entry["revprops"]["svn:log"])
 
     def assertLogEntryDateAlmostEquals(self, expected, entry, delta):
-        actual = datetime.strptime(entry["revprops"]["svn:date"], "%Y-%m-%dT%H:%M:%S.%fZ")
+        actual = datetime.strptime(
+            entry["revprops"]["svn:date"].decode('utf-8'),
+            "%Y-%m-%dT%H:%M:%S.%fZ")
         self.assertTrue((actual - expected) < delta)
 
     def test_log(self):
         log_entries = []
-        commit_msg_1 = "Commit"
-        commit_msg_2 = "Commit 2"
+        commit_msg_1 = b"Commit"
+        commit_msg_2 = b"Commit 2"
         delta = timedelta(hours=1)
         def cb(changed_paths, revision, revprops, has_children=False):
             log_entries.append({
index 3de0a96..5cbefcb 100644 (file)
@@ -77,7 +77,7 @@ class TestRemoteAccess(SubversionTestCase):
         self.assertEqual(1, self.ra.get_latest_revnum())
 
     def test_get_uuid(self):
-        self.assertIsInstance(self.ra.get_uuid(), unicode)
+        self.assertEqual(36, len(self.ra.get_uuid()))
 
     def test_get_repos_root(self):
         self.assertEqual(self.repos_url, self.ra.get_repos_root())
@@ -254,7 +254,10 @@ class TestRemoteAccess(SubversionTestCase):
         root.close()
         editor.close()
 
-        self.assertEqual(set(['bar:foo', 'svn:author', 'svn:custom:blie', 'svn:date', 'svn:log']), set(self.ra.rev_proplist(1).keys()))
+        revprops = self.ra.rev_proplist(1)
+        self.assertEqual(
+            set(['bar:foo', 'svn:author', 'svn:custom:blie', 'svn:date', 'svn:log']),
+            set(revprops.keys()), "result: %r" % revprops)
 
     def test_get_commit_editor_context_manager(self):
         def mycb(paths, rev, revprops):
@@ -292,7 +295,7 @@ class TestRemoteAccess(SubversionTestCase):
 
         stream = BytesIO()
         props = self.ra.get_file("bar", stream, 1)[1]
-        self.assertEqual("blie", props.get("bla:bar"))
+        self.assertEqual(b"blie", props.get("bla:bar"))
         stream = BytesIO()
         props = self.ra.get_file("bar", stream, 2)[1]
         self.assertIs(None, props.get("bla:bar"))
index a65b054..08dd9d5 100644 (file)
@@ -44,13 +44,13 @@ class VersionTest(TestCase):
 class WorkingCopyTests(TestCase):
 
     def test_get_adm_dir(self):
-        self.assertEqual(".svn", wc.get_adm_dir())
+        self.assertEqual(b".svn", wc.get_adm_dir())
 
     def test_set_adm_dir(self):
         old_dir_name = wc.get_adm_dir()
         try:
-            wc.set_adm_dir("_svn")
-            self.assertEqual("_svn", wc.get_adm_dir())
+            wc.set_adm_dir(b"_svn")
+            self.assertEqual(b"_svn", wc.get_adm_dir())
         finally:
             wc.set_adm_dir(old_dir_name)
 
index 568a69e..94a0477 100644 (file)
@@ -38,7 +38,7 @@ void PyErr_SetAprStatus(apr_status_t status)
 {
        char errmsg[1024];
 
-       PyErr_SetString(PyExc_Exception, 
+       PyErr_SetString(PyExc_Exception,
                apr_strerror(status, errmsg, sizeof(errmsg)));
 }
 
@@ -119,23 +119,24 @@ const char *py_object_to_svn_uri(PyObject *obj, apr_pool_t *pool)
 const char *py_object_to_svn_relpath(PyObject *obj, apr_pool_t *pool)
 {
        const char *ret;
-       PyObject *bytes_obj = NULL;
 
        if (PyUnicode_Check(obj)) {
-               bytes_obj = obj = PyUnicode_AsUTF8String(obj);
+               obj = PyUnicode_AsUTF8String(obj);
                if (obj == NULL) {
                        return NULL;
                }
+       } else {
+               Py_INCREF(obj);
        }
 
        if (PyBytes_Check(obj)) {
                ret = svn_relpath_canonicalize(PyBytes_AsString(obj), pool);
-               Py_XDECREF(bytes_obj);
+               Py_DECREF(obj);
                return ret;
        } else {
-               Py_XDECREF(bytes_obj);
                PyErr_SetString(PyExc_TypeError,
                                                "relative paths need to be UTF-8 bytestrings or unicode strings");
+               Py_DECREF(obj);
                return NULL;
        }
 }
@@ -239,7 +240,7 @@ void PyErr_SetSubversionException(svn_error_t *error)
                return;
        }
 
-       if (error->apr_err >= APR_OS_START_SYSERR && 
+       if (error->apr_err >= APR_OS_START_SYSERR &&
                error->apr_err < APR_OS_START_SYSERR + APR_OS_ERRSPACE_SIZE) {
                PyObject *excval = Py_BuildValue("(iz)", error->apr_err - APR_OS_START_SYSERR, error->message);
                PyErr_SetObject(PyExc_OSError, excval);
@@ -303,10 +304,10 @@ void handle_svn_error(svn_error_t *error)
                return; /* Cancelled because of a Python exception, let Python deal with it. */
 
        if (error->apr_err == SVN_ERR_RA_SVN_UNKNOWN_CMD) {
-               /* svnserve doesn't handle the 'failure' command sent back 
+               /* svnserve doesn't handle the 'failure' command sent back
                 * by the client if one of the editor commands failed.
-                * Rather than bouncing the error sent by the client 
-                * (BZR_SVN_APR_ERROR_OFFSET for example), it will send 
+                * Rather than bouncing the error sent by the client
+                * (BZR_SVN_APR_ERROR_OFFSET for example), it will send
                 * SVN_ERR_RA_SVN_UNKNOWN_CMD. */
                if (PyErr_Occurred() != NULL)
                        return;
@@ -351,22 +352,27 @@ bool string_list_to_apr_array(apr_pool_t *pool, PyObject *l, apr_array_header_t
 bool relpath_list_to_apr_array(apr_pool_t *pool, PyObject *l, apr_array_header_t **ret)
 {
        int i;
+       const char *relpath;
        if (l == Py_None) {
                *ret = NULL;
                return true;
        }
-       if (PyString_Check(l)) {
+       if (PyUnicode_Check(l) || PyBytes_Check(l)) {
                *ret = apr_array_make(pool, 1, sizeof(char *));
-               APR_ARRAY_PUSH(*ret, const char *) = py_object_to_svn_relpath(l, pool);
+               relpath = py_object_to_svn_relpath(l, pool);
+               if (relpath == NULL) {
+                       return false;
+               }
+               APR_ARRAY_PUSH(*ret, const char *) = relpath;
        } else if (PyList_Check(l)) {
                *ret = apr_array_make(pool, PyList_Size(l), sizeof(char *));
                for (i = 0; i < PyList_GET_SIZE(l); i++) {
                        PyObject *item = PyList_GET_ITEM(l, i);
-                       if (!PyString_Check(item)) {
-                               PyErr_Format(PyExc_TypeError, "Expected list of strings, item was %s", item->ob_type->tp_name);
+                       relpath = py_object_to_svn_relpath(item, pool);
+                       if (relpath == NULL) {
                                return false;
                        }
-                       APR_ARRAY_PUSH(*ret, const char *) = py_object_to_svn_relpath(item, pool);
+                       APR_ARRAY_PUSH(*ret, const char *) = relpath;
                }
        } else {
                PyErr_Format(PyExc_TypeError, "Expected list of strings, got: %s",
@@ -394,7 +400,7 @@ PyObject *prop_hash_to_dict(apr_hash_t *props)
        if (py_props == NULL) {
                goto fail_props;
        }
-       for (idx = apr_hash_first(pool, props); idx != NULL; 
+       for (idx = apr_hash_first(pool, props); idx != NULL;
                 idx = apr_hash_next(idx)) {
                PyObject *py_key, *py_val;
                apr_hash_this(idx, (const void **)&key, &klen, (void **)&val);
@@ -425,7 +431,7 @@ PyObject *prop_hash_to_dict(apr_hash_t *props)
        }
        apr_pool_destroy(pool);
        return py_props;
-       
+
 fail_item:
        Py_DECREF(py_props);
 fail_props:
@@ -460,16 +466,23 @@ apr_hash_t *prop_dict_to_hash(apr_pool_t *pool, PyObject *py_props)
                }
 
                if (!PyBytes_Check(k)) {
-                       PyErr_SetString(PyExc_TypeError, 
+                       PyErr_SetString(PyExc_TypeError,
                                                        "property name should be unicode or byte string");
                        Py_DECREF(k);
                        return NULL;
                }
 
+               if (PyUnicode_Check(v)) {
+                       v = PyUnicode_AsUTF8String(v);
+               } else {
+                       Py_INCREF(v);
+               }
+
                if (!PyBytes_Check(v)) {
-                       PyErr_SetString(PyExc_TypeError, 
-                                                       "property value should be byte string");
+                       PyErr_SetString(PyExc_TypeError,
+                                                       "property value should be unicode or byte string");
                        Py_DECREF(k);
+                       Py_DECREF(v);
                        return NULL;
                }
 
@@ -478,6 +491,7 @@ apr_hash_t *prop_dict_to_hash(apr_pool_t *pool, PyObject *py_props)
                apr_hash_set(hash_props, PyBytes_AsString(k),
                                         PyBytes_Size(k), val_string);
                Py_DECREF(k);
+               Py_DECREF(v);
        }
 
        return hash_props;
@@ -678,8 +692,8 @@ svn_error_t *py_svn_error()
 
 PyObject *wrap_lock(svn_lock_t *lock)
 {
-       return Py_BuildValue("(zzzbzz)", lock->path, lock->token, lock->owner, 
-                                                lock->comment, lock->is_dav_comment, 
+       return Py_BuildValue("(zzzbzz)", lock->path, lock->token, lock->owner,
+                                                lock->comment, lock->is_dav_comment,
                                                 lock->creation_date, lock->expiration_date);
 }
 
@@ -719,8 +733,8 @@ static svn_error_t *py_stream_read(void *baton, char *buffer, apr_size_t *length
        ret = PyObject_CallMethod(self, "read", "i", *length);
        CB_CHECK_PYRETVAL(ret);
 
-       if (!PyString_Check(ret)) {
-               PyErr_SetString(PyExc_TypeError, "Expected stream read function to return string");
+       if (!PyBytes_Check(ret)) {
+               PyErr_SetString(PyExc_TypeError, "Expected stream read function to return bytes");
                PyGILState_Release(state);
                return py_svn_error();
        }
@@ -733,10 +747,13 @@ static svn_error_t *py_stream_read(void *baton, char *buffer, apr_size_t *length
 
 static svn_error_t *py_stream_write(void *baton, const char *data, apr_size_t *len)
 {
-       PyObject *self = (PyObject *)baton, *ret;
+       PyObject *self = (PyObject *)baton, *ret, *py_data;
        PyGILState_STATE state = PyGILState_Ensure();
 
-       ret = PyObject_CallMethod(self, "write", "s#", data, len[0]);
+       py_data = PyBytes_FromStringAndSize(data, *len);
+       CB_CHECK_PYRETVAL(py_data);
+
+       ret = PyObject_CallMethod(self, "write", "O", py_data);
        CB_CHECK_PYRETVAL(ret);
        Py_DECREF(ret);
        PyGILState_Release(state);
@@ -793,7 +810,7 @@ static apr_hash_t *get_default_config(void)
 
        if (!initialised) {
                pool = Pool(NULL);
-               RUN_SVN_WITH_POOL(pool, 
+               RUN_SVN_WITH_POOL(pool,
                                          svn_config_get_config(&default_config, NULL, pool));
                initialised = true;
        }
@@ -961,7 +978,7 @@ static PyObject *stream_read_full(StreamObject *self, PyObject *args)
        }
 
        temp_pool = Pool(NULL);
-       if (temp_pool == NULL) 
+       if (temp_pool == NULL)
                return NULL;
        if (len != -1) {
                char *buffer;
@@ -983,7 +1000,7 @@ static PyObject *stream_read_full(StreamObject *self, PyObject *args)
        } else {
 #if ONLY_SINCE_SVN(1, 6)
                svn_string_t *result;
-               RUN_SVN_WITH_POOL(temp_pool, svn_string_from_stream(&result, 
+               RUN_SVN_WITH_POOL(temp_pool, svn_string_from_stream(&result,
                                                           self->stream,
                                                           temp_pool,
                                                           temp_pool));
@@ -992,7 +1009,7 @@ static PyObject *stream_read_full(StreamObject *self, PyObject *args)
                apr_pool_destroy(temp_pool);
                return ret;
 #else
-               PyErr_SetString(PyExc_NotImplementedError, 
+               PyErr_SetString(PyExc_NotImplementedError,
                        "Subversion 1.5 does not provide svn_string_from_stream().");
                return NULL;
 #endif
@@ -1010,7 +1027,7 @@ static PyMethodDef stream_methods[] = {
 PyTypeObject Stream_Type = {
        PyVarObject_HEAD_INIT(NULL, 0)
        "repos.Stream", /*      const char *tp_name;  For printing, in format "<module>.<name>" */
-       sizeof(StreamObject), 
+       sizeof(StreamObject),
        0,/*    Py_ssize_t tp_basicsize, tp_itemsize;  For allocation */
 
        /* Methods to implement standard operations */
index 24cbb81..be9a8d7 100644 (file)
@@ -2445,13 +2445,19 @@ static PyObject *set_adm_dir(PyObject *self, PyObject *args)
 {
        apr_pool_t *temp_pool;
        char *name;
+       PyObject *py_name;
 
-       if (!PyArg_ParseTuple(args, "s", &name))
+       if (!PyArg_ParseTuple(args, "O", &py_name))
                return NULL;
 
        temp_pool = Pool(NULL);
        if (temp_pool == NULL)
                return NULL;
+       name = py_object_to_svn_string(py_name, temp_pool);
+       if (name == NULL) {
+               apr_pool_destroy(temp_pool);
+               return NULL;
+       }
        RUN_SVN_WITH_POOL(temp_pool, svn_wc_set_adm_dir(name, temp_pool));
        apr_pool_destroy(temp_pool);
        Py_RETURN_NONE;
@@ -2462,14 +2468,22 @@ static PyObject *get_pristine_copy_path(PyObject *self, PyObject *args)
        apr_pool_t *pool;
        const char *pristine_path;
        char *path;
+       PyObject *py_path;
        PyObject *ret;
 
-       if (!PyArg_ParseTuple(args, "s", &path))
+       if (!PyArg_ParseTuple(args, "O", &py_path))
                return NULL;
 
        pool = Pool(NULL);
        if (pool == NULL)
                return NULL;
+
+       path = py_object_to_svn_string(py_path, pool);
+       if (path == NULL) {
+               apr_pool_destroy(pool);
+               return NULL;
+       }
+
        PyErr_WarnEx(PyExc_DeprecationWarning, "get_pristine_copy_path is deprecated. Use get_pristine_contents instead.", 2);
        RUN_SVN_WITH_POOL(pool,
                  svn_wc_get_pristine_copy_path(svn_dirent_canonicalize(path, pool),