← Back to team overview

duplicity-team team mailing list archive

[Merge] lp:~aaron-whitehouse/duplicity/08-python-futurize-stage-1 into lp:duplicity

 

Aaron Whitehouse has proposed merging lp:~aaron-whitehouse/duplicity/08-python-futurize-stage-1 into lp:duplicity.

Requested reviews:
  duplicity-team (duplicity-team)

For more details, see:
https://code.launchpad.net/~aaron-whitehouse/duplicity/08-python-futurize-stage-1/+merge/317038

* Made many of the safer changes for improved Python 3 support (python-future's futurize -stage1) without functional change to the code (and leaving the isinstance(s, types.StringType) tests unchanged).
* Created Python 2/3 compatible tests for int and long.
* Update setup.py to show only Python 2.7 support.

-- 
Your team duplicity-team is requested to review the proposed merge of lp:~aaron-whitehouse/duplicity/08-python-futurize-stage-1 into lp:duplicity.
=== modified file 'duplicity/collections.py'
--- duplicity/collections.py	2016-07-02 12:53:12 +0000
+++ duplicity/collections.py	2017-02-11 23:01:59 +0000
@@ -25,7 +25,7 @@
 
 import types
 import gettext
-
+import sys
 
 from duplicity import log
 from duplicity import file_naming
@@ -37,6 +37,12 @@
 from duplicity import util
 from duplicity.gpg import GPGError
 
+# For type testing against both int and long types that works in python 2/3
+if sys.version_info < (3,):
+    integer_types = (int, types.LongType)
+else:
+    integer_types = (int,)
+
 
 class CollectionsError(Exception):
     pass
@@ -489,7 +495,7 @@
         Check to make sure times are in whole seconds
         """
         for time in time_list:
-            if type(time) not in (types.LongType, types.IntType):
+            if type(time) not in integer_types:
                 assert 0, "Time %s in %s wrong type" % (time, time_list)
 
     def islocal(self):

=== modified file 'duplicity/commandline.py'
--- duplicity/commandline.py	2017-01-20 15:26:13 +0000
+++ duplicity/commandline.py	2017-02-11 23:01:59 +0000
@@ -20,6 +20,7 @@
 # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 """Parse command line, check for consistency, and set globals"""
+from __future__ import print_function
 
 from future_builtins import filter
 
@@ -260,7 +261,7 @@
                            log.ErrorCode.cant_open_filelist)
 
     def print_ver(o, s, v, p):
-        print "duplicity %s" % (globals.version)
+        print("duplicity %s" % (globals.version))
         sys.exit(0)
 
     def add_rename(o, s, v, p):

=== modified file 'duplicity/diffdir.py'
--- duplicity/diffdir.py	2015-05-08 12:28:47 +0000
+++ duplicity/diffdir.py	2017-02-11 23:01:59 +0000
@@ -83,7 +83,7 @@
     """
     global stats
     stats = statistics.StatsDeltaProcess()
-    if isinstance(dirsig_fileobj_list, types.ListType):
+    if isinstance(dirsig_fileobj_list, list):
         sig_iter = combine_path_iters([sigtar2path_iter(x) for x
                                        in dirsig_fileobj_list])
     else:
@@ -273,7 +273,7 @@
     while 1:
         if not relem1:
             try:
-                relem1 = riter1.next()
+                relem1 = next(riter1)
             except StopIteration:
                 if relem2:
                     yield (None, relem2)
@@ -283,7 +283,7 @@
             index1 = relem1.index
         if not relem2:
             try:
-                relem2 = riter2.next()
+                relem2 = next(riter2)
             except StopIteration:
                 if relem1:
                     yield (relem1, None)
@@ -324,7 +324,7 @@
         Represent the next element as a triple, to help sorting
         """
         try:
-            path = path_iter_list[iter_index].next()
+            path = next(path_iter_list[iter_index])
         except StopIteration:
             return None
         return (path.index, iter_index, path)
@@ -364,7 +364,7 @@
     """
     global stats
     stats = statistics.StatsDeltaProcess()
-    if isinstance(sig_infp_list, types.ListType):
+    if isinstance(sig_infp_list, list):
         sig_path_iter = get_combined_path_iter(sig_infp_list)
     else:
         sig_path_iter = sigtar2path_iter(sig_infp_list)
@@ -520,7 +520,7 @@
             result = self.process_continued()
         else:
             # Below a StopIteration exception will just be passed upwards
-            result = self.process(self.input_iter.next())
+            result = self.process(next(self.input_iter))
         block_number = self.process_next_vol_number
         self.offset += len(result.data)
         self.previous_index = result.index

=== modified file 'duplicity/dup_time.py'
--- duplicity/dup_time.py	2015-02-01 17:37:37 +0000
+++ duplicity/dup_time.py	2017-02-11 23:01:59 +0000
@@ -27,8 +27,15 @@
 import types
 import re
 import calendar
+import sys
 from duplicity import globals
 
+# For type testing against both int and long types that works in python 2/3
+if sys.version_info < (3,):
+    integer_types = (int, types.LongType)
+else:
+    integer_types = (int,)
+
 
 class TimeException(Exception):
     pass
@@ -69,14 +76,14 @@
     """Sets the current time in curtime and curtimestr"""
     global curtime, curtimestr
     t = time_in_secs or int(time.time())
-    assert type(t) in (types.LongType, types.IntType)
+    assert type(t) in integer_types
     curtime, curtimestr = t, timetostring(t)
 
 
 def setprevtime(time_in_secs):
     """Sets the previous time in prevtime and prevtimestr"""
     global prevtime, prevtimestr
-    assert type(time_in_secs) in (types.LongType, types.IntType), prevtime
+    assert type(time_in_secs) in integer_types, prevtime
     prevtime, prevtimestr = time_in_secs, timetostring(time_in_secs)
 
 
@@ -181,7 +188,7 @@
     if seconds == 1:
         partlist.append("1 second")
     elif not partlist or seconds > 1:
-        if isinstance(seconds, (types.LongType, types.IntType)):
+        if isinstance(seconds, integer_types):
             partlist.append("%s seconds" % seconds)
         else:
             partlist.append("%.2f seconds" % seconds)

=== modified file 'duplicity/gpg.py'
--- duplicity/gpg.py	2017-01-16 15:29:58 +0000
+++ duplicity/gpg.py	2017-02-11 23:01:59 +0000
@@ -76,13 +76,13 @@
         self.sign_key = sign_key
         self.encrypt_secring = None
         if recipients is not None:
-            assert isinstance(recipients, types.ListType)  # must be list, not tuple
+            assert isinstance(recipients, list)  # must be list, not tuple
             self.recipients = recipients
         else:
             self.recipients = []
 
         if hidden_recipients is not None:
-            assert isinstance(hidden_recipients, types.ListType)  # must be list, not tuple
+            assert isinstance(hidden_recipients, list)  # must be list, not tuple
             self.hidden_recipients = hidden_recipients
         else:
             self.hidden_recipients = []
@@ -418,7 +418,7 @@
         if bytes_to_go < block_iter.get_read_size():
             break
         try:
-            new_block = block_iter.next()
+            new_block = next(block_iter)
         except StopIteration:
             at_end_of_blockiter = 1
             break

=== modified file 'duplicity/lazy.py'
--- duplicity/lazy.py	2016-01-29 11:43:58 +0000
+++ duplicity/lazy.py	2017-02-11 23:01:59 +0000
@@ -20,6 +20,7 @@
 # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 """Define some lazy data structures and functions acting on them"""
+from __future__ import print_function
 
 import os
 
@@ -76,21 +77,21 @@
         """
         for i1 in iter1:
             try:
-                i2 = iter2.next()
+                i2 = next(iter2)
             except StopIteration:
                 if verbose:
-                    print "End when i1 = %s" % (i1,)
+                    print("End when i1 = %s" % (i1,))
                 return None
             if not operator(i1, i2):
                 if verbose:
-                    print "%s not equal to %s" % (i1, i2)
+                    print("%s not equal to %s" % (i1, i2))
                 return None
         try:
-            i2 = iter2.next()
+            i2 = next(iter2)
         except StopIteration:
             return 1
         if verbose:
-            print "End when i2 = %s" % (i2,)
+            print("End when i2 = %s" % (i2,))
         return None
 
     @staticmethod
@@ -117,7 +118,7 @@
         i = 0
         while 1:
             try:
-                iter.next()
+                next(iter)
             except StopIteration:
                 return i
             i = i + 1
@@ -126,20 +127,20 @@
     def foldr(f, default, iter):  # @NoSelf
         """foldr the "fundamental list recursion operator"?"""
         try:
-            next = iter.next()
+            next_item = next(iter)
         except StopIteration:
             return default
-        return f(next, Iter.foldr(f, default, iter))
+        return f(next_item, Iter.foldr(f, default, iter))
 
     @staticmethod
     def foldl(f, default, iter):  # @NoSelf
         """the fundamental list iteration operator.."""
         while 1:
             try:
-                next = iter.next()
+                next_item = next(iter)
             except StopIteration:
                 return default
-            default = f(default, next)
+            default = f(default, next_item)
 
     @staticmethod
     def multiplex(iter, num_of_forks, final_func=None, closing_func=None):  # @NoSelf
@@ -174,7 +175,7 @@
             """Return the next element requested by fork_num"""
             if forkposition[fork_num] == -1:
                 try:
-                    buffer.insert(0, iter.next())
+                    buffer.insert(0, next(iter))
                 except StopIteration:
                     # call closing_func if necessary
                     if (forkposition == starting_forkposition and
@@ -222,7 +223,7 @@
         while(1):
             if self.a_leading_by >= 0:
                 # a is in front, add new element
-                elem = iter.next()  # exception will be passed
+                elem = next(iter)  # exception will be passed
                 buf.append(elem)
             else:
                 # b is in front, subtract an element
@@ -236,7 +237,7 @@
         while(1):
             if self.a_leading_by <= 0:
                 # b is in front, add new element
-                elem = iter.next()  # exception will be passed
+                elem = next(iter)  # exception will be passed
                 buf.append(elem)
             else:
                 # a is in front, subtract an element

=== modified file 'duplicity/patchdir.py'
--- duplicity/patchdir.py	2015-09-10 13:24:15 +0000
+++ duplicity/patchdir.py	2017-02-11 23:01:59 +0000
@@ -118,7 +118,7 @@
     # The next tar_info is stored in this one element list so
     # Multivol_Filelike below can update it.  Any StopIterations will
     # be passed upwards.
-    tarinfo_list = [tar_iter.next()]
+    tarinfo_list = [next(tar_iter)]
 
     while 1:
         # This section relevant when a multivol diff is last in tar
@@ -144,7 +144,7 @@
             else:
                 ropath.setfileobj(diff_tarfile.extractfile(tarinfo_list[0]))
         yield ropath
-        tarinfo_list[0] = tar_iter.next()
+        tarinfo_list[0] = next(tar_iter)
 
 
 def get_index_from_tarinfo(tarinfo):
@@ -234,7 +234,7 @@
         fp.close()
 
         try:
-            self.tarinfo_list[0] = self.tar_iter.next()
+            self.tarinfo_list[0] = next(self.tar_iter)
         except StopIteration:
             self.tarinfo_list[0] = None
             self.at_end = 1
@@ -330,7 +330,7 @@
         """Set tarfile from next file object, or raise StopIteration"""
         if self.current_fp:
             assert not self.current_fp.close()
-        self.current_fp = self.fileobj_iter.next()
+        self.current_fp = next(self.fileobj_iter)
         self.tarfile = util.make_tarfile("r", self.current_fp)
         self.tar_iter = iter(self.tarfile)
 
@@ -338,11 +338,11 @@
         if not self.tarfile:
             self.set_tarfile()
         try:
-            return self.tar_iter.next()
+            return next(self.tar_iter)
         except StopIteration:
             assert not self.tarfile.close()
             self.set_tarfile()
-            return self.tar_iter.next()
+            return next(self.tar_iter)
 
     def extractfile(self, tarinfo):
         """Return data associated with given tarinfo"""
@@ -375,7 +375,7 @@
         for i in range(iter_num):
             if not overflow[i] and elems[i] is None:
                 try:
-                    elems[i] = iter_list[i].next()
+                    elems[i] = next(iter_list[i])
                 except StopIteration:
                     overflow[i] = 1
                     elems[i] = None
@@ -442,7 +442,7 @@
     def __eq__(self, other):
         if isinstance(other, IndexedTuple):
             return self.index == other.index and self.data == other.data
-        elif isinstance(other, types.TupleType):
+        elif isinstance(other, tuple):
             return self.data == other
         else:
             return None

=== modified file 'duplicity/selection.py'
--- duplicity/selection.py	2017-02-05 01:14:33 +0000
+++ duplicity/selection.py	2017-02-11 23:01:59 +0000
@@ -176,7 +176,7 @@
 
         while diryield_stack:
             try:
-                subpath, val = diryield_stack[-1].next()
+                subpath, val = next(diryield_stack[-1])
             except StopIteration:
                 diryield_stack.pop()
                 if delayed_path_stack:

=== modified file 'setup.py'
--- setup.py	2016-08-24 12:12:14 +0000
+++ setup.py	2017-02-11 23:01:59 +0000
@@ -30,8 +30,8 @@
 
 version_string = "$version"
 
-if sys.version_info[:2] < (2, 6) or sys.version_info[:2] > (2, 7):
-    print("Sorry, duplicity requires version 2.6 or 2.7 of python.")
+if sys.version_info[:2] < (2, 7) or sys.version_info[:2] > (2, 7):
+    print("Sorry, duplicity requires version 2.7 of python.")
     sys.exit(1)
 
 incdir_list = libdir_list = None
@@ -203,4 +203,6 @@
                 'install': InstallCommand,
                 'sdist': SDistCommand,
                 'build_scripts': BSCommand},
+      classifiers=["Programming Language :: Python :: 2 :: Only",
+                   "Programming Language :: Python :: 2.7"]
       )

=== modified file 'testing/unit/test_collections.py'
--- testing/unit/test_collections.py	2015-02-01 17:37:37 +0000
+++ testing/unit/test_collections.py	2017-02-11 23:01:59 +0000
@@ -1,3 +1,4 @@
+from __future__ import print_function
 # -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
 #
 # Copyright 2002 Ben Escoto <ben@xxxxxxxxxxx>
@@ -100,8 +101,8 @@
         cs = collections.CollectionsStatus(None, globals.archive_dir)
         chains, orphaned, incomplete = cs.get_backup_chains(filename_list1)  # @UnusedVariable
         if len(chains) != 1 or len(orphaned) != 0:
-            print chains
-            print orphaned
+            print(chains)
+            print(orphaned)
             assert 0
 
         chain = chains[0]
@@ -145,7 +146,7 @@
         """Test chains and orphaned_paths values for two above tests"""
         if orphaned_paths:
             for op in orphaned_paths:
-                print op
+                print(op)
             assert 0
         assert len(chains) == 1, chains
         assert chains[0].end_time == 1029826800

=== modified file 'testing/unit/test_diffdir.py'
--- testing/unit/test_diffdir.py	2015-08-01 12:05:34 +0000
+++ testing/unit/test_diffdir.py	2017-02-11 23:01:59 +0000
@@ -1,3 +1,4 @@
+from __future__ import print_function
 # -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
 #
 # Copyright 2002 Ben Escoto <ben@xxxxxxxxxxx>
@@ -235,16 +236,16 @@
         result = diffdir.combine_path_iters([get_iter1(),
                                              get_iter2(),
                                              get_iter3()])
-        elem1 = result.next()
+        elem1 = next(result)
         assert elem1.index == () and elem1.other == 3, elem1
-        elem2 = result.next()
+        elem2 = next(result)
         assert elem2.index == (1,) and elem2.other is None, elem2
-        elem3 = result.next()
+        elem3 = next(result)
         assert elem3.index == (1, 5) and elem3.other is None
-        elem4 = result.next()
+        elem4 = next(result)
         assert elem4.index == (2,) and elem4.other == 1
         try:
-            elem5 = result.next()
+            elem5 = next(result)
         except StopIteration:
             pass
         else:
@@ -259,7 +260,7 @@
 
     for ti1 in tf1:
         try:
-            ti2 = tf2_iter.next()
+            ti2 = next(tf2_iter)
         except StopIteration:
             assert 0, ("Premature end to second tarfile, "
                        "ti1.name = %s" % ti1.name)
@@ -274,7 +275,7 @@
             fp2.close()
             assert buf1 == buf2
     try:
-        ti2 = tf2_iter.next()
+        ti2 = next(tf2_iter)
     except StopIteration:
         pass
     else:
@@ -287,29 +288,29 @@
 
 def tarinfo_eq(ti1, ti2):
     if ti1.name != ti2.name:
-        print "Name:", ti1.name, ti2.name
+        print("Name:", ti1.name, ti2.name)
         return 0
     if ti1.size != ti2.size:
-        print "Size:", ti1.size, ti2.size
+        print("Size:", ti1.size, ti2.size)
         return 0
     if ti1.mtime != ti2.mtime:
-        print "Mtime:", ti1.mtime, ti2.mtime
+        print("Mtime:", ti1.mtime, ti2.mtime)
         return 0
     if ti1.mode != ti2.mode:
-        print "Mode:", ti1.mode, ti2.mode
+        print("Mode:", ti1.mode, ti2.mode)
         return 0
     if ti1.type != ti2.type:
-        print "Type:", ti1.type, ti2.type
+        print("Type:", ti1.type, ti2.type)
         return 0
     if ti1.issym() or ti1.islnk():
         if ti1.linkname != ti2.linkname:
-            print "Linkname:", ti1.linkname, ti2.linkname
+            print("Linkname:", ti1.linkname, ti2.linkname)
             return 0
     if ti1.uid != ti2.uid or ti1.gid != ti2.gid:
-        print "IDs:", ti1.uid, ti2.uid, ti1.gid, ti2.gid
+        print("IDs:", ti1.uid, ti2.uid, ti1.gid, ti2.gid)
         return 0
     if ti1.uname != ti2.uname or ti1.gname != ti2.gname:
-        print "Owner names:", ti1.uname, ti2.uname, ti1.gname, ti2.gname
+        print("Owner names:", ti1.uname, ti2.uname, ti1.gname, ti2.gname)
         return 0
     return 1
 

=== modified file 'testing/unit/test_dup_time.py'
--- testing/unit/test_dup_time.py	2015-02-01 17:37:37 +0000
+++ testing/unit/test_dup_time.py	2017-02-11 23:01:59 +0000
@@ -26,12 +26,18 @@
 from duplicity import dup_time
 from . import UnitTestCase
 
+# For type testing against both int and long types that works in python 2/3
+if sys.version_info < (3,):
+    integer_types = (int, types.LongType)
+else:
+    integer_types = (int,)
+
 
 class TimeTest:
     def testConversion(self):
         """test timetostring and stringtotime"""
         dup_time.setcurtime()
-        assert type(dup_time.curtime) in (types.IntType, types.LongType)
+        assert type(dup_time.curtime) in integer_types
         assert isinstance(dup_time.curtimestr, types.StringType)
         assert (dup_time.cmp(int(dup_time.curtime), dup_time.curtimestr) == 0 or
                 dup_time.cmp(int(dup_time.curtime) + 1, dup_time.curtimestr) == 0)

=== modified file 'testing/unit/test_lazy.py'
--- testing/unit/test_lazy.py	2015-02-01 17:37:37 +0000
+++ testing/unit/test_lazy.py	2017-02-11 23:01:59 +0000
@@ -143,7 +143,7 @@
             if x == "hello":
                 raise NameError
         i = Iter.map(f, self.trueerror_maker())
-        i.next()
+        next(i)
         self.assertRaises(NameError, i.next)
 
     def testEmpty(self):
@@ -165,8 +165,8 @@
     def testShortcut(self):
         """Process iterators in order"""
         i = Iter.cat(self.typeerror_maker(), self.nameerror_maker())
-        i.next()
-        i.next()
+        next(i)
+        next(i)
         self.assertRaises(TypeError, i.next)
 
 


Follow ups