← Back to team overview

duplicity-team team mailing list archive

[Merge] lp:~aaron-whitehouse/duplicity/bug_1620085_exclude-if-present-locked-folder into lp:duplicity

 

Kenneth Loafman has proposed merging lp:~aaron-whitehouse/duplicity/bug_1620085_exclude-if-present-locked-folder into lp:duplicity.

Requested reviews:
  duplicity-team (duplicity-team)
Related bugs:
  Bug #1620085 in Duplicity: "--exclude-if-present gives OSError looking for tag in locked folders"
  https://bugs.launchpad.net/duplicity/+bug/1620085

For more details, see:
https://code.launchpad.net/~aaron-whitehouse/duplicity/bug_1620085_exclude-if-present-locked-folder/+merge/304924
-- 
Your team duplicity-team is requested to review the proposed merge of lp:~aaron-whitehouse/duplicity/bug_1620085_exclude-if-present-locked-folder into lp:duplicity.
=== modified file 'CHANGELOG'
--- CHANGELOG	2016-08-22 11:11:55 +0000
+++ CHANGELOG	2016-09-05 14:30:45 +0000
@@ -1,19 +1,21 @@
-New in v0.8.00 (2016/07/??)
----------------------------
-* Merged in lp:~aaron-whitehouse/duplicity/remove-python26
-  - Remove Python 2.6 support references and tests.
-* Fixed bug #1600692 with patch from Wolfgang Rohdewald
-  - Allow symlink to have optional trailing slash during verify.
-* Merged in lp:~aaron-whitehouse/duplicity/07-fix_deja_dup_error_on_locked_files
-  - Revert log.Error to log.Warn, as it was prior to the merge in rev 1224,
-    as this was affecting other applications (e.g. deja dup; Bug #1605939).
-* Merged in lp:~mwilck/duplicity/duplicity
+New in v0.7.11 (2016/09/??)
+---------------------------
+* Fixed bugs #815510 and #1615480
+  - Changed default --volsize to 200MB
+* Merged in lp:~mstoll-de/duplicity/duplicity
+  - Backblaze announced a new domain for the b2 api
+
+New in v0.7.10 (2016/08/20)
+---------------------------
+* Merged in lp:~mwilck/duplicity/0.7-series
   - Speedup of path_matches_glob() by about 8x.  See
-    https://code.launchpad.net/~mwilck/duplicity/duplicity/+merge/301268
+    https://code.launchpad.net/~mwilck/duplicity/0.7-series/+merge/301332
     for more details.
+* Remove -w from setsid in functional tests.
 * Fixed conflict in merge from Martin Wilck and applied
   - https://code.launchpad.net/~mwilck/duplicity/0.7-series/+merge/301492
   - merge fixes setsid usage in functional testing.
+<<<<<<< TREE
 * Fixed bug #1612472 with patch from David Cuthbert
   - Restore from S3 fails with --with-prefix-archive if prefix includes '/'
 * Merged in lp:~arashad.ahamad/duplicity/duplicity_latest
@@ -24,6 +26,24 @@
   - Changed default --volsize to 200MB
 * Merged in lp:~mstoll-de/duplicity/duplicity
   - Backblaze announced a new domain for the b2 api
+=======
+* Fixed bug #1612472 with patch from David Cuthbert
+  - Restore from S3 fails with --with-prefix-archive if prefix includes '/'
+* Merged in lp:~arashad.ahamad/duplicity/duplicity_latest
+  - Changes for connecting to IBM Bluemix ObjectStorage.  See man page.
+* Merged in lp:~fenisilius/duplicity/acd_init_mkdir
+  - Allow duplicity to create remote folder
+
+
+New in v0.7.09 (2016/07/24)
+---------------------------
+* Fixed bug #1600692 with patch from Wolfgang Rohdewald
+  - Allow symlink to have optional trailing slash during verify.
+* Merged in lp:~aaron-whitehouse/duplicity/07-fix_deja_dup_error_on_locked_files
+  - Revert log.Error to log.Warn, as it was prior to the merge in rev 1224,
+    as this was affecting other applications (e.g. deja dup; Bug #1605939).
+* Merged in lp:~duplicity-team/duplicity/po-updates
+>>>>>>> MERGE-SOURCE
 
 
 New in v0.7.08 (2016/07/02)
@@ -81,6 +101,9 @@
 * Fixed bug #1570293 duplicity is very slow due to excessive fsync
   - removed flush() after write.
   - revert to previous version
+* Merged in lp:~aaron-whitehouse/duplicity/07-fix_deja_dup_error_on_locked_files
+  - Revert log.Error to log.Warn, as it was prior to the merge in rev 1224,
+    as this was affecting other applications (e.g. deja dup; Bug #1605939).
 
 
 New in v0.7.07 (2016/04/10)
@@ -333,9 +356,6 @@
 * Merged in lp:~ed.so/duplicity/gpg.binary
   - new parameter --gpg-binary allows user to point to a different gpg binary,
     not necessarily in path
-* Merged in lp:~ed.so/duplicity/gpg.binary
-  - new parameter --gpg-binary allows user to point to a different gpg binary,
-    not necessarily in path
 * Merged in lp:~aaron-whitehouse/duplicity/fix_POTFILES.in_and_run-tests
   - Fixed two filename references in po/POTFILES.in, a mistake which crept in in
     rev 1093 and caused testing/run-tests to fail with "IndexError: list index

=== modified file 'Changelog.GNU'
--- Changelog.GNU	2016-08-22 11:11:55 +0000
+++ Changelog.GNU	2016-09-05 14:30:45 +0000
@@ -1,22 +1,48 @@
-2016-08-22  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
-
-    * Fixed bugs #815510 and #1615480
-      - Changed default --volsize to 200MB
-    * Merged in lp:~mstoll-de/duplicity/duplicity
-      - Backblaze announced a new domain for the b2 api
-
-2016-08-18  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
-
-    * Merged in lp:~fenisilius/duplicity/acd_init_mkdir
-      - Allow duplicity to create remote folder
-
-2016-08-12  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
-
-    * Fixed bug #1612472 with patch from David Cuthbert
-      - Restore from S3 fails with --with-prefix-archive if prefix includes '/'
-    * Merged in lp:~arashad.ahamad/duplicity/duplicity_latest
-      - Changes for connecting to IBM Bluemix ObjectStorage.  See man page.
-
+<<<<<<< TREE
+2016-08-22  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
+
+    * Fixed bugs #815510 and #1615480
+      - Changed default --volsize to 200MB
+    * Merged in lp:~mstoll-de/duplicity/duplicity
+      - Backblaze announced a new domain for the b2 api
+
+2016-08-18  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
+
+    * Merged in lp:~fenisilius/duplicity/acd_init_mkdir
+      - Allow duplicity to create remote folder
+
+2016-08-12  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
+
+    * Fixed bug #1612472 with patch from David Cuthbert
+      - Restore from S3 fails with --with-prefix-archive if prefix includes '/'
+    * Merged in lp:~arashad.ahamad/duplicity/duplicity_latest
+      - Changes for connecting to IBM Bluemix ObjectStorage.  See man page.
+
+=======
+2016-08-22  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
+
+    * Fixed bugs #815510 and #1615480
+      - Changed default --volsize to 200MB
+    * Merged in lp:~mstoll-de/duplicity/duplicity
+      - Backblaze announced a new domain for the b2 api
+
+2016-08-20  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
+
+    * Prep for 0.7.10
+
+2016-08-18  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
+
+    * Merged in lp:~fenisilius/duplicity/acd_init_mkdir
+      - Allow duplicity to create remote folder
+
+2016-08-12  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
+
+    * Fixed bug #1612472 with patch from David Cuthbert
+      - Restore from S3 fails with --with-prefix-archive if prefix includes '/'
+    * Merged in lp:~arashad.ahamad/duplicity/duplicity_latest
+      - Changes for connecting to IBM Bluemix ObjectStorage.  See man page.
+
+>>>>>>> MERGE-SOURCE
 2016-07-31  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
 
     * Fixed conflict in merge from Martin Wilck and applied
@@ -25,27 +51,24 @@
 
 2016-07-28  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
 
-    * Merged in lp:~mwilck/duplicity/duplicity
+    * Merged in lp:~mwilck/duplicity/0.7-series
       - Speedup of path_matches_glob() by about 8x.  See
-        https://code.launchpad.net/~mwilck/duplicity/duplicity/+merge/301268
+        https://code.launchpad.net/~mwilck/duplicity/0.7-series/+merge/301332
         for more details.
+    * Remove -w from setsid in functional tests.
 
 2016-07-24  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
 
     * Merged in lp:~aaron-whitehouse/duplicity/07-fix_deja_dup_error_on_locked_files
       - Revert log.Error to log.Warn, as it was prior to the merge in rev 1224,
         as this was affecting other applications (e.g. deja dup; Bug #1605939).
+    * Prep for 0.7.09
 
 2016-07-20  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
 
     * Fixed bug #1600692 with patch from Wolfgang Rohdewald
       - Allow symlink to have optional trailing slash during verify.
 
-2016-07-03  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
-
-    * Merged in lp:~aaron-whitehouse/duplicity/remove-python26
-      - Remove Python 2.6 support references and tests.
-
 2016-07-02  Kenneth Loafman  <kenneth@xxxxxxxxxxx>
 
     * Merged in lp:~aaron-whitehouse/duplicity/PEP8_W503_fixes

=== modified file 'README'
--- README	2016-07-02 17:12:58 +0000
+++ README	2016-09-05 14:30:45 +0000
@@ -19,7 +19,7 @@
 
 REQUIREMENTS:
 
- * Python v2.7 or later
+ * Python v2.6 or later
  * librsync v0.9.6 or later
  * GnuPG v1.x for encryption
  * python-lockfile v0.9 or later for concurrency locking

=== modified file 'README-REPO'
--- README-REPO	2016-07-02 17:12:58 +0000
+++ README-REPO	2016-09-05 14:30:45 +0000
@@ -47,18 +47,35 @@
 Please run all tests on your branch (run-tests) before proposing a merge, to
 ensure that all tests pass. The decorator @unittest.expectedFailure can be used
 to commit a known-failing test case without breaking the test suite, for
-example to exhibit the behaviour in a bug report before it has been fixed.
+example to exhibit the behaviour in a bug report before it has been fixed:
+
+if sys.version_info < (2, 7):
+    import unittest2 as unittest
+else:
+    import unittest
+
+
+class TestClass(unittest.TestCase):
+    """Test class to show expectedFailure"""
+
+    @unittest.expectedFailure
+    def test_expected_failure(self):
+        """Test behaviour of expectedFailure"""
+        self.assertEqual(1, 2)
 
 -----------------------------------------
 Testing against multiple Python versions:
 -----------------------------------------
 
-Duplicity uses tox to make it easy to test your code against multiple
-environments. Running tests using the commands above will automatically test
-code against different supported environments, including the versions of
-dependencies used by the Launchpad build system.
-
+Duplicity currently supports Python versions v2.6 or later. Duplicity uses tox
+to make it easy to test your code against multiple Python versions. Running
+tests using the commands above will automatically test code against both
+Python v2.6 and v2.7, if you have both installed on your system. It will also
+test against the versions of dependencies used by the Launchpad build system.
 You can test against a single environment, e.g.
-tox -e py27
+tox -e py26
 for example if you are working on fixing a bug, but please do a full run-tests
 before submitting a merge request.
+
+For instructions on installing Python v2.6 on newer versions of Ubuntu, see
+https://launchpad.net/~fkrull/+archive/ubuntu/deadsnakes

=== modified file 'duplicity/selection.py'
--- duplicity/selection.py	2016-07-27 11:56:07 +0000
+++ duplicity/selection.py	2016-09-05 14:30:45 +0000
@@ -447,10 +447,24 @@
 
         def exclude_sel_func(path):
             # do not follow symbolic links when checking for file existence!
-            if path.isdir() and path.append(filename).exists():
-                return 0
-            else:
-                return None
+            if path.isdir():
+                # First check path is read accessible
+                if not (os.access(path.name, os.R_OK)):
+                    # Path is not read accessible
+                    # ToDo: Ideally this error would only show if the folder
+                    # was ultimately included by the full set of selection
+                    # functions. Currently this will give an error for any
+                    # locked directory within the folder being backed up.
+                    log.Warn(_(
+                        "Error accessing possibly locked file %s") % util.ufn(
+                        path.name),
+                        log.WarningCode.cannot_read, util.escape(path.name))
+                    if diffdir.stats:
+                        diffdir.stats.Errors += 1
+                elif path.append(filename).exists():
+                    return 0
+                else:
+                    return None
 
         if include == 0:
             sel_func = exclude_sel_func

=== modified file 'po/duplicity.pot'
--- po/duplicity.pot	2016-08-18 16:06:51 +0000
+++ po/duplicity.pot	2016-09-05 14:30:45 +0000
@@ -8,7 +8,11 @@
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: Kenneth Loafman <kenneth@xxxxxxxxxxx>\n"
+<<<<<<< TREE
 "POT-Creation-Date: 2016-08-18 10:50-0500\n"
+=======
+"POT-Creation-Date: 2016-08-20 14:02-0500\n"
+>>>>>>> MERGE-SOURCE
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@xxxxxx>\n"

=== modified file 'testing/__init__.py'
--- testing/__init__.py	2016-07-02 19:39:05 +0000
+++ testing/__init__.py	2016-09-05 14:30:45 +0000
@@ -21,7 +21,11 @@
 import os
 import sys
 import time
-import unittest
+
+if sys.version_info < (2, 7):
+    import unittest2 as unittest
+else:
+    import unittest
 
 from duplicity import backend
 from duplicity import globals

=== modified file 'testing/functional/test_selection.py'
--- testing/functional/test_selection.py	2015-07-31 08:22:31 +0000
+++ testing/functional/test_selection.py	2016-09-05 14:30:45 +0000
@@ -837,6 +837,57 @@
         self.restore_and_check()
 
 
+class TestTrailingSlash2(IncludeExcludeFunctionalTest):
+    """ This tests the behaviour of globbing strings with a trailing slash"""
+    # See Bug #1479545 (https://bugs.launchpad.net/duplicity/+bug/1479545)
+
+    def test_no_trailing_slash(self):
+        """ Test that including 1.py works as expected"""
+        self.backup("full", "testfiles/select2",
+                    options=["--include", "testfiles/select2/1.py",
+                             "--exclude", "**"])
+        self.restore()
+        restore_dir = 'testfiles/restore_out'
+        restored = self.directory_tree_to_list_of_lists(restore_dir)
+        self.assertEqual(restored, [['1.py']])
+
+    def test_trailing_slash(self):
+        """ Test that globs with a trailing slash only match directories"""
+        # Regression test for Bug #1479545
+        # (https://bugs.launchpad.net/duplicity/+bug/1479545)
+        self.backup("full", "testfiles/select2",
+                    options=["--include", "testfiles/select2/1.py/",
+                             "--exclude", "**"])
+        self.restore()
+        restore_dir = 'testfiles/restore_out'
+        restored = self.directory_tree_to_list_of_lists(restore_dir)
+        self.assertEqual(restored, [])
+
+    def test_include_files_not_subdirectories(self):
+        """ Test that a trailing slash glob followed by a * glob only matches
+        files and not subdirectories"""
+        self.backup("full", "testfiles/select2",
+                    options=["--exclude", "testfiles/select2/*/",
+                             "--include", "testfiles/select2/*",
+                             "--exclude", "**"])
+        self.restore()
+        restore_dir = 'testfiles/restore_out'
+        restored = self.directory_tree_to_list_of_lists(restore_dir)
+        self.assertEqual(restored, [['1.doc', '1.py']])
+
+    def test_include_subdirectories_not_files(self):
+        """ Test that a trailing slash glob only matches directories"""
+        self.backup("full", "testfiles/select2",
+                    options=["--include", "testfiles/select2/1/1sub1/**/",
+                             "--exclude", "testfiles/select2/1/1sub1/**",
+                             "--exclude", "**"])
+        self.restore()
+        restore_dir = 'testfiles/restore_out'
+        restored = self.directory_tree_to_list_of_lists(restore_dir)
+        self.assertEqual(restored, [['1'], ['1sub1'],
+                                    ['1sub1sub1', '1sub1sub2', '1sub1sub3']])
+
+
 class TestGlobbingReplacement(IncludeExcludeFunctionalTest):
     """ This tests the behaviour of the extended shell globbing pattern replacement functions."""
     # See the manual for a description of behaviours, but in summary:
@@ -875,55 +926,85 @@
         self.assertEqual(restored, self.expected_restored_tree)
 
 
-class TestTrailingSlash(IncludeExcludeFunctionalTest):
-    """ This tests the behaviour of globbing strings with a trailing slash"""
-    # See Bug #1479545 (https://bugs.launchpad.net/duplicity/+bug/1479545)
-
-    def test_no_trailing_slash(self):
-        """ Test that including 1.py works as expected"""
-        self.backup("full", "testfiles/select2",
-                    options=["--include", "testfiles/select2/1.py",
-                             "--exclude", "**"])
-        self.restore()
-        restore_dir = 'testfiles/restore_out'
-        restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['1.py']])
-
-    def test_trailing_slash(self):
-        """ Test that globs with a trailing slash only match directories"""
-        # ToDo: Bug #1479545
-        # (https://bugs.launchpad.net/duplicity/+bug/1479545)
-        self.backup("full", "testfiles/select2",
-                    options=["--include", "testfiles/select2/1.py/",
-                             "--exclude", "**"])
-        self.restore()
-        restore_dir = 'testfiles/restore_out'
-        restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [])
-
-    def test_include_files_not_subdirectories(self):
-        """ Test that a trailing slash glob followed by a * glob only matches
-        files and not subdirectories"""
-        self.backup("full", "testfiles/select2",
-                    options=["--exclude", "testfiles/select2/*/",
-                             "--include", "testfiles/select2/*",
-                             "--exclude", "**"])
-        self.restore()
-        restore_dir = 'testfiles/restore_out'
-        restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['1.doc', '1.py']])
-
-    def test_include_subdirectories_not_files(self):
-        """ Test that a trailing slash glob only matches directories"""
-        self.backup("full", "testfiles/select2",
-                    options=["--include", "testfiles/select2/1/1sub1/**/",
-                             "--exclude", "testfiles/select2/1/1sub1/**",
-                             "--exclude", "**"])
-        self.restore()
-        restore_dir = 'testfiles/restore_out'
-        restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['1'], ['1sub1'],
-                                     ['1sub1sub1', '1sub1sub2', '1sub1sub3']])
+class TestExcludeIfPresent(IncludeExcludeFunctionalTest):
+    """ This tests the behaviour of duplicity's --exclude-if-present option"""
+
+    def test_exclude_if_present_baseline(self):
+        """ Test that duplicity normally backs up files"""
+        with open("testfiles/select2/1/1sub1/1sub1sub1/.nobackup", "w") as tag:
+            tag.write("Files in this folder should not be backed up.")
+        self.backup("full", "testfiles/select2/1/1sub1",
+                    options=["--include", "testfiles/select2/1/1sub1/1sub1sub1/*",
+                             "--exclude", "**"])
+        self.restore()
+        restore_dir = 'testfiles/restore_out'
+        restored = self.directory_tree_to_list_of_lists(restore_dir)
+        self.assertEqual(restored, [['1sub1sub1'],
+                                    ['.nobackup', '1sub1sub1_file.txt']])
+
+    def test_exclude_if_present_excludes(self):
+        """ Test that duplicity excludes files with relevant tag"""
+        with open("testfiles/select2/1/1sub1/1sub1sub1/.nobackup", "w") as tag:
+            tag.write("Files in this folder should not be backed up.")
+        self.backup("full", "testfiles/select2/1/1sub1",
+                    options=["--exclude-if-present", ".nobackup",
+                             "--include", "testfiles/select2/1/1sub1/1sub1sub1/*",
+                             "--exclude", "**"])
+        self.restore()
+        restore_dir = 'testfiles/restore_out'
+        restored = self.directory_tree_to_list_of_lists(restore_dir)
+        self.assertEqual(restored, [])
+
+    def test_exclude_if_present_excludes_2(self):
+        """ Test that duplicity excludes files with relevant tag"""
+        with open("testfiles/select2/1/1sub1/1sub1sub1/EXCLUDE.tag", "w") as tag:
+            tag.write("Files in this folder should also not be backed up.")
+        self.backup("full", "testfiles/select2/1/1sub1",
+                    options=["--exclude-if-present", "EXCLUDE.tag",
+                             "--include", "testfiles/select2/1/1sub1/1sub1sub1/*",
+                             "--exclude", "**"])
+        self.restore()
+        restore_dir = 'testfiles/restore_out'
+        restored = self.directory_tree_to_list_of_lists(restore_dir)
+        self.assertEqual(restored, [])
+
+
+class TestLockedFoldersNoError(IncludeExcludeFunctionalTest):
+    """ This tests that inaccessible folders do not cause an error"""
+
+    def test_locked_baseline(self):
+        """ Test no error if locked in path but excluded"""
+        folder_to_lock = "testfiles/select2/1/1sub1/1sub1sub3"
+        initial_mode = os.stat(folder_to_lock).st_mode
+        os.chmod(folder_to_lock, 0o0000)
+        self.backup("full", "testfiles/select2/1/1sub1",
+                    options=["--include", "testfiles/select2/1/1sub1/1sub1sub1/*",
+                             "--exclude", "**"])
+        os.chmod(folder_to_lock, initial_mode)
+        self.restore()
+        restore_dir = 'testfiles/restore_out'
+        restored = self.directory_tree_to_list_of_lists(restore_dir)
+        self.assertEqual(restored, [['1sub1sub1'],
+                                    ['1sub1sub1_file.txt']])
+
+    def test_locked_excl_if_present(self):
+        """ Test no error if excluded locked with --exclude-if-present"""
+        # Regression test for Bug #1620085
+        # https://bugs.launchpad.net/duplicity/+bug/1620085
+        folder_to_lock = "testfiles/select2/1/1sub1/1sub1sub3"
+        initial_mode = os.stat(folder_to_lock).st_mode
+        os.chmod(folder_to_lock, 0o0000)
+        self.backup("full", "testfiles/select2/1/1sub1",
+                    options=["--exclude-if-present", "EXCLUDE.tag",
+                             "--include", "testfiles/select2/1/1sub1/1sub1sub1/*",
+                             "--exclude", "**"])
+        os.chmod(folder_to_lock, initial_mode)
+        self.restore()
+        restore_dir = 'testfiles/restore_out'
+        restored = self.directory_tree_to_list_of_lists(restore_dir)
+        self.assertEqual(restored, [['1sub1sub1'],
+                                    ['1sub1sub1_file.txt']])
+
 
 if __name__ == "__main__":
     unittest.main()

=== added file 'testing/gnupg/gpg.conf'
--- testing/gnupg/gpg.conf	1970-01-01 00:00:00 +0000
+++ testing/gnupg/gpg.conf	2016-09-05 14:30:45 +0000
@@ -0,0 +1,9 @@
+# gpg2 doesn't try all secrets by default, so add this option
+# Otherwise the tests with hidden encryption key will fail
+try-all-secrets
+
+# gpg2 2.1.13 has a bug that prevents the line above from working
+# (https://bugs.gnupg.org/gnupg/issue1985)
+# Uncomment the line below if you have gnupg2 2.1.13
+# (but that line will break gpg 1.x, so we can't use it by default)
+#try-secret-key 96B629431B77DC52B1917B40839E6A2856538CCF

=== removed file 'testing/gnupg/gpg.conf'
--- testing/gnupg/gpg.conf	2016-08-01 14:57:22 +0000
+++ testing/gnupg/gpg.conf	1970-01-01 00:00:00 +0000
@@ -1,9 +0,0 @@
-# gpg2 doesn't try all secrets by default, so add this option
-# Otherwise the tests with hidden encryption key will fail
-try-all-secrets
-
-# gpg2 2.1.13 has a bug that prevents the line above from working
-# (https://bugs.gnupg.org/gnupg/issue1985)
-# Uncomment the line below if you have gnupg2 2.1.13
-# (but that line will break gpg 1.x, so we can't use it by default)
-#try-secret-key 96B629431B77DC52B1917B40839E6A2856538CCF

=== modified file 'testing/test_code.py'
--- testing/test_code.py	2016-07-02 19:39:05 +0000
+++ testing/test_code.py	2016-09-05 14:30:45 +0000
@@ -22,7 +22,10 @@
 import sys
 import subprocess
 
-import unittest
+if sys.version_info < (2, 7):
+    import unittest2 as unittest  # @UnresolvedImport @UnusedImport
+else:
+    import unittest  # @Reimport
 
 from . import _top_dir, DuplicityTestCase  # @IgnorePep8
 

=== modified file 'tox.ini'
--- tox.ini	2016-07-02 19:33:34 +0000
+++ tox.ini	2016-09-05 14:30:45 +0000
@@ -1,5 +1,14 @@
 [tox]
-envlist=py27,lpbuildd-precise
+envlist=py26,py27,lpbuildd-precise
+
+[testenv:py26]
+setenv=
+    RUN_CODE_TESTS=0
+deps=
+    mock==0.7.2
+    pexpect==2.4
+    ptyprocess==0.4
+    unittest2
 
 [testenv:py27]
 setenv=
@@ -20,5 +29,5 @@
     {envpython} {toxinidir}/setup.py test {posargs}
 
 [pep8]
-ignore=E402,E731
+ignore=E402,E501,E731,W503
 max-line-length=120


Follow ups