Modified: 
subversion/trunk/subversion/bindings/swig/python/tests/trac/versioncontrol/svn_fs.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/tests/trac/versioncontrol/svn_fs.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- 
subversion/trunk/subversion/bindings/swig/python/tests/trac/versioncontrol/svn_fs.py
 (original)
+++ 
subversion/trunk/subversion/bindings/swig/python/tests/trac/versioncontrol/svn_fs.py
 Mon Nov  4 05:59:36 2019
@@ -63,7 +63,7 @@ _kindmap = {core.svn_node_dir: Node.DIRE
 
 def _get_history(path, authz, fs_ptr, start, end, limit=None):
     history = []
-    if hasattr(repos, 'svn_repos_history2'):
+    if getattr(repos, 'svn_repos_history2', None) is not None:
         # For Subversion >= 1.1
         def authz_cb(root, path, pool):
             if limit and len(history) >= limit:
@@ -107,17 +107,17 @@ class SubversionRepository(Repository):
             raise TracError("%s does not appear to be a Subversion 
repository." % (path, ))
         if self.path != path:
             self.scope = path[len(self.path):]
-            if not self.scope[-1] == '/':
-                self.scope += '/'
+            if not self.scope[-1:] == b'/':
+                self.scope += b'/'
         else:
-            self.scope = '/'
+            self.scope = b'/'
 
         self.repos = repos.svn_repos_open(self.path)
         self.fs_ptr = repos.svn_repos_fs(self.repos)
         self.rev = fs.youngest_rev(self.fs_ptr)
 
         self.history = None
-        if self.scope != '/':
+        if self.scope != b'/':
             self.history = []
             for path,rev in _get_history(self.scope[1:], self.authz,
                                          self.fs_ptr, 0, self.rev):
@@ -132,7 +132,7 @@ class SubversionRepository(Repository):
         return node_type in _kindmap
 
     def normalize_path(self, path):
-        return path == '/' and path or path and path.strip('/') or ''
+        return path == b'/' and path or path and path.strip(b'/') or b''
 
     def normalize_rev(self, rev):
         try:
@@ -157,7 +157,7 @@ class SubversionRepository(Repository):
 
     def get_node(self, path, rev=None):
         self.authz.assert_permission(self.scope + path)
-        if path and path[-1] == '/':
+        if path and path[-1] == b'/':
             path = path[:-1]
 
         rev = self.normalize_rev(rev)
@@ -166,13 +166,13 @@ class SubversionRepository(Repository):
 
     def get_oldest_rev(self):
         rev = 0
-        if self.scope == '/':
+        if self.scope == b'/':
             return rev
         return self.history[-1]
 
     def get_youngest_rev(self):
         rev = self.rev
-        if self.scope == '/':
+        if self.scope == b'/':
             return rev
         return self.history[0]
 
@@ -180,7 +180,7 @@ class SubversionRepository(Repository):
         rev = int(rev)
         if rev == 0:
             return None
-        if self.scope == '/':
+        if self.scope == b'/':
             return rev - 1
         idx = self.history.index(rev)
         if idx + 1 < len(self.history):
@@ -191,7 +191,7 @@ class SubversionRepository(Repository):
         rev = int(rev)
         if rev == self.rev:
             return None
-        if self.scope == '/':
+        if self.scope == b'/':
             return rev + 1
         if rev == 0:
             return self.oldest_rev
@@ -224,7 +224,7 @@ class SubversionRepository(Repository):
                         else: # the path changed: 'newer' was a copy
                             rev = self.previous_rev(newer[1]) # restart before 
the copy op
                             yield newer[0], newer[1], Changeset.COPY
-                            older = (older[0], older[1], 'unknown')
+                            older = (older[0], older[1], b'unknown')
                             break
                     newer = older
                 if older: # either a real ADD or the source of a COPY
@@ -262,7 +262,7 @@ class SubversionRepository(Repository):
             def authz_cb(root, path, pool): return 1
             text_deltas = 0 # as this is anyway re-done in Diff.py...
             entry_props = 0 # ("... typically used only for working copy 
updates")
-            repos.svn_repos_dir_delta(old_root, old_path, '',
+            repos.svn_repos_dir_delta(old_root, old_path, b'',
                                       new_root, new_path,
                                       e_ptr, e_baton, authz_cb,
                                       text_deltas,
@@ -290,7 +290,7 @@ class SubversionNode(Node):
     def __init__(self, path, rev, authz, scope, fs_ptr):
         self.authz = authz
         self.scope = scope
-        if scope != '/':
+        if scope != b'/':
             self.scoped_path = scope + path
         else:
             self.scoped_path = path
@@ -300,7 +300,8 @@ class SubversionNode(Node):
         self.root = fs.revision_root(fs_ptr, rev)
         node_type = fs.check_path(self.root, self.scoped_path)
         if not node_type in _kindmap:
-            raise TracError("No node at %s in revision %s" % (path, rev))
+            raise TracError("No node at %s in revision %s"
+                            % (path.decode('UTF-8'), rev))
         self.created_rev = fs.node_created_rev(self.root, self.scoped_path)
         self.created_path = fs.node_created_path(self.root, self.scoped_path)
         # Note: 'created_path' differs from 'path' if the last change was a 
copy,
@@ -322,8 +323,8 @@ class SubversionNode(Node):
         if self.isfile:
             return
         entries = fs.dir_entries(self.root, self.scoped_path)
-        for item in entries.keys():
-            path = '/'.join((self.path, item))
+        for item in entries:
+            path = b'/'.join((self.path, item))
             if not self.authz.has_permission(path):
                 continue
             yield SubversionNode(path, self._requested_rev, self.authz,
@@ -349,8 +350,8 @@ class SubversionNode(Node):
 
     def get_properties(self):
         props = fs.node_proplist(self.root, self.scoped_path)
-        for name,value in props.items():
-            props[name] = str(value) # Make sure the value is a proper string
+        for name,value in core._as_list(props.items()):
+            props[name] = value
         return props
 
     def get_content_length(self):
@@ -366,7 +367,7 @@ class SubversionNode(Node):
     def get_last_modified(self):
         date = fs.revision_prop(self.fs_ptr, self.created_rev,
                                 core.SVN_PROP_REVISION_DATE)
-        return core.svn_time_from_cstring(date) / 1000000
+        return core.svn_time_from_cstring(date) // 1000000
 
     def _get_prop(self, name):
         return fs.node_prop(self.root, self.scoped_path, name)
@@ -382,7 +383,7 @@ class SubversionChangeset(Changeset):
         message = self._get_prop(core.SVN_PROP_REVISION_LOG)
         author = self._get_prop(core.SVN_PROP_REVISION_AUTHOR)
         date = self._get_prop(core.SVN_PROP_REVISION_DATE)
-        date = core.svn_time_from_cstring(date) / 1000000
+        date = core.svn_time_from_cstring(date) // 1000000
         Changeset.__init__(self, rev, message, author, date)
 
     def get_changes(self):
@@ -392,9 +393,10 @@ class SubversionChangeset(Changeset):
         repos.svn_repos_replay(root, e_ptr, e_baton)
 
         idx = 0
+        # Variables to record copy/deletes for later move detection
         copies, deletions = {}, {}
         changes = []
-        for path, change in editor.changes.items():
+        for path, change in core._as_list(editor.changes.items()):
             if not self.authz.has_permission(path):
                 # FIXME: what about base_path?
                 continue
@@ -409,10 +411,12 @@ class SubversionChangeset(Changeset):
             action = ''
             if change.action == repos.CHANGE_ACTION_DELETE:
                 action = Changeset.DELETE
+                # Save off the index within changes of this deletion
                 deletions[change.base_path] = idx
             elif change.added:
                 if change.base_path and change.base_rev:
                     action = Changeset.COPY
+                    # Save off the index within changes of this copy
                     copies[change.base_path] = idx
                 else:
                     action = Changeset.ADD
@@ -423,18 +427,19 @@ class SubversionChangeset(Changeset):
             changes.append([path, kind, action, base_path, change.base_rev])
             idx += 1
 
-        moves = []
-        for k,v in copies.items():
+        # Detect moves by checking for copies whose source was deleted in this
+        # change set.
+        moves = set()
+        for k,v in core._as_list(copies.items()):
             if k in deletions:
                 changes[v][2] = Changeset.MOVE
-                moves.append(deletions[k])
-        offset = 0
-        for i in moves:
-            del changes[i - offset]
-            offset += 1
+                # Record the index of the now redundant delete action.
+                moves.add(deletions[k])
 
-        for change in changes:
-            yield tuple(change)
+        for i, change in enumerate(changes):
+            # Do not return the 'delete' changes that were part of moves.
+            if i not in moves:
+                yield tuple(change)
 
     def _get_prop(self, name):
         return fs.revision_prop(self.fs_ptr, self.rev, name)
@@ -457,7 +462,7 @@ class DiffChangeEditor(delta.Editor):
     # -- svn.delta.Editor callbacks
 
     def open_root(self, base_revision, dir_pool):
-        return ('/', Changeset.EDIT)
+        return (b'/', Changeset.EDIT)
 
     def add_directory(self, path, dir_baton, copyfrom_path, copyfrom_rev, 
dir_pool):
         self.deltas.append((path, Node.DIRECTORY, Changeset.ADD))

Modified: 
subversion/trunk/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- 
subversion/trunk/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py
 (original)
+++ 
subversion/trunk/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py
 Mon Nov  4 05:59:36 2019
@@ -53,17 +53,14 @@ import shutil
 import sys
 import tempfile
 import unittest
-from urllib import pathname2url
+from io import BytesIO
 
 if sys.version_info[0] >= 3:
   # Python >=3.0
-  from io import StringIO
+  from urllib.request import pathname2url
 else:
   # Python <3.0
-  try:
-    from cStringIO import StringIO
-  except ImportError:
-    from StringIO import StringIO
+  from urllib import pathname2url
 
 from svn import core, repos
 
@@ -72,35 +69,34 @@ from trac.versioncontrol import Changese
 from trac.versioncontrol.svn_fs import SubversionRepository
 
 temp_path = tempfile.mktemp("-trac-svnrepos")
-REPOS_PATH = core.svn_dirent_internal_style(temp_path)
-REPOS_URL = pathname2url(temp_path)
+REPOS_PATH = core.svn_dirent_internal_style(temp_path.encode('UTF-8'))
+REPOS_URL = pathname2url(temp_path).encode('UTF-8')
 del temp_path
 
-if REPOS_URL.startswith("///"):
+if REPOS_URL.startswith(b"///"):
   # Don't add extra slashes if they're already present.
   # (This is important for Windows compatibility).
-  REPOS_URL = "file:" + REPOS_URL
+  REPOS_URL = b"file:" + REPOS_URL
 else:
   # If the URL simply starts with '/', we need to add two
   # extra slashes to make it a valid 'file://' URL
-  REPOS_URL = "file://" + REPOS_URL
+  REPOS_URL = b"file://" + REPOS_URL
 
 REPOS_URL = core.svn_uri_canonicalize(REPOS_URL)
 
 class SubversionRepositoryTestSetup(TestSetup):
 
     def setUp(self):
-        dumpfile = open(os.path.join(os.path.split(__file__)[0],
-                                     'svnrepos.dump'), 'rb')
-
-        # Remove the trac-svnrepos directory, so that we can
-        # ensure a fresh start.
-        self.tearDown()
-
-        r = repos.svn_repos_create(REPOS_PATH, '', '', None, None)
-        repos.svn_repos_load_fs2(r, dumpfile, StringIO(),
-                                repos.svn_repos_load_uuid_ignore, '',
-                                0, 0, None)
+        dump_path = os.path.join(os.path.split(__file__)[0], 'svnrepos.dump')
+        with open(dump_path, 'rb') as dumpfile:
+            # Remove the trac-svnrepos directory, so that we can
+            # ensure a fresh start.
+            self.tearDown()
+
+            r = repos.svn_repos_create(REPOS_PATH, b'', b'', None, None)
+            repos.svn_repos_load_fs2(r, dumpfile, BytesIO(),
+                                    repos.svn_repos_load_uuid_ignore, b'',
+                                    0, 0, None)
 
     def tearDown(self):
         if os.path.exists(REPOS_PATH):
@@ -126,110 +122,111 @@ class SubversionRepositoryTestCase(unitt
         self.assertEqual(None, self.repos.next_rev(12))
 
     def test_get_node(self):
-        node = self.repos.get_node('/trunk')
-        self.assertEqual('trunk', node.name)
-        self.assertEqual('/trunk', node.path)
+        node = self.repos.get_node(b'/trunk')
+        self.assertEqual(b'trunk', node.name)
+        self.assertEqual(b'/trunk', node.path)
         self.assertEqual(Node.DIRECTORY, node.kind)
         self.assertEqual(6, node.rev)
         self.assertEqual(1112381806, node.last_modified)
-        node = self.repos.get_node('/trunk/README.txt')
-        self.assertEqual('README.txt', node.name)
-        self.assertEqual('/trunk/README.txt', node.path)
+        node = self.repos.get_node(b'/trunk/README.txt')
+        self.assertEqual(b'README.txt', node.name)
+        self.assertEqual(b'/trunk/README.txt', node.path)
         self.assertEqual(Node.FILE, node.kind)
         self.assertEqual(3, node.rev)
         self.assertEqual(1112361898, node.last_modified)
 
     def test_get_node_specific_rev(self):
-        node = self.repos.get_node('/trunk', 1)
-        self.assertEqual('trunk', node.name)
-        self.assertEqual('/trunk', node.path)
+        node = self.repos.get_node(b'/trunk', 1)
+        self.assertEqual(b'trunk', node.name)
+        self.assertEqual(b'/trunk', node.path)
         self.assertEqual(Node.DIRECTORY, node.kind)
         self.assertEqual(1, node.rev)
         self.assertEqual(1112349652, node.last_modified)
-        node = self.repos.get_node('/trunk/README.txt', 2)
-        self.assertEqual('README.txt', node.name)
-        self.assertEqual('/trunk/README.txt', node.path)
+        node = self.repos.get_node(b'/trunk/README.txt', 2)
+        self.assertEqual(b'README.txt', node.name)
+        self.assertEqual(b'/trunk/README.txt', node.path)
         self.assertEqual(Node.FILE, node.kind)
         self.assertEqual(2, node.rev)
         self.assertEqual(1112361138, node.last_modified)
 
     def test_get_dir_entries(self):
-        node = self.repos.get_node('/trunk')
+        node = self.repos.get_node(b'/trunk')
         entries = node.get_entries()
-        self.assertEqual('README2.txt', entries.next().name)
-        self.assertEqual('dir1', entries.next().name)
-        self.assertEqual('README.txt', entries.next().name)
-        self.assertRaises(StopIteration, entries.next)
+        self.assertSequenceEqual(sorted([entry.name for entry in entries]),
+                                 sorted([b'README2.txt',
+                                  b'dir1',
+                                  b'README.txt']))
 
     def test_get_file_entries(self):
-        node = self.repos.get_node('/trunk/README.txt')
+        node = self.repos.get_node(b'/trunk/README.txt')
         entries = node.get_entries()
-        self.assertRaises(StopIteration, entries.next)
+        self.assertSequenceEqual([entry.name for entry in entries],
+                                 [])
 
     def test_get_dir_content(self):
-        node = self.repos.get_node('/trunk')
+        node = self.repos.get_node(b'/trunk')
         self.assertEqual(None, node.content_length)
         self.assertEqual(None, node.content_type)
         self.assertEqual(None, node.get_content())
 
     def test_get_file_content(self):
-        node = self.repos.get_node('/trunk/README.txt')
+        node = self.repos.get_node(b'/trunk/README.txt')
         self.assertEqual(8, node.content_length)
-        self.assertEqual('text/plain', node.content_type)
-        self.assertEqual('A test.\n', node.get_content().read())
+        self.assertEqual(b'text/plain', node.content_type)
+        self.assertEqual(b'A test.\n', node.get_content().read())
 
     def test_get_dir_properties(self):
-        f = self.repos.get_node('/trunk')
+        f = self.repos.get_node(b'/trunk')
         props = f.get_properties()
         self.assertEqual(0, len(props))
 
     def test_get_file_properties(self):
-        f = self.repos.get_node('/trunk/README.txt')
+        f = self.repos.get_node(b'/trunk/README.txt')
         props = f.get_properties()
-        self.assertEqual('native', props['svn:eol-style'])
-        self.assertEqual('text/plain', props['svn:mime-type'])
+        self.assertEqual(b'native', props[b'svn:eol-style'])
+        self.assertEqual(b'text/plain', props[b'svn:mime-type'])
 
     # Revision Log / node history
 
     def test_get_node_history(self):
-        node = self.repos.get_node('/trunk/README2.txt')
+        node = self.repos.get_node(b'/trunk/README2.txt')
         history = node.get_history()
-        self.assertEqual(('trunk/README2.txt', 6, 'copy'), history.next())
-        self.assertEqual(('trunk/README.txt', 3, 'edit'), history.next())
-        self.assertEqual(('trunk/README.txt', 2, 'add'), history.next())
-        self.assertRaises(StopIteration, history.next)
+        self.assertSequenceEqual([x for x in history],
+                                 [(b'trunk/README2.txt', 6, b'copy'),
+                                  (b'trunk/README.txt', 3, b'edit'),
+                                  (b'trunk/README.txt', 2, b'add')])
 
     def test_get_node_history_follow_copy(self):
-        node = self.repos.get_node('/tags/v1/README.txt')
+        node = self.repos.get_node(b'/tags/v1/README.txt')
         history = node.get_history()
-        self.assertEqual(('tags/v1/README.txt', 7, 'copy'), history.next())
-        self.assertEqual(('trunk/README.txt', 3, 'edit'), history.next())
-        self.assertEqual(('trunk/README.txt', 2, 'add'), history.next())
-        self.assertRaises(StopIteration, history.next)
+        self.assertSequenceEqual([x for x in history],
+                                 [(b'tags/v1/README.txt', 7, b'copy'),
+                                  (b'trunk/README.txt', 3, b'edit'),
+                                  (b'trunk/README.txt', 2, b'add')])
 
     # Revision Log / path history
 
     def test_get_path_history(self):
-        history = self.repos.get_path_history('/trunk/README2.txt', None)
-        self.assertEqual(('trunk/README2.txt', 6, 'copy'), history.next())
-        self.assertEqual(('trunk/README.txt', 3, 'unknown'), history.next())
-        self.assertRaises(StopIteration, history.next)
+        history = self.repos.get_path_history(b'/trunk/README2.txt', None)
+        self.assertSequenceEqual([x for x in history],
+                                 [(b'trunk/README2.txt', 6, b'copy'),
+                                  (b'trunk/README.txt', 3, b'unknown')])
 
     def test_get_path_history_copied_file(self):
-        history = self.repos.get_path_history('/tags/v1/README.txt', None)
-        self.assertEqual(('tags/v1/README.txt', 7, 'copy'), history.next())
-        self.assertEqual(('trunk/README.txt', 3, 'unknown'), history.next())
-        self.assertRaises(StopIteration, history.next)
+        history = self.repos.get_path_history(b'/tags/v1/README.txt', None)
+        self.assertSequenceEqual([x for x in history],
+                                 [(b'tags/v1/README.txt', 7, b'copy'),
+                                  (b'trunk/README.txt', 3, b'unknown')])
 
     def test_get_path_history_copied_dir(self):
-        history = self.repos.get_path_history('/branches/v1x', None)
-        self.assertEqual(('branches/v1x', 12, 'copy'), history.next())
-        self.assertEqual(('tags/v1.1', 10, 'unknown'), history.next())
-        self.assertEqual(('branches/v1x', 11, 'delete'), history.next())
-        self.assertEqual(('branches/v1x', 9, 'edit'), history.next())
-        self.assertEqual(('branches/v1x', 8, 'copy'), history.next())
-        self.assertEqual(('tags/v1', 7, 'unknown'), history.next())
-        self.assertRaises(StopIteration, history.next)
+        history = self.repos.get_path_history(b'/branches/v1x', None)
+        self.assertSequenceEqual([x for x in history],
+                                 [(b'branches/v1x', 12, b'copy'),
+                                  (b'tags/v1.1', 10, b'unknown'),
+                                  (b'branches/v1x', 11, b'delete'),
+                                  (b'branches/v1x', 9, b'edit'),
+                                  (b'branches/v1x', 8, b'copy'),
+                                  (b'tags/v1', 7, b'unknown')])
 
     # Diffs
 
@@ -243,63 +240,63 @@ class SubversionRepositoryTestCase(unitt
         self.assertEqual(expected[2], (got[2], got[3]))
 
     def test_diff_file_different_revs(self):
-        diffs = self.repos.get_deltas('trunk/README.txt', 2, 
'trunk/README.txt', 3)
-        self._cmp_diff((('trunk/README.txt', 2),
-                        ('trunk/README.txt', 3),
-                        (Node.FILE, Changeset.EDIT)), diffs.next())
-        self.assertRaises(StopIteration, diffs.next)
+        diffs = self.repos.get_deltas(b'trunk/README.txt', 2, 
b'trunk/README.txt', 3)
+        self._cmp_diff(((b'trunk/README.txt', 2),
+                        (b'trunk/README.txt', 3),
+                        (Node.FILE, Changeset.EDIT)), next(diffs))
+        self.assertRaises(StopIteration, lambda: next(diffs))
 
     def test_diff_file_different_files(self):
-        diffs = self.repos.get_deltas('branches/v1x/README.txt', 12,
-                                      'branches/v1x/README2.txt', 12)
-        self._cmp_diff((('branches/v1x/README.txt', 12),
-                        ('branches/v1x/README2.txt', 12),
-                        (Node.FILE, Changeset.EDIT)), diffs.next())
-        self.assertRaises(StopIteration, diffs.next)
+        diffs = self.repos.get_deltas(b'branches/v1x/README.txt', 12,
+                                      b'branches/v1x/README2.txt', 12)
+        self._cmp_diff(((b'branches/v1x/README.txt', 12),
+                        (b'branches/v1x/README2.txt', 12),
+                        (Node.FILE, Changeset.EDIT)), next(diffs))
+        self.assertRaises(StopIteration, lambda: next(diffs))
 
     def test_diff_file_no_change(self):
-        diffs = self.repos.get_deltas('trunk/README.txt', 7,
-                                      'tags/v1/README.txt', 7)
-        self.assertRaises(StopIteration, diffs.next)
+        diffs = self.repos.get_deltas(b'trunk/README.txt', 7,
+                                      b'tags/v1/README.txt', 7)
+        self.assertRaises(StopIteration, lambda: next(diffs))
 
     def test_diff_dir_different_revs(self):
-        diffs = self.repos.get_deltas('trunk', 4, 'trunk', 8)
+        diffs = self.repos.get_deltas(b'trunk', 4, b'trunk', 8)
         expected = [
-          (None, ('trunk/README2.txt', 6),
+          (None, (b'trunk/README2.txt', 6),
            (Node.FILE, Changeset.ADD)),
-          (None, ('trunk/dir1/dir2', 8),
+          (None, (b'trunk/dir1/dir2', 8),
            (Node.DIRECTORY, Changeset.ADD)),
-          (None, ('trunk/dir1/dir3', 8),
+          (None, (b'trunk/dir1/dir3', 8),
            (Node.DIRECTORY, Changeset.ADD)),
-          (('trunk/dir2', 4), None,
+          ((b'trunk/dir2', 4), None,
            (Node.DIRECTORY, Changeset.DELETE)),
-          (('trunk/dir3', 4), None,
+          ((b'trunk/dir3', 4), None,
            (Node.DIRECTORY, Changeset.DELETE)),
         ]
-        actual = [diffs.next() for i in range(5)]
+        actual = [next(diffs) for i in range(5)]
         actual = sorted(actual,
                         key=lambda diff: ((diff[0] or diff[1]).path,
                                           (diff[0] or diff[1]).rev))
         self.assertEqual(len(expected), len(actual))
         for e,a in zip(expected, actual):
           self._cmp_diff(e,a)
-        self.assertRaises(StopIteration, diffs.next)
+        self.assertRaises(StopIteration, lambda: next(diffs))
 
     def test_diff_dir_different_dirs(self):
-        diffs = self.repos.get_deltas('trunk', 1, 'branches/v1x', 12)
+        diffs = self.repos.get_deltas(b'trunk', 1, b'branches/v1x', 12)
         expected = [
-          (None, ('branches/v1x/README.txt', 12),
+          (None, (b'branches/v1x/README.txt', 12),
            (Node.FILE, Changeset.ADD)),
-          (None, ('branches/v1x/README2.txt', 12),
+          (None, (b'branches/v1x/README2.txt', 12),
            (Node.FILE, Changeset.ADD)),
-          (None, ('branches/v1x/dir1', 12),
+          (None, (b'branches/v1x/dir1', 12),
            (Node.DIRECTORY, Changeset.ADD)),
-          (None, ('branches/v1x/dir1/dir2', 12),
+          (None, (b'branches/v1x/dir1/dir2', 12),
            (Node.DIRECTORY, Changeset.ADD)),
-          (None, ('branches/v1x/dir1/dir3', 12),
+          (None, (b'branches/v1x/dir1/dir3', 12),
            (Node.DIRECTORY, Changeset.ADD)),
         ]
-        actual = [diffs.next() for i in range(5)]
+        actual = [next(diffs) for i in range(5)]
         actual = sorted(actual, key=lambda diff: (diff[1].path, diff[1].rev))
         # for e,a in zip(expected, actual):
         #   t.write("%r\n" % (e,))
@@ -308,12 +305,12 @@ class SubversionRepositoryTestCase(unitt
         self.assertEqual(len(expected), len(actual))
         for e,a in zip(expected, actual):
           self._cmp_diff(e,a)
-        self.assertRaises(StopIteration, diffs.next)
+        self.assertRaises(StopIteration, lambda: next(diffs))
 
     def test_diff_dir_no_change(self):
-        diffs = self.repos.get_deltas('trunk', 7,
-                                      'tags/v1', 7)
-        self.assertRaises(StopIteration, diffs.next)
+        diffs = self.repos.get_deltas(b'trunk', 7,
+                                      b'tags/v1', 7)
+        self.assertRaises(StopIteration, lambda: next(diffs))
 
     # Changesets
 
@@ -323,61 +320,57 @@ class SubversionRepositoryTestCase(unitt
         self.assertEqual(None, chgset.message)
         self.assertEqual(None, chgset.author)
         self.assertEqual(1112349461, chgset.date)
-        self.assertRaises(StopIteration, chgset.get_changes().next)
+        self.assertRaises(StopIteration, lambda: next(chgset.get_changes()))
 
     def test_changeset_added_dirs(self):
         chgset = self.repos.get_changeset(1)
         self.assertEqual(1, chgset.rev)
-        self.assertEqual('Initial directory layout.', chgset.message)
-        self.assertEqual('john', chgset.author)
+        self.assertEqual(b'Initial directory layout.', chgset.message)
+        self.assertEqual(b'john', chgset.author)
         self.assertEqual(1112349652, chgset.date)
 
         changes = chgset.get_changes()
-        self.assertEqual(('trunk', Node.DIRECTORY, Changeset.ADD, None, -1),
-                         changes.next())
-        self.assertEqual(('branches', Node.DIRECTORY, Changeset.ADD, None, -1),
-                         changes.next())
-        self.assertEqual(('tags', Node.DIRECTORY, Changeset.ADD, None, -1),
-                         changes.next())
-        self.assertRaises(StopIteration, changes.next)
+        self.assertSequenceEqual(sorted([x for x in changes]),
+          sorted([(b'trunk', Node.DIRECTORY, Changeset.ADD, None, -1),
+                  (b'branches', Node.DIRECTORY, Changeset.ADD, None, -1),
+                  (b'tags', Node.DIRECTORY, Changeset.ADD, None, -1)]))
 
     def test_changeset_file_edit(self):
         chgset = self.repos.get_changeset(3)
         self.assertEqual(3, chgset.rev)
-        self.assertEqual('Fixed README.\n', chgset.message)
-        self.assertEqual('kate', chgset.author)
+        self.assertEqual(b'Fixed README.\n', chgset.message)
+        self.assertEqual(b'kate', chgset.author)
         self.assertEqual(1112361898, chgset.date)
 
         changes = chgset.get_changes()
-        self.assertEqual(('trunk/README.txt', Node.FILE, Changeset.EDIT,
-                          'trunk/README.txt', 2), changes.next())
-        self.assertRaises(StopIteration, changes.next)
+        self.assertSequenceEqual(sorted([x for x in changes]),
+                                 sorted([(b'trunk/README.txt', Node.FILE, 
Changeset.EDIT,
+                                   b'trunk/README.txt', 2)]))
 
     def test_changeset_dir_moves(self):
         chgset = self.repos.get_changeset(5)
         self.assertEqual(5, chgset.rev)
-        self.assertEqual('Moved directories.', chgset.message)
-        self.assertEqual('kate', chgset.author)
+        self.assertEqual(b'Moved directories.', chgset.message)
+        self.assertEqual(b'kate', chgset.author)
         self.assertEqual(1112372739, chgset.date)
 
         changes = chgset.get_changes()
-        self.assertEqual(('trunk/dir1/dir2', Node.DIRECTORY, Changeset.MOVE,
-                          'trunk/dir2', 4), changes.next())
-        self.assertEqual(('trunk/dir1/dir3', Node.DIRECTORY, Changeset.MOVE,
-                          'trunk/dir3', 4), changes.next())
-        self.assertRaises(StopIteration, changes.next)
+        self.assertSequenceEqual(sorted([x for x in changes]),
+          sorted([
+            (b'trunk/dir1/dir2', Node.DIRECTORY, Changeset.MOVE, 
b'trunk/dir2', 4),
+            (b'trunk/dir1/dir3', Node.DIRECTORY, Changeset.MOVE, 
b'trunk/dir3', 4)]))
 
     def test_changeset_file_copy(self):
         chgset = self.repos.get_changeset(6)
         self.assertEqual(6, chgset.rev)
-        self.assertEqual('More things to read', chgset.message)
-        self.assertEqual('john', chgset.author)
+        self.assertEqual(b'More things to read', chgset.message)
+        self.assertEqual(b'john', chgset.author)
         self.assertEqual(1112381806, chgset.date)
 
         changes = chgset.get_changes()
-        self.assertEqual(('trunk/README2.txt', Node.FILE, Changeset.COPY,
-                          'trunk/README.txt', 3), changes.next())
-        self.assertRaises(StopIteration, changes.next)
+        self.assertSequenceEqual(sorted([x for x in changes]),
+          sorted([(b'trunk/README2.txt', Node.FILE, Changeset.COPY,
+                   b'trunk/README.txt', 3)]))
 
 
 def suite():

Modified: subversion/trunk/subversion/bindings/swig/python/tests/utils.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/tests/utils.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/tests/utils.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/tests/utils.py Mon Nov  4 
05:59:36 2019
@@ -18,9 +18,15 @@
 # under the License.
 #
 #
-import os.path, sys, tempfile, urllib
+import os.path, sys, tempfile
 from svn import core, repos
-from StringIO import StringIO
+from io import BytesIO
+try:
+  # Python >=3.0
+  from urllib.request import pathname2url
+except ImportError:
+  # Python <3.0
+  from urllib import pathname2url
 
 class Temper(object):
   """Class to simplify allocation and cleanup of dummy Subversion
@@ -41,14 +47,19 @@ class Temper(object):
   def alloc_empty_dir(self, suffix = ""):
     """Create an empty temporary directory. Returns its full path
        in canonical internal form."""
-    temp_dir_name = core.svn_dirent_internal_style(tempfile.mkdtemp(suffix))
+    if isinstance(suffix, bytes):
+      suffix = suffix.decode('UTF-8')
+    temp_dir_name = tempfile.mkdtemp(suffix).encode('UTF-8')
+    temp_dir_name = core.svn_dirent_internal_style(temp_dir_name)
     self._cleanup_list.append((temp_dir_name, core.svn_io_remove_dir))
     return temp_dir_name
 
   def alloc_empty_repo(self, suffix = ""):
     """Create an empty repository. Returns a tuple of its handle, path and
        file: URI in canonical internal form."""
-    temp_path = tempfile.mkdtemp(suffix)
+    if isinstance(suffix, bytes):
+      suffix = suffix.decode('UTF-8')
+    temp_path = tempfile.mkdtemp(suffix).encode('UTF-8')
     repo_path = core.svn_dirent_internal_style(temp_path)
     repo_uri = core.svn_uri_canonicalize(file_uri_for_path(temp_path))
     handle = repos.create(repo_path, None, None, None, None)
@@ -61,15 +72,18 @@ class Temper(object):
        location. Returns the same as alloc_empty_repo."""
     dump_path = os.path.join(os.path.dirname(sys.argv[0]), repo_id)
     (handle, repo_path, repo_uri) = self.alloc_empty_repo(suffix=suffix)
-    repos.svn_repos_load_fs2(handle, open(dump_path, 'rb'), StringIO(),
-                             repos.load_uuid_default, None, False, False, None)
+    with open(dump_path, 'rb') as dump_fp:
+      repos.svn_repos_load_fs2(handle, dump_fp, BytesIO(),
+                               repos.load_uuid_default, None, False, False, 
None)
     return (handle, repo_path, repo_uri)
 
 def file_uri_for_path(path):
   """Return the file: URI corresponding to the given path."""
-  uri_path = urllib.pathname2url(path)
+  if not isinstance(path, str):
+    path = path.decode('UTF-8')
+  uri_path = pathname2url(path).encode('UTF-8')
 
   # pathname2url claims to return the path part of the URI, but on Windows
   # it returns both the authority and path parts for no reason, which
   # means we have to trim the leading slashes to "normalize" the result.
-  return 'file:///' + uri_path.lstrip('/')
+  return b'file:///' + uri_path.lstrip(b'/')

Modified: subversion/trunk/subversion/bindings/swig/python/tests/wc.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/tests/wc.py?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/tests/wc.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/tests/wc.py Mon Nov  4 
05:59:36 2019
@@ -19,12 +19,7 @@
 #
 #
 from sys import version_info # For Python version check
-if version_info[0] >= 3:
-  # Python >=3.0
-  from io import StringIO
-else:
-  # Python <3.0
-  from cStringIO import StringIO
+from io import BytesIO
 import unittest, os, tempfile, setup_path, binascii
 import svn.diff
 from svn import core, repos, wc, client
@@ -61,10 +56,10 @@ class SubversionWorkingCopyTestCase(unit
       wc.entry(self.path, self.wc, True)
 
   def test_lock(self):
-      readme_path = '%s/trunk/README.txt' % self.path
+      readme_path = b'%s/trunk/README.txt' % self.path
 
       lock = core.svn_lock_create(core.Pool())
-      lock.token = 'http://svnbook.org/nightly/en/svn.advanced.locking.html'
+      lock.token = b'http://svnbook.org/nightly/en/svn.advanced.locking.html'
 
       wc.add_lock(readme_path, lock, self.wc)
       self.assertEqual(True, wc.adm_locked(self.wc))
@@ -78,23 +73,23 @@ class SubversionWorkingCopyTestCase(unit
       self.assertEqual(self.path, wc.adm_access_path(self.wc))
 
   def test_is_adm_dir(self):
-      self.assert_(wc.is_adm_dir(".svn"))
-      self.failIf(wc.is_adm_dir(".foosvn"))
+      self.assertTrue(wc.is_adm_dir(b".svn"))
+      self.assertFalse(wc.is_adm_dir(b".foosvn"))
 
   def test_get_adm_dir(self):
-      self.assert_(isinstance(wc.get_adm_dir(), basestring))
+      self.assertTrue(isinstance(wc.get_adm_dir(), bytes))
 
   def test_set_adm_dir(self):
-      self.assertRaises(SubversionException, wc.set_adm_dir, ".foobar")
-      self.assert_(wc.is_adm_dir(".svn"))
-      self.failIf(wc.is_adm_dir("_svn"))
-      self.failIf(wc.is_adm_dir(".foobar"))
-      wc.set_adm_dir("_svn")
-      self.assert_(wc.is_adm_dir("_svn"))
-      self.assertEqual("_svn", wc.get_adm_dir())
-      wc.set_adm_dir(".svn")
-      self.failIf(wc.is_adm_dir("_svn"))
-      self.assertEqual(".svn", wc.get_adm_dir())
+      self.assertRaises(SubversionException, wc.set_adm_dir, b".foobar")
+      self.assertTrue(wc.is_adm_dir(b".svn"))
+      self.assertFalse(wc.is_adm_dir(b"_svn"))
+      self.assertFalse(wc.is_adm_dir(b".foobar"))
+      wc.set_adm_dir(b"_svn")
+      self.assertTrue(wc.is_adm_dir(b"_svn"))
+      self.assertEqual(b"_svn", wc.get_adm_dir())
+      wc.set_adm_dir(b".svn")
+      self.assertFalse(wc.is_adm_dir(b"_svn"))
+      self.assertEqual(b".svn", wc.get_adm_dir())
 
   def test_init_traversal_info(self):
       wc.init_traversal_info()
@@ -127,8 +122,8 @@ class SubversionWorkingCopyTestCase(unit
               pass
 
       # Remove trunk/README.txt
-      readme_path = '%s/trunk/README.txt' % self.path
-      self.assert_(os.path.exists(readme_path))
+      readme_path = b'%s/trunk/README.txt' % self.path
+      self.assertTrue(os.path.exists(readme_path))
       os.remove(readme_path)
 
       # Restore trunk/README.txt using crawl_revision2
@@ -138,8 +133,8 @@ class SubversionWorkingCopyTestCase(unit
                           True, True, False, notify, info)
 
       # Check that the report finished
-      self.assert_(reporter.finished_report)
-      self.assertEqual([''], set_paths)
+      self.assertTrue(reporter.finished_report)
+      self.assertEqual([b''], set_paths)
       self.assertEqual(1, len(infos))
 
       # Check content of infos object
@@ -152,7 +147,7 @@ class SubversionWorkingCopyTestCase(unit
       wc.create_notify(self.path, wc.notify_add)
 
   def test_check_wc(self):
-      self.assert_(wc.check_wc(self.path) > 0)
+      self.assertTrue(wc.check_wc(self.path) > 0)
 
   def test_get_ancestry(self):
       self.assertEqual([self.repos_uri, 12],
@@ -164,7 +159,6 @@ class SubversionWorkingCopyTestCase(unit
   def test_status_editor(self):
       paths = []
       def status_func(target, status):
-        self.assert_(target.startswith(self.path))
         paths.append(target)
 
       (anchor_access, target_access,
@@ -181,54 +175,79 @@ class SubversionWorkingCopyTestCase(unit
                                               None,  # traversal_info
                                               )
       editor.close_edit(edit_baton)
-      self.assert_(len(paths) > 0)
+      self.assertTrue(len(paths) > 0)
+      for target in paths:
+        self.assertTrue(target.startswith(self.path))
+
+  def test_status_editor_callback_exception(self):
+      """test case for status_editor call back not to be crashed by Python 
exception"""
+      def status_func(target, status):
+        # Note: exception with in this call back doesn't propagate to 
+        # the caller
+        raise AssertionError('intentional exception')
+
+      (anchor_access, target_access,
+       target) = wc.adm_open_anchor(self.path, False, -1, None)
+      (editor, edit_baton, set_locks_baton,
+       edit_revision) = wc.get_status_editor2(anchor_access,
+                                              target,
+                                              None,  # SvnConfig
+                                              True,  # recursive
+                                              True, # get_all
+                                              False, # no_ignore
+                                              status_func,
+                                              None,  # cancel_func
+                                              None,  # traversal_info
+                                              )
+      editor.close_edit(edit_baton)
 
   def test_is_normal_prop(self):
-      self.failIf(wc.is_normal_prop('svn:wc:foo:bar'))
-      self.failIf(wc.is_normal_prop('svn:entry:foo:bar'))
-      self.assert_(wc.is_normal_prop('svn:foo:bar'))
-      self.assert_(wc.is_normal_prop('foreign:foo:bar'))
+      self.assertFalse(wc.is_normal_prop(b'svn:wc:foo:bar'))
+      self.assertFalse(wc.is_normal_prop(b'svn:entry:foo:bar'))
+      self.assertTrue(wc.is_normal_prop(b'svn:foo:bar'))
+      self.assertTrue(wc.is_normal_prop(b'foreign:foo:bar'))
 
   def test_is_wc_prop(self):
-      self.assert_(wc.is_wc_prop('svn:wc:foo:bar'))
-      self.failIf(wc.is_wc_prop('svn:entry:foo:bar'))
-      self.failIf(wc.is_wc_prop('svn:foo:bar'))
-      self.failIf(wc.is_wc_prop('foreign:foo:bar'))
+      self.assertTrue(wc.is_wc_prop(b'svn:wc:foo:bar'))
+      self.assertFalse(wc.is_wc_prop(b'svn:entry:foo:bar'))
+      self.assertFalse(wc.is_wc_prop(b'svn:foo:bar'))
+      self.assertFalse(wc.is_wc_prop(b'foreign:foo:bar'))
 
   def test_is_entry_prop(self):
-      self.assert_(wc.is_entry_prop('svn:entry:foo:bar'))
-      self.failIf(wc.is_entry_prop('svn:wc:foo:bar'))
-      self.failIf(wc.is_entry_prop('svn:foo:bar'))
-      self.failIf(wc.is_entry_prop('foreign:foo:bar'))
+      self.assertTrue(wc.is_entry_prop(b'svn:entry:foo:bar'))
+      self.assertFalse(wc.is_entry_prop(b'svn:wc:foo:bar'))
+      self.assertFalse(wc.is_entry_prop(b'svn:foo:bar'))
+      self.assertFalse(wc.is_entry_prop(b'foreign:foo:bar'))
 
   def test_get_prop_diffs(self):
-      wc.prop_set("foreign:foo", "bla", self.path, self.wc)
-      self.assertEquals([{"foreign:foo": "bla"}, {}],
+      wc.prop_set(b"foreign:foo", b"bla", self.path, self.wc)
+      self.assertEqual([{b"foreign:foo": b"bla"}, {}],
               wc.get_prop_diffs(self.path, self.wc))
 
   def test_get_pristine_copy_path(self):
-      path_to_file = '%s/trunk/README.txt' % self.path
+      path_to_file = b'%s/trunk/README.txt' % self.path
       path_to_text_base = wc.get_pristine_copy_path(path_to_file)
-      text_base = open(path_to_text_base).read()
+      with open(path_to_text_base, 'rb') as fp:
+          text_base = fp.read()
       # TODO: This test should modify the working file first, to ensure the
       # path isn't just the path to the working file.
-      self.assertEqual(text_base, 'A test.\n')
+      self.assertEqual(text_base, b'A test.\n')
 
   def test_entries_read(self):
       entries = wc.entries_read(self.wc, True)
-      keys = list(entries.keys())
+      keys = core._as_list(entries.keys())
       keys.sort()
-      self.assertEqual(['', 'branches', 'tags', 'trunk'], keys)
+      self.assertEqual([b'', b'branches', b'tags', b'trunk'], keys)
 
   def test_get_ignores(self):
-      self.assert_(isinstance(wc.get_ignores(None, self.wc), list))
+      self.assertTrue(isinstance(wc.get_ignores(None, self.wc), list))
 
   def test_commit(self):
     # Replace README.txt's contents, using binary mode so we know the
     # exact contents even on Windows, and therefore the MD5 checksum.
-    readme_path = '%s/trunk/README.txt' % self.path
+    readme_path = b'%s/trunk/README.txt' % self.path
     fp = open(readme_path, 'wb')
-    fp.write('hello\n')
+    fp.write(b'hello\n')
     fp.close()
 
     # Setup ra_ctx.
@@ -240,7 +259,7 @@ class SubversionWorkingCopyTestCase(unit
     commit_info = [None]
     def commit_cb(_commit_info, pool):
       commit_info[0] = _commit_info
-    (editor, edit_baton) = ra.get_commit_editor2(ra_ctx, 'log message',
+    (editor, edit_baton) = ra.get_commit_editor2(ra_ctx, b'log message',
                                                  commit_cb,
                                                  None,
                                                  False)
@@ -254,7 +273,7 @@ class SubversionWorkingCopyTestCase(unit
                                                   False, editor, baton, pool)
       return baton
     try:
-      delta.path_driver(editor, edit_baton, -1, ['trunk/README.txt'],
+      delta.path_driver(editor, edit_baton, -1, [b'trunk/README.txt'],
                         driver_cb)
       editor.close_edit(edit_baton)
     except:
@@ -269,9 +288,9 @@ class SubversionWorkingCopyTestCase(unit
     (commit_info,) = commit_info
 
     # Assert the commit.
-    self.assertEquals(binascii.b2a_hex(checksum),
-                      'b1946ac92492d2347c6235b4d2611184')
-    self.assertEquals(commit_info.revision, 13)
+    self.assertEqual(binascii.b2a_hex(checksum),
+                      b'b1946ac92492d2347c6235b4d2611184')
+    self.assertEqual(commit_info.revision, 13)
 
     # Bump working copy state.
     wc.process_committed4(readme_path,
@@ -282,10 +301,10 @@ class SubversionWorkingCopyTestCase(unit
 
     # Assert bumped state.
     entry = wc.entry(readme_path, self.wc, False)
-    self.assertEquals(entry.revision, commit_info.revision)
-    self.assertEquals(entry.schedule, wc.schedule_normal)
-    self.assertEquals(entry.cmt_rev, commit_info.revision)
-    self.assertEquals(entry.cmt_date,
+    self.assertEqual(entry.revision, commit_info.revision)
+    self.assertEqual(entry.schedule, wc.schedule_normal)
+    self.assertEqual(entry.cmt_rev, commit_info.revision)
+    self.assertEqual(entry.cmt_date,
                       core.svn_time_from_cstring(commit_info.date))
 
   def test_diff_editor4(self):
@@ -294,14 +313,14 @@ class SubversionWorkingCopyTestCase(unit
     url = self.repos_uri
 
     # cause file_changed: Replace README.txt's contents.
-    readme_path = '%s/trunk/README.txt' % self.path
-    fp = open(readme_path, 'w')
-    fp.write('hello\n')
+    readme_path = b'%s/trunk/README.txt' % self.path
+    fp = open(readme_path, 'wb')
+    fp.write(b'hello\n')
     fp.close()
     # cause file_added: Create readme3.
-    readme3_path = '%s/trunk/readme3' % self.path
-    fp = open(readme3_path, 'w')
-    fp.write('hello\n')
+    readme3_path = b'%s/trunk/readme3' % self.path
+    fp = open(readme3_path, 'wb')
+    fp.write(b'hello\n')
     fp.close()
     wc.add2(readme3_path,
             wc.adm_probe_retrieve(self.wc,
@@ -311,7 +330,7 @@ class SubversionWorkingCopyTestCase(unit
             None,                     # notify_func
             pool)
     # cause file_deleted: Delete README2.txt.
-    readme2_path = '%s/trunk/README2.txt' % self.path
+    readme2_path = b'%s/trunk/README2.txt' % self.path
     wc.delete3(readme2_path,
                wc.adm_probe_retrieve(self.wc,
                                      os.path.dirname(readme2_path), pool),
@@ -320,8 +339,8 @@ class SubversionWorkingCopyTestCase(unit
                False,                 # keep_local
                pool)
     # cause dir_props_changed: ps testprop testval dir1/dir2
-    dir2_path = '%s/trunk/dir1/dir2' % self.path
-    wc.prop_set2('testprop', 'testval', dir2_path,
+    dir2_path = b'%s/trunk/dir1/dir2' % self.path
+    wc.prop_set2(b'testprop', b'testval', dir2_path,
                  wc.adm_probe_retrieve(self.wc,
                                        os.path.dirname(dir2_path), pool),
                  False,               # skip_checks
@@ -331,7 +350,7 @@ class SubversionWorkingCopyTestCase(unit
     # Save prop changes.
     got_prop_changes = []
     def props_changed(path, propchanges):
-      for (name, value) in propchanges.items():
+      for (name, value) in core._as_list(propchanges.items()):
         (kind, _) = core.svn_property_kind(name)
         if kind != core.svn_prop_regular_kind:
           continue
@@ -342,16 +361,16 @@ class SubversionWorkingCopyTestCase(unit
     def write_diff(path, left, right):
       options = svn.diff.file_options_create()
       diff = svn.diff.file_diff_2(left, right, options, pool)
-      original_header = modified_header = ''
-      encoding = 'utf8'
+      original_header = modified_header = b''
+      encoding = b'utf8'
       relative_to_dir = None
-      sio = StringIO()
-      svn.diff.file_output_unified3(sio, diff,
+      bio = BytesIO()
+      svn.diff.file_output_unified3(bio, diff,
                                     left, right,
                                     original_header, modified_header,
                                     encoding, relative_to_dir,
                                     options.show_c_function, pool)
-      got_diffs[path[len(self.path) + 1:]] = sio.getvalue().splitlines()
+      got_diffs[path[len(self.path) + 1:]] = bio.getvalue().splitlines()
 
     # Diff callbacks that call props_changed and write_diff.
     contentstate = propstate = state = wc.notify_state_unknown
@@ -383,7 +402,7 @@ class SubversionWorkingCopyTestCase(unit
 
     # Setup wc diff editor.
     (editor, edit_baton) = wc.get_diff_editor4(
-      self.wc, '', diff_callbacks, depth,
+      self.wc, b'', diff_callbacks, depth,
       False,                    # ignore_ancestry
       False,                    # use_text_base
       False,                    # reverse_order
@@ -400,39 +419,39 @@ class SubversionWorkingCopyTestCase(unit
     (reporter, report_baton) = ra.do_diff3(
       ra_ctx,
       head,                     # versus_url revision
-      '',                       # diff_target
+      b'',                       # diff_target
       depth,
       False,                    # ignore_ancestry
       True,                     # text_deltas
       url,                      # versus_url
       editor, edit_baton, pool)
     # Report wc state (pretty plain).
-    reporter.set_path(report_baton, '', head, depth,
+    reporter.set_path(report_baton, b'', head, depth,
                       False,    # start_empty
                       None,     # lock_token
                       pool)
     reporter.finish_report(report_baton, pool)
 
     # Assert we got the right diff.
-    expected_prop_changes = [('trunk/dir1/dir2',
-                              'testprop', 'testval')]
+    expected_prop_changes = [(b'trunk/dir1/dir2',
+                              b'testprop', b'testval')]
     expected_diffs = {
-      'trunk/readme3':
-        ['--- ',
-         '+++ ',
-         '@@ -0,0 +1 @@',
-         '+hello'],
-      'trunk/README.txt':
-        ['--- ',
-         '+++ ',
-         '@@ -1 +1 @@',
-         '-A test.',
-         '+hello'],
-      'trunk/README2.txt':
-        ['--- ',
-         '+++ ',
-         '@@ -1 +0,0 @@',
-         '-A test.'],
+      b'trunk/readme3':
+        [b'--- ',
+         b'+++ ',
+         b'@@ -0,0 +1 @@',
+         b'+hello'],
+      b'trunk/README.txt':
+        [b'--- ',
+         b'+++ ',
+         b'@@ -1 +1 @@',
+         b'-A test.',
+         b'+hello'],
+      b'trunk/README2.txt':
+        [b'--- ',
+         b'+++ ',
+         b'@@ -1 +0,0 @@',
+         b'-A test.'],
       }
     self.assertEqual(got_prop_changes, expected_prop_changes)
     self.assertEqual(got_diffs, expected_diffs)

Modified: subversion/trunk/subversion/bindings/swig/svn_client.i
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/svn_client.i?rev=1869354&r1=1869353&r2=1869354&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/svn_client.i (original)
+++ subversion/trunk/subversion/bindings/swig/svn_client.i Mon Nov  4 05:59:36 
2019
@@ -119,7 +119,7 @@
     ppitem = (svn_client_proplist_item_t **)(*$1)->elts;
     for (i = 0; i < nelts; ++i, ++ppitem) {
         PyObject *item = PyTuple_New(2);
-        PyObject *name = PyString_FromStringAndSize((*ppitem)->node_name->data,
+        PyObject *name = PyBytes_FromStringAndSize((*ppitem)->node_name->data,
                                                     (*ppitem)->node_name->len);
         PyObject *hash = svn_swig_py_prophash_to_dict((*ppitem)->prop_hash);
 
@@ -239,6 +239,33 @@ Callback: svn_client_diff_summarize_func
                   svn_swig_rb_changelist_receiver)
 #endif
 
+ /* -----------------------------------------------------------------------
+    Callback: svn_client_status_func_t
+    svn_client_status*()
+    svn_client__shelf_save_new_version3()
+ */
+
+#ifdef SWIGPYTHON
+%callback_typemap(svn_client_status_func_t status_func,
+                  void *status_baton,
+                  svn_swig_py_client_status_func,
+                  ,
+                  )
+
+%callback_typemap_maybenull(svn_client_status_func_t shelved_func,
+                            void *shelved_baton,
+                            svn_swig_py_client_status_func,
+                            ,
+                            )
+
+%callback_typemap_maybenull(svn_client_status_func_t not_shelved_func,
+                            void *not_shelved_baton,
+                            svn_swig_py_client_status_func,
+                            ,
+                            )
+#endif
+
+
 /* -----------------------------------------------------------------------
    We use 'svn_wc_status_t *' in some custom code, but it isn't in the
    API anywhere. Thus, SWIG doesn't generate a typemap entry for it. by

Propchange: subversion/trunk/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
  Merged /subversion/branches/swig-py3/subversion/libsvn_fs_x:r1813660-1869353

Propchange: subversion/trunk/subversion/libsvn_subr/utf8proc/
------------------------------------------------------------------------------
  Merged 
/subversion/branches/swig-py3/subversion/libsvn_subr/utf8proc:r1813660-1869353


Reply via email to