← Back to team overview

duplicity-team team mailing list archive

[Merge] lp:~aaron-whitehouse/duplicity/08-unicode into lp:duplicity

 

Aaron Whitehouse has proposed merging lp:~aaron-whitehouse/duplicity/08-unicode into lp:duplicity.

Commit message:
Many strings have been changed to unicode for better handling of international characters and to make the transition to Python 3 significantly easier, primarily on the 'local' side of duplicity (selection, commandline arguments etc) rather than any backends etc.

Requested reviews:
  duplicity-team (duplicity-team)

For more details, see:
https://code.launchpad.net/~aaron-whitehouse/duplicity/08-unicode/+merge/334622

Many strings have been changed to unicode for better handling of international characters and to make the transition to Python 3 significantly easier.

In order to merge the changes back into trunk as soon as possible, this branch focuses on just the strings in the 'local' side of duplicity, i.e. those involved in interpreting the selection functions from the commandline arguments or include/exclude lists and reading each file from the local filesystem to compare to these selection functions.

Note:
* This branch introduces Path.uc_name with the filename in unicode, in addition to Path.name with the filename in bytes (i.e. each Path will have a .name and .uc_name). These are both created for each Path object and code throughout duplicity should move to using .uc_name where it needs the unicode name and .name where it needs the bytes name, rather than converting. Valid filenames on the disk in Linux can be invalid unicode, so for Python 2 support it is important that we keep the original bytes .name and use that rather than converting the unicode version. That said, for all internal purposes (e.g. string comparison) we should be using the unicode version. From Python 3.2, it looks as though this has been solved properly and os.fsencode/os.fsencode uses 'surrogateescape' characters (https://www.python.org/dev/peps/pep-0383/ ) to ensure you can always recreate the original bytes filename from the internal unicode representation. As I understand it, that should allow the more standard "decode/encode at the boundaries, use unicode everywhere internally" approach.
* Path.name may be renamed Path.b_name in the future: http://lists.nongnu.org/archive/html/duplicity-talk/2017-11/msg00017.html
-- 
Your team duplicity-team is requested to review the proposed merge of lp:~aaron-whitehouse/duplicity/08-unicode into lp:duplicity.
=== modified file 'bin/duplicity.1'
--- bin/duplicity.1	2017-09-06 14:57:00 +0000
+++ bin/duplicity.1	2017-12-01 23:01:42 +0000
@@ -1498,11 +1498,11 @@
 and
 .BI --exclude-filelist ,
 options also introduce file selection conditions.  They direct
-duplicity to read in a file, each line of which is a file
-specification, and to include or exclude the matching files.  Lines
-are separated by newlines or nulls, depending on whether the
---null-separator switch was given.  Each line in the filelist will be
-interpreted as a globbing pattern the way
+duplicity to read in a text file (either ASCII or UTF-8), each line
+of which is a file specification, and to include or exclude the
+matching files.  Lines are separated by newlines or nulls, depending
+on whether the --null-separator switch was given.  Each line in the
+filelist will be interpreted as a globbing pattern the way
 .BI --include
 and
 .BI --exclude

=== modified file 'debian/control'
--- debian/control	2017-10-12 19:42:50 +0000
+++ debian/control	2017-12-01 23:01:42 +0000
@@ -11,6 +11,7 @@
                pylint,
                python-dev,
                python-fasteners,
+               python-future,
                python-mock,
                python-pexpect,
                python-setuptools,
@@ -28,6 +29,7 @@
          ${shlibs:Depends},
          gnupg,
          python-fasteners,
+         python-future,
          python-pexpect,
 Suggests: ncftp,
           python-boto,

=== modified file 'duplicity/backend.py'
--- duplicity/backend.py	2017-11-23 13:02:23 +0000
+++ duplicity/backend.py	2017-12-01 23:01:42 +0000
@@ -383,7 +383,7 @@
                     if at_end and fatal:
                         def make_filename(f):
                             if isinstance(f, path.ROPath):
-                                return util.escape(f.name)
+                                return util.escape(f.uc_name)
                             else:
                                 return util.escape(f)
                         extra = ' '.join([operation] + [make_filename(x) for x in args if x])

=== modified file 'duplicity/commandline.py'
--- duplicity/commandline.py	2017-09-01 11:46:59 +0000
+++ duplicity/commandline.py	2017-12-01 23:01:42 +0000
@@ -30,6 +30,7 @@
 import re
 import sys
 import socket
+import io
 
 try:
     from hashlib import md5
@@ -251,14 +252,13 @@
         globals.time_separator = sep
         old_fn_deprecation(opt)
 
-    def add_selection(o, s, v, p):
-        select_opts.append((s, v))
+    def add_selection(o, option, additional_arg, p):
+        select_opts.append((util.fsdecode(option), util.fsdecode(additional_arg)))
 
-    def add_filelist(o, s, v, p):
-        filename = v
-        select_opts.append((s, filename))
+    def add_filelist(o, s, filename, p):
+        select_opts.append((util.fsdecode(s), util.fsdecode(filename)))
         try:
-            select_files.append(open(filename, "r"))
+            select_files.append(io.open(filename, "rt", encoding="UTF-8"))
         except IOError:
             log.FatalError(_("Error opening file %s") % filename,
                            log.ErrorCode.cant_open_filelist)

=== modified file 'duplicity/globals.py'
--- duplicity/globals.py	2017-11-23 13:02:23 +0000
+++ duplicity/globals.py	2017-12-01 23:01:42 +0000
@@ -321,4 +321,4 @@
 # 'utf-8' or some other sane encoding, but will sometimes fail and return
 # either 'ascii' or None.  Both are bogus, so default to 'utf-8' if it does.
 fsencoding = sys.getfilesystemencoding()
-fsencoding = fsencoding if fsencoding not in ['ascii', None] else 'utf-8'
+fsencoding = fsencoding if fsencoding not in ['ascii', 'ANSI_X3.4-1968', None] else 'utf-8'

=== modified file 'duplicity/globmatch.py'
--- duplicity/globmatch.py	2017-07-11 14:55:38 +0000
+++ duplicity/globmatch.py	2017-12-01 23:01:42 +0000
@@ -19,9 +19,15 @@
 # You should have received a copy of the GNU General Public License
 # along with duplicity; if not, write to the Free Software Foundation,
 # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# All functions in this module only accept unicode. Any byte strings should
+# be converted to unicode before sending them into this.
 
 import re
 
+from builtins import map
+from builtins import range
+
 
 class GlobbingError(Exception):
     """Something has gone wrong when parsing a glob string"""
@@ -36,16 +42,16 @@
 def _glob_get_prefix_regexs(glob_str):
     """Return list of regexps equivalent to prefixes of glob_str"""
     # Internal. Used by glob_get_normal_sf.
-    glob_parts = glob_str.split("/")
-    if "" in glob_parts[1:-1]:
+    glob_parts = glob_str.split(u"/")
+    if u"" in glob_parts[1:-1]:
         # "" OK if comes first or last, as in /foo/
-        raise GlobbingError("Consecutive '/'s found in globbing string " +
+        raise GlobbingError(u"Consecutive '/'s found in globbing string " +
                             glob_str)
 
-    prefixes = ["/".join(glob_parts[:i + 1]) for i in range(len(glob_parts))]
+    prefixes = [u"/".join(glob_parts[:i + 1]) for i in range(len(glob_parts))]
     # we must make exception for root "/", only dir to end in slash
-    if prefixes[0] == "":
-        prefixes[0] = "/"
+    if prefixes[0] == u"":
+        prefixes[0] = u"/"
     return list(map(glob_to_regex, prefixes))
 
 
@@ -62,12 +68,13 @@
 
     Note: including a folder implicitly includes everything within it.
     """
+    assert isinstance(glob_str, unicode)
     glob_ends_w_slash = False
 
-    if glob_str == "/":
+    if glob_str == u"/":
         # If the glob string is '/', it implicitly includes everything
-        glob_str = "/**"
-    elif glob_str[-1] == "/":
+        glob_str = u"/**"
+    elif glob_str[-1] == u"/":
         glob_ends_w_slash = True
         # Remove trailing / from directory name (unless that is the entire
         # string)
@@ -87,39 +94,39 @@
     # Note that the "/" at the end of the regex means that it will match
     # if the glob matches a parent folders of path, i.e. including a folder
     # includes everything within it.
-    glob_comp_re = re_comp("^%s($|/)" % glob_to_regex(glob_str))
+    glob_comp_re = re_comp(u"^%s($|/)" % glob_to_regex(glob_str))
 
     if glob_ends_w_slash:
         # Creates a version of glob_comp_re that does not match folder contents
         # This can be used later to check that an exact match is actually a
         # folder, rather than a file.
-        glob_comp_re_exact = re_comp("^%s($)" % glob_to_regex(glob_str))
+        glob_comp_re_exact = re_comp(u"^%s($)" % glob_to_regex(glob_str))
 
-    if glob_str.find("**") != -1:
+    if glob_str.find(u"**") != -1:
         # glob_str has a ** in it
-        glob_str = glob_str[:glob_str.find("**") + 2]  # truncate after **
+        glob_str = glob_str[:glob_str.find(u"**") + 2]  # truncate after **
 
     # Below regex is translates to:
     # ^ string must be at the beginning of path
     # the regexs corresponding to the parent directories of glob_str
     # $ nothing must follow except for the end of the string or newline
-    scan_comp_re = re_comp("^(%s)$" %
-                           "|".join(_glob_get_prefix_regexs(glob_str)))
+    scan_comp_re = re_comp(u"^(%s)$" %
+                           u"|".join(_glob_get_prefix_regexs(glob_str)))
 
     def test_fn(path):
-        assert not path.name[-1] == "/" or path.name == "/", \
-            "path.name should never end in '/' during normal operation for " \
-            "normal paths (except '/' alone)\n" \
-            "path.name here is " + path.name + " and glob is " + glob_str
+        assert not path.uc_name[-1] == u"/" or path.uc_name == u"/", \
+            u"path.name should never end in '/' during normal operation for " \
+            u"normal paths (except '/' alone)\n" \
+            u"path.name here is " + path.uc_name + u" and glob is " + glob_str
 
-        if glob_comp_re.match(path.name):
+        if glob_comp_re.match(path.uc_name):
             # Path matches glob, or is contained within a matching folder
             if not glob_ends_w_slash:
                 return include
             else:
                 # Glob ended with a /, so we need to check any exact match was
                 # a folder
-                if glob_comp_re_exact.match(path.name):
+                if glob_comp_re_exact.match(path.uc_name):
                     # Not an included file/folder, so must be a folder to match
                     if path.isdir():
                         # Is a directory, so all is well
@@ -131,7 +138,7 @@
                     # An included file/folder, so normal approach is fine
                     return include
 
-        elif include == 1 and scan_comp_re.match(path.name):
+        elif include == 1 and scan_comp_re.match(path.uc_name):
             return 2
         else:
             return None
@@ -151,34 +158,37 @@
 
     """
     # Internal. Used by glob_get_normal_sf, glob_get_prefix_res and unit tests.
+
+    assert isinstance(pat, unicode)
+
     i, n, res = 0, len(pat), ''
     while i < n:
         c, s = pat[i], pat[i:i + 2]
         i = i + 1
-        if s == '**':
-            res = res + '.*'
+        if s == u'**':
+            res = res + u'.*'
             i = i + 1
-        elif c == '*':
-            res = res + '[^/]*'
-        elif c == '?':
-            res = res + '[^/]'
-        elif c == '[':
+        elif c == u'*':
+            res = res + u'[^/]*'
+        elif c == u'?':
+            res = res + u'[^/]'
+        elif c == u'[':
             j = i
-            if j < n and pat[j] in '!^':
-                j = j + 1
-            if j < n and pat[j] == ']':
-                j = j + 1
-            while j < n and pat[j] != ']':
+            if j < n and pat[j] in u'!^':
+                j = j + 1
+            if j < n and pat[j] == u']':
+                j = j + 1
+            while j < n and pat[j] != u']':
                 j = j + 1
             if j >= n:
-                res = res + '\\['  # interpret the [ literally
+                res = res + u'\\['  # interpret the [ literally
             else:
                 # Deal with inside of [..]
-                stuff = pat[i:j].replace('\\', '\\\\')
+                stuff = pat[i:j].replace(u'\\', u'\\\\')
                 i = j + 1
-                if stuff[0] in '!^':
-                    stuff = '^' + stuff[1:]
-                res = res + '[' + stuff + ']'
+                if stuff[0] in u'!^':
+                    stuff = u'^' + stuff[1:]
+                res = res + u'[' + stuff + u']'
         else:
             res = res + re.escape(c)
     return res

=== modified file 'duplicity/path.py'
--- duplicity/path.py	2017-07-11 14:55:38 +0000
+++ duplicity/path.py	2017-12-01 23:01:42 +0000
@@ -35,6 +35,7 @@
 import re
 import gzip
 import shutil
+import sys
 
 from duplicity import tarfile
 from duplicity import file_naming
@@ -511,9 +512,21 @@
         # self.opened should be true if the file has been opened, and
         # self.fileobj can override returned fileobj
         self.opened, self.fileobj = None, None
+        if isinstance(base, unicode):
+            # For now (Python 2), it is helpful to know that all paths
+            # are starting with bytes -- see note above util.fsencode definition
+            base = util.fsencode(base)
         self.base = base
+
+        # Create self.index, which is the path as a tuple
         self.index = self.rename_index(index)
+
         self.name = os.path.join(base, *self.index)
+
+        # We converted any unicode base to filesystem encoding, so self.name should
+        # be in filesystem encoding already and does not need to change
+        self.uc_name = util.fsdecode(self.name)
+
         self.setdata()
 
     def setdata(self):

=== modified file 'duplicity/selection.py'
--- duplicity/selection.py	2017-07-11 14:55:38 +0000
+++ duplicity/selection.py	2017-12-01 23:01:42 +0000
@@ -90,7 +90,7 @@
         assert isinstance(path, Path), str(path)
         self.selection_functions = []
         self.rootpath = path
-        self.prefix = self.rootpath.name
+        self.prefix = self.rootpath.uc_name
 
     def set_iter(self):
         """Initialize generator, prepare to iterate."""
@@ -164,10 +164,10 @@
 
         if not path.type:
             # base doesn't exist
-            log.Warn(_("Warning: base %s doesn't exist, continuing") %
-                     util.ufn(path.name))
+            log.Warn(_(u"Warning: base %s doesn't exist, continuing") %
+                     path.uc_name)
             return
-        log.Debug(_("Selecting %s") % util.ufn(path.name))
+        log.Debug(_(u"Selecting %s") % path.uc_name)
         yield path
         if not path.isdir():
             return
@@ -185,10 +185,10 @@
             if val == 0:
                 if delayed_path_stack:
                     for delayed_path in delayed_path_stack:
-                        log.Log(_("Selecting %s") % util.ufn(delayed_path.name), 6)
+                        log.Log(_(u"Selecting %s") % delayed_path.uc_name, 6)
                         yield delayed_path
                     del delayed_path_stack[:]
-                log.Debug(_("Selecting %s") % util.ufn(subpath.name))
+                log.Debug(_(u"Selecting %s") % subpath.uc_name)
                 yield subpath
                 if subpath.isdir():
                     diryield_stack.append(diryield(subpath))
@@ -199,14 +199,14 @@
     def Select(self, path):
         """Run through the selection functions and return dominant val 0/1/2"""
         # Only used by diryield and tests. Internal.
-        log.Debug("Selection: examining path %s" % util.ufn(path.name))
+        log.Debug(u"Selection: examining path %s" % path.uc_name)
         if not self.selection_functions:
-            log.Debug("Selection:     + no selection functions found. Including")
+            log.Debug(u"Selection:     + no selection functions found. Including")
             return 1
         scan_pending = False
         for sf in self.selection_functions:
             result = sf(path)
-            log.Debug("Selection:     result: %4s from function: %s" %
+            log.Debug(u"Selection:     result: %4s from function: %s" %
                       (str(result), sf.name))
             if result is 2:
                 # Selection function says that the path should be scanned for matching files, but keep going
@@ -224,12 +224,12 @@
             result = 1
 
         if result == 0:
-            log.Debug("Selection:     - excluding file")
+            log.Debug(u"Selection:     - excluding file")
         elif result == 1:
-            log.Debug("Selection:     + including file")
+            log.Debug(u"Selection:     + including file")
         else:
             assert result == 2
-            log.Debug("Selection:     ? scanning directory for matches")
+            log.Debug(u"Selection:     ? scanning directory for matches")
 
         return result
 
@@ -246,36 +246,41 @@
         filelists_index = 0
         try:
             for opt, arg in argtuples:
-                if opt == "--exclude":
+                assert isinstance(opt, unicode), u"option " + opt.decode(sys.getfilesystemencoding(), "ignore") + \
+                                                 u" is not unicode"
+                assert isinstance(arg, unicode), u"option " + arg.decode(sys.getfilesystemencoding(), "ignore") + \
+                                                 u" is not unicode"
+
+                if opt == u"--exclude":
                     self.add_selection_func(self.glob_get_sf(arg, 0))
-                elif opt == "--exclude-if-present":
+                elif opt == u"--exclude-if-present":
                     self.add_selection_func(self.present_get_sf(arg, 0))
-                elif opt == "--exclude-device-files":
+                elif opt == u"--exclude-device-files":
                     self.add_selection_func(self.devfiles_get_sf())
-                elif (opt == "--exclude-filelist") or (opt == "--exclude-globbing-filelist"):
+                elif (opt == u"--exclude-filelist") or (opt == u"--exclude-globbing-filelist"):
                     # --exclude-globbing-filelist is now deprecated, as all filelists are globbing
                     # but keep this here for the short term for backwards-compatibility
                     for sf in self.filelist_globbing_get_sfs(filelists[filelists_index], 0, arg):
                         self.add_selection_func(sf)
                     filelists_index += 1
-                elif opt == "--exclude-other-filesystems":
+                elif opt == u"--exclude-other-filesystems":
                     self.add_selection_func(self.other_filesystems_get_sf(0))
-                elif opt == "--exclude-regexp":
+                elif opt == u"--exclude-regexp":
                     self.add_selection_func(self.regexp_get_sf(arg, 0))
-                elif opt == "--exclude-older-than":
+                elif opt == u"--exclude-older-than":
                     self.add_selection_func(self.exclude_older_get_sf(arg))
-                elif opt == "--include":
+                elif opt == u"--include":
                     self.add_selection_func(self.glob_get_sf(arg, 1))
-                elif (opt == "--include-filelist") or (opt == "--include-globbing-filelist"):
+                elif (opt == u"--include-filelist") or (opt == u"--include-globbing-filelist"):
                     # --include-globbing-filelist is now deprecated, as all filelists are globbing
                     # but keep this here for the short term for backwards-compatibility
                     for sf in self.filelist_globbing_get_sfs(filelists[filelists_index], 1, arg):
                         self.add_selection_func(sf)
                     filelists_index += 1
-                elif opt == "--include-regexp":
+                elif opt == u"--include-regexp":
                     self.add_selection_func(self.regexp_get_sf(arg, 1))
                 else:
-                    assert 0, "Bad selection option %s" % opt
+                    assert 0, u"Bad selection option %s" % opt
         except SelectError as e:
             self.parse_catch_error(e)
         assert filelists_index == len(filelists)
@@ -285,16 +290,16 @@
         """Deal with selection error exc"""
         # Internal, used by ParseArgs.
         if isinstance(exc, FilePrefixError):
-            log.FatalError(_("""\
+            log.FatalError(_(u"""\
 Fatal Error: The file specification
     %s
 cannot match any files in the base directory
     %s
 Useful file specifications begin with the base directory or some
 pattern (such as '**') which matches the base directory.""") %
-                           (exc, util.ufn(self.prefix)), log.ErrorCode.file_prefix_error)
+                           (exc, self.prefix), log.ErrorCode.file_prefix_error)
         elif isinstance(exc, GlobbingError):
-            log.FatalError(_("Fatal Error while processing expression\n"
+            log.FatalError(_(u"Fatal Error while processing expression\n"
                              "%s") % exc, log.ErrorCode.globbing_error)
         else:
             raise  # pylint: disable=misplaced-bare-raise
@@ -304,7 +309,7 @@
         # Internal. Used by ParseArgs.
         if (self.selection_functions and
                 not self.selection_functions[-1].exclude):
-            log.FatalError(_("""\
+            log.FatalError(_(u"""\
 Last selection expression:
     %s
 only specifies that files be included.  Because the default is to
@@ -333,19 +338,19 @@
         line = line.strip()
         if not line:  # skip blanks
             return None, include_default
-        if line[0] == "#":  # skip full-line comments
+        if line.startswith(u"#"):  # skip full-line comments
             return None, include_default
 
         include = include_default
-        if line[:2] == "+ ":
+        if line.startswith(u"+ "):
             # Check for "+ " or "- " syntax
             include = 1
             line = line[2:]
-        elif line[:2] == "- ":
+        elif line.startswith(u"- "):
             include = 0
             line = line[2:]
 
-        if (line[:1] == "'" and line[-1:] == "'") or (line[:1] == '"' and line[-1:] == '"'):
+        if (line.startswith(u"'") and line.endswith(u"'")) or (line.startswith(u'"') and line.endswith(u'"')):
             line = line[1:-1]
 
         return line, include
@@ -360,8 +365,8 @@
 
         """
         # Internal. Used by ParseArgs.
-        log.Notice(_("Reading globbing filelist %s") % list_name)
-        separator = globals.null_separator and "\0" or "\n"
+        log.Notice(_(u"Reading globbing filelist %s") % list_name)
+        separator = globals.null_separator and u"\0" or u"\n"
         filelist_fp.seek(0)
         for line in filelist_fp.read().split(separator):
             line, include = self.filelist_sanitise_line(line, inc_default)
@@ -383,7 +388,7 @@
                 return None
 
         sel_func.exclude = not include
-        sel_func.name = "Match other filesystems"
+        sel_func.name = u"Match other filesystems"
         return sel_func
 
     def regexp_get_sf(self, regexp_string, include):
@@ -393,24 +398,24 @@
         try:
             regexp = re.compile(regexp_string)
         except Exception:
-            log.Warn(_("Error compiling regular expression %s") % regexp_string)
+            log.Warn(_(u"Error compiling regular expression %s") % regexp_string)
             raise
 
         def sel_func(path):
-            if regexp.search(path.name):
+            if regexp.search(path.uc_name):
                 return include
             else:
                 return None
 
         sel_func.exclude = not include
-        sel_func.name = "Regular expression: %s" % regexp_string
+        sel_func.name = u"Regular expression: %s" % regexp_string
         return sel_func
 
     def devfiles_get_sf(self):
         """Return a selection function to exclude all dev files"""
         # Internal. Used by ParseArgs.
         if self.selection_functions:
-            log.Warn(_("Warning: exclude-device-files is not the first "
+            log.Warn(_(u"Warning: exclude-device-files is not the first "
                        "selector.\nThis may not be what you intended"))
 
         def sel_func(path):
@@ -420,21 +425,22 @@
                 return None
 
         sel_func.exclude = 1
-        sel_func.name = "Exclude device files"
+        sel_func.name = u"Exclude device files"
         return sel_func
 
     def glob_get_sf(self, glob_str, include):
         """Return selection function given by glob string"""
         # Internal. Used by ParseArgs, filelist_globbing_get_sfs and unit tests.
         assert include == 0 or include == 1
-        if glob_str == "**":
+        assert isinstance(glob_str, unicode)
+        if glob_str == u"**":
             sel_func = lambda path: include
         else:
             sel_func = self.glob_get_normal_sf(glob_str, include)
 
         sel_func.exclude = not include
-        sel_func.name = "Command-line %s glob: %s" % \
-                        (include and "include" or "exclude", glob_str)
+        sel_func.name = u"Command-line %s glob: %s" % \
+                        (include and u"include" or u"exclude", glob_str)
         return sel_func
 
     def present_get_sf(self, filename, include):
@@ -453,9 +459,8 @@
                     # 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))
+                        u"Error accessing possibly locked file %s") % path.uc_name,
+                        log.WarningCode.cannot_read, util.escape(path.uc_name))
                     if diffdir.stats:
                         diffdir.stats.Errors += 1
                 elif path.append(filename).exists():
@@ -470,8 +475,8 @@
                            log.ErrorCode.not_implemented)
 
         sel_func.exclude = not include
-        sel_func.name = "Command-line %s filename: %s" % \
-                        (include and "include-if-present" or "exclude-if-present", filename)
+        sel_func.name = u"Command-line %s filename: %s" % \
+                        (include and u"include-if-present" or u"exclude-if-present", filename)
         return sel_func
 
     def glob_get_normal_sf(self, glob_str, include):
@@ -489,8 +494,8 @@
         things similar to this.
 
         """
-        # Internal. Used by glob_get_sf and unit tests.
-
+        assert isinstance(glob_str, unicode), \
+            u"The glob string " + glob_str.decode(sys.getfilesystemencoding(), "ignore") + u" is not unicode"
         ignore_case = False
 
         if glob_str.lower().startswith("ignorecase:"):

=== modified file 'duplicity/util.py'
--- duplicity/util.py	2017-11-23 13:02:23 +0000
+++ duplicity/util.py	2017-12-01 23:01:42 +0000
@@ -34,6 +34,37 @@
 import duplicity.globals as globals
 import duplicity.log as log
 
+try:
+    # For paths, just use path.name/uname rather than converting with these
+    from os import fsencode, fsdecode
+except ImportError:
+    # Most likely Python version < 3.2, so define our own fsencode/fsdecode.
+    # These are functions that encode/decode unicode paths to filesystem encoding,
+    # but the cleverness is that they handle non-unicode characters on Linux
+    # There is a *partial* backport to Python2 available here:
+    # https://github.com/pjdelport/backports.os/blob/master/src/backports/os.py
+    # but if it cannot be trusted for full-circle translation, then we may as well
+    # just read and store the bytes version of the path as path.name before
+    # creating the unicode version (for path matching etc) and ensure that in
+    # real-world usage (as opposed to testing) we create the path objects from a
+    # bytes string.
+    # ToDo: Revisit this once we drop Python 2 support/the backport is complete
+
+    def fsencode(unicode_filename):
+        """Convert a unicode filename to a filename encoded in the system encoding"""
+        # For paths, just use path.name rather than converting with this
+        # If we are not doing any cleverness with non-unicode filename bytes,
+        # encoding to system encoding is good enough
+        return unicode_filename.encode(sys.getfilesystemencoding(), "replace")
+
+    def fsdecode(bytes_filename):
+        """Convert a filename encoded in the system encoding to unicode"""
+        # For paths, just use path.uname rather than converting with this
+        # If we are not doing any cleverness with non-unicode filename bytes,
+        # decoding using system encoding is good enough. Use "ignore" as
+        # Linux paths can contain non-Unicode characters
+        return bytes_filename.decode(globals.fsencoding, "ignore")
+
 
 def exception_traceback(limit=50):
     """
@@ -58,9 +89,9 @@
 
 
 def ufn(filename):
-    "Convert a (bytes) filename to unicode for printing"
-    assert not isinstance(filename, unicode)
-    return filename.decode(globals.fsencoding, 'replace')
+    """Convert a (bytes) filename to unicode for printing"""
+    # Note: path.uc_name is preferable for paths
+    return filename.decode(globals.fsencoding, "replace")
 
 
 def uindex(index):

=== modified file 'requirements.txt'
--- requirements.txt	2017-05-20 15:07:38 +0000
+++ requirements.txt	2017-12-01 23:01:42 +0000
@@ -2,6 +2,7 @@
 coverage
 dropbox==6.9.0
 fasteners
+future
 paramiko
 pexpect
 pycodestyle

=== modified file 'setup.py'
--- setup.py	2017-07-11 14:55:38 +0000
+++ setup.py	2017-12-01 23:01:42 +0000
@@ -196,7 +196,7 @@
       ext_modules=ext_modules,
       scripts=['bin/rdiffdir', 'bin/duplicity'],
       data_files=data_files,
-      install_requires=['fasteners'],
+      install_requires=['fasteners', 'future'],
       tests_require=['fasteners', 'mock', 'pexpect'],
       test_suite='testing',
       cmdclass={'test': TestCommand,

=== modified file 'testing/__init__.py'
--- testing/__init__.py	2017-07-11 14:55:38 +0000
+++ testing/__init__.py	2017-12-01 23:01:42 +0000
@@ -55,10 +55,12 @@
 
 class DuplicityTestCase(unittest.TestCase):
 
-    sign_key = '839E6A2856538CCF'
-    sign_passphrase = 'test'
-    encrypt_key1 = '839E6A2856538CCF'
-    encrypt_key2 = '453005CE9B736B2A'
+    sign_key = u'839E6A2856538CCF'
+    sign_passphrase = u'test'
+    # ToDo: remove the below when gpg code (and test_gpg) is converted to unicode
+    sign_passphrase_bytes = b'test'
+    encrypt_key1 = u'839E6A2856538CCF'
+    encrypt_key2 = u'453005CE9B736B2A'
 
     def setUp(self):
         super(DuplicityTestCase, self).setUp()

=== modified file 'testing/functional/__init__.py'
--- testing/functional/__init__.py	2017-07-11 14:55:38 +0000
+++ testing/functional/__init__.py	2017-12-01 23:01:42 +0000
@@ -25,10 +25,11 @@
 import platform
 import sys
 import time
-import unittest
 
 from duplicity import backend
+from duplicity import util
 from .. import DuplicityTestCase
+from pkg_resources import parse_version
 
 
 class CmdError(Exception):
@@ -64,7 +65,7 @@
         self.unpack_testfiles()
 
         self.class_args = []
-        self.backend_url = "file://testfiles/output"
+        self.backend_url = u"file://testfiles/output"
         self.last_backup = None
         self.set_environ('PASSPHRASE', self.sign_passphrase)
         self.set_environ("SIGN_PASSPHRASE", self.sign_passphrase)
@@ -84,30 +85,57 @@
         # We run under setsid and take input from /dev/null (below) because
         # this way we force a failure if duplicity tries to read from the
         # console unexpectedly (like for gpg password or such).
-        if platform.platform().startswith('Linux'):
-            cmd_list = ['setsid']
+
+        # Check all string inputs are unicode -- we will convert to system encoding before running the command
+        for item in options:
+            assert not isinstance(item, str), "item " + unicode(item) + " in options is not unicode"
+
+        for item in passphrase_input:
+            assert isinstance(item, unicode), "item " + unicode(item) + " in passphrase_input is not unicode"
+
+        if platform.platform().startswith(u'Linux'):
+            cmd_list = [u'setsid']
             if self._setsid_w:
-                cmd_list.extend(["-w"])
+                cmd_list.extend([u"-w"])
         else:
             cmd_list = []
-        cmd_list.extend(["duplicity"])
+        cmd_list.extend([u"duplicity"])
         cmd_list.extend(options)
-        cmd_list.extend(["-v0"])
-        cmd_list.extend(["--no-print-statistics"])
-        cmd_list.extend(["--allow-source-mismatch"])
-        cmd_list.extend(["--archive-dir=testfiles/cache"])
+        cmd_list.extend([u"-v0"])
+        cmd_list.extend([u"--no-print-statistics"])
+        cmd_list.extend([u"--allow-source-mismatch"])
+        cmd_list.extend([u"--archive-dir=testfiles/cache"])
         if current_time:
-            cmd_list.extend(["--current-time", current_time])
+            cmd_list.extend([u"--current-time", current_time])
         cmd_list.extend(self.class_args)
         if fail:
-            cmd_list.extend(["--fail", str(fail)])
-        cmdline = " ".join(map(lambda x: '"%s"' % x, cmd_list))
+            cmd_list.extend([u"--fail", unicode(fail)])
+        cmdline = u" ".join(map(lambda x: u'"%s"' % x, cmd_list))
 
         if not passphrase_input:
-            cmdline += " < /dev/null"
-        child = pexpect.spawn('/bin/sh', ['-c', cmdline], timeout=None)
+            cmdline += u" < /dev/null"
+
+        # The immediately following block is the nicer way to execute pexpect with
+        # unicode strings, but we need to have the pre-4.0 version for some time yet,
+        # so for now this is commented out so tests execute the same way on all systems.
+
+        # if parse_version(pexpect.__version__) >= parse_version("4.0"):
+        #     # pexpect.spawn only supports unicode from version 4.0
+        #     # there was a separate pexpect.spawnu in 3.x, but it has an error on readline
+        #     child = pexpect.spawn(u'/bin/sh', [u'-c', cmdline], timeout=None, encoding=sys.getfilesystemencoding())
+        #
+        #     for passphrase in passphrase_input:
+        #         child.expect(u'passphrase.*:')
+        #         child.sendline(passphrase)
+        # else:
+
+        # Manually encode to filesystem encoding and send to spawn as bytes
+        # ToDo: Remove this once we no longer have to support systems with pexpect < 4.0
+        child = pexpect.spawn(b'/bin/sh', [b'-c', cmdline.encode(sys.getfilesystemencoding(),
+                                                                 'replace')], timeout=None)
+
         for passphrase in passphrase_input:
-            child.expect('passphrase.*:')
+            child.expect(b'passphrase.*:')
             child.sendline(passphrase)
 
         # if the command fails, we need to clear its output
@@ -132,7 +160,7 @@
 
     def backup(self, type, input_dir, options=[], **kwargs):
         """Run duplicity backup to default directory"""
-        options = [type, input_dir, self.backend_url, "--volsize", "1"] + options
+        options = [type, input_dir, self.backend_url, u"--volsize", u"1"] + options
         before_files = self.get_backend_files()
 
         # If a chain ends with time X and the next full chain begins at time X,
@@ -149,27 +177,27 @@
 
     def restore(self, file_to_restore=None, time=None, options=[], **kwargs):
         assert not os.system("rm -rf testfiles/restore_out")
-        options = [self.backend_url, "testfiles/restore_out"] + options
+        options = [self.backend_url, u"testfiles/restore_out"] + options
         if file_to_restore:
-            options.extend(['--file-to-restore', file_to_restore])
+            options.extend([u'--file-to-restore', file_to_restore])
         if time:
-            options.extend(['--restore-time', str(time)])
+            options.extend([u'--restore-time', unicode(time)])
         self.run_duplicity(options=options, **kwargs)
 
     def verify(self, dirname, file_to_verify=None, time=None, options=[],
                **kwargs):
-        options = ["verify", self.backend_url, dirname] + options
+        options = [u"verify", self.backend_url, dirname] + options
         if file_to_verify:
-            options.extend(['--file-to-restore', file_to_verify])
+            options.extend([u'--file-to-restore', file_to_verify])
         if time:
-            options.extend(['--restore-time', str(time)])
+            options.extend([u'--restore-time', unicode(time)])
         self.run_duplicity(options=options, **kwargs)
 
     def cleanup(self, options=[]):
         """
         Run duplicity cleanup to default directory
         """
-        options = ["cleanup", self.backend_url, "--force"] + options
+        options = [u"cleanup", self.backend_url, u"--force"] + options
         self.run_duplicity(options=options)
 
     def get_backend_files(self):
@@ -183,6 +211,6 @@
         Makes a number of large files in testfiles/largefiles that each are
         the specified number of megabytes.
         """
-        assert not os.system("mkdir testfiles/largefiles")
+        assert not os.system(u"mkdir testfiles/largefiles")
         for n in range(count):
-            assert not os.system("dd if=/dev/urandom of=testfiles/largefiles/file%d bs=1024 count=%d > /dev/null 2>&1" % (n + 1, size * 1024))
+            assert not os.system(u"dd if=/dev/urandom of=testfiles/largefiles/file%d bs=1024 count=%d > /dev/null 2>&1" % (n + 1, size * 1024))

=== modified file 'testing/functional/test_badupload.py'
--- testing/functional/test_badupload.py	2014-12-27 15:16:06 +0000
+++ testing/functional/test_badupload.py	2017-12-01 23:01:42 +0000
@@ -34,7 +34,7 @@
         Test basic lost file
         """
         try:
-            self.backup("full", "testfiles/dir1", options=["--skip-volume=1"])
+            self.backup(u"full", u"testfiles/dir1", options=[u"--skip-volume=1"])
             self.fail()
         except CmdError as e:
             self.assertEqual(e.exit_status, 44, str(e))

=== modified file 'testing/functional/test_cleanup.py'
--- testing/functional/test_cleanup.py	2014-04-20 05:58:47 +0000
+++ testing/functional/test_cleanup.py	2017-12-01 23:01:42 +0000
@@ -35,27 +35,27 @@
         after a failed backup.
         """
         self.make_largefiles()
-        good_files = self.backup("full", "testfiles/largefiles")
-        good_files |= self.backup("inc", "testfiles/largefiles")
-        good_files |= self.backup("inc", "testfiles/largefiles")
-        self.backup("full", "testfiles/largefiles", fail=1)
+        good_files = self.backup(u"full", u"testfiles/largefiles")
+        good_files |= self.backup(u"inc", u"testfiles/largefiles")
+        good_files |= self.backup(u"inc", u"testfiles/largefiles")
+        self.backup(u"full", u"testfiles/largefiles", fail=1)
         bad_files = self.get_backend_files()
         bad_files -= good_files
         self.assertNotEqual(bad_files, set())
         # the cleanup should go OK
-        self.run_duplicity(options=["cleanup", self.backend_url, "--force"])
+        self.run_duplicity(options=[u"cleanup", self.backend_url, u"--force"])
         leftovers = self.get_backend_files()
         self.assertEqual(good_files, leftovers)
-        self.backup("inc", "testfiles/largefiles")
-        self.verify("testfiles/largefiles")
+        self.backup(u"inc", u"testfiles/largefiles")
+        self.verify(u"testfiles/largefiles")
 
     def test_remove_all_but_n(self):
         """
         Test that remove-all-but-n works in the simple case.
         """
-        full1_files = self.backup("full", "testfiles/empty_dir")
-        full2_files = self.backup("full", "testfiles/empty_dir")
-        self.run_duplicity(options=["remove-all-but-n", "1", self.backend_url, "--force"])
+        full1_files = self.backup(u"full", u"testfiles/empty_dir")
+        full2_files = self.backup(u"full", u"testfiles/empty_dir")
+        self.run_duplicity(options=[u"remove-all-but-n", u"1", self.backend_url, u"--force"])
         leftovers = self.get_backend_files()
         self.assertEqual(full2_files, leftovers)
 
@@ -63,10 +63,10 @@
         """
         Test that remove-all-inc-of-but-n-full works in the simple case.
         """
-        full1_files = self.backup("full", "testfiles/empty_dir")
-        inc1_files = self.backup("inc", "testfiles/empty_dir")
-        full2_files = self.backup("full", "testfiles/empty_dir")
-        self.run_duplicity(options=["remove-all-inc-of-but-n-full", "1", self.backend_url, "--force"])
+        full1_files = self.backup(u"full", u"testfiles/empty_dir")
+        inc1_files = self.backup(u"inc", u"testfiles/empty_dir")
+        full2_files = self.backup(u"full", u"testfiles/empty_dir")
+        self.run_duplicity(options=[u"remove-all-inc-of-but-n-full", u"1", self.backend_url, u"--force"])
         leftovers = self.get_backend_files()
         self.assertEqual(full1_files | full2_files, leftovers)
 

=== modified file 'testing/functional/test_final.py'
--- testing/functional/test_final.py	2017-04-22 19:30:28 +0000
+++ testing/functional/test_final.py	2017-12-01 23:01:42 +0000
@@ -36,11 +36,11 @@
 
         # Back up directories to local backend
         current_time = 100000
-        self.backup("full", dirlist[0], current_time=current_time,
+        self.backup(u"full", dirlist[0], current_time=current_time,
                     options=backup_options)
         for new_dir in dirlist[1:]:
             current_time += 100000
-            self.backup("inc", new_dir, current_time=current_time,
+            self.backup(u"inc", new_dir, current_time=current_time,
                         options=backup_options)
 
         # Restore each and compare them
@@ -48,7 +48,7 @@
             dirname = dirlist[i]
             current_time = 100000 * (i + 1)
             self.restore(time=current_time, options=restore_options)
-            self.check_same(dirname, "testfiles/restore_out")
+            self.check_same(dirname, u"testfiles/restore_out")
             self.verify(dirname,
                         time=current_time, options=restore_options)
 
@@ -59,57 +59,57 @@
 
     def test_basic_cycle(self, backup_options=[], restore_options=[]):
         """Run backup/restore test on basic directories"""
-        self.runtest(["testfiles/dir1",
-                      "testfiles/dir2",
-                      "testfiles/dir3"],
+        self.runtest([u"testfiles/dir1",
+                      u"testfiles/dir2",
+                      u"testfiles/dir3"],
                      backup_options=backup_options,
                      restore_options=restore_options)
 
         # Test restoring various sub files
-        for filename, time, dir in [('symbolic_link', 99999, 'dir1'),
-                                    ('directory_to_file', 100100, 'dir1'),
-                                    ('directory_to_file', 200100, 'dir2'),
-                                    ('largefile', 300000, 'dir3')]:
+        for filename, time, dir in [(u'symbolic_link', 99999, u'dir1'),
+                                    (u'directory_to_file', 100100, u'dir1'),
+                                    (u'directory_to_file', 200100, u'dir2'),
+                                    (u'largefile', 300000, u'dir3')]:
             self.restore(filename, time, options=restore_options)
-            self.check_same('testfiles/%s/%s' % (dir, filename),
-                            'testfiles/restore_out')
-            self.verify('testfiles/%s/%s' % (dir, filename),
+            self.check_same(u'testfiles/%s/%s' % (dir, filename),
+                            u'testfiles/restore_out')
+            self.verify(u'testfiles/%s/%s' % (dir, filename),
                         file_to_verify=filename, time=time,
                         options=restore_options)
 
     def test_asym_cycle(self):
         """Like test_basic_cycle but use asymmetric encryption and signing"""
-        backup_options = ["--encrypt-key", self.encrypt_key1,
-                          "--sign-key", self.sign_key]
-        restore_options = ["--encrypt-key", self.encrypt_key1,
-                           "--sign-key", self.sign_key]
+        backup_options = [u"--encrypt-key", self.encrypt_key1,
+                          u"--sign-key", self.sign_key]
+        restore_options = [u"--encrypt-key", self.encrypt_key1,
+                           u"--sign-key", self.sign_key]
         self.test_basic_cycle(backup_options=backup_options,
                               restore_options=restore_options)
 
     def test_asym_with_hidden_recipient_cycle(self):
         """Like test_basic_cycle but use asymmetric encryption (hiding key id) and signing"""
-        backup_options = ["--hidden-encrypt-key", self.encrypt_key1,
-                          "--sign-key", self.sign_key]
-        restore_options = ["--hidden-encrypt-key", self.encrypt_key1,
-                           "--sign-key", self.sign_key]
+        backup_options = [u"--hidden-encrypt-key", self.encrypt_key1,
+                          u"--sign-key", self.sign_key]
+        restore_options = [u"--hidden-encrypt-key", self.encrypt_key1,
+                           u"--sign-key", self.sign_key]
         self.test_basic_cycle(backup_options=backup_options,
                               restore_options=restore_options)
 
     def test_single_regfile(self):
         """Test backing and restoring up a single regular file"""
-        self.runtest(["testfiles/various_file_types/regular_file"])
+        self.runtest([u"testfiles/various_file_types/regular_file"])
 
     def test_empty_backup(self):
         """Make sure backup works when no files change"""
-        self.backup("full", "testfiles/empty_dir")
-        self.backup("inc", "testfiles/empty_dir")
+        self.backup(u"full", u"testfiles/empty_dir")
+        self.backup(u"inc", u"testfiles/empty_dir")
 
     def test_long_filenames(self):
         """Test backing up a directory with long filenames in it"""
         # Note that some versions of ecryptfs (at least through Ubuntu 11.10)
         # have a bug where they treat the max path segment length as 143
         # instead of 255.  So make sure that these segments don't break that.
-        lf_dir = path.Path("testfiles/long_filenames")
+        lf_dir = path.Path(u"testfiles/long_filenames")
         if lf_dir.exists():
             lf_dir.deltree()
         lf_dir.mkdir()
@@ -130,36 +130,36 @@
         fp.write("hello" * 1000)
         assert not fp.close()
 
-        self.runtest(["testfiles/empty_dir", lf_dir.name,
-                      "testfiles/empty_dir", lf_dir.name])
+        self.runtest([u"testfiles/empty_dir", lf_dir.uc_name,
+                      u"testfiles/empty_dir", lf_dir.uc_name])
 
     def test_empty_restore(self):
         """Make sure error raised when restore doesn't match anything"""
-        self.backup("full", "testfiles/dir1")
-        self.assertRaises(CmdError, self.restore, "this_file_does_not_exist")
-        self.backup("inc", "testfiles/empty_dir")
-        self.assertRaises(CmdError, self.restore, "this_file_does_not_exist")
+        self.backup(u"full", u"testfiles/dir1")
+        self.assertRaises(CmdError, self.restore, u"this_file_does_not_exist")
+        self.backup(u"inc", u"testfiles/empty_dir")
+        self.assertRaises(CmdError, self.restore, u"this_file_does_not_exist")
 
     def test_remove_older_than(self):
         """Test removing old backup chains"""
-        first_chain = self.backup("full", "testfiles/dir1", current_time=10000)
-        first_chain |= self.backup("inc", "testfiles/dir2", current_time=20000)
-        second_chain = self.backup("full", "testfiles/dir1", current_time=30000)
-        second_chain |= self.backup("inc", "testfiles/dir3", current_time=40000)
+        first_chain = self.backup(u"full", u"testfiles/dir1", current_time=10000)
+        first_chain |= self.backup(u"inc", u"testfiles/dir2", current_time=20000)
+        second_chain = self.backup(u"full", u"testfiles/dir1", current_time=30000)
+        second_chain |= self.backup(u"inc", u"testfiles/dir3", current_time=40000)
 
         self.assertEqual(self.get_backend_files(), first_chain | second_chain)
 
-        self.run_duplicity(options=["remove-older-than", "35000", "--force", self.backend_url])
+        self.run_duplicity(options=[u"remove-older-than", u"35000", u"--force", self.backend_url])
         self.assertEqual(self.get_backend_files(), second_chain)
 
         # Now check to make sure we can't delete only chain
-        self.run_duplicity(options=["remove-older-than", "50000", "--force", self.backend_url])
+        self.run_duplicity(options=[u"remove-older-than", u"50000", u"--force", self.backend_url])
         self.assertEqual(self.get_backend_files(), second_chain)
 
     def test_piped_password(self):
         """Make sure that prompting for a password works"""
-        self.set_environ("PASSPHRASE", None)
-        self.backup("full", "testfiles/empty_dir",
+        self.set_environ(u"PASSPHRASE", None)
+        self.backup(u"full", u"testfiles/empty_dir",
                     passphrase_input=[self.sign_passphrase, self.sign_passphrase])
         self.restore(passphrase_input=[self.sign_passphrase])
 
@@ -168,14 +168,14 @@
 
     def setUp(self):
         super(OldFilenamesFinalTest, self).setUp()
-        self.class_args.extend(["--old-filenames"])
+        self.class_args.extend([u"--old-filenames"])
 
 
 class ShortFilenamesFinalTest(FinalTest):
 
     def setUp(self):
         super(ShortFilenamesFinalTest, self).setUp()
-        self.class_args.extend(["--short-filenames"])
+        self.class_args.extend([u"--short-filenames"])
 
 if __name__ == "__main__":
     unittest.main()

=== modified file 'testing/functional/test_replicate.py'
--- testing/functional/test_replicate.py	2017-06-20 15:20:35 +0000
+++ testing/functional/test_replicate.py	2017-12-01 23:01:42 +0000
@@ -34,17 +34,17 @@
     def runtest(self, dirlist, backup_options=[], replicate_options=[], restore_options=[]):
         # Back up directories to local backend
         current_time = 100000
-        self.backup("full", dirlist[0], current_time=current_time,
+        self.backup(u"full", dirlist[0], current_time=current_time,
                     options=backup_options)
         for new_dir in dirlist[1:]:
             current_time += 100000
-            self.backup("inc", new_dir, current_time=current_time,
+            self.backup(u"inc", new_dir, current_time=current_time,
                         options=backup_options)
 
         # Replicate to other backend
         source_url = self.backend_url
-        target_url = "file://testfiles/replicate_out"
-        self.run_duplicity(options=["replicate"] +
+        target_url = u"file://testfiles/replicate_out"
+        self.run_duplicity(options=[u"replicate"] +
                            replicate_options + [source_url, target_url])
 
         self.backend_url = target_url
@@ -54,7 +54,7 @@
             dirname = dirlist[i]
             current_time = 100000 * (i + 1)
             self.restore(time=current_time, options=restore_options)
-            self.check_same(dirname, "testfiles/restore_out")
+            self.check_same(dirname, u"testfiles/restore_out")
             self.verify(dirname,
                         time=current_time, options=restore_options)
 
@@ -65,15 +65,15 @@
 
     def test_replicate(self):
         """Test replication"""
-        self.runtest(["testfiles/dir1", "testfiles/dir2"])
+        self.runtest([u"testfiles/dir1", u"testfiles/dir2"])
 
     def test_replicate_noencryption(self):
         """Test replication with decryption"""
-        self.runtest(["testfiles/dir1", "testfiles/dir2"],
-                     replicate_options=["--no-encryption"])
+        self.runtest([u"testfiles/dir1", u"testfiles/dir2"],
+                     replicate_options=[u"--no-encryption"])
 
     def test_replicate_asym(self):
         """Test replication with reencryption"""
-        asym_options = ["--encrypt-key", self.encrypt_key1]
-        self.runtest(["testfiles/dir1", "testfiles/dir2"],
+        asym_options = [u"--encrypt-key", self.encrypt_key1]
+        self.runtest([u"testfiles/dir1", u"testfiles/dir2"],
                      replicate_options=asym_options, restore_options=asym_options)

=== modified file 'testing/functional/test_restart.py'
--- testing/functional/test_restart.py	2017-07-11 14:55:38 +0000
+++ testing/functional/test_restart.py	2017-12-01 23:01:42 +0000
@@ -37,20 +37,20 @@
         Test basic Checkpoint/Restart
         """
         self.make_largefiles()
-        self.backup("full", "testfiles/largefiles", fail=1)
-        self.backup("full", "testfiles/largefiles")
-        self.verify("testfiles/largefiles")
+        self.backup(u"full", u"testfiles/largefiles", fail=1)
+        self.backup(u"full", u"testfiles/largefiles")
+        self.verify(u"testfiles/largefiles")
 
     def test_multiple_checkpoint_restart(self):
         """
         Test multiple Checkpoint/Restart
         """
         self.make_largefiles()
-        self.backup("full", "testfiles/largefiles", fail=1)
-        self.backup("full", "testfiles/largefiles", fail=2)
-        self.backup("full", "testfiles/largefiles", fail=3)
-        self.backup("full", "testfiles/largefiles")
-        self.verify("testfiles/largefiles")
+        self.backup(u"full", u"testfiles/largefiles", fail=1)
+        self.backup(u"full", u"testfiles/largefiles", fail=2)
+        self.backup(u"full", u"testfiles/largefiles", fail=3)
+        self.backup(u"full", u"testfiles/largefiles")
+        self.verify(u"testfiles/largefiles")
 
     def test_first_volume_failure(self):
         """
@@ -58,10 +58,10 @@
         Caused when duplicity fails before the first transfer.
         """
         self.make_largefiles()
-        self.backup("full", "testfiles/largefiles", fail=1)
-        assert not os.system("rm testfiles/output/duplicity-full*difftar*")
-        self.backup("full", "testfiles/largefiles")
-        self.verify("testfiles/largefiles")
+        self.backup(u"full", u"testfiles/largefiles", fail=1)
+        assert not os.system(u"rm testfiles/output/duplicity-full*difftar*")
+        self.backup(u"full", u"testfiles/largefiles")
+        self.verify(u"testfiles/largefiles")
 
     def test_multi_volume_failure(self):
         """
@@ -70,10 +70,10 @@
         fails the last queued transfer(s).
         """
         self.make_largefiles()
-        self.backup("full", "testfiles/largefiles", fail=3)
-        assert not os.system("rm testfiles/output/duplicity-full*vol[23].difftar*")
-        self.backup("full", "testfiles/largefiles")
-        self.verify("testfiles/largefiles")
+        self.backup(u"full", u"testfiles/largefiles", fail=3)
+        assert not os.system(u"rm testfiles/output/duplicity-full*vol[23].difftar*")
+        self.backup(u"full", u"testfiles/largefiles")
+        self.verify(u"testfiles/largefiles")
 
     def test_restart_sign_and_encrypt(self):
         """
@@ -81,10 +81,10 @@
         https://bugs.launchpad.net/duplicity/+bug/946988
         """
         self.make_largefiles()
-        enc_opts = ["--sign-key", self.sign_key, "--encrypt-key", self.sign_key]
-        self.backup("full", "testfiles/largefiles", options=enc_opts, fail=2)
-        self.backup("full", "testfiles/largefiles", options=enc_opts)
-        self.verify("testfiles/largefiles")
+        enc_opts = [u"--sign-key", self.sign_key, u"--encrypt-key", self.sign_key]
+        self.backup(u"full", u"testfiles/largefiles", options=enc_opts, fail=2)
+        self.backup(u"full", u"testfiles/largefiles", options=enc_opts)
+        self.verify(u"testfiles/largefiles")
 
     def test_restart_sign_and_hidden_encrypt(self):
         """
@@ -92,10 +92,10 @@
         https://bugs.launchpad.net/duplicity/+bug/946988
         """
         self.make_largefiles()
-        enc_opts = ["--sign-key", self.sign_key, "--hidden-encrypt-key", self.sign_key]
-        self.backup("full", "testfiles/largefiles", options=enc_opts, fail=2)
-        self.backup("full", "testfiles/largefiles", options=enc_opts)
-        self.verify("testfiles/largefiles")
+        enc_opts = [u"--sign-key", self.sign_key, u"--hidden-encrypt-key", self.sign_key]
+        self.backup(u"full", u"testfiles/largefiles", options=enc_opts, fail=2)
+        self.backup(u"full", u"testfiles/largefiles", options=enc_opts)
+        self.verify(u"testfiles/largefiles")
 
     def test_last_file_missing_in_middle(self):
         """
@@ -104,12 +104,12 @@
         the file in the middle of the backup, with files following.
         """
         self.make_largefiles()
-        self.backup("full", "testfiles/largefiles", fail=3)
-        assert not os.system("rm testfiles/largefiles/file2")
-        self.backup("full", "testfiles/largefiles")
+        self.backup(u"full", u"testfiles/largefiles", fail=3)
+        assert not os.system(u"rm testfiles/largefiles/file2")
+        self.backup(u"full", u"testfiles/largefiles")
         # TODO: we can't verify but we need to to check for other errors that might show up
         # there should be 2 differences found, one missing file, one mtime change
-        # self.verify("testfiles/largefiles")
+        # self.verify(u"testfiles/largefiles")
 
     def test_last_file_missing_at_end(self):
         """
@@ -118,22 +118,22 @@
         the file at the end of the backup, with no files following.
         """
         self.make_largefiles()
-        self.backup("full", "testfiles/largefiles", fail=6)
-        assert not os.system("rm testfiles/largefiles/file3")
-        self.backup("full", "testfiles/largefiles")
+        self.backup(u"full", u"testfiles/largefiles", fail=6)
+        assert not os.system(u"rm testfiles/largefiles/file3")
+        self.backup(u"full", u"testfiles/largefiles")
         # TODO: we can't verify but we need to to check for other errors that might show up
         # there should be 2 differences found, one missing file, one mtime change
-        # self.verify("testfiles/largefiles")
+        # self.verify(u"testfiles/largefiles")
 
     def test_restart_incremental(self):
         """
         Test restarting an incremental backup
         """
         self.make_largefiles()
-        self.backup("full", "testfiles/dir1")
-        self.backup("inc", "testfiles/largefiles", fail=2)
-        self.backup("inc", "testfiles/largefiles")
-        self.verify("testfiles/largefiles")
+        self.backup(u"full", u"testfiles/dir1")
+        self.backup(u"inc", u"testfiles/largefiles", fail=2)
+        self.backup(u"inc", u"testfiles/largefiles")
+        self.verify(u"testfiles/largefiles")
 
     def make_fake_second_volume(self, name):
         """
@@ -175,16 +175,16 @@
         If we restart right after a volume that ended with a small
         (one-block) file, make sure we restart in the right place.
         """
-        source = 'testfiles/largefiles'
+        source = u'testfiles/largefiles'
         assert not os.system("mkdir -p %s" % source)
         assert not os.system("echo hello > %s/file1" % source)
-        self.backup("full", source, options=["--name=backup1"])
+        self.backup(u"full", source, options=[u"--name=backup1"])
         # Fake an interruption
-        self.make_fake_second_volume("backup1")
+        self.make_fake_second_volume(u"backup1")
         # Add new file
         assert not os.system("cp %s/file1 %s/newfile" % (source, source))
         # 'restart' the backup
-        self.backup("full", source, options=["--name=backup1"])
+        self.backup(u"full", source, options=[u"--name=backup1"])
         # Confirm we actually resumed the previous backup
         self.assertEqual(len(os.listdir("testfiles/output")), 4)
         # Now make sure everything is byte-for-byte the same once restored
@@ -196,15 +196,15 @@
         If we restart right after a volume that ended with a large
         (multi-block) file, make sure we restart in the right place.
         """
-        source = 'testfiles/largefiles'
+        source = u'testfiles/largefiles'
         self.make_largefiles(count=1, size=1)
-        self.backup("full", source, options=["--volsize=5", "--name=backup1"])
+        self.backup(u"full", source, options=[u"--volsize=5", u"--name=backup1"])
         # Fake an interruption
-        self.make_fake_second_volume("backup1")
+        self.make_fake_second_volume(u"backup1")
         # Add new file
         assert not os.system("cp %s/file1 %s/newfile" % (source, source))
         # 'restart' the backup
-        self.backup("full", source, options=["--volsize=5", "--name=backup1"])
+        self.backup(u"full", source, options=[u"--volsize=5", u"--name=backup1"])
         # Confirm we actually resumed the previous backup
         self.assertEqual(len(os.listdir("testfiles/output")), 4)
         # Now make sure everything is byte-for-byte the same once restored
@@ -216,13 +216,13 @@
         If we restart right after a volume that ended inside of a large
         (multi-block) file, make sure we restart in the right place.
         """
-        source = 'testfiles/largefiles'
+        source = u'testfiles/largefiles'
         self.make_largefiles(count=1, size=3)
-        self.backup("full", source, options=["--name=backup1"])
+        self.backup(u"full", source, options=[u"--name=backup1"])
         # Fake an interruption
-        self.make_fake_second_volume("backup1")
+        self.make_fake_second_volume(u"backup1")
         # 'restart' the backup
-        self.backup("full", source, options=["--name=backup1"])
+        self.backup(u"full", source, options=[u"--name=backup1"])
         # Now make sure everything is byte-for-byte the same once restored
         self.restore()
         assert not os.system("diff -r %s testfiles/restore_out" % source)
@@ -234,16 +234,16 @@
         (Expected result is to ignore new, ealier files, but pick up later
         ones.)
         """
-        source = 'testfiles/largefiles'
+        source = u'testfiles/largefiles'
         self.make_largefiles(count=1, size=1)
-        self.backup("full", source, options=["--name=backup1"])
+        self.backup(u"full", source, options=[u"--name=backup1"])
         # Fake an interruption
-        self.make_fake_second_volume("backup1")
+        self.make_fake_second_volume(u"backup1")
         # Add new files, earlier and later in filename sort order
         assert not os.system("echo hello > %s/a" % source)
         assert not os.system("echo hello > %s/z" % source)
         # 'restart' the backup
-        self.backup("full", source, options=["--name=backup1"])
+        self.backup(u"full", source, options=[u"--name=backup1"])
         # Now make sure everything is the same once restored, except 'a'
         self.restore()
         assert not os.system("test ! -e testfiles/restore_out/a")
@@ -258,15 +258,15 @@
         if the source data changes to be small enough to not create a vol3 on
         restart.
         """
-        source = 'testfiles/largefiles'
+        source = u'testfiles/largefiles'
         self.make_largefiles(count=5, size=1)
-        self.backup("full", source, fail=3)
+        self.backup(u"full", source, fail=3)
         # now delete the last volume on remote end and some source files
         assert not os.system("rm testfiles/output/duplicity-full*vol3.difftar*")
         assert not os.system("rm %s/file[2345]" % source)
         assert not os.system("echo hello > %s/z" % source)
         # finish backup
-        self.backup("full", source)
+        self.backup(u"full", source)
         # and verify we can restore
         self.restore()
 
@@ -277,14 +277,14 @@
         possible that the first chunk of the next file will be skipped unless
         we're careful.
         """
-        source = 'testfiles/largefiles'
+        source = u'testfiles/largefiles'
         self.make_largefiles(count=1)
-        self.backup("full", source, fail=2)
+        self.backup(u"full", source, fail=2)
         # now remove starting source data and make sure we add something after
         assert not os.system("rm %s/*" % source)
         assert not os.system("echo hello > %s/z" % source)
         # finish backup
-        self.backup("full", source)
+        self.backup(u"full", source)
         # and verify we can restore
         self.restore()
         assert not os.system("diff %s/z testfiles/restore_out/z" % source)
@@ -295,7 +295,7 @@
 
     def setUp(self):
         super(RestartTestWithoutEncryption, self).setUp()
-        self.class_args.extend(["--no-encryption"])
+        self.class_args.extend([u"--no-encryption"])
 
     def test_no_write_double_snapshot(self):
         """
@@ -305,8 +305,8 @@
         https://launchpad.net/bugs/929067
         """
         self.make_largefiles()
-        self.backup("full", "testfiles/largefiles", fail=2)
-        self.backup("full", "testfiles/largefiles")
+        self.backup(u"full", u"testfiles/largefiles", fail=2)
+        self.backup(u"full", u"testfiles/largefiles")
         # Now check sigtar
         sigtars = glob.glob("testfiles/output/duplicity-full*.sigtar.gz")
         self.assertEqual(1, len(sigtars))
@@ -333,7 +333,7 @@
             raise Exception("Platform %s not supported by tar/gtar." % platform.platform())
 
         # Intial normal backup
-        self.backup("full", "testfiles/blocktartest")
+        self.backup(u"full", u"testfiles/blocktartest")
         # Create an exact clone of the snapshot folder in the sigtar already.
         # Permissions and mtime must match.
         os.mkdir("testfiles/snapshot", 0o755)
@@ -353,7 +353,7 @@
         self.assertEqual(0, os.system("rm -r testfiles/cache"))
         # Try a follow on incremental (which in buggy versions, would create
         # a deleted entry for the base dir)
-        self.backup("inc", "testfiles/blocktartest")
+        self.backup(u"inc", u"testfiles/blocktartest")
         self.assertEqual(1, len(glob.glob("testfiles/output/duplicity-new*.sigtar.gz")))
         # Confirm we can restore it (which in buggy versions, would fail)
         self.restore()

=== modified file 'testing/functional/test_selection.py'
--- testing/functional/test_selection.py	2017-07-11 14:55:38 +0000
+++ testing/functional/test_selection.py	2017-12-01 23:01:42 +0000
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
 #
 # Copyright 2014 Aaron Whitehouse <aaron@xxxxxxxxxxxxxxxxxx>
@@ -21,6 +22,7 @@
 import os
 import sys
 import platform
+import io
 
 import unittest
 
@@ -91,57 +93,57 @@
     # --------- trailing_space sub2_file.txt (ea)  # Excluded until trailing_space test, when (is)
 
     complete_directory_tree = [
-        ['1', '2', '3', 'trailing_space ', '1.doc', '1.py'],
-        ['1sub1', '1sub2', '1sub3'],
-        ['1sub1sub1', '1sub1sub2', '1sub1sub3'],
-        ['1sub1sub1_file.txt'],
-        ['1sub1sub2_file.txt'],
-        ['1sub1sub3_file.txt'],
-        ['1sub2sub1', '1sub2sub2', '1sub2sub3'],
-        ['1sub3sub1', '1sub3sub2', '1sub3sub3'],
-        ['2sub1', '2sub2', '2sub3'],
-        ['2sub1sub1', '2sub1sub2', '2sub1sub3'],
-        ['2sub1sub1_file.txt'],
-        ['2sub2sub1', '2sub2sub2', '2sub2sub3'],
-        ['2sub3sub1', '2sub3sub2', '2sub3sub3'],
-        ['3sub1', '3sub2', '3sub3'],
-        ['3sub1sub1', '3sub1sub2', '3sub1sub3'],
-        ['3sub2sub1', '3sub2sub2', '3sub2sub3'],
-        ['3sub3sub1', '3sub3sub2', '3sub3sub3'],
-        ['3sub3sub2_file.txt'],
-        ['trailing_space sub1', 'trailing_space sub2'],
-        ['trailing_space sub2_file.txt']
+        [u"1", u"2", u"3", u"trailing_space ", u"1.doc", u"1.py"],
+        [u"1sub1", u"1sub2", u"1sub3"],
+        [u"1sub1sub1", u"1sub1sub2", u"1sub1sub3"],
+        [u"1sub1sub1_file.txt"],
+        [u"1sub1sub2_file.txt"],
+        [u"1sub1sub3_file.txt"],
+        [u"1sub2sub1", u"1sub2sub2", u"1sub2sub3"],
+        [u"1sub3sub1", u"1sub3sub2", u"1sub3sub3"],
+        [u"2sub1", u"2sub2", u"2sub3"],
+        [u"2sub1sub1", u"2sub1sub2", u"2sub1sub3"],
+        [u"2sub1sub1_file.txt"],
+        [u"2sub2sub1", u"2sub2sub2", u"2sub2sub3"],
+        [u"2sub3sub1", u"2sub3sub2", u"2sub3sub3"],
+        [u"3sub1", u"3sub2", u"3sub3"],
+        [u"3sub1sub1", u"3sub1sub2", u"3sub1sub3"],
+        [u"3sub2sub1", u"3sub2sub2", u"3sub2sub3"],
+        [u"3sub3sub1", u"3sub3sub2", u"3sub3sub3"],
+        [u"3sub3sub2_file.txt"],
+        [u"trailing_space sub1", u"trailing_space sub2"],
+        [u"trailing_space sub2_file.txt"]
     ]
 
-    expected_restored_tree = [['1', '2', '3', '1.py'],
-                              ['1sub1', '1sub2', '1sub3'],
-                              ['1sub1sub1', '1sub1sub3'],
-                              ['1sub1sub1_file.txt'],
-                              ['1sub2sub1'],
-                              ['1sub3sub3'],
-                              ['2sub1'],
-                              ['2sub1sub1'],
-                              ['2sub1sub1_file.txt'],
-                              ['3sub2', '3sub3'],
-                              ['3sub2sub1', '3sub2sub2', '3sub2sub3'],
-                              ['3sub3sub1', '3sub3sub2', '3sub3sub3'],
-                              ['3sub3sub2_file.txt']]
+    expected_restored_tree = [[u"1", u"2", u"3", u"1.py"],
+                              [u"1sub1", u"1sub2", u"1sub3"],
+                              [u"1sub1sub1", u"1sub1sub3"],
+                              [u"1sub1sub1_file.txt"],
+                              [u"1sub2sub1"],
+                              [u"1sub3sub3"],
+                              [u"2sub1"],
+                              [u"2sub1sub1"],
+                              [u"2sub1sub1_file.txt"],
+                              [u"3sub2", u"3sub3"],
+                              [u"3sub2sub1", u"3sub2sub2", u"3sub2sub3"],
+                              [u"3sub3sub1", u"3sub3sub2", u"3sub3sub3"],
+                              [u"3sub3sub2_file.txt"]]
 
-    expected_restored_tree_with_trailing_space = [['1', '2', '3', 'trailing_space ', '1.py'],
-                                                  ['1sub1', '1sub2', '1sub3'],
-                                                  ['1sub1sub1', '1sub1sub3'],
-                                                  ['1sub1sub1_file.txt'],
-                                                  ['1sub2sub1'],
-                                                  ['1sub3sub3'],
-                                                  ['2sub1'],
-                                                  ['2sub1sub1'],
-                                                  ['2sub1sub1_file.txt'],
-                                                  ['3sub2', '3sub3'],
-                                                  ['3sub2sub1', '3sub2sub2', '3sub2sub3'],
-                                                  ['3sub3sub1', '3sub3sub2', '3sub3sub3'],
-                                                  ['3sub3sub2_file.txt'],
-                                                  ['trailing_space sub1', 'trailing_space sub2'],
-                                                  ['trailing_space sub2_file.txt']]
+    expected_restored_tree_with_trailing_space = [[u"1", u"2", u"3", u"trailing_space ", u"1.py"],
+                                                  [u"1sub1", u"1sub2", u"1sub3"],
+                                                  [u"1sub1sub1", u"1sub1sub3"],
+                                                  [u"1sub1sub1_file.txt"],
+                                                  [u"1sub2sub1"],
+                                                  [u"1sub3sub3"],
+                                                  [u"2sub1"],
+                                                  [u"2sub1sub1"],
+                                                  [u"2sub1sub1_file.txt"],
+                                                  [u"3sub2", u"3sub3"],
+                                                  [u"3sub2sub1", u"3sub2sub2", u"3sub2sub3"],
+                                                  [u"3sub3sub1", u"3sub3sub2", u"3sub3sub3"],
+                                                  [u"3sub3sub2_file.txt"],
+                                                  [u"trailing_space sub1", u"trailing_space sub2"],
+                                                  [u"trailing_space sub2_file.txt"]]
 
     def directory_tree_to_list_of_lists(self, parent_directory):
         """
@@ -167,7 +169,7 @@
 
     def test_files_are_as_expected(self):
         """Test that the contents of testfiles/select are as expected."""
-        testfiles = self.directory_tree_to_list_of_lists('testfiles/select2')
+        testfiles = self.directory_tree_to_list_of_lists(u"testfiles/select2")
         # print(testfiles)
         self.assertEqual(testfiles, self.complete_directory_tree)
 
@@ -177,28 +179,28 @@
 
     def test_include_exclude_basic(self):
         """ Test --include and --exclude work in the basic case """
-        self.backup("full", "testfiles/select2",
-                    options=["--include", "testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt",
-                             "--exclude", "testfiles/select2/3/3sub3/3sub3sub2",
-                             "--include", "testfiles/select2/3/3sub2/3sub2sub2",
-                             "--include", "testfiles/select2/3/3sub3",
-                             "--exclude", "testfiles/select2/3/3sub1",
-                             "--exclude", "testfiles/select2/2/2sub1/2sub1sub3",
-                             "--exclude", "testfiles/select2/2/2sub1/2sub1sub2",
-                             "--include", "testfiles/select2/2/2sub1",
-                             "--exclude", "testfiles/select2/1/1sub3/1sub3sub2",
-                             "--exclude", "testfiles/select2/1/1sub3/1sub3sub1",
-                             "--exclude", "testfiles/select2/1/1sub2/1sub2sub3",
-                             "--include", "testfiles/select2/1/1sub2/1sub2sub1",
-                             "--exclude", "testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt",
-                             "--exclude", "testfiles/select2/1/1sub1/1sub1sub2",
-                             "--exclude", "testfiles/select2/1/1sub2",
-                             "--include", "testfiles/select2/1.py",
-                             "--include", "testfiles/select2/3",
-                             "--include", "testfiles/select2/1",
-                             "--exclude", "testfiles/select2/**"])
+        self.backup(u"full", u"testfiles/select2",
+                    options=[u"--include", u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt",
+                             u"--exclude", u"testfiles/select2/3/3sub3/3sub3sub2",
+                             u"--include", u"testfiles/select2/3/3sub2/3sub2sub2",
+                             u"--include", u"testfiles/select2/3/3sub3",
+                             u"--exclude", u"testfiles/select2/3/3sub1",
+                             u"--exclude", u"testfiles/select2/2/2sub1/2sub1sub3",
+                             u"--exclude", u"testfiles/select2/2/2sub1/2sub1sub2",
+                             u"--include", u"testfiles/select2/2/2sub1",
+                             u"--exclude", u"testfiles/select2/1/1sub3/1sub3sub2",
+                             u"--exclude", u"testfiles/select2/1/1sub3/1sub3sub1",
+                             u"--exclude", u"testfiles/select2/1/1sub2/1sub2sub3",
+                             u"--include", u"testfiles/select2/1/1sub2/1sub2sub1",
+                             u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt",
+                             u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub2",
+                             u"--exclude", u"testfiles/select2/1/1sub2",
+                             u"--include", u"testfiles/select2/1.py",
+                             u"--include", u"testfiles/select2/3",
+                             u"--include", u"testfiles/select2/1",
+                             u"--exclude", u"testfiles/select2/**"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, self.expected_restored_tree)
 
@@ -207,32 +209,32 @@
         # Note that, because this only passes items in as a list of options, this test does not test whether duplicity
         # would correctly interpret commandline options with spaces. However, bin/duplicity uses sys.argv[1:], which
         # should return a list of strings after having correctly processed quotes etc.
-        self.backup("full", "testfiles/select2",
-                    options=["--include",
-                             "testfiles/select2/trailing_space /trailing_space sub2/trailing_space sub2_file.txt",
-                             "--exclude", "testfiles/select2/trailing_space /trailing_space sub2",
-                             "--include", "testfiles/select2/trailing_space ",
-                             "--include", "testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt",
-                             "--exclude", "testfiles/select2/3/3sub3/3sub3sub2",
-                             "--include", "testfiles/select2/3/3sub2/3sub2sub2",
-                             "--include", "testfiles/select2/3/3sub3",
-                             "--exclude", "testfiles/select2/3/3sub1",
-                             "--exclude", "testfiles/select2/2/2sub1/2sub1sub3",
-                             "--exclude", "testfiles/select2/2/2sub1/2sub1sub2",
-                             "--include", "testfiles/select2/2/2sub1",
-                             "--exclude", "testfiles/select2/1/1sub3/1sub3sub2",
-                             "--exclude", "testfiles/select2/1/1sub3/1sub3sub1",
-                             "--exclude", "testfiles/select2/1/1sub2/1sub2sub3",
-                             "--include", "testfiles/select2/1/1sub2/1sub2sub1",
-                             "--exclude", "testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt",
-                             "--exclude", "testfiles/select2/1/1sub1/1sub1sub2",
-                             "--exclude", "testfiles/select2/1/1sub2",
-                             "--include", "testfiles/select2/1.py",
-                             "--include", "testfiles/select2/3",
-                             "--include", "testfiles/select2/1",
-                             "--exclude", "testfiles/select2/**"])
+        self.backup(u"full", u"testfiles/select2",
+                    options=[u"--include",
+                             u"testfiles/select2/trailing_space /trailing_space sub2/trailing_space sub2_file.txt",
+                             u"--exclude", u"testfiles/select2/trailing_space /trailing_space sub2",
+                             u"--include", u"testfiles/select2/trailing_space ",
+                             u"--include", u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt",
+                             u"--exclude", u"testfiles/select2/3/3sub3/3sub3sub2",
+                             u"--include", u"testfiles/select2/3/3sub2/3sub2sub2",
+                             u"--include", u"testfiles/select2/3/3sub3",
+                             u"--exclude", u"testfiles/select2/3/3sub1",
+                             u"--exclude", u"testfiles/select2/2/2sub1/2sub1sub3",
+                             u"--exclude", u"testfiles/select2/2/2sub1/2sub1sub2",
+                             u"--include", u"testfiles/select2/2/2sub1",
+                             u"--exclude", u"testfiles/select2/1/1sub3/1sub3sub2",
+                             u"--exclude", u"testfiles/select2/1/1sub3/1sub3sub1",
+                             u"--exclude", u"testfiles/select2/1/1sub2/1sub2sub3",
+                             u"--include", u"testfiles/select2/1/1sub2/1sub2sub1",
+                             u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt",
+                             u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub2",
+                             u"--exclude", u"testfiles/select2/1/1sub2",
+                             u"--include", u"testfiles/select2/1.py",
+                             u"--include", u"testfiles/select2/3",
+                             u"--include", u"testfiles/select2/1",
+                             u"--exclude", u"testfiles/select2/**"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, self.expected_restored_tree_with_trailing_space)
 
@@ -246,29 +248,29 @@
         """Test that exclude filelist works in the basic case """
         # As this is an exclude filelist any lines with no +/- modifier should be treated as if they have a -.
         # Create a filelist
-        with open('testfiles/exclude.txt', 'w') as f:
-            f.write('+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'
-                    'testfiles/select2/3/3sub3/3sub3sub2\n'
-                    '+ testfiles/select2/3/3sub2/3sub2sub2\n'
-                    '+ testfiles/select2/3/3sub3\n'
-                    '- testfiles/select2/3/3sub1\n'  # - added to ensure it makes no difference
-                    'testfiles/select2/2/2sub1/2sub1sub3\n'
-                    'testfiles/select2/2/2sub1/2sub1sub2\n'
-                    '+ testfiles/select2/2/2sub1\n'
-                    'testfiles/select2/1/1sub3/1sub3sub2\n'
-                    'testfiles/select2/1/1sub3/1sub3sub1\n'
-                    'testfiles/select2/1/1sub2/1sub2sub3\n'
-                    '+ testfiles/select2/1/1sub2/1sub2sub1\n'
-                    'testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'
-                    'testfiles/select2/1/1sub1/1sub1sub2\n'
-                    '- testfiles/select2/1/1sub2\n'  # - added to ensure it makes no difference
-                    '+ testfiles/select2/1.py\n'
-                    '+ testfiles/select2/3\n'
-                    '+ testfiles/select2/1\n'
-                    'testfiles/select2/**')
-        self.backup("full", "testfiles/select2", options=["--exclude-filelist=testfiles/exclude.txt"])
+        with io.open(u"testfiles/exclude.txt", u"w") as f:
+            f.write(u"+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
+                    u"testfiles/select2/3/3sub3/3sub3sub2\n"
+                    u"+ testfiles/select2/3/3sub2/3sub2sub2\n"
+                    u"+ testfiles/select2/3/3sub3\n"
+                    u"- testfiles/select2/3/3sub1\n"  # - added to ensure it makes no difference
+                    u"testfiles/select2/2/2sub1/2sub1sub3\n"
+                    u"testfiles/select2/2/2sub1/2sub1sub2\n"
+                    u"+ testfiles/select2/2/2sub1\n"
+                    u"testfiles/select2/1/1sub3/1sub3sub2\n"
+                    u"testfiles/select2/1/1sub3/1sub3sub1\n"
+                    u"testfiles/select2/1/1sub2/1sub2sub3\n"
+                    u"+ testfiles/select2/1/1sub2/1sub2sub1\n"
+                    u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
+                    u"testfiles/select2/1/1sub1/1sub1sub2\n"
+                    u"- testfiles/select2/1/1sub2\n"  # - added to ensure it makes no difference
+                    u"+ testfiles/select2/1.py\n"
+                    u"+ testfiles/select2/3\n"
+                    u"+ testfiles/select2/1\n"
+                    u"testfiles/select2/**")
+        self.backup(u"full", u"testfiles/select2", options=[u"--exclude-filelist=testfiles/exclude.txt"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, self.expected_restored_tree)
 
@@ -285,33 +287,33 @@
         # * Unnecessarily quoted filenames with/without modifier (both " and ')
 
         # Create a filelist
-        with open('testfiles/exclude.txt', 'w') as f:
-            f.write('+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'
-                    'testfiles/select2/3/3sub3/3sub3sub2\n'
-                    '+ testfiles/select2/3/3sub2/3sub2sub2\n'
-                    ' + testfiles/select2/3/3sub3\n'  # Note leading space added here
-                    '- testfiles/select2/3/3sub1\n'
-                    '  testfiles/select2/2/2sub1/2sub1sub3\n'  # Note leading spaces added here
-                    '\n'
-                    'testfiles/select2/2/2sub1/2sub1sub2\n'
-                    ' + testfiles/select2/2/2sub1 \n'  # Note added trailing/leading space here
-                    '- "testfiles/select2/1/1sub3/1sub3sub2"\n'  # Unnecessary quotes
-                    '# Testing a full-line comment\n'
-                    "'testfiles/select2/1/1sub3/1sub3sub1'  \n"  # Note added spaces and quotes here
-                    'testfiles/select2/1/1sub2/1sub2sub3\n'
-                    '    \n'
-                    '+ testfiles/select2/1/1sub2/1sub2sub1\n'
-                    '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'
-                    'testfiles/select2/1/1sub1/1sub1sub2\n'
-                    '     # Testing a full-line comment with leading and trailing spaces     \n'
-                    'testfiles/select2/1/1sub2  \n'  # Note added spaces here
-                    '+ testfiles/select2/1.py\n'
-                    '+ testfiles/select2/3 \n'  # Note added space here
-                    '+ testfiles/select2/1\n'
-                    '- testfiles/select2/**')
-        self.backup("full", "testfiles/select2", options=["--exclude-filelist=testfiles/exclude.txt"])
+        with io.open(u"testfiles/exclude.txt", u"w") as f:
+            f.write(u"+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
+                    u"testfiles/select2/3/3sub3/3sub3sub2\n"
+                    u"+ testfiles/select2/3/3sub2/3sub2sub2\n"
+                    u" + testfiles/select2/3/3sub3\n"  # Note leading space added here
+                    u"- testfiles/select2/3/3sub1\n"
+                    u"  testfiles/select2/2/2sub1/2sub1sub3\n"  # Note leading spaces added here
+                    u"\n"
+                    u"testfiles/select2/2/2sub1/2sub1sub2\n"
+                    u" + testfiles/select2/2/2sub1 \n"  # Note added trailing/leading space here
+                    u'- "testfiles/select2/1/1sub3/1sub3sub2"\n'  # Unnecessary quotes
+                    u"# Testing a full-line comment\n"
+                    u"'testfiles/select2/1/1sub3/1sub3sub1'  \n"  # Note added spaces and quotes here
+                    u"testfiles/select2/1/1sub2/1sub2sub3\n"
+                    u"    \n"
+                    u"+ testfiles/select2/1/1sub2/1sub2sub1\n"
+                    u"- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
+                    u"testfiles/select2/1/1sub1/1sub1sub2\n"
+                    u"     # Testing a full-line comment with leading and trailing spaces     \n"
+                    u"testfiles/select2/1/1sub2  \n"  # Note added spaces here
+                    u"+ testfiles/select2/1.py\n"
+                    u"+ testfiles/select2/3 \n"  # Note added space here
+                    u"+ testfiles/select2/1\n"
+                    u"- testfiles/select2/**")
+        self.backup(u"full", u"testfiles/select2", options=[u"--exclude-filelist=testfiles/exclude.txt"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, self.expected_restored_tree)
 
@@ -330,65 +332,65 @@
         # * Unnecessarily quoted filenames with/without modifier (both " and ')
 
         # Create a filelist
-        with open('testfiles/exclude.txt', 'w') as f:
-            f.write('+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'
-                    'testfiles/select2/3/3sub3/3sub3sub2\n'
-                    '+ testfiles/select2/3/3sub2/3sub2sub2\n'
-                    ' + testfiles/select2/3/3sub3\n'  # Note leading space added here
-                    '- testfiles/select2/3/3sub1\n'
-                    '  testfiles/select2/2/2sub1/2sub1sub3\n'  # Note leading spaces added here
-                    '\n'
-                    'testfiles/select2/2/2sub1/2sub1sub2\n'
-                    ' + testfiles/select2/2/2sub1 \n'  # Note added trailing/leading space here
-                    '- "testfiles/select2/1/1sub3/1sub3sub2"\n'  # Unnecessary quotes
-                    '# Testing a full-line comment\n'
-                    "'testfiles/select2/1/1sub3/1sub3sub1'  \n"  # Note added spaces and quotes here
-                    'testfiles/select2/1/1sub2/1sub2sub3\n'
-                    '    \n'
-                    '+ testfiles/select2/1/1sub2/1sub2sub1\n'
-                    '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'
-                    'testfiles/select2/1/1sub1/1sub1sub2\n'
-                    '     # Testing a full-line comment with leading and trailing spaces     \n'
-                    'testfiles/select2/1/1sub2  \n'  # Note added spaces here
-                    '+ testfiles/select2/1.py\n'
-                    '+ testfiles/select2/3 \n'  # Note added space here
-                    '+ testfiles/select2/1\n'
-                    '- testfiles/select2/**')
-        self.backup("full", "testfiles/select2", options=["--exclude-globbing-filelist=testfiles/exclude.txt"])
+        with io.open(u"testfiles/exclude.txt", u"w") as f:
+            f.write(u"+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
+                    u"testfiles/select2/3/3sub3/3sub3sub2\n"
+                    u"+ testfiles/select2/3/3sub2/3sub2sub2\n"
+                    u" + testfiles/select2/3/3sub3\n"  # Note leading space added here
+                    u"- testfiles/select2/3/3sub1\n"
+                    u"  testfiles/select2/2/2sub1/2sub1sub3\n"  # Note leading spaces added here
+                    u"\n"
+                    u"testfiles/select2/2/2sub1/2sub1sub2\n"
+                    u" + testfiles/select2/2/2sub1 \n"  # Note added trailing/leading space here
+                    u'- "testfiles/select2/1/1sub3/1sub3sub2"\n'  # Unnecessary quotes
+                    u"# Testing a full-line comment\n"
+                    u"'testfiles/select2/1/1sub3/1sub3sub1'  \n"  # Note added spaces and quotes here
+                    u"testfiles/select2/1/1sub2/1sub2sub3\n"
+                    u"    \n"
+                    u"+ testfiles/select2/1/1sub2/1sub2sub1\n"
+                    u"- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
+                    u"testfiles/select2/1/1sub1/1sub1sub2\n"
+                    u"     # Testing a full-line comment with leading and trailing spaces     \n"
+                    u"testfiles/select2/1/1sub2  \n"  # Note added spaces here
+                    u"+ testfiles/select2/1.py\n"
+                    u"+ testfiles/select2/3 \n"  # Note added space here
+                    u"+ testfiles/select2/1\n"
+                    u"- testfiles/select2/**")
+        self.backup(u"full", u"testfiles/select2", options=[u"--exclude-globbing-filelist=testfiles/exclude.txt"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, self.expected_restored_tree)
 
     def test_exclude_filelist_trailing_whitespace_folders_work_with_quotes(self):
         """Test that folders with trailing whitespace in the names work correctly if they are enclosed in quotes"""
         # Create a filelist
-        with open('testfiles/exclude.txt', 'w') as f:
-            f.write('+ "testfiles/select2/trailing_space /trailing_space sub2/trailing_space sub2_file.txt"\n'  # New
-                    '- "testfiles/select2/trailing_space /trailing_space sub2"\n'  # New
-                    '+ "testfiles/select2/trailing_space "\n'  # New
-                    '+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'
-                    'testfiles/select2/3/3sub3/3sub3sub2\n'
-                    '+ testfiles/select2/3/3sub2/3sub2sub2\n'
-                    '+ testfiles/select2/3/3sub3\n'
-                    '- testfiles/select2/3/3sub1\n'
-                    'testfiles/select2/2/2sub1/2sub1sub3\n'
-                    'testfiles/select2/2/2sub1/2sub1sub2\n'
-                    '+ testfiles/select2/2/2sub1\n'
-                    'testfiles/select2/1/1sub3/1sub3sub2\n'
-                    'testfiles/select2/1/1sub3/1sub3sub1\n'
-                    'testfiles/select2/1/1sub2/1sub2sub3\n'
-                    '+ testfiles/select2/1/1sub2/1sub2sub1\n'
-                    'testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'
-                    'testfiles/select2/1/1sub1/1sub1sub2\n'
-                    '- testfiles/select2/1/1sub2\n'
-                    '+ testfiles/select2/1.py\n'
-                    '+ testfiles/select2/3\n'
-                    '+ testfiles/select2/1\n'
-                    'testfiles/select2/**')
-        self.backup("full", "testfiles/select2", options=["--exclude-filelist=testfiles/exclude.txt"])
+        with io.open(u"testfiles/exclude.txt", u"w") as f:
+            f.write(u'+ "testfiles/select2/trailing_space /trailing_space sub2/trailing_space sub2_file.txt"\n'  # New
+                    u"- 'testfiles/select2/trailing_space /trailing_space sub2'\n"  # New
+                    u'+ "testfiles/select2/trailing_space "\n'  # New
+                    u"+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
+                    u"testfiles/select2/3/3sub3/3sub3sub2\n"
+                    u"+ testfiles/select2/3/3sub2/3sub2sub2\n"
+                    u"+ testfiles/select2/3/3sub3\n"
+                    u"- testfiles/select2/3/3sub1\n"
+                    u"testfiles/select2/2/2sub1/2sub1sub3\n"
+                    u"testfiles/select2/2/2sub1/2sub1sub2\n"
+                    u"+ testfiles/select2/2/2sub1\n"
+                    u"testfiles/select2/1/1sub3/1sub3sub2\n"
+                    u"testfiles/select2/1/1sub3/1sub3sub1\n"
+                    u"testfiles/select2/1/1sub2/1sub2sub3\n"
+                    u"+ testfiles/select2/1/1sub2/1sub2sub1\n"
+                    u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
+                    u"testfiles/select2/1/1sub1/1sub1sub2\n"
+                    u"- testfiles/select2/1/1sub2\n"
+                    u"+ testfiles/select2/1.py\n"
+                    u"+ testfiles/select2/3\n"
+                    u"+ testfiles/select2/1\n"
+                    u"testfiles/select2/**")
+        self.backup(u"full", u"testfiles/select2", options=[u"--exclude-filelist=testfiles/exclude.txt"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, self.expected_restored_tree_with_trailing_space)
 
@@ -396,32 +398,32 @@
         """Test that exclude filelist is unaffected by the --progress option"""
         # Regression test for Bug #1264744 (https://bugs.launchpad.net/duplicity/+bug/1264744)
         # Create a filelist identical to that used in test_exclude_filelist
-        with open('testfiles/exclude.txt', 'w') as f:
-            f.write('+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'
-                    'testfiles/select2/3/3sub3/3sub3sub2\n'
-                    '+ testfiles/select2/3/3sub2/3sub2sub2\n'
-                    '+ testfiles/select2/3/3sub3\n'
-                    '- testfiles/select2/3/3sub1\n'  # - added to ensure it makes no difference
-                    'testfiles/select2/2/2sub1/2sub1sub3\n'
-                    'testfiles/select2/2/2sub1/2sub1sub2\n'
-                    '+ testfiles/select2/2/2sub1\n'
-                    'testfiles/select2/1/1sub3/1sub3sub2\n'
-                    'testfiles/select2/1/1sub3/1sub3sub1\n'
-                    'testfiles/select2/1/1sub2/1sub2sub3\n'
-                    '+ testfiles/select2/1/1sub2/1sub2sub1\n'
-                    'testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'
-                    'testfiles/select2/1/1sub1/1sub1sub2\n'
-                    '- testfiles/select2/1/1sub2\n'  # - added to ensure it makes no difference
-                    '+ testfiles/select2/1.py\n'
-                    '+ testfiles/select2/3\n'
-                    '+ testfiles/select2/1\n'
-                    'testfiles/select2/**')
+        with io.open(u"testfiles/exclude.txt", u"w") as f:
+            f.write(u"+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
+                    u"testfiles/select2/3/3sub3/3sub3sub2\n"
+                    u"+ testfiles/select2/3/3sub2/3sub2sub2\n"
+                    u"+ testfiles/select2/3/3sub3\n"
+                    u"- testfiles/select2/3/3sub1\n"  # - added to ensure it makes no difference
+                    u"testfiles/select2/2/2sub1/2sub1sub3\n"
+                    u"testfiles/select2/2/2sub1/2sub1sub2\n"
+                    u"+ testfiles/select2/2/2sub1\n"
+                    u"testfiles/select2/1/1sub3/1sub3sub2\n"
+                    u"testfiles/select2/1/1sub3/1sub3sub1\n"
+                    u"testfiles/select2/1/1sub2/1sub2sub3\n"
+                    u"+ testfiles/select2/1/1sub2/1sub2sub1\n"
+                    u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
+                    u"testfiles/select2/1/1sub1/1sub1sub2\n"
+                    u"- testfiles/select2/1/1sub2\n"  # - added to ensure it makes no difference
+                    u"+ testfiles/select2/1.py\n"
+                    u"+ testfiles/select2/3\n"
+                    u"+ testfiles/select2/1\n"
+                    u"testfiles/select2/**")
 
         # Backup the files exactly as in test_exclude_filelist, but with the --progress option
-        self.backup("full", "testfiles/select2", options=["--exclude-filelist=testfiles/exclude.txt",
-                                                          "--progress"])
+        self.backup(u"full", u"testfiles/select2", options=[u"--exclude-filelist=testfiles/exclude.txt",
+                                                          u"--progress"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         # The restored files should match those restored in test_exclude_filelist
         self.assertEqual(restored, self.expected_restored_tree)
@@ -437,29 +439,29 @@
         # See test_exclude_filelist above for explanation of what is expected. As this is an include filelist
         # any lines with no +/- modifier should be treated as if they have a +.
         # Create a filelist
-        with open('testfiles/include.txt', 'w') as f:
-            f.write('testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'
-                    '- testfiles/select2/3/3sub3/3sub3sub2\n'
-                    'testfiles/select2/3/3sub2/3sub2sub2\n'
-                    '+ testfiles/select2/3/3sub3\n'  # + added to ensure it makes no difference
-                    '- testfiles/select2/3/3sub1\n'
-                    '- testfiles/select2/2/2sub1/2sub1sub3\n'
-                    '- testfiles/select2/2/2sub1/2sub1sub2\n'
-                    'testfiles/select2/2/2sub1\n'
-                    '- testfiles/select2/1/1sub3/1sub3sub2\n'
-                    '- testfiles/select2/1/1sub3/1sub3sub1\n'
-                    '- testfiles/select2/1/1sub2/1sub2sub3\n'
-                    '+ testfiles/select2/1/1sub2/1sub2sub1\n'  # + added to ensure it makes no difference
-                    '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'
-                    '- testfiles/select2/1/1sub1/1sub1sub2\n'
-                    '- testfiles/select2/1/1sub2\n'
-                    'testfiles/select2/1.py\n'
-                    'testfiles/select2/3\n'
-                    'testfiles/select2/1\n'
-                    '- testfiles/select2/**')
-        self.backup("full", "testfiles/select2", options=["--include-filelist=testfiles/include.txt"])
+        with io.open(u"testfiles/include.txt", u"w") as f:
+            f.write(u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
+                    u"- testfiles/select2/3/3sub3/3sub3sub2\n"
+                    u"testfiles/select2/3/3sub2/3sub2sub2\n"
+                    u"+ testfiles/select2/3/3sub3\n"  # + added to ensure it makes no difference
+                    u"- testfiles/select2/3/3sub1\n"
+                    u"- testfiles/select2/2/2sub1/2sub1sub3\n"
+                    u"- testfiles/select2/2/2sub1/2sub1sub2\n"
+                    u"testfiles/select2/2/2sub1\n"
+                    u"- testfiles/select2/1/1sub3/1sub3sub2\n"
+                    u"- testfiles/select2/1/1sub3/1sub3sub1\n"
+                    u"- testfiles/select2/1/1sub2/1sub2sub3\n"
+                    u"+ testfiles/select2/1/1sub2/1sub2sub1\n"  # + added to ensure it makes no difference
+                    u"- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
+                    u"- testfiles/select2/1/1sub1/1sub1sub2\n"
+                    u"- testfiles/select2/1/1sub2\n"
+                    u"testfiles/select2/1.py\n"
+                    u"testfiles/select2/3\n"
+                    u"testfiles/select2/1\n"
+                    u"- testfiles/select2/**")
+        self.backup(u"full", u"testfiles/select2", options=[u"--include-filelist=testfiles/include.txt"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, self.expected_restored_tree)
 
@@ -475,33 +477,33 @@
         # * Full-line comments with # as the first character and with leading/trailing spaces
         # * Unnecessarily quoted filenames with/without modifier  (both " and ')
         # Create a filelist
-        with open('testfiles/include.txt', 'w') as f:
-            f.write('testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'
-                    '- testfiles/select2/3/3sub3/3sub3sub2\n'
-                    '"testfiles/select2/3/3sub2/3sub2sub2"\n'
-                    '  + testfiles/select2/3/3sub3\n'  # + added to ensure it makes no difference
-                    '- testfiles/select2/3/3sub1\n'
-                    '- testfiles/select2/2/2sub1/2sub1sub3\n'
-                    ' - "testfiles/select2/2/2sub1/2sub1sub2"\n'
-                    'testfiles/select2/2/2sub1  \n'
-                    '\n'
-                    '- testfiles/select2/1/1sub3/1sub3sub2\n'
-                    '- testfiles/select2/1/1sub3/1sub3sub1 \n'
-                    "- 'testfiles/select2/1/1sub2/1sub2sub3'\n"
-                    '             \n'
-                    ' + testfiles/select2/1/1sub2/1sub2sub1 \n'  # + added to ensure it makes no difference
-                    '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'
-                    '  - testfiles/select2/1/1sub1/1sub1sub2  \n'
-                    '# Testing full-line comment\n'
-                    '- testfiles/select2/1/1sub2\n'
-                    "'testfiles/select2/1.py'\n"
-                    'testfiles/select2/3\n'
-                    '        #  Testing another full-line comment      \n'
-                    'testfiles/select2/1\n'
-                    '- testfiles/select2/**')
-        self.backup("full", "testfiles/select2", options=["--include-filelist=testfiles/include.txt"])
+        with io.open(u"testfiles/include.txt", u"w") as f:
+            f.write(u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
+                    u"- testfiles/select2/3/3sub3/3sub3sub2\n"
+                    u'"testfiles/select2/3/3sub2/3sub2sub2"\n'
+                    u"  + testfiles/select2/3/3sub3\n"  # + added to ensure it makes no difference
+                    u"- testfiles/select2/3/3sub1\n"
+                    u"- testfiles/select2/2/2sub1/2sub1sub3\n"
+                    u' - "testfiles/select2/2/2sub1/2sub1sub2"\n'
+                    u"testfiles/select2/2/2sub1  \n"
+                    u"\n"
+                    u"- testfiles/select2/1/1sub3/1sub3sub2\n"
+                    u"- testfiles/select2/1/1sub3/1sub3sub1 \n"
+                    u"- 'testfiles/select2/1/1sub2/1sub2sub3'\n"
+                    u"             \n"
+                    u" + testfiles/select2/1/1sub2/1sub2sub1 \n"  # + added to ensure it makes no difference
+                    u"- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
+                    u"  - testfiles/select2/1/1sub1/1sub1sub2  \n"
+                    u"# Testing full-line comment\n"
+                    u"- testfiles/select2/1/1sub2\n"
+                    u"'testfiles/select2/1.py'\n"
+                    u"testfiles/select2/3\n"
+                    u"        #  Testing another full-line comment      \n"
+                    u"testfiles/select2/1\n"
+                    u"- testfiles/select2/**")
+        self.backup(u"full", u"testfiles/select2", options=[u"--include-filelist=testfiles/include.txt"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, self.expected_restored_tree)
 
@@ -519,37 +521,37 @@
         # * Full-line comments with # as the first character and with leading/trailing spaces
         # * Unnecessarily quoted filenames with/without modifier  (both " and ')
         # Create a filelist
-        with open('testfiles/include.txt', 'w') as f:
-            f.write('testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'
-                    'testfiles/select2/3/3sub2/3sub2sub2 \n'
-                    '  + testfiles/select2/3/3sub3\n'  # + added to ensure it makes no difference
-                    ' - testfiles/select2/3/3sub1  \n'
-                    '- testfiles/select2/2/2sub1/2sub1sub3\n'
-                    '- testfiles/select2/2/2sub1/2sub1sub2\n'
-                    '"testfiles/select2/2/2sub1"\n'
-                    '   - testfiles/select2/2/2sub3 \n'  # Added because of Bug #1408411
-                    '- testfiles/select2/2/2sub2\n'  # Added because of Bug #1408411
-                    "- 'testfiles/select2/1/1sub3/1sub3sub2'\n"
-                    '\n'
-                    '- testfiles/select2/1/1sub3/1sub3sub1\n'
-                    '- testfiles/select2/1/1sub2/1sub2sub3\n'
-                    '- "testfiles/select2/1/1sub2/1sub2sub2"\n'  # Added because of Bug #1408411
-                    '# This is a full-line comment\n'
-                    '+ testfiles/select2/1/1sub2/1sub2sub1  \n'  # + added to ensure it makes no difference
-                    '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'
-                    '          \n'
-                    '- testfiles/select2/1/1sub1/1sub1sub2\n'
-                    #  '- testfiles/select2/1/1sub2\n'  # Commented out because of Bug #1408411
-                    "'testfiles/select2/1.py'\n"
-                    '       # This is another full-line comment, with spaces     \n'
-                    'testfiles/select2/3\n'
-                    #  '- testfiles/select2/2\n' # Commented out because of Bug #1408411
-                    'testfiles/select2/1\n'
-                    '- "testfiles/select2/trailing_space "\n'  # es instead of ea as no wildcard - **
-                    '- testfiles/select2/1.doc')  # es instead of ea as no wildcard - **
-        self.backup("full", "testfiles/select2", options=["--include-filelist=testfiles/include.txt"])
+        with io.open(u"testfiles/include.txt", u"w") as f:
+            f.write(u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
+                    u"testfiles/select2/3/3sub2/3sub2sub2 \n"
+                    u"  + testfiles/select2/3/3sub3\n"  # + added to ensure it makes no difference
+                    u" - testfiles/select2/3/3sub1  \n"
+                    u"- testfiles/select2/2/2sub1/2sub1sub3\n"
+                    u"- testfiles/select2/2/2sub1/2sub1sub2\n"
+                    u'"testfiles/select2/2/2sub1"\n'
+                    u"   - testfiles/select2/2/2sub3 \n"  # Added because of Bug #1408411
+                    u"- testfiles/select2/2/2sub2\n"  # Added because of Bug #1408411
+                    u"- 'testfiles/select2/1/1sub3/1sub3sub2'\n"
+                    u"\n"
+                    u"- testfiles/select2/1/1sub3/1sub3sub1\n"
+                    u"- testfiles/select2/1/1sub2/1sub2sub3\n"
+                    u'- "testfiles/select2/1/1sub2/1sub2sub2"\n'  # Added because of Bug #1408411
+                    u"# This is a full-line comment\n"
+                    u"+ testfiles/select2/1/1sub2/1sub2sub1  \n"  # + added to ensure it makes no difference
+                    u"- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
+                    u"          \n"
+                    u"- testfiles/select2/1/1sub1/1sub1sub2\n"
+                    #  u"- testfiles/select2/1/1sub2\n"  # Commented out because of Bug #1408411
+                    u"'testfiles/select2/1.py'\n"
+                    u"       # This is another full-line comment, with spaces     \n"
+                    u"testfiles/select2/3\n"
+                    #  u"- testfiles/select2/2\n" # Commented out because of Bug #1408411
+                    u"testfiles/select2/1\n"
+                    u'- "testfiles/select2/trailing_space "\n'  # es instead of ea as no wildcard - **
+                    u"- testfiles/select2/1.doc")  # es instead of ea as no wildcard - **
+        self.backup(u"full", u"testfiles/select2", options=[u"--include-filelist=testfiles/include.txt"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, self.expected_restored_tree)
 
@@ -567,33 +569,33 @@
         # * Full-line comments with # as the first character and with leading/trailing spaces
         # * Unnecessarily quoted filenames with/without modifier  (both " and ')
         # Create a filelist
-        with open('testfiles/include.txt', 'w') as f:
-            f.write('testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'
-                    '- testfiles/select2/3/3sub3/3sub3sub2\n'
-                    '"testfiles/select2/3/3sub2/3sub2sub2"\n'
-                    '  + testfiles/select2/3/3sub3\n'  # + added to ensure it makes no difference
-                    '- testfiles/select2/3/3sub1\n'
-                    '- testfiles/select2/2/2sub1/2sub1sub3\n'
-                    ' - "testfiles/select2/2/2sub1/2sub1sub2"\n'
-                    'testfiles/select2/2/2sub1  \n'
-                    '\n'
-                    '- testfiles/select2/1/1sub3/1sub3sub2\n'
-                    '- testfiles/select2/1/1sub3/1sub3sub1 \n'
-                    "- 'testfiles/select2/1/1sub2/1sub2sub3'\n"
-                    '             \n'
-                    ' + testfiles/select2/1/1sub2/1sub2sub1 \n'  # + added to ensure it makes no difference
-                    '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'
-                    '  - testfiles/select2/1/1sub1/1sub1sub2  \n'
-                    '# Testing full-line comment\n'
-                    '- testfiles/select2/1/1sub2\n'
-                    "'testfiles/select2/1.py'\n"
-                    'testfiles/select2/3\n'
-                    '        #  Testing another full-line comment      \n'
-                    'testfiles/select2/1\n'
-                    '- testfiles/select2/**')
-        self.backup("full", "testfiles/select2", options=["--include-globbing-filelist=testfiles/include.txt"])
+        with io.open(u"testfiles/include.txt", u"w") as f:
+            f.write(u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
+                    u"- testfiles/select2/3/3sub3/3sub3sub2\n"
+                    u'"testfiles/select2/3/3sub2/3sub2sub2"\n'
+                    u"  + testfiles/select2/3/3sub3\n"  # + added to ensure it makes no difference
+                    u"- testfiles/select2/3/3sub1\n"
+                    u"- testfiles/select2/2/2sub1/2sub1sub3\n"
+                    u' - "testfiles/select2/2/2sub1/2sub1sub2"\n'
+                    u"testfiles/select2/2/2sub1  \n"
+                    u"\n"
+                    u"- testfiles/select2/1/1sub3/1sub3sub2\n"
+                    u"- testfiles/select2/1/1sub3/1sub3sub1 \n"
+                    u"- 'testfiles/select2/1/1sub2/1sub2sub3'\n"
+                    u"             \n"
+                    u" + testfiles/select2/1/1sub2/1sub2sub1 \n"  # + added to ensure it makes no difference
+                    u"- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
+                    u"  - testfiles/select2/1/1sub1/1sub1sub2  \n"
+                    u"# Testing full-line comment\n"
+                    u"- testfiles/select2/1/1sub2\n"
+                    u"'testfiles/select2/1.py'\n"
+                    u"testfiles/select2/3\n"
+                    u"        #  Testing another full-line comment      \n"
+                    u"testfiles/select2/1\n"
+                    u"- testfiles/select2/**")
+        self.backup(u"full", u"testfiles/select2", options=[u"--include-globbing-filelist=testfiles/include.txt"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, self.expected_restored_tree)
 
@@ -605,54 +607,54 @@
     def write_filelist(self, filelist_name):
         """Used by the below tests to write the filelist"""
         assert filelist_name is not None
-        with open(filelist_name, 'w') as f:
-            f.write("+ testfiles/select/1/2/1\n"
-                    "- testfiles/select/1/2\n"
-                    "- testfiles/select/1/1\n"
-                    "- testfiles/select/1/3")
+        with io.open(filelist_name, u"w") as f:
+            f.write(u"+ testfiles/select/1/2/1\n"
+                    u"- testfiles/select/1/2\n"
+                    u"- testfiles/select/1/1\n"
+                    u"- testfiles/select/1/3")
 
     def restore_and_check(self):
         """Restores the backup and compares to what was expected (based on the filelist in write_filelist)"""
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['2'], ['1']])
+        self.assertEqual(restored, [[u"2"], [u"1"]])
 
     def test_commandline_include_exclude(self):
         """test an excluded folder is included for included contents when using commandline includes and excludes"""
-        self.backup("full", "testfiles/select/1",
-                    options=["--include", "testfiles/select/1/2/1",
-                             "--exclude", "testfiles/select/1/2",
-                             "--exclude", "testfiles/select/1/1",
-                             "--exclude", "testfiles/select/1/3"])
+        self.backup(u"full", u"testfiles/select/1",
+                    options=[u"--include", u"testfiles/select/1/2/1",
+                             u"--exclude", u"testfiles/select/1/2",
+                             u"--exclude", u"testfiles/select/1/1",
+                             u"--exclude", u"testfiles/select/1/3"])
         self.restore_and_check()
 
     def test_include_globbing_filelist(self):
         """test an excluded folder is included for included contents with an include-globbing-filelist """
         # Deprecated, but include for now to ensure it keeps working until it is deliberately removed.
-        self.write_filelist("testfiles/include.txt")
-        self.backup("full", "testfiles/select/1", options=["--include-globbing-filelist=testfiles/include.txt"])
+        self.write_filelist(u"testfiles/include.txt")
+        self.backup(u"full", u"testfiles/select/1", options=[u"--include-globbing-filelist=testfiles/include.txt"])
         self.restore_and_check()
 
     def test_exclude_globbing_filelist(self):
         """test an excluded folder is included for included contents with an exclude-globbing-filelist """
         # Deprecated, but include for now to ensure it keeps working until it is deliberately removed.
-        self.write_filelist("testfiles/exclude.txt")
-        self.backup("full", "testfiles/select/1", options=["--exclude-globbing-filelist=testfiles/exclude.txt"])
+        self.write_filelist(u"testfiles/exclude.txt")
+        self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-globbing-filelist=testfiles/exclude.txt"])
         self.restore_and_check()
 
     def test_include_filelist(self):
         """test an excluded folder is included for included contents with an include-filelist (non-globbing) """
         # Regression test for Bug #1408411 (https://bugs.launchpad.net/duplicity/+bug/1408411)
-        self.write_filelist("testfiles/include.txt")
-        self.backup("full", "testfiles/select/1", options=["--include-filelist=testfiles/include.txt"])
+        self.write_filelist(u"testfiles/include.txt")
+        self.backup(u"full", u"testfiles/select/1", options=[u"--include-filelist=testfiles/include.txt"])
         self.restore_and_check()
 
     def test_exclude_filelist(self):
         """test an excluded folder is included for included contents with an exclude-filelist  (non-globbing) """
         # Regression test for Bug #1408411 (https://bugs.launchpad.net/duplicity/+bug/1408411)
-        self.write_filelist("testfiles/exclude.txt")
-        self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/exclude.txt"])
+        self.write_filelist(u"testfiles/exclude.txt")
+        self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/exclude.txt"])
         self.restore_and_check()
 
 
@@ -664,112 +666,112 @@
     def restore_and_check(self):
         """Restores the backup and compares to what is expected."""
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['2'], ['1']])
+        self.assertEqual(restored, [[u"2"], [u"1"]])
 
     def test_exclude_filelist_asterisks_none(self):
         """Basic exclude filelist."""
-        with open("testfiles/filelist.txt", 'w') as f:
-            f.write("+ testfiles/select/1/2/1\n"
-                    "- testfiles/select/1/2\n"
-                    "- testfiles/select/1/1\n"
-                    "- testfiles/select/1/3")
-        self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])
+        with io.open(u"testfiles/filelist.txt", u"w") as f:
+            f.write(u"+ testfiles/select/1/2/1\n"
+                    u"- testfiles/select/1/2\n"
+                    u"- testfiles/select/1/1\n"
+                    u"- testfiles/select/1/3")
+        self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
         self.restore_and_check()
 
     def test_exclude_filelist_asterisks_single(self):
         """Exclude filelist with asterisks replacing folders."""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        with open("testfiles/filelist.txt", 'w') as f:
-            f.write("+ */select/1/2/1\n"
-                    "- */select/1/2\n"
-                    "- testfiles/*/1/1\n"
-                    "- */*/1/3")
-        self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])
+        with io.open(u"testfiles/filelist.txt", u"w") as f:
+            f.write(u"+ */select/1/2/1\n"
+                    u"- */select/1/2\n"
+                    u"- testfiles/*/1/1\n"
+                    u"- */*/1/3")
+        self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
         self.restore_and_check()
 
     def test_exclude_filelist_asterisks_double_asterisks(self):
         """Exclude filelist with double asterisks replacing folders."""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        with open("testfiles/filelist.txt", 'w') as f:
-            f.write("+ **/1/2/1\n"
-                    "- **/1/2\n"
-                    "- **/select/1/1\n"
-                    "- testfiles/select/1/3")
-        self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])
+        with io.open(u"testfiles/filelist.txt", u"w") as f:
+            f.write(u"+ **/1/2/1\n"
+                    u"- **/1/2\n"
+                    u"- **/select/1/1\n"
+                    u"- testfiles/select/1/3")
+        self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
         self.restore_and_check()
 
     def test_commandline_asterisks_single_excludes_only(self):
         """test_commandline_include_exclude with single asterisks on exclude lines."""
-        self.backup("full", "testfiles/select/1",
-                    options=["--include", "testfiles/select/1/2/1",
-                             "--exclude", "testfiles/*/1/2",
-                             "--exclude", "*/select/1/1",
-                             "--exclude", "*/select/1/3"])
+        self.backup(u"full", u"testfiles/select/1",
+                    options=[u"--include", u"testfiles/select/1/2/1",
+                             u"--exclude", u"testfiles/*/1/2",
+                             u"--exclude", u"*/select/1/1",
+                             u"--exclude", u"*/select/1/3"])
         self.restore_and_check()
 
     def test_commandline_asterisks_single_both(self):
         """test_commandline_include_exclude with single asterisks on both exclude and include lines."""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        self.backup("full", "testfiles/select/1",
-                    options=["--include", "*/select/1/2/1",
-                             "--exclude", "testfiles/*/1/2",
-                             "--exclude", "*/select/1/1",
-                             "--exclude", "*/select/1/3"])
+        self.backup(u"full", u"testfiles/select/1",
+                    options=[u"--include", u"*/select/1/2/1",
+                             u"--exclude", u"testfiles/*/1/2",
+                             u"--exclude", u"*/select/1/1",
+                             u"--exclude", u"*/select/1/3"])
         self.restore_and_check()
 
     def test_commandline_asterisks_double_exclude_only(self):
         """test_commandline_include_exclude with double asterisks on exclude lines."""
-        self.backup("full", "testfiles/select/1",
-                    options=["--include", "testfiles/select/1/2/1",
-                             "--exclude", "**/1/2",
-                             "--exclude", "**/1/1",
-                             "--exclude", "**/1/3"])
+        self.backup(u"full", u"testfiles/select/1",
+                    options=[u"--include", u"testfiles/select/1/2/1",
+                             u"--exclude", u"**/1/2",
+                             u"--exclude", u"**/1/1",
+                             u"--exclude", u"**/1/3"])
         self.restore_and_check()
 
     def test_commandline_asterisks_double_both(self):
         """test_commandline_include_exclude with double asterisks on both exclude and include lines."""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        self.backup("full", "testfiles/select/1",
-                    options=["--include", "**/1/2/1",
-                             "--exclude", "**/1/2",
-                             "--exclude", "**/1/1",
-                             "--exclude", "**/1/3"])
+        self.backup(u"full", u"testfiles/select/1",
+                    options=[u"--include", u"**/1/2/1",
+                             u"--exclude", u"**/1/2",
+                             u"--exclude", u"**/1/1",
+                             u"--exclude", u"**/1/3"])
         self.restore_and_check()
 
     def test_single_and_double_asterisks(self):
         """This compares a backup using --include-globbing-filelist with a single and double *."""
-        with open("testfiles/filelist.txt", 'w') as f:
-            f.write("+ testfiles/select2/*\n"
-                    "- testfiles/select")
-        self.backup("full", "testfiles/", options=["--include-globbing-filelist=testfiles/filelist.txt"])
-        self.restore()
-        restore_dir = 'testfiles/restore_out'
-        restored = self.directory_tree_to_list_of_lists(restore_dir + "/select2")
-        with open("testfiles/filelist2.txt", 'w') as f:
-            f.write("+ testfiles/select2/**\n"
-                    "- testfiles/select")
-        self.backup("full", "testfiles/", options=["--include-globbing-filelist=testfiles/filelist2.txt"])
-        self.restore()
-        restore_dir = 'testfiles/restore_out'
-        restored2 = self.directory_tree_to_list_of_lists(restore_dir + "/select2")
+        with io.open(u"testfiles/filelist.txt", u"w") as f:
+            f.write(u"+ testfiles/select2/*\n"
+                    u"- testfiles/select")
+        self.backup(u"full", u"testfiles/", options=[u"--include-globbing-filelist=testfiles/filelist.txt"])
+        self.restore()
+        restore_dir = u"testfiles/restore_out"
+        restored = self.directory_tree_to_list_of_lists(restore_dir + u"/select2")
+        with io.open(u"testfiles/filelist2.txt", u"w") as f:
+            f.write(u"+ testfiles/select2/**\n"
+                    u"- testfiles/select")
+        self.backup(u"full", u"testfiles/", options=[u"--include-globbing-filelist=testfiles/filelist2.txt"])
+        self.restore()
+        restore_dir = u"testfiles/restore_out"
+        restored2 = self.directory_tree_to_list_of_lists(restore_dir + u"/select2")
         self.assertEqual(restored, restored2)
 
     def test_single_and_double_asterisks_includes_excludes(self):
         """This compares a backup using --includes/--excludes with a single and double *."""
-        self.backup("full", "testfiles/",
-                    options=["--include", "testfiles/select2/*",
-                             "--exclude", "testfiles/select"])
-        self.restore()
-        restore_dir = 'testfiles/restore_out'
-        restored = self.directory_tree_to_list_of_lists(restore_dir + "/select2")
-        self.backup("full", "testfiles/",
-                    options=["--include", "testfiles/select2/**",
-                             "--exclude", "testfiles/select"])
-        self.restore()
-        restore_dir = 'testfiles/restore_out'
-        restored2 = self.directory_tree_to_list_of_lists(restore_dir + "/select2")
+        self.backup(u"full", u"testfiles/",
+                    options=[u"--include", u"testfiles/select2/*",
+                             u"--exclude", u"testfiles/select"])
+        self.restore()
+        restore_dir = u"testfiles/restore_out"
+        restored = self.directory_tree_to_list_of_lists(restore_dir + u"/select2")
+        self.backup(u"full", u"testfiles/",
+                    options=[u"--include", u"testfiles/select2/**",
+                             u"--exclude", u"testfiles/select"])
+        self.restore()
+        restore_dir = u"testfiles/restore_out"
+        restored2 = self.directory_tree_to_list_of_lists(restore_dir + u"/select2")
         self.assertEqual(restored, restored2)
 
 
@@ -780,62 +782,62 @@
     def restore_and_check(self):
         """Restores the backup and compares to what is expected."""
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['2'], ['1']])
+        self.assertEqual(restored, [[u"2"], [u"1"]])
 
     def test_exclude_filelist_trailing_slashes(self):
         """test_exclude_filelist_asterisks_none with trailing slashes."""
-        with open("testfiles/filelist.txt", 'w') as f:
-            f.write("+ testfiles/select/1/2/1/\n"
-                    "- testfiles/select/1/2/\n"
-                    "- testfiles/select/1/1/\n"
-                    "- testfiles/select/1/3/")
-        self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])
+        with io.open(u"testfiles/filelist.txt", u"w") as f:
+            f.write(u"+ testfiles/select/1/2/1/\n"
+                    u"- testfiles/select/1/2/\n"
+                    u"- testfiles/select/1/1/\n"
+                    u"- testfiles/select/1/3/")
+        self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
         self.restore_and_check()
 
     def test_exclude_filelist_trailing_slashes_single_wildcards_excludes(self):
         """test_exclude_filelist_trailing_slashes with single wildcards in excludes."""
         # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)
-        with open("testfiles/filelist.txt", 'w') as f:
-            f.write("+ testfiles/select/1/2/1/\n"
-                    "- */select/1/2/\n"
-                    "- testfiles/*/1/1/\n"
-                    "- */*/1/3/")
-        self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])
+        with io.open(u"testfiles/filelist.txt", u"w") as f:
+            f.write(u"+ testfiles/select/1/2/1/\n"
+                    u"- */select/1/2/\n"
+                    u"- testfiles/*/1/1/\n"
+                    u"- */*/1/3/")
+        self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
         self.restore_and_check()
 
     def test_exclude_filelist_trailing_slashes_double_wildcards_excludes(self):
         """test_exclude_filelist_trailing_slashes with double wildcards in excludes."""
         # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)
-        with open("testfiles/filelist.txt", 'w') as f:
-            f.write("+ testfiles/select/1/2/1/\n"
-                    "- **/1/2/\n"
-                    "- **/1/1/\n"
-                    "- **/1/3/")
-        self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])
+        with io.open(u"testfiles/filelist.txt", u"w") as f:
+            f.write(u"+ testfiles/select/1/2/1/\n"
+                    u"- **/1/2/\n"
+                    u"- **/1/1/\n"
+                    u"- **/1/3/")
+        self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
         self.restore_and_check()
 
     def test_exclude_filelist_trailing_slashes_double_wildcards_excludes_2(self):
         """second test_exclude_filelist_trailing_slashes with double wildcards in excludes."""
         # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482) and
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        with open("testfiles/filelist.txt", 'w') as f:
-            f.write("+ **/1/2/1/\n"
-                    "- **/1/2/\n"
-                    "- **/1/1/\n"
-                    "- **/1/3/")
-        self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])
+        with io.open(u"testfiles/filelist.txt", u"w") as f:
+            f.write(u"+ **/1/2/1/\n"
+                    u"- **/1/2/\n"
+                    u"- **/1/1/\n"
+                    u"- **/1/3/")
+        self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
         self.restore_and_check()
 
     def test_exclude_filelist_trailing_slashes_wildcards(self):
         """test_commandline_asterisks_single_excludes_only with trailing slashes."""
         # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)
-        self.backup("full", "testfiles/select/1",
-                    options=["--include", "testfiles/select/1/2/1/",
-                             "--exclude", "testfiles/*/1/2/",
-                             "--exclude", "*/select/1/1/",
-                             "--exclude", "*/select/1/3/"])
+        self.backup(u"full", u"testfiles/select/1",
+                    options=[u"--include", u"testfiles/select/1/2/1/",
+                             u"--exclude", u"testfiles/*/1/2/",
+                             u"--exclude", u"*/select/1/1/",
+                             u"--exclude", u"*/select/1/3/"])
         self.restore_and_check()
 
 
@@ -845,49 +847,49 @@
 
     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.backup(u"full", u"testfiles/select2",
+                    options=[u"--include", u"testfiles/select2/1.py",
+                             u"--exclude", u"**"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['1.py']])
+        self.assertEqual(restored, [[u"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.backup(u"full", u"testfiles/select2",
+                    options=[u"--include", u"testfiles/select2/1.py/",
+                             u"--exclude", u"**"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"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.backup(u"full", u"testfiles/select2",
+                    options=[u"--exclude", u"testfiles/select2/*/",
+                             u"--include", u"testfiles/select2/*",
+                             u"--exclude", u"**"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['1.doc', '1.py']])
+        self.assertEqual(restored, [[u"1.doc", u"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.backup(u"full", u"testfiles/select2",
+                    options=[u"--include", u"testfiles/select2/1/1sub1/**/",
+                             u"--exclude", u"testfiles/select2/1/1sub1/**",
+                             u"--exclude", u"**"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['1'], ['1sub1'],
-                                    ['1sub1sub1', '1sub1sub2', '1sub1sub3']])
+        self.assertEqual(restored, [[u"1"], [u"1sub1"],
+                                    [u"1sub1sub1", u"1sub1sub2", u"1sub1sub3"]])
 
 
 class TestGlobbingReplacement(IncludeExcludeFunctionalTest):
@@ -905,25 +907,25 @@
         # Identical to test_include_exclude_basic with globbing characters added to both include and exclude lines
         # Exhibits the issue reported in Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371).
         # See above and the unit tests for more granularity on the issue.
-        self.backup("full", "testfiles/select2",
-                    options=["--include", "testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt",  # Note ** and ? added
-                             "--exclude", "testfiles/select2/*/3s*1",  # Note * added in both directory and filename
-                             "--exclude", "testfiles/select2/**/2sub1sub3",  # Note ** added
-                             "--exclude", "ignorecase:testfiles/select2/2/2sub1/2Sub1Sub2",  # Note ignorecase added
-                             "--include", "ignorecase:testfiles/sel[w,u,e,q]ct2/2/2S?b1",    # Note ignorecase, [] and
+        self.backup(u"full", u"testfiles/select2",
+                    options=[u"--include", u"testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt",  # Note ** and ? added
+                             u"--exclude", u"testfiles/select2/*/3s*1",  # Note * added in both directory and filename
+                             u"--exclude", u"testfiles/select2/**/2sub1sub3",  # Note ** added
+                             u"--exclude", u"ignorecase:testfiles/select2/2/2sub1/2Sub1Sub2",  # Note ignorecase added
+                             u"--include", u"ignorecase:testfiles/sel[w,u,e,q]ct2/2/2S?b1",    # Note ignorecase, [] and
                              # ? added
-                             "--exclude", "testfiles/select2/1/1sub3/1s[w,u,p,q]b3sub2",  # Note [] added
-                             "--exclude", "testfiles/select2/1/1sub[1-4]/1sub3sub1",  # Note [range] added
-                             "--include", "testfiles/select2/*/1sub2/1s[w,u,p,q]b2sub1",  # Note * and [] added
-                             "--exclude", "testfiles/select2/1/1sub1/1sub1sub3/1su?1sub3_file.txt",  # Note ? added
-                             "--exclude", "testfiles/select2/1/1*1/1sub1sub2",  # Note * added
-                             "--exclude", "testfiles/select2/1/1sub2",
-                             "--include", "testfiles/select[2-4]/*.py",  # Note * and [range] added
-                             "--include", "testfiles/*2/3",  # Note * added
-                             "--include", "**/select2/1",  # Note ** added
-                             "--exclude", "testfiles/select2/**"])
+                             u"--exclude", u"testfiles/select2/1/1sub3/1s[w,u,p,q]b3sub2",  # Note [] added
+                             u"--exclude", u"testfiles/select2/1/1sub[1-4]/1sub3sub1",  # Note [range] added
+                             u"--include", u"testfiles/select2/*/1sub2/1s[w,u,p,q]b2sub1",  # Note * and [] added
+                             u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3/1su?1sub3_file.txt",  # Note ? added
+                             u"--exclude", u"testfiles/select2/1/1*1/1sub1sub2",  # Note * added
+                             u"--exclude", u"testfiles/select2/1/1sub2",
+                             u"--include", u"testfiles/select[2-4]/*.py",  # Note * and [range] added
+                             u"--include", u"testfiles/*2/3",  # Note * added
+                             u"--include", u"**/select2/1",  # Note ** added
+                             u"--exclude", u"testfiles/select2/**"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, self.expected_restored_tree)
 
@@ -933,40 +935,40 @@
 
     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", "**"])
+        with io.open(u"testfiles/select2/1/1sub1/1sub1sub1/.nobackup", u"w") as tag:
+            tag.write(u"Files in this folder should not be backed up.")
+        self.backup(u"full", u"testfiles/select2/1/1sub1",
+                    options=[u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/*",
+                             u"--exclude", u"**"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['1sub1sub1'],
-                                    ['.nobackup', '1sub1sub1_file.txt']])
+        self.assertEqual(restored, [[u"1sub1sub1"],
+                                    [u".nobackup", u"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", "**"])
+        with io.open(u"testfiles/select2/1/1sub1/1sub1sub1/.nobackup", u"w") as tag:
+            tag.write(u"Files in this folder should not be backed up.")
+        self.backup(u"full", u"testfiles/select2/1/1sub1",
+                    options=[u"--exclude-if-present", u".nobackup",
+                             u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/*",
+                             u"--exclude", u"**"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"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", "**"])
+        with io.open(u"testfiles/select2/1/1sub1/1sub1sub1/EXCLUDE.tag", u"w") as tag:
+            tag.write(u"Files in this folder should also not be backed up.")
+        self.backup(u"full", u"testfiles/select2/1/1sub1",
+                    options=[u"--exclude-if-present", u"EXCLUDE.tag",
+                             u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/*",
+                             u"--exclude", u"**"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, [])
 
@@ -974,42 +976,42 @@
 class TestLockedFoldersNoError(IncludeExcludeFunctionalTest):
     """ This tests that inaccessible folders do not cause an error"""
 
-    @unittest.skipUnless(platform.platform().startswith('Linux'),
-                         'Skip on non-Linux systems')
+    @unittest.skipUnless(platform.platform().startswith("Linux"),
+                         u"Skip on non-Linux systems")
     def test_locked_baseline(self):
         """ Test no error if locked in path but excluded"""
-        folder_to_lock = "testfiles/select2/1/1sub1/1sub1sub3"
+        folder_to_lock = u"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", "**"])
+        self.backup(u"full", u"testfiles/select2/1/1sub1",
+                    options=[u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/*",
+                             u"--exclude", u"**"])
         os.chmod(folder_to_lock, initial_mode)
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['1sub1sub1'],
-                                    ['1sub1sub1_file.txt']])
+        self.assertEqual(restored, [[u"1sub1sub1"],
+                                    [u"1sub1sub1_file.txt"]])
 
-    @unittest.skipUnless(platform.platform().startswith('Linux'),
-                         'Skip on non-Linux systems')
+    @unittest.skipUnless(platform.platform().startswith("Linux"),
+                         u"Skip on non-Linux systems")
     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"
+        folder_to_lock = u"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", "**"])
+        self.backup(u"full", u"testfiles/select2/1/1sub1",
+                    options=[u"--exclude-if-present", u"EXCLUDE.tag",
+                             u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/*",
+                             u"--exclude", u"**"])
         os.chmod(folder_to_lock, initial_mode)
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['1sub1sub1'],
-                                    ['1sub1sub1_file.txt']])
+        self.assertEqual(restored, [[u"1sub1sub1"],
+                                    [u"1sub1sub1_file.txt"]])
 
 
 class TestFolderIncludesFiles(IncludeExcludeFunctionalTest):
@@ -1018,73 +1020,73 @@
 
     def test_includes_files(self):
         """This tests that including a folder includes the files within it"""
-        self.backup("full", "testfiles/select2/1/1sub1",
-                    options=["--include", "testfiles/select2/1/1sub1/1sub1sub1",
-                             "--exclude", "**"])
+        self.backup(u"full", u"testfiles/select2/1/1sub1",
+                    options=[u"--include", u"testfiles/select2/1/1sub1/1sub1sub1",
+                             u"--exclude", u"**"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['1sub1sub1'],
-                                    ['1sub1sub1_file.txt']])
+        self.assertEqual(restored, [[u"1sub1sub1"],
+                                    [u"1sub1sub1_file.txt"]])
 
     def test_includes_files_trailing_slash(self):
         """This tests that including a folder includes the files within it"""
-        self.backup("full", "testfiles/select2/1/1sub1",
-                    options=["--include", "testfiles/select2/1/1sub1/1sub1sub1/",
-                             "--exclude", "**"])
+        self.backup(u"full", u"testfiles/select2/1/1sub1",
+                    options=[u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/",
+                             u"--exclude", u"**"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['1sub1sub1'],
-                                    ['1sub1sub1_file.txt']])
+        self.assertEqual(restored, [[u"1sub1sub1"],
+                                    [u"1sub1sub1_file.txt"]])
 
     def test_includes_files_trailing_slash_globbing_chars(self):
         """Tests folder includes with globbing char and /"""
-        self.backup("full", "testfiles/select2/1/1sub1",
-                    options=["--include", "testfiles/s?lect2/1/1sub1/1sub1sub1/",
-                             "--exclude", "**"])
+        self.backup(u"full", u"testfiles/select2/1/1sub1",
+                    options=[u"--include", u"testfiles/s?lect2/1/1sub1/1sub1sub1/",
+                             u"--exclude", u"**"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
-        self.assertEqual(restored, [['1sub1sub1'],
-                                    ['1sub1sub1_file.txt']])
+        self.assertEqual(restored, [[u"1sub1sub1"],
+                                    [u"1sub1sub1_file.txt"]])
 
     def test_excludes_files_no_trailing_slash(self):
         """This tests that excluding a folder excludes the files within it"""
-        self.backup("full", "testfiles/select2/1/1sub1",
-                    options=["--exclude", "testfiles/select2/1/1sub1/1sub1sub1",
-                             "--exclude", "testfiles/select2/1/1sub1/1sub1sub2",
-                             "--exclude", "testfiles/select2/1/1sub1/1sub1sub3",
-                             "--include", "testfiles/select2/1/1sub1/1sub1**",
-                             "--exclude", "testfiles/select2/1/1sub1/irrelevant.txt"])
+        self.backup(u"full", u"testfiles/select2/1/1sub1",
+                    options=[u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub1",
+                             u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub2",
+                             u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3",
+                             u"--include", u"testfiles/select2/1/1sub1/1sub1**",
+                             u"--exclude", u"testfiles/select2/1/1sub1/irrelevant.txt"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, [])
 
     def test_excludes_files_trailing_slash(self):
         """Excluding a folder excludes the files within it, if ends with /"""
-        self.backup("full", "testfiles/select2/1/1sub1",
-                    options=["--exclude", "testfiles/select2/1/1sub1/1sub1sub1/",
-                             "--exclude", "testfiles/select2/1/1sub1/1sub1sub2/",
-                             "--exclude", "testfiles/select2/1/1sub1/1sub1sub3/",
-                             "--include", "testfiles/select2/1/1sub1/1sub1**",
-                             "--exclude", "testfiles/select2/1/1sub1/irrelevant.txt"])
+        self.backup(u"full", u"testfiles/select2/1/1sub1",
+                    options=[u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub1/",
+                             u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub2/",
+                             u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3/",
+                             u"--include", u"testfiles/select2/1/1sub1/1sub1**",
+                             u"--exclude", u"testfiles/select2/1/1sub1/irrelevant.txt"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, [])
 
     def test_excludes_files_trailing_slash_globbing_chars(self):
         """Tests folder excludes with globbing char and /"""
-        self.backup("full", "testfiles/select2/1/1sub1",
-                    options=["--exclude", "testfiles/sel?ct2/1/1sub1/1sub1sub1/",
-                             "--exclude", "testfiles/sel[e,f]ct2/1/1sub1/1sub1sub2/",
-                             "--exclude", "testfiles/sel*t2/1/1sub1/1sub1sub3/",
-                             "--include", "testfiles/select2/1/1sub1/1sub1**",
-                             "--exclude", "testfiles/select2/1/1sub1/irrelevant.txt"])
+        self.backup(u"full", u"testfiles/select2/1/1sub1",
+                    options=[u"--exclude", u"testfiles/sel?ct2/1/1sub1/1sub1sub1/",
+                             u"--exclude", u"testfiles/sel[e,f]ct2/1/1sub1/1sub1sub2/",
+                             u"--exclude", u"testfiles/sel*t2/1/1sub1/1sub1sub3/",
+                             u"--include", u"testfiles/select2/1/1sub1/1sub1**",
+                             u"--exclude", u"testfiles/select2/1/1sub1/irrelevant.txt"])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, [])
 
@@ -1094,30 +1096,110 @@
 
     def test_absolute_paths_non_globbing(self):
         """ Test --include and --exclude work with absolute paths"""
-        self.backup("full", os.path.abspath("testfiles/select2"),
-                    options=["--include", os.path.abspath("testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt"),
-                             "--exclude", os.path.abspath("testfiles/select2/3/3sub3/3sub3sub2"),
-                             "--include", os.path.abspath("testfiles/select2/3/3sub2/3sub2sub2"),
-                             "--include", os.path.abspath("testfiles/select2/3/3sub3"),
-                             "--exclude", os.path.abspath("testfiles/select2/3/3sub1"),
-                             "--exclude", os.path.abspath("testfiles/select2/2/2sub1/2sub1sub3"),
-                             "--exclude", os.path.abspath("testfiles/select2/2/2sub1/2sub1sub2"),
-                             "--include", os.path.abspath("testfiles/select2/2/2sub1"),
-                             "--exclude", os.path.abspath("testfiles/select2/1/1sub3/1sub3sub2"),
-                             "--exclude", os.path.abspath("testfiles/select2/1/1sub3/1sub3sub1"),
-                             "--exclude", os.path.abspath("testfiles/select2/1/1sub2/1sub2sub3"),
-                             "--include", os.path.abspath("testfiles/select2/1/1sub2/1sub2sub1"),
-                             "--exclude", os.path.abspath("testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt"),
-                             "--exclude", os.path.abspath("testfiles/select2/1/1sub1/1sub1sub2"),
-                             "--exclude", os.path.abspath("testfiles/select2/1/1sub2"),
-                             "--include", os.path.abspath("testfiles/select2/1.py"),
-                             "--include", os.path.abspath("testfiles/select2/3"),
-                             "--include", os.path.abspath("testfiles/select2/1"),
-                             "--exclude", os.path.abspath("testfiles/select2/**")])
+        self.backup(u"full", os.path.abspath(u"testfiles/select2"),
+                    options=[u"--include", os.path.abspath(u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt"),
+                             u"--exclude", os.path.abspath(u"testfiles/select2/3/3sub3/3sub3sub2"),
+                             u"--include", os.path.abspath(u"testfiles/select2/3/3sub2/3sub2sub2"),
+                             u"--include", os.path.abspath(u"testfiles/select2/3/3sub3"),
+                             u"--exclude", os.path.abspath(u"testfiles/select2/3/3sub1"),
+                             u"--exclude", os.path.abspath(u"testfiles/select2/2/2sub1/2sub1sub3"),
+                             u"--exclude", os.path.abspath(u"testfiles/select2/2/2sub1/2sub1sub2"),
+                             u"--include", os.path.abspath(u"testfiles/select2/2/2sub1"),
+                             u"--exclude", os.path.abspath(u"testfiles/select2/1/1sub3/1sub3sub2"),
+                             u"--exclude", os.path.abspath(u"testfiles/select2/1/1sub3/1sub3sub1"),
+                             u"--exclude", os.path.abspath(u"testfiles/select2/1/1sub2/1sub2sub3"),
+                             u"--include", os.path.abspath(u"testfiles/select2/1/1sub2/1sub2sub1"),
+                             u"--exclude", os.path.abspath(u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt"),
+                             u"--exclude", os.path.abspath(u"testfiles/select2/1/1sub1/1sub1sub2"),
+                             u"--exclude", os.path.abspath(u"testfiles/select2/1/1sub2"),
+                             u"--include", os.path.abspath(u"testfiles/select2/1.py"),
+                             u"--include", os.path.abspath(u"testfiles/select2/3"),
+                             u"--include", os.path.abspath(u"testfiles/select2/1"),
+                             u"--exclude", os.path.abspath(u"testfiles/select2/**")])
         self.restore()
-        restore_dir = 'testfiles/restore_out'
+        restore_dir = u"testfiles/restore_out"
         restored = self.directory_tree_to_list_of_lists(restore_dir)
         self.assertEqual(restored, self.expected_restored_tree)
 
+
+@unittest.skipUnless(sys.getfilesystemencoding() == "UTF-8",
+                     u"Skipping TestUnicode -- Only tested to work on UTF-8 systems")
+class TestUnicode(IncludeExcludeFunctionalTest):
+    """ Tests include/exclude options with unicode paths"""
+
+    def test_unicode_paths_non_globbing(self):
+        """ Test --include and --exclude work with unicode paths"""
+        self.backup(u"full", u"testfiles/select-unicode",
+                    options=[u"--exclude", u"testfiles/select-unicode/прыклад/пример/例/Παράδειγμα/उदाहरण.txt",
+                             u"--exclude", u"testfiles/select-unicode/прыклад/пример/例/Παράδειγμα/דוגמא.txt",
+                             u"--exclude", u"testfiles/select-unicode/прыклад/пример/例/მაგალითი/",
+                             u"--include", u"testfiles/select-unicode/прыклад/пример/例/",
+                             u"--exclude", u"testfiles/select-unicode/прыклад/пример/",
+                             u"--include", u"testfiles/select-unicode/прыклад/",
+                             u"--include", u"testfiles/select-unicode/օրինակ.txt",
+                             u"--exclude", u"testfiles/select-unicode/**"])
+        self.restore()
+        restore_dir = u"testfiles/restore_out"
+        restored = self.directory_tree_to_list_of_lists(restore_dir)
+        self.assertEqual(restored, [[u"прыклад", u"օրինակ.txt"],
+                                    [u"пример", u"উদাহরণ"], [u"例"], [u"Παράδειγμα"], [u"ઉદાહરણ.log"]])
+
+    def test_unicode_paths_asterisks(self):
+        """ Test --include and --exclude work with unicode paths and globs containing * and **"""
+        p = u"testfiles/select-unicode/"
+        self.backup(u"full", u"testfiles/select-unicode",
+                    options=[u"--exclude", p + u"прыклад/пример/例/Παρά*ειγμα/उदाहरण.txt",  # Note *
+                             u"--exclude", p + u"прыклад/пример/例/Παράδειγμα/דוגמא.txt",
+                             u"--exclude", p + u"прыклад/пример/例/მაგალითი/",
+                             u"--include", p + u"пр**/例/",  # Note **
+                             u"--exclude", p + u"прыклад/пример/",
+                             u"--include", p + u"прыкла*/",  # Note *
+                             u"--include", p + u"օր*ակ.txt",  # Note *
+                             u"--exclude", p + u"**"])
+        self.restore()
+        restore_dir = u"testfiles/restore_out"
+        restored = self.directory_tree_to_list_of_lists(restore_dir)
+        self.assertEqual(restored, [[u"прыклад", u"օրինակ.txt"],
+                                    [u"пример", u"উদাহরণ"], [u"例"], [u"Παράδειγμα"], [u"ઉદાહરણ.log"]])
+
+    def test_unicode_paths_square_brackets(self):
+        """ Test --include and --exclude work with unicode paths with character options in []s and [!]s"""
+        p = u"testfiles/select-unicode/"
+        self.backup(u"full", u"testfiles/select-unicode",
+                    options=[u"--exclude", p + u"прыклад/пример/例/Παράδειγμα/उदाहरण.txt",
+                             u"--exclude", p + u"пры[к,и,р]лад/пример/例/Παράδειγμα/דוגמא.txt",
+                             u"--exclude", p + u"прыклад/пр[!a,b,c]мер/例/მაგალითი/",
+                             u"--include", p + u"прыклад/при[g,м,д]ер/例/",
+                             u"--exclude", p + u"прыклад/пример/",
+                             u"--include", p + u"прыклад/",
+                             u"--include", p + u"օրինակ.txt",
+                             u"--exclude", p + u"**"])
+        self.restore()
+        restore_dir = u"testfiles/restore_out"
+        restored = self.directory_tree_to_list_of_lists(restore_dir)
+        self.assertEqual(restored, [[u"прыклад", u"օրինակ.txt"],
+                                    [u"пример", u"উদাহরণ"], [u"例"], [u"Παράδειγμα"], [u"ઉદાહરણ.log"]])
+
+    def test_unicode_filelist(self):
+        """Test that exclude filelist works with unicode filenames"""
+        # As this is an exclude filelist any lines with no +/- modifier should be treated as if they have a -.
+        path = u"testfiles/select-unicode/"
+        # Create a filelist
+        with io.open(u"testfiles/exclude.txt", u"w", encoding="UTF-8") as f:
+            f.write(u"- " + path + u"прыклад/пример/例/Παράδειγμα/उदाहरण.txt\n"
+                    u"- " + path + u"прыклад/пример/例/Παράδειγμα/דוגמא.txt\n"
+                    u"- " + path + u"прыклад/пример/例/მაგალითი/\n"
+                    u"+ " + path + u"прыклад/пример/例/\n"
+                    u"- " + path + u"прыклад/пример/\n"
+                    u"+ " + path + u"прыклад/\n"
+                    u"+ " + path + u"օրինակ.txt\n"
+                    u"- " + path + u"**")
+        self.backup(u"full", path, options=[u"--exclude-filelist=testfiles/exclude.txt"])
+        self.restore()
+        restore_dir = u"testfiles/restore_out"
+        restored = self.directory_tree_to_list_of_lists(restore_dir)
+        self.assertEqual(restored, [[u"прыклад", u"օրինակ.txt"],
+                                    [u"пример", u"উদাহরণ"], [u"例"], [u"Παράδειγμα"], [u"ઉદાહરણ.log"]])
+
 if __name__ == "__main__":
     unittest.main()

=== modified file 'testing/functional/test_verify.py'
--- testing/functional/test_verify.py	2015-01-01 13:07:31 +0000
+++ testing/functional/test_verify.py	2017-12-01 23:01:42 +0000
@@ -32,20 +32,20 @@
     """
     def test_verify(self):
         """Test that verify (without --compare-data) works in the basic case"""
-        self.backup("full", "testfiles/various_file_types", options=[])
-        self.verify('testfiles/various_file_types/executable', file_to_verify='executable', options=[])
+        self.backup(u"full", u"testfiles/various_file_types", options=[])
+        self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable', options=[])
 
     def test_verify_changed_source_file(self):
         """Test verify (without --compare-data) gives no error if a source file is changed"""
         # This test was made to pass in fixing Bug #1354880
-        self.backup("full", "testfiles/various_file_types", options=[])
+        self.backup(u"full", u"testfiles/various_file_types", options=[])
 
         # Edit source file
         with open('testfiles/various_file_types/executable', 'r+') as f:
             f.write('This changes a source file.')
 
         # Test verify for the file
-        self.verify('testfiles/various_file_types/executable', file_to_verify='executable', options=[])
+        self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable', options=[])
 
     def test_verify_changed_source_file_adjust_mtime(self):
         """Test verify (without --compare-data) gives no error if a source file is changed and the mtime is changed
@@ -58,7 +58,7 @@
         # the times from a stat call don't match what a utime will set.
         os.utime('testfiles/various_file_types/executable', (file_info.st_atime, file_info.st_mtime))
 
-        self.backup("full", "testfiles/various_file_types", options=[])
+        self.backup(u"full", u"testfiles/various_file_types", options=[])
 
         # Edit source file
         with open('testfiles/various_file_types/executable', 'r+') as f:
@@ -68,19 +68,19 @@
         os.utime('testfiles/various_file_types/executable', (file_info.st_atime, file_info.st_mtime))
 
         # Test verify for the file
-        self.verify('testfiles/various_file_types/executable', file_to_verify='executable', options=[])
+        self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable', options=[])
 
     def test_verify_compare_data(self):
         """Test that verify works in the basic case when the --compare-data option is used"""
-        self.backup("full", "testfiles/various_file_types", options=[])
+        self.backup(u"full", u"testfiles/various_file_types", options=[])
 
         # Test verify for the file with --compare-data
-        self.verify('testfiles/various_file_types/executable', file_to_verify='executable',
-                    options=["--compare-data"])
+        self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable',
+                    options=[u"--compare-data"])
 
     def test_verify_compare_data_changed_source_file(self):
         """Test verify with --compare-data gives an error if a source file is changed"""
-        self.backup("full", "testfiles/various_file_types", options=[])
+        self.backup(u"full", u"testfiles/various_file_types", options=[])
 
         # Edit source file
         with open('testfiles/various_file_types/executable', 'r+') as f:
@@ -88,8 +88,8 @@
 
         # Test verify for edited file fails with --compare-data
         try:
-            self.verify('testfiles/various_file_types/executable', file_to_verify='executable',
-                        options=["--compare-data"])
+            self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable',
+                        options=[u"--compare-data"])
         except CmdError as e:
             self.assertEqual(e.exit_status, 1, str(e))
         else:
@@ -105,7 +105,7 @@
         # the times from a stat call don't match what a utime will set
         os.utime('testfiles/various_file_types/executable', (file_info.st_atime, file_info.st_mtime))
 
-        self.backup("full", "testfiles/various_file_types", options=[])
+        self.backup(u"full", u"testfiles/various_file_types", options=[])
         # Edit source file
         with open('testfiles/various_file_types/executable', 'r+') as f:
             f.write('This changes a source file.')
@@ -115,8 +115,8 @@
 
         # Test verify for edited file fails with --compare-data
         try:
-            self.verify('testfiles/various_file_types/executable', file_to_verify='executable',
-                        options=["--compare-data"])
+            self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable',
+                        options=[u"--compare-data"])
         except CmdError as e:
             self.assertEqual(e.exit_status, 1, str(e))
         else:
@@ -124,7 +124,7 @@
 
     def test_verify_corrupt_archive(self):
         """Test verify (without --compare-data) gives an error if the archive is corrupted"""
-        self.backup("full", "testfiles/various_file_types", options=[])
+        self.backup(u"full", u"testfiles/various_file_types", options=[])
         output_files = os.listdir("testfiles/output")
         archives = [elem for elem in output_files if "vol" in elem]
         for archive in archives:
@@ -133,7 +133,7 @@
                 f.write('This writes text into each archive file to corrupt it.')
         # Test verify for the file
         try:
-            self.verify('testfiles/various_file_types/executable', file_to_verify='executable', options=[])
+            self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable', options=[])
         except CmdError as e:
             # Should return a 21 error code for "hash mismatch"
             self.assertEqual(e.exit_status, 21, str(e))
@@ -142,7 +142,7 @@
 
     def test_verify_corrupt_archive_compare_data(self):
         """Test verify with --compare-data gives an error if the archive is corrupted"""
-        self.backup("full", "testfiles/various_file_types", options=[])
+        self.backup(u"full", u"testfiles/various_file_types", options=[])
         output_files = os.listdir("testfiles/output")
         archives = [elem for elem in output_files if "vol" in elem]
         for archive in archives:
@@ -151,8 +151,8 @@
                 f.write('This writes text into each archive file to corrupt it.')
         # Test verify for the file
         try:
-            self.verify('testfiles/various_file_types/executable', file_to_verify='executable',
-                        options=["--compare-data"])
+            self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable',
+                        options=[u"--compare-data"])
         except CmdError as e:
             # Should return a 21 error code for "hash mismatch"
             self.assertEqual(e.exit_status, 21, str(e))

=== added file 'testing/testfiles.tar.gz'
Binary files testing/testfiles.tar.gz	1970-01-01 00:00:00 +0000 and testing/testfiles.tar.gz	2017-12-01 23:01:42 +0000 differ
=== removed file 'testing/testfiles.tar.gz'
Binary files testing/testfiles.tar.gz	2017-11-14 16:53:17 +0000 and testing/testfiles.tar.gz	1970-01-01 00:00:00 +0000 differ
=== modified file 'testing/unit/test_diffdir.py'
--- testing/unit/test_diffdir.py	2017-01-18 22:59:29 +0000
+++ testing/unit/test_diffdir.py	2017-12-01 23:01:42 +0000
@@ -20,8 +20,6 @@
 # along with duplicity; if not, write to the Free Software Foundation,
 # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
-import os
-import sys
 import unittest
 
 from duplicity.path import *  # @UnusedWildImport

=== modified file 'testing/unit/test_globmatch.py'
--- testing/unit/test_globmatch.py	2017-07-11 14:55:38 +0000
+++ testing/unit/test_globmatch.py	2017-12-01 23:01:42 +0000
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
 #
 # Copyright 2002 Ben Escoto <ben@xxxxxxxxxxx>
@@ -20,6 +21,8 @@
 # along with duplicity; if not, write to the Free Software Foundation,
 # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
+import unittest
+
 from duplicity.globmatch import *
 from duplicity.path import *
 from . import UnitTestCase
@@ -75,14 +78,14 @@
 
     def test_glob_to_regex(self):
         """test_glob_re - test translation of shell pattern to regular exp"""
-        self.assertEqual(glob_to_regex("hello"), "hello")
-        self.assertEqual(glob_to_regex(".e?ll**o"), "\\.e[^/]ll.*o")
-        self.assertEqual(glob_to_regex("[abc]el[^de][!fg]h"),
-                         "[abc]el[^de][^fg]h")
-        self.assertEqual(glob_to_regex("/usr/*/bin/"),
-                         "\\/usr\\/[^/]*\\/bin\\/")
-        self.assertEqual(glob_to_regex("[a.b/c]"), "[a.b/c]")
-        self.assertEqual(glob_to_regex("[a*b-c]e[!]]"), "[a*b-c]e[^]]")
+        self.assertEqual(glob_to_regex(u"hello"), u"hello")
+        self.assertEqual(glob_to_regex(u".e?ll**o"), u"\\.e[^/]ll.*o")
+        self.assertEqual(glob_to_regex(u"[abc]el[^de][!fg]h"),
+                         u"[abc]el[^de][^fg]h")
+        self.assertEqual(glob_to_regex(u"/usr/*/bin/"),
+                         u"\\/usr\\/[^/]*\\/bin\\/")
+        self.assertEqual(glob_to_regex(u"[a.b/c]"), u"[a.b/c]")
+        self.assertEqual(glob_to_regex(u"[a*b-c]e[!]]"), u"[a*b-c]e[^]]")
 
 
 class TestSelectValuesFromGlobs(UnitTestCase):
@@ -91,22 +94,22 @@
     def test_glob_scans_parent_directories(self):
         """Test glob scans parent"""
         self.assertEqual(
-            inc_sel_dir("testfiles/parent/sub", "testfiles/parent"), 2)
+            inc_sel_dir(u"testfiles/parent/sub", u"testfiles/parent"), 2)
         self.assertEqual(
-            inc_sel_dir("testfiles/select2/3/3sub2", "testfiles/select2/3"), 2)
+            inc_sel_dir(u"testfiles/select2/3/3sub2", u"testfiles/select2/3"), 2)
 
     def test_double_asterisk_include(self):
         """Test a few globbing patterns, including **"""
-        self.assertEqual(inc_sel_file("**", "foo.txt"), 1)
-        self.assertEqual(inc_sel_dir("**", "folder"), 1)
+        self.assertEqual(inc_sel_file(u"**", u"foo.txt"), 1)
+        self.assertEqual(inc_sel_dir(u"**", u"folder"), 1)
 
     def test_double_asterisk_extension_include(self):
         """Test **.py"""
-        self.assertEqual(inc_sel_file("**.py", "what/ever.py"), 1)
-        self.assertEqual(inc_sel_file("**.py", "what/ever.py/foo"), 1)
-        self.assertEqual(inc_sel_dir("**.py", "foo"), 2)
-        self.assertEqual(inc_sel_dir("**.py", "usr/local/bin"), 2)
-        self.assertEqual(inc_sel_dir("**.py", "/usr/local/bin"), 2)
+        self.assertEqual(inc_sel_file(u"**.py", u"what/ever.py"), 1)
+        self.assertEqual(inc_sel_file(u"**.py", u"what/ever.py/foo"), 1)
+        self.assertEqual(inc_sel_dir(u"**.py", u"foo"), 2)
+        self.assertEqual(inc_sel_dir(u"**.py", u"usr/local/bin"), 2)
+        self.assertEqual(inc_sel_dir(u"**.py", u"/usr/local/bin"), 2)
 
 
 class TestTrailingSlash(UnitTestCase):
@@ -115,95 +118,95 @@
     def test_trailing_slash_matches_only_dirs(self):
         """Test matching where glob includes a trailing slash"""
         # Test the folder named "folder" is included
-        self.assertEqual(inc_sel_dir("fold*/", "folder"), 1)
+        self.assertEqual(inc_sel_dir(u"fold*/", u"folder"), 1)
 
         # Test the file (not folder) named "folder" is not included
-        self.assertEqual(inc_sel_file("fold*/", "folder"), None)
-        self.assertEqual(inc_sel_file("folder/", "folder"), None)
+        self.assertEqual(inc_sel_file(u"fold*/", u"folder"), None)
+        self.assertEqual(inc_sel_file(u"folder/", u"folder"), None)
 
         # Test miscellaneous file/folder
-        self.assertEqual(inc_sel_file("fo*/", "foo.txt"), None)
+        self.assertEqual(inc_sel_file(u"fo*/", u"foo.txt"), None)
 
     def test_included_files_are_matched_no_slash(self):
         """Test that files within an included folder are matched"""
-        self.assertEqual(inc_sel_file("fold*", "folder/file.txt"), 1)
-        self.assertEqual(inc_sel_file("fold*", "folder/file.txt"), 1)
-        self.assertEqual(inc_sel_file("fold*", "folder/2/file.txt"), 1)
+        self.assertEqual(inc_sel_file(u"fold*", u"folder/file.txt"), 1)
+        self.assertEqual(inc_sel_file(u"fold*", u"folder/file.txt"), 1)
+        self.assertEqual(inc_sel_file(u"fold*", u"folder/2/file.txt"), 1)
 
     def test_included_files_are_matched_no_slash_2(self):
         """Test that files within an included folder are matched"""
-        self.assertEqual(inc_sel_file("folder", "folder/file.txt"), 1)
-        self.assertEqual(inc_sel_file("folder/2", "folder/2/file.txt"), 1)
+        self.assertEqual(inc_sel_file(u"folder", u"folder/file.txt"), 1)
+        self.assertEqual(inc_sel_file(u"folder/2", u"folder/2/file.txt"), 1)
 
     def test_included_files_are_matched_slash(self):
         """Test that files within an included folder are matched with /"""
         # Bug #1624725
         # https://bugs.launchpad.net/duplicity/+bug/1624725
-        self.assertEqual(inc_sel_file("folder/", "folder/file.txt"), 1)
+        self.assertEqual(inc_sel_file(u"folder/", u"folder/file.txt"), 1)
 
     def test_included_files_are_matched_slash_2(self):
         """Test that files within an included folder are matched with /"""
         # Bug #1624725
         # https://bugs.launchpad.net/duplicity/+bug/1624725
         self.assertEqual(inc_sel_file(
-            "testfiles/select2/1/1sub1/1sub1sub1/",
-            "testfiles/select2/1/1sub1/1sub1sub1/1sub1sub1_file.txt"), 1)
+            u"testfiles/select2/1/1sub1/1sub1sub1/",
+            u"testfiles/select2/1/1sub1/1sub1sub1/1sub1sub1_file.txt"), 1)
 
     def test_included_files_are_matched_slash_2_parents(self):
         """Test that duplicity will scan parent of glob/"""
         # Bug #1624725
         # https://bugs.launchpad.net/duplicity/+bug/1624725
         self.assertEqual(inc_sel_dir(
-            "testfiles/select2/1/1sub1/1sub1sub1/",
-            "testfiles/select2/1/1sub1/1sub1sub1"), 1)
+            u"testfiles/select2/1/1sub1/1sub1sub1/",
+            u"testfiles/select2/1/1sub1/1sub1sub1"), 1)
         self.assertEqual(inc_sel_dir(
-            "testfiles/select2/1/1sub1/1sub1sub1/",
-            "testfiles/select2/1/1sub1"), 2)
+            u"testfiles/select2/1/1sub1/1sub1sub1/",
+            u"testfiles/select2/1/1sub1"), 2)
 
     def test_included_files_are_matched_slash_wildcard(self):
         """Test that files within an included folder are matched with /"""
         # Bug #1624725
         # https://bugs.launchpad.net/duplicity/+bug/1624725
-        self.assertEqual(inc_sel_file("fold*/", "folder/file.txt"), 1)
+        self.assertEqual(inc_sel_file(u"fold*/", u"folder/file.txt"), 1)
 
     def test_slash_matches_everything(self):
         """Test / matches everything"""
-        self.assertEqual(inc_sel_dir("/", "/tmp/testfiles/select/1/2"), 1)
-        self.assertEqual(inc_sel_dir("/", "/test/random/path"), 1)
-        self.assertEqual(exc_sel_dir("/", "/test/random/path"), 0)
-        self.assertEqual(inc_sel_dir("/", "/"), 1)
-        self.assertEqual(inc_sel_dir("/", "/var/log"), 1)
-        self.assertEqual(inc_sel_file("/", "/var/log/log.txt"), 1)
+        self.assertEqual(inc_sel_dir(u"/", u"/tmp/testfiles/select/1/2"), 1)
+        self.assertEqual(inc_sel_dir(u"/", u"/test/random/path"), 1)
+        self.assertEqual(exc_sel_dir(u"/", u"/test/random/path"), 0)
+        self.assertEqual(inc_sel_dir(u"/", u"/"), 1)
+        self.assertEqual(inc_sel_dir(u"/", u"/var/log"), 1)
+        self.assertEqual(inc_sel_file(u"/", u"/var/log/log.txt"), 1)
 
     def test_slash_star_scans_folder(self):
         """Test that folder/* scans folder/"""
         # This behaviour is a bit ambiguous - either include or scan could be
         # argued as most appropriate here, but only an empty folder is at stake
         # so long as test_slash_star_includes_folder_contents passes.
-        self.assertEqual(inc_sel_dir("folder/*", "folder"), 2)
+        self.assertEqual(inc_sel_dir(u"folder/*", u"folder"), 2)
 
     def test_slash_star_includes_folder_contents(self):
         """Test that folder/* includes folder contents"""
-        self.assertEqual(inc_sel_file("folder/*", "folder/file.txt"), 1)
-        self.assertEqual(inc_sel_file("folder/*", "folder/other_file.log"), 1)
+        self.assertEqual(inc_sel_file(u"folder/*", u"folder/file.txt"), 1)
+        self.assertEqual(inc_sel_file(u"folder/*", u"folder/other_file.log"), 1)
 
     def test_slash_star_star_scans_folder(self):
         """Test that folder/** scans folder/"""
-        self.assertEqual(inc_sel_dir("folder/**", "folder"), 2)
+        self.assertEqual(inc_sel_dir(u"folder/**", u"folder"), 2)
 
     def test_simple_trailing_slash_match(self):
         """Test that a normal folder string ending in / matches that path"""
-        self.assertEqual(inc_sel_dir("testfiles/select/1/2/1/",
-                                     "testfiles/select/1/2/1"), 1)
+        self.assertEqual(inc_sel_dir(u"testfiles/select/1/2/1/",
+                                     u"testfiles/select/1/2/1"), 1)
 
     def test_double_asterisk_string_slash(self):
         """Test string starting with ** and ending in /"""
-        self.assertEqual(inc_sel_dir("**/1/2/", "testfiles/select/1/2"), 1)
+        self.assertEqual(inc_sel_dir(u"**/1/2/", u"testfiles/select/1/2"), 1)
 
     def test_string_double_asterisk_string_slash(self):
         """Test string ** string /"""
-        self.assertEqual(inc_sel_dir("testfiles**/2/",
-                                     "testfiles/select/1/2"), 1)
+        self.assertEqual(inc_sel_dir(u"testfiles**/2/",
+                                     u"testfiles/select/1/2"), 1)
 
 
 class TestDoubleAsterisk(UnitTestCase):
@@ -211,19 +214,75 @@
 
     def test_double_asterisk_no_match(self):
         """Test that a folder string ending /** does not match other paths"""
-        self.assertEqual(inc_sel_dir("/test/folder/**", "/test/foo"), None)
+        self.assertEqual(inc_sel_dir(u"/test/folder/**", u"/test/foo"), None)
 
     def test_double_asterisk_match(self):
         """Test that a folder string ending in /** matches that path"""
-        self.assertEqual(inc_sel_dir("/test/folder/**",
-                                     "/test/folder/foo"), 1)
-        self.assertEqual(inc_sel_file("/test/folder/**",
-                                      "/test/folder/foo.txt"), 1)
-        self.assertEqual(inc_sel_dir("/test/folder/**",
-                                     "/test/folder/2/foo"), 1)
-        self.assertEqual(inc_sel_file("/test/folder/**",
-                                      "/test/folder/2/foo.txt"), 1)
+        self.assertEqual(inc_sel_dir(u"/test/folder/**",
+                                     u"/test/folder/foo"), 1)
+        self.assertEqual(inc_sel_file(u"/test/folder/**",
+                                      u"/test/folder/foo.txt"), 1)
+        self.assertEqual(inc_sel_dir(u"/test/folder/**",
+                                     u"/test/folder/2/foo"), 1)
+        self.assertEqual(inc_sel_file(u"/test/folder/**",
+                                      u"/test/folder/2/foo.txt"), 1)
 
     def test_asterisk_slash_double_asterisk(self):
         """Test folder string ending in */**"""
-        self.assertEqual(inc_sel_dir("fold*/**", "folder"), 2)
+        self.assertEqual(inc_sel_dir(u"fold*/**", u"folder"), 2)
+
+
+class TestSimpleUnicode(UnitTestCase):
+    """Test simple unicode comparison"""
+
+    def test_simple_unicode(self):
+        """Test simple unicode comparison"""
+        self.assertEqual(inc_sel_file(u"прыклад/пример/例/Παράδειγμα/उदाहरण.txt",
+                                      u"прыклад/пример/例/Παράδειγμα/उदाहरण.txt"), 1)
+
+
+class TestSquareBrackets(UnitTestCase):
+    """Test glob matching where the glob includes []s and [!]s"""
+
+    def test_square_bracket_options(self):
+        """Test file including options in []s"""
+        self.assertEqual(inc_sel_file(u"/test/f[o,s,p]lder/foo.txt",
+                                      u"/test/folder/foo.txt"), 1)
+        self.assertEqual(inc_sel_file(u"/test/f[i,s,p]lder/foo.txt",
+                                      u"/test/folder/foo.txt"), None)
+        self.assertEqual(inc_sel_file(u"/test/f[s,o,p]lder/foo.txt",
+                                      u"/test/folder/foo.txt"), 1)
+
+    def test_square_bracket_options_unicode(self):
+        """Test file including options in []s"""
+        self.assertEqual(inc_sel_file(u"прыклад/пр[и,j,l]мер/例/Παράδειγμα/उदाहरण.txt",
+                                      u"прыклад/пример/例/Παράδειγμα/उदाहरण.txt"), 1)
+        self.assertEqual(inc_sel_file(u"прыклад/п[a,b,c]имер/例/Παράδειγμα/उदाहरण.txt",
+                                      u"прыклад/пример/例/Παράδειγμα/उदाहरण.txt"), None)
+
+    def test_not_square_bracket_options(self):
+        """Test file including options in [!]s"""
+        self.assertEqual(inc_sel_file(u"/test/f[!o,s,p]lder/foo.txt",
+                                      u"/test/folder/foo.txt"), None)
+        self.assertEqual(inc_sel_file(u"/test/f[!i,s,p]lder/foo.txt",
+                                      u"/test/folder/foo.txt"), 1)
+        self.assertEqual(inc_sel_file(u"/test/f[!s,o,p]lder/foo.txt",
+                                      u"/test/folder/foo.txt"), None)
+
+    def test_square_bracket_range(self):
+        """Test file including range in []s"""
+        self.assertEqual(inc_sel_file(u"/test/folder[1-5]/foo.txt",
+                                      u"/test/folder4/foo.txt"), 1)
+        self.assertEqual(inc_sel_file(u"/test/folder[5-9]/foo.txt",
+                                      u"/test/folder4/foo.txt"), None)
+        self.assertEqual(inc_sel_file(u"/test/folder[1-5]/foo.txt",
+                                      u"/test/folder6/foo.txt"), None)
+
+    def test_square_bracket_not_range(self):
+        """Test file including range in [!]s"""
+        self.assertEqual(inc_sel_file(u"/test/folder[!1-5]/foo.txt",
+                                      u"/test/folder4/foo.txt"), None)
+        self.assertEqual(inc_sel_file(u"/test/folder[!5-9]/foo.txt",
+                                      u"/test/folder4/foo.txt"), 1)
+        self.assertEqual(inc_sel_file(u"/test/folder[!1-5]/foo.txt",
+                                      u"/test/folder6/foo.txt"), 1)

=== modified file 'testing/unit/test_gpg.py'
--- testing/unit/test_gpg.py	2017-07-11 14:55:38 +0000
+++ testing/unit/test_gpg.py	2017-12-01 23:01:42 +0000
@@ -71,23 +71,23 @@
 
     def test_gpg_asym(self):
         """Test GPG asymmetric encryption"""
-        profile = gpg.GPGProfile(passphrase=self.sign_passphrase,
+        profile = gpg.GPGProfile(passphrase=self.sign_passphrase_bytes,
                                  recipients=[self.encrypt_key1,
                                              self.encrypt_key2])
         self.gpg_cycle("aoensutha aonetuh saoe", profile)
 
-        profile2 = gpg.GPGProfile(passphrase=self.sign_passphrase,
+        profile2 = gpg.GPGProfile(passphrase=self.sign_passphrase_bytes,
                                   recipients=[self.encrypt_key1])
         self.gpg_cycle("aoeu" * 10000, profile2)
 
     def test_gpg_hidden_asym(self):
         """Test GPG asymmetric encryption with hidden key id"""
-        profile = gpg.GPGProfile(passphrase=self.sign_passphrase,
+        profile = gpg.GPGProfile(passphrase=self.sign_passphrase_bytes,
                                  hidden_recipients=[self.encrypt_key1,
                                                     self.encrypt_key2])
         self.gpg_cycle("aoensutha aonetuh saoe", profile)
 
-        profile2 = gpg.GPGProfile(passphrase=self.sign_passphrase,
+        profile2 = gpg.GPGProfile(passphrase=self.sign_passphrase_bytes,
                                   hidden_recipients=[self.encrypt_key1])
         self.gpg_cycle("aoeu" * 10000, profile2)
 
@@ -95,7 +95,7 @@
         """Test to make sure GPG reports the proper signature key"""
         plaintext = "hello" * 50000
 
-        signing_profile = gpg.GPGProfile(passphrase=self.sign_passphrase,
+        signing_profile = gpg.GPGProfile(passphrase=self.sign_passphrase_bytes,
                                          sign_key=self.sign_key,
                                          recipients=[self.encrypt_key1])
 
@@ -114,7 +114,7 @@
         """Test to make sure GPG reports the proper signature key even with hidden encryption key id"""
         plaintext = "hello" * 50000
 
-        signing_profile = gpg.GPGProfile(passphrase=self.sign_passphrase,
+        signing_profile = gpg.GPGProfile(passphrase=self.sign_passphrase_bytes,
                                          sign_key=self.sign_key,
                                          hidden_recipients=[self.encrypt_key1])
 

=== modified file 'testing/unit/test_patchdir.py'
--- testing/unit/test_patchdir.py	2015-02-01 17:37:37 +0000
+++ testing/unit/test_patchdir.py	2017-12-01 23:01:42 +0000
@@ -21,7 +21,6 @@
 
 from future_builtins import map
 
-import sys
 import cStringIO
 import unittest
 

=== modified file 'testing/unit/test_selection.py'
--- testing/unit/test_selection.py	2017-07-11 14:55:38 +0000
+++ testing/unit/test_selection.py	2017-12-01 23:01:42 +0000
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
 #
 # Copyright 2002 Ben Escoto <ben@xxxxxxxxxxx>
@@ -36,165 +37,165 @@
     def setUp(self):
         super(MatchingTest, self).setUp()
         self.unpack_testfiles()
-        self.root = Path("testfiles/select")
+        self.root = Path(u"testfiles/select")
         self.Select = Select(self.root)
 
     def makeext(self, path):
-        return self.root.new_index(tuple(path.split("/")))
+        return self.root.new_index(tuple(path.split(u"/")))
 
     def testRegexp(self):
         """Test regular expression selection func"""
-        sf1 = self.Select.regexp_get_sf(".*\.py", 1)
-        assert sf1(self.makeext("1.py")) == 1
-        assert sf1(self.makeext("usr/foo.py")) == 1
-        assert sf1(self.root.append("1.doc")) is None
+        sf1 = self.Select.regexp_get_sf(u".*\.py", 1)
+        assert sf1(self.makeext(u"1.py")) == 1
+        assert sf1(self.makeext(u"usr/foo.py")) == 1
+        assert sf1(self.root.append(u"1.doc")) is None
 
-        sf2 = self.Select.regexp_get_sf("hello", 0)
-        assert sf2(Path("hello")) == 0
-        assert sf2(Path("foohello_there")) == 0
-        assert sf2(Path("foo")) is None
+        sf2 = self.Select.regexp_get_sf(u"hello", 0)
+        assert sf2(Path(u"hello")) == 0
+        assert sf2(Path(u"foohello_there")) == 0
+        assert sf2(Path(u"foo")) is None
 
     def test_tuple_include(self):
         """Test include selection function made from a regular filename"""
         self.assertRaises(FilePrefixError, self.Select.glob_get_normal_sf,
-                          "foo", 1)
-
-        sf2 = self.Select.glob_get_sf("testfiles/select/usr/local/bin/", 1)
-
-        with patch('duplicity.path.ROPath.isdir') as mock_isdir:
+                          u"foo", 1)
+
+        sf2 = self.Select.glob_get_sf(u"testfiles/select/usr/local/bin/", 1)
+
+        with patch(u"duplicity.path.ROPath.isdir") as mock_isdir:
             mock_isdir.return_value = True
             # Can't pass the return_value as an argument to patch, i.e.:
-            # with patch('duplicity.path.ROPath.isdir', return_value=True):
+            # with patch("duplicity.path.ROPath.isdir", return_value=True):
             # as build system's mock is too old to support it.
 
-            self.assertEqual(sf2(self.makeext("usr")), 2)
-            self.assertEqual(sf2(self.makeext("usr/local")), 2)
-            self.assertEqual(sf2(self.makeext("usr/local/bin")), 1)
-            self.assertEqual(sf2(self.makeext("usr/local/doc")), None)
-            self.assertEqual(sf2(self.makeext("usr/local/bin/gzip")), 1)
-            self.assertEqual(sf2(self.makeext("usr/local/bingzip")), None)
+            self.assertEqual(sf2(self.makeext(u"usr")), 2)
+            self.assertEqual(sf2(self.makeext(u"usr/local")), 2)
+            self.assertEqual(sf2(self.makeext(u"usr/local/bin")), 1)
+            self.assertEqual(sf2(self.makeext(u"usr/local/doc")), None)
+            self.assertEqual(sf2(self.makeext(u"usr/local/bin/gzip")), 1)
+            self.assertEqual(sf2(self.makeext(u"usr/local/bingzip")), None)
 
     def test_tuple_exclude(self):
         """Test exclude selection function made from a regular filename"""
         self.assertRaises(FilePrefixError, self.Select.glob_get_normal_sf,
-                          "foo", 0)
-
-        sf2 = self.Select.glob_get_sf("testfiles/select/usr/local/bin/", 0)
-
-        with patch('duplicity.path.ROPath.isdir') as mock_isdir:
+                          u"foo", 0)
+
+        sf2 = self.Select.glob_get_sf(u"testfiles/select/usr/local/bin/", 0)
+
+        with patch(u"duplicity.path.ROPath.isdir") as mock_isdir:
             mock_isdir.return_value = True
 
-            assert sf2(self.makeext("usr")) is None
-            assert sf2(self.makeext("usr/local")) is None
-            assert sf2(self.makeext("usr/local/bin")) == 0
-            assert sf2(self.makeext("usr/local/doc")) is None
-            assert sf2(self.makeext("usr/local/bin/gzip")) == 0
-            assert sf2(self.makeext("usr/local/bingzip")) is None
+            assert sf2(self.makeext(u"usr")) is None
+            assert sf2(self.makeext(u"usr/local")) is None
+            assert sf2(self.makeext(u"usr/local/bin")) == 0
+            assert sf2(self.makeext(u"usr/local/doc")) is None
+            assert sf2(self.makeext(u"usr/local/bin/gzip")) == 0
+            assert sf2(self.makeext(u"usr/local/bingzip")) is None
 
     def test_glob_star_include(self):
         """Test a few globbing patterns, including **"""
-        sf1 = self.Select.glob_get_sf("**", 1)
-        assert sf1(self.makeext("foo")) == 1
-        assert sf1(self.makeext("")) == 1
+        sf1 = self.Select.glob_get_sf(u"**", 1)
+        assert sf1(self.makeext(u"foo")) == 1
+        assert sf1(self.makeext(u"")) == 1
 
-        sf2 = self.Select.glob_get_sf("**.py", 1)
-        assert sf2(self.makeext("foo")) == 2
-        assert sf2(self.makeext("usr/local/bin")) == 2
-        assert sf2(self.makeext("what/ever.py")) == 1
-        assert sf2(self.makeext("what/ever.py/foo")) == 1
+        sf2 = self.Select.glob_get_sf(u"**.py", 1)
+        assert sf2(self.makeext(u"foo")) == 2
+        assert sf2(self.makeext(u"usr/local/bin")) == 2
+        assert sf2(self.makeext(u"what/ever.py")) == 1
+        assert sf2(self.makeext(u"what/ever.py/foo")) == 1
 
     def test_glob_star_exclude(self):
         """Test a few glob excludes, including **"""
-        sf1 = self.Select.glob_get_sf("**", 0)
-        assert sf1(self.makeext("/usr/local/bin")) == 0
+        sf1 = self.Select.glob_get_sf(u"**", 0)
+        assert sf1(self.makeext(u"/usr/local/bin")) == 0
 
-        sf2 = self.Select.glob_get_sf("**.py", 0)
-        assert sf2(self.makeext("foo")) is None
-        assert sf2(self.makeext("usr/local/bin")) is None
-        assert sf2(self.makeext("what/ever.py")) == 0
-        assert sf2(self.makeext("what/ever.py/foo")) == 0
+        sf2 = self.Select.glob_get_sf(u"**.py", 0)
+        assert sf2(self.makeext(u"foo")) is None
+        assert sf2(self.makeext(u"usr/local/bin")) is None
+        assert sf2(self.makeext(u"what/ever.py")) == 0
+        assert sf2(self.makeext(u"what/ever.py/foo")) == 0
 
     def test_simple_glob_double_asterisk(self):
         """test_simple_glob_double_asterisk - primarily to check that the defaults used by the error tests work"""
-        assert self.Select.glob_get_normal_sf("**", 1)
+        assert self.Select.glob_get_normal_sf(u"**", 1)
 
     def test_glob_sf_exception(self):
         """test_glob_sf_exception - see if globbing errors returned"""
         self.assertRaises(GlobbingError, self.Select.glob_get_normal_sf,
-                          "testfiles/select/hello//there", 1)
+                          u"testfiles/select/hello//there", 1)
 
     def test_file_prefix_sf_exception(self):
         """test_file_prefix_sf_exception - see if FilePrefix error is returned"""
         # These should raise a FilePrefixError because the root directory for the selection is "testfiles/select"
         self.assertRaises(FilePrefixError,
-                          self.Select.glob_get_sf, "testfiles/whatever", 1)
+                          self.Select.glob_get_sf, u"testfiles/whatever", 1)
         self.assertRaises(FilePrefixError,
-                          self.Select.glob_get_sf, "testfiles/?hello", 0)
+                          self.Select.glob_get_sf, u"testfiles/?hello", 0)
 
     def test_scan(self):
         """Tests what is returned for selection tests regarding directory scanning"""
-        select = Select(Path("/"))
+        select = Select(Path(u"/"))
 
-        assert select.glob_get_sf("**.py", 1)(Path("/")) == 2
-        assert select.glob_get_sf("**.py", 1)(Path("foo")) == 2
-        assert select.glob_get_sf("**.py", 1)(Path("usr/local/bin")) == 2
-        assert select.glob_get_sf("/testfiles/select/**.py", 1)(Path("/testfiles/select")) == 2
-        assert select.glob_get_sf("/testfiles/select/test.py", 1)(Path("/testfiles/select")) == 2
-        assert select.glob_get_normal_sf("/testfiles/se?ect/test.py", 1)(Path("/testfiles/select")) == 2
-        assert select.glob_get_sf("/testfiles/select/test.py", 0)(Path("/testfiles/select")) is None
-        assert select.glob_get_normal_sf("/testfiles/select/test.py", 0)(Path("/testfiles/select")) is None
+        assert select.glob_get_sf(u"**.py", 1)(Path(u"/")) == 2
+        assert select.glob_get_sf(u"**.py", 1)(Path(u"foo")) == 2
+        assert select.glob_get_sf(u"**.py", 1)(Path(u"usr/local/bin")) == 2
+        assert select.glob_get_sf(u"/testfiles/select/**.py", 1)(Path(u"/testfiles/select")) == 2
+        assert select.glob_get_sf(u"/testfiles/select/test.py", 1)(Path(u"/testfiles/select")) == 2
+        assert select.glob_get_normal_sf(u"/testfiles/se?ect/test.py", 1)(Path(u"/testfiles/select")) == 2
+        assert select.glob_get_sf(u"/testfiles/select/test.py", 0)(Path(u"/testfiles/select")) is None
+        assert select.glob_get_normal_sf(u"/testfiles/select/test.py", 0)(Path(u"/testfiles/select")) is None
 
     def test_ignore_case(self):
         """test_ignore_case - try a few expressions with ignorecase:"""
 
-        sf = self.Select.glob_get_sf("ignorecase:testfiles/SeLect/foo/bar", 1)
-        assert sf(self.makeext("FOO/BAR")) == 1
-        assert sf(self.makeext("foo/bar")) == 1
-        assert sf(self.makeext("fOo/BaR")) == 1
-        self.assertRaises(FilePrefixError, self.Select.glob_get_sf, "ignorecase:tesfiles/sect/foo/bar", 1)
+        sf = self.Select.glob_get_sf(u"ignorecase:testfiles/SeLect/foo/bar", 1)
+        assert sf(self.makeext(u"FOO/BAR")) == 1
+        assert sf(self.makeext(u"foo/bar")) == 1
+        assert sf(self.makeext(u"fOo/BaR")) == 1
+        self.assertRaises(FilePrefixError, self.Select.glob_get_sf, u"ignorecase:tesfiles/sect/foo/bar", 1)
 
     def test_root(self):
         """test_root - / may be a counterexample to several of these.."""
-        root = Path("/")
+        root = Path(u"/")
         select = Select(root)
 
-        self.assertEqual(select.glob_get_sf("/", 1)(root), 1)
-        self.assertEqual(select.glob_get_sf("/foo", 1)(root), 2)
-        self.assertEqual(select.glob_get_sf("/foo/bar", 1)(root), 2)
-        self.assertEqual(select.glob_get_sf("/", 0)(root), 0)
-        self.assertEqual(select.glob_get_sf("/foo", 0)(root), None)
+        self.assertEqual(select.glob_get_sf(u"/", 1)(root), 1)
+        self.assertEqual(select.glob_get_sf(u"/foo", 1)(root), 2)
+        self.assertEqual(select.glob_get_sf(u"/foo/bar", 1)(root), 2)
+        self.assertEqual(select.glob_get_sf(u"/", 0)(root), 0)
+        self.assertEqual(select.glob_get_sf(u"/foo", 0)(root), None)
 
-        assert select.glob_get_sf("**.py", 1)(root) == 2
-        assert select.glob_get_sf("**", 1)(root) == 1
-        assert select.glob_get_sf("ignorecase:/", 1)(root) == 1
-        assert select.glob_get_sf("**.py", 0)(root) is None
-        assert select.glob_get_sf("**", 0)(root) == 0
-        assert select.glob_get_sf("/foo/*", 0)(root) is None
+        assert select.glob_get_sf(u"**.py", 1)(root) == 2
+        assert select.glob_get_sf(u"**", 1)(root) == 1
+        assert select.glob_get_sf(u"ignorecase:/", 1)(root) == 1
+        assert select.glob_get_sf(u"**.py", 0)(root) is None
+        assert select.glob_get_sf(u"**", 0)(root) == 0
+        assert select.glob_get_sf(u"/foo/*", 0)(root) is None
 
     def test_other_filesystems(self):
         """Test to see if --exclude-other-filesystems works correctly"""
-        root = Path("/")
+        root = Path(u"/")
         select = Select(root)
         sf = select.other_filesystems_get_sf(0)
         assert sf(root) is None
-        if os.path.ismount("/usr/bin"):
-            sfval = 0
-        else:
-            sfval = None
-        assert sf(Path("/usr/bin")) == sfval, \
-            "Assumption: /usr/bin is on the same filesystem as /"
-        if os.path.ismount("/dev"):
-            sfval = 0
-        else:
-            sfval = None
-        assert sf(Path("/dev")) == sfval, \
-            "Assumption: /dev is on a different filesystem"
-        if os.path.ismount("/proc"):
-            sfval = 0
-        else:
-            sfval = None
-        assert sf(Path("/proc")) == sfval, \
-            "Assumption: /proc is on a different filesystem"
+        if os.path.ismount(u"/usr/bin"):
+            sfval = 0
+        else:
+            sfval = None
+        assert sf(Path(u"/usr/bin")) == sfval, \
+            u"Assumption: /usr/bin is on the same filesystem as /"
+        if os.path.ismount(u"/dev"):
+            sfval = 0
+        else:
+            sfval = None
+        assert sf(Path(u"/dev")) == sfval, \
+            u"Assumption: /dev is on a different filesystem"
+        if os.path.ismount(u"/proc"):
+            sfval = 0
+        else:
+            sfval = None
+        assert sf(Path(u"/proc")) == sfval, \
+            u"Assumption: /proc is on a different filesystem"
 
 
 class ParseArgsTest(UnitTestCase):
@@ -203,24 +204,34 @@
         super(ParseArgsTest, self).setUp()
         self.unpack_testfiles()
         self.root = None
-        self.expected_restored_tree = [(), ('1',), ('1', '1sub1'), ('1', '1sub1', '1sub1sub1'),
-                                       ('1', '1sub1', '1sub1sub1', '1sub1sub1_file.txt'), ('1', '1sub1', '1sub1sub3'),
-                                       ('1', '1sub2'), ('1', '1sub2', '1sub2sub1'), ('1', '1sub3'),
-                                       ('1', '1sub3', '1sub3sub3'), ('1.py',), ('2',), ('2', '2sub1'),
-                                       ('2', '2sub1', '2sub1sub1'), ('2', '2sub1', '2sub1sub1', '2sub1sub1_file.txt'),
-                                       ('3',), ('3', '3sub2'), ('3', '3sub2', '3sub2sub1'),
-                                       ('3', '3sub2', '3sub2sub2'), ('3', '3sub2', '3sub2sub3'), ('3', '3sub3'),
-                                       ('3', '3sub3', '3sub3sub1'), ('3', '3sub3', '3sub3sub2'),
-                                       ('3', '3sub3', '3sub3sub2', '3sub3sub2_file.txt'), ('3', '3sub3', '3sub3sub3')]
+        self.expected_restored_tree = [(), (u"1",), (u"1", u"1sub1"), (u"1", u"1sub1", u"1sub1sub1"),
+                                       (u"1", u"1sub1", u"1sub1sub1", u"1sub1sub1_file.txt"),
+                                       (u"1", u"1sub1", u"1sub1sub3"), (u"1", u"1sub2"), (u"1", u"1sub2", u"1sub2sub1"),
+                                       (u"1", u"1sub3"), (u"1", u"1sub3", u"1sub3sub3"), (u"1.py",), (u"2",),
+                                       (u"2", u"2sub1"), (u"2", u"2sub1", u"2sub1sub1"),
+                                       (u"2", u"2sub1", u"2sub1sub1", u"2sub1sub1_file.txt"),
+                                       (u"3",), (u"3", u"3sub2"), (u"3", u"3sub2", u"3sub2sub1"),
+                                       (u"3", u"3sub2", u"3sub2sub2"), (u"3", u"3sub2", u"3sub2sub3"), (u"3", u"3sub3"),
+                                       (u"3", u"3sub3", u"3sub3sub1"), (u"3", u"3sub3", u"3sub3sub2"),
+                                       (u"3", u"3sub3", u"3sub3sub2", u"3sub3sub2_file.txt"),
+                                       (u"3", u"3sub3", u"3sub3sub3")]
+
+    def uc_index_from_path(self, path):
+        """Takes a path type and returns path.index, with each element converted into unicode"""
+        uindex = tuple([element.decode(sys.getfilesystemencoding(), "strict") for element in path.index])
+        return uindex
 
     def ParseTest(self, tuplelist, indicies, filelists=[]):
         """No error if running select on tuple goes over indicies"""
         if not self.root:
-            self.root = Path("testfiles/select")
+            self.root = Path(u"testfiles/select")
         self.Select = Select(self.root)
         self.Select.ParseArgs(tuplelist, self.remake_filelists(filelists))
         self.Select.set_iter()
-        results_as_list = list(Iter.map(lambda path: path.index, self.Select))
+
+        # Create a list of the paths returned by the select function, converted
+        # into path.index styled tuples
+        results_as_list = list(Iter.map(self.uc_index_from_path, self.Select))
         # print(results_as_list)
         self.assertEqual(indicies, results_as_list)
 
@@ -228,7 +239,7 @@
         """Turn strings in filelist into fileobjs"""
         new_filelists = []
         for f in filelist:
-            if isinstance(f, types.StringType):
+            if isinstance(f, unicode):
                 new_filelists.append(StringIO.StringIO(f))
             else:
                 new_filelists.append(f)
@@ -236,629 +247,645 @@
 
     def test_parse(self):
         """Test just one include, all exclude"""
-        self.ParseTest([("--include", "testfiles/select/1/1"),
-                        ("--exclude", "**")],
-                       [(), ('1',), ("1", "1"), ("1", '1', '1'),
-                        ('1', '1', '2'), ('1', '1', '3')])
+        self.ParseTest([(u"--include", u"testfiles/select/1/1"),
+                        (u"--exclude", u"**")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"1"),
+                        (u"1", u"1", u"2"), (u"1", u"1", u"3")])
 
     def test_parse2(self):
         """Test three level include/exclude"""
-        self.ParseTest([("--exclude", "testfiles/select/1/1/1"),
-                        ("--include", "testfiles/select/1/1"),
-                        ("--exclude", "testfiles/select/1"),
-                        ("--exclude", "**")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')])
+        self.ParseTest([(u"--exclude", u"testfiles/select/1/1/1"),
+                        (u"--include", u"testfiles/select/1/1"),
+                        (u"--exclude", u"testfiles/select/1"),
+                        (u"--exclude", u"**")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")])
 
     def test_filelist(self):
         """Filelist glob test similar to above testParse2"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/select/1/1/1\n"
-                        "testfiles/select/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1\n"
+                        u"testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_1_trailing_whitespace(self):
         """Filelist glob test similar to globbing filelist, but with 1 trailing whitespace on include"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/select/1/1/1\n"
-                        "testfiles/select/1/1 \n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1\n"
+                        u"testfiles/select/1/1 \n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_2_trailing_whitespaces(self):
         """Filelist glob test similar to globbing filelist, but with 2 trailing whitespaces on include"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/select/1/1/1\n"
-                        "testfiles/select/1/1  \n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1\n"
+                        u"testfiles/select/1/1  \n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_1_leading_whitespace(self):
         """Filelist glob test similar to globbing filelist, but with 1 leading whitespace on include"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/select/1/1/1\n"
-                        " testfiles/select/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1\n"
+                        u" testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_2_leading_whitespaces(self):
         """Filelist glob test similar to globbing filelist, but with 2 leading whitespaces on include"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/select/1/1/1\n"
-                        "  testfiles/select/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1\n"
+                        u"  testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_1_trailing_whitespace_exclude(self):
         """Filelist glob test similar to globbing filelist, but with 1 trailing whitespace on exclude"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/select/1/1/1 \n"
-                        "testfiles/select/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1 \n"
+                        u"testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_2_trailing_whitespace_exclude(self):
         """Filelist glob test similar to globbing filelist, but with 2 trailing whitespaces on exclude"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/select/1/1/1  \n"
-                        "testfiles/select/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1  \n"
+                        u"testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_1_leading_whitespace_exclude(self):
         """Filelist glob test similar to globbing filelist, but with 1 leading whitespace on exclude"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       [" - testfiles/select/1/1/1\n"
-                        "testfiles/select/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u" - testfiles/select/1/1/1\n"
+                        u"testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_2_leading_whitespaces_exclude(self):
         """Filelist glob test similar to globbing filelist, but with 2 leading whitespaces on exclude"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["  - testfiles/select/1/1/1\n"
-                        "testfiles/select/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"  - testfiles/select/1/1/1\n"
+                        u"testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_check_excluded_folder_included_for_contents(self):
         """Filelist glob test to check excluded folder is included if contents are"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3'), ('1', '2'), ('1', '2', '1'), ('1', '3'), ('1', '3', '1'), ('1', '3', '2'),
-                        ('1', '3', '3')],
-                       ["+ testfiles/select/1/2/1\n"
-                        "- testfiles/select/1/2\n"
-                        "testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3"), (u"1", u"2"), (u"1", u"2", u"1"), (u"1", u"3"), (u"1", u"3", u"1"),
+                        (u"1", u"3", u"2"), (u"1", u"3", u"3")],
+                       [u"+ testfiles/select/1/2/1\n"
+                        u"- testfiles/select/1/2\n"
+                        u"testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_with_unnecessary_quotes(self):
         """Filelist glob test similar to globbing filelist, but with quotes around one of the paths."""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- 'testfiles/select/1/1/1'\n"
-                        "testfiles/select/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- 'testfiles/select/1/1/1'\n"
+                        u"testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_with_unnecessary_double_quotes(self):
         """Filelist glob test similar to globbing filelist, but with double quotes around one of the paths."""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ['- "testfiles/select/1/1/1"\n'
-                        'testfiles/select/1/1\n'
-                        '- testfiles/select/1\n'
-                        '- **'])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u'- "testfiles/select/1/1/1"\n'
+                        u"testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_with_full_line_comment(self):
         """Filelist glob test similar to globbing filelist, but with a full-line comment."""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ['- testfiles/select/1/1/1\n'
-                        '# This is a test\n'
-                        'testfiles/select/1/1\n'
-                        '- testfiles/select/1\n'
-                        '- **'])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1\n"
+                        u"# This is a test\n"
+                        u"testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_with_blank_line(self):
         """Filelist glob test similar to globbing filelist, but with a blank line."""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ['- testfiles/select/1/1/1\n'
-                        '\n'
-                        'testfiles/select/1/1\n'
-                        '- testfiles/select/1\n'
-                        '- **'])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1\n"
+                        u"\n"
+                        u"testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_with_blank_line_and_whitespace(self):
         """Filelist glob test similar to globbing filelist, but with a blank line and whitespace."""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ['- testfiles/select/1/1/1\n'
-                        '  \n'
-                        'testfiles/select/1/1\n'
-                        '- testfiles/select/1\n'
-                        '- **'])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1\n"
+                        u"  \n"
+                        u"testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_asterisk(self):
         """Filelist glob test with * instead of 'testfiles'"""
         # Thank you to Elifarley Cruz for this test case
         # (https://bugs.launchpad.net/duplicity/+bug/884371).
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '1'),
-                        ('1', '1', '2'), ('1', '1', '3')],
-                       ["*/select/1/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"1"),
+                        (u"1", u"1", u"2"), (u"1", u"1", u"3")],
+                       [u"*/select/1/1\n"
+                        u"- **"])
 
     def test_include_filelist_asterisk_2(self):
-        """Identical to test_filelist, but with the exclude 'select' replaced with '*'"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/*/1/1/1\n"
-                        "testfiles/select/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        """Identical to test_filelist, but with the exclude "select" replaced with '*'"""
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/*/1/1/1\n"
+                        u"testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_asterisk_3(self):
-        """Identical to test_filelist, but with the auto-include 'select' replaced with '*'"""
+        """Identical to test_filelist, but with the auto-include "select" replaced with '*'"""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/select/1/1/1\n"
-                        "testfiles/*/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1\n"
+                        u"testfiles/*/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_asterisk_4(self):
-        """Identical to test_filelist, but with a specific include 'select' replaced with '*'"""
+        """Identical to test_filelist, but with a specific include "select" replaced with '*'"""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/select/1/1/1\n"
-                        "+ testfiles/*/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1\n"
+                        u"+ testfiles/*/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_asterisk_5(self):
         """Identical to test_filelist, but with all 'select's replaced with '*'"""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/*/1/1/1\n"
-                        "+ testfiles/*/1/1\n"
-                        "- testfiles/*/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/*/1/1/1\n"
+                        u"+ testfiles/*/1/1\n"
+                        u"- testfiles/*/1\n"
+                        u"- **"])
 
     def test_include_filelist_asterisk_6(self):
         """Identical to test_filelist, but with numerous excluded folders replaced with '*'"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- */*/1/1/1\n"
-                        "+ testfiles/select/1/1\n"
-                        "- */*/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- */*/1/1/1\n"
+                        u"+ testfiles/select/1/1\n"
+                        u"- */*/1\n"
+                        u"- **"])
 
     def test_include_filelist_asterisk_7(self):
         """Identical to test_filelist, but with numerous included/excluded folders replaced with '*'"""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- */*/1/1/1\n"
-                        "+ */*/1/1\n"
-                        "- */*/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- */*/1/1/1\n"
+                        u"+ */*/1/1\n"
+                        u"- */*/1\n"
+                        u"- **"])
 
     def test_include_filelist_double_asterisk_1(self):
-        """Identical to test_filelist, but with the exclude 'select' replaced with '**'"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/**/1/1/1\n"
-                        "testfiles/select/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        """Identical to test_filelist, but with the exclude "select' replaced with '**'"""
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/**/1/1/1\n"
+                        u"testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_double_asterisk_2(self):
         """Identical to test_filelist, but with the include 'select' replaced with '**'"""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/select/1/1/1\n"
-                        "**ct/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1\n"
+                        u"**ct/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_double_asterisk_3(self):
         """Identical to test_filelist, but with the exclude 'testfiles/select' replaced with '**'"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- **/1/1/1\n"
-                        "testfiles/select/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- **/1/1/1\n"
+                        u"testfiles/select/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_double_asterisk_4(self):
         """Identical to test_filelist, but with the include 'testfiles/select' replaced with '**'"""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/select/1/1/1\n"
-                        "**t/1/1\n"
-                        "- testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1\n"
+                        u"**t/1/1\n"
+                        u"- testfiles/select/1\n"
+                        u"- **"])
 
     def test_include_filelist_double_asterisk_5(self):
         """Identical to test_filelist, but with all 'testfiles/select's replaced with '**'"""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- **/1/1/1\n"
-                        "**t/1/1\n"
-                        "- **t/1\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- **/1/1/1\n"
+                        u"**t/1/1\n"
+                        u"- **t/1\n"
+                        u"- **"])
 
     def test_include_filelist_trailing_slashes(self):
         """Filelist glob test similar to globbing filelist, but with trailing slashes"""
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- testfiles/select/1/1/1/\n"
-                        "testfiles/select/1/1/\n"
-                        "- testfiles/select/1/\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- testfiles/select/1/1/1/\n"
+                        u"testfiles/select/1/1/\n"
+                        u"- testfiles/select/1/\n"
+                        u"- **"])
 
     def test_include_filelist_trailing_slashes_and_single_asterisks(self):
         """Filelist glob test similar to globbing filelist, but with trailing slashes and single asterisks"""
         # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- */select/1/1/1/\n"
-                        "testfiles/select/1/1/\n"
-                        "- testfiles/*/1/\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- */select/1/1/1/\n"
+                        u"testfiles/select/1/1/\n"
+                        u"- testfiles/*/1/\n"
+                        u"- **"])
 
     def test_include_filelist_trailing_slashes_and_double_asterisks(self):
         """Filelist glob test similar to globbing filelist, but with trailing slashes and double asterisks"""
         # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["- **/1/1/1/\n"
-                        "testfiles/select/1/1/\n"
-                        "- **t/1/\n"
-                        "- **"])
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"- **/1/1/1/\n"
+                        u"testfiles/select/1/1/\n"
+                        u"- **t/1/\n"
+                        u"- **"])
 
     def test_filelist_null_separator(self):
         """test_filelist, but with null_separator set"""
-        self.set_global('null_separator', 1)
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["\0- testfiles/select/1/1/1\0testfiles/select/1/1\0- testfiles/select/1\0- **\0"])
+        self.set_global(u"null_separator", 1)
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"\0- testfiles/select/1/1/1\0testfiles/select/1/1\0- testfiles/select/1\0- **\0"])
 
     def test_exclude_filelist(self):
         """Exclude version of test_filelist"""
-        self.ParseTest([("--exclude-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["testfiles/select/1/1/1\n"
-                        "+ testfiles/select/1/1\n"
-                        "testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--exclude-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"testfiles/select/1/1/1\n"
+                        u"+ testfiles/select/1/1\n"
+                        u"testfiles/select/1\n"
+                        u"- **"])
 
     def test_exclude_filelist_asterisk_1(self):
         """Exclude version of test_include_filelist_asterisk"""
-        self.ParseTest([("--exclude-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '1'),
-                        ('1', '1', '2'), ('1', '1', '3')],
-                       ["+ */select/1/1\n"
-                        "- **"])
+        self.ParseTest([(u"--exclude-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"1"),
+                        (u"1", u"1", u"2"), (u"1", u"1", u"3")],
+                       [u"+ */select/1/1\n"
+                        u"- **"])
 
     def test_exclude_filelist_asterisk_2(self):
-        """Identical to test_exclude_filelist, but with the exclude 'select' replaced with '*'"""
-        self.ParseTest([("--exclude-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["testfiles/*/1/1/1\n"
-                        "+ testfiles/select/1/1\n"
-                        "testfiles/select/1\n"
-                        "- **"])
+        """Identical to test_exclude_filelist, but with the exclude "select" replaced with '*'"""
+        self.ParseTest([(u"--exclude-filelist", u"file")],
+                       [(), (u"1",), (u"1", "1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"testfiles/*/1/1/1\n"
+                        u"+ testfiles/select/1/1\n"
+                        u"testfiles/select/1\n"
+                        u"- **"])
 
     def test_exclude_filelist_asterisk_3(self):
-        """Identical to test_exclude_filelist, but with the include 'select' replaced with '*'"""
+        """Identical to test_exclude_filelist, but with the include "select" replaced with '*'"""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        self.ParseTest([("--exclude-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["testfiles/select/1/1/1\n"
-                        "+ testfiles/*/1/1\n"
-                        "testfiles/select/1\n"
-                        "- **"])
+        self.ParseTest([(u"--exclude-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"testfiles/select/1/1/1\n"
+                        u"+ testfiles/*/1/1\n"
+                        u"testfiles/select/1\n"
+                        u"- **"])
 
     def test_exclude_filelist_asterisk_4(self):
         """Identical to test_exclude_filelist, but with numerous excluded folders replaced with '*'"""
-        self.ParseTest([("--exclude-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["*/select/1/1/1\n"
-                        "+ testfiles/select/1/1\n"
-                        "*/*/1\n"
-                        "- **"])
+        self.ParseTest([(u"--exclude-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"*/select/1/1/1\n"
+                        u"+ testfiles/select/1/1\n"
+                        u"*/*/1\n"
+                        u"- **"])
 
     def test_exclude_filelist_asterisk_5(self):
         """Identical to test_exclude_filelist, but with numerous included/excluded folders replaced with '*'"""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        self.ParseTest([("--exclude-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["*/select/1/1/1\n"
-                        "+ */*/1/1\n"
-                        "*/*/1\n"
-                        "- **"])
+        self.ParseTest([(u"--exclude-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"*/select/1/1/1\n"
+                        u"+ */*/1/1\n"
+                        u"*/*/1\n"
+                        u"- **"])
 
     def test_exclude_filelist_double_asterisk(self):
         """Identical to test_exclude_filelist, but with all included/excluded folders replaced with '**'"""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        self.ParseTest([("--exclude-filelist", "file")],
-                       [(), ('1',), ('1', '1'), ('1', '1', '2'),
-                        ('1', '1', '3')],
-                       ["**/1/1/1\n"
-                        "+ **t/1/1\n"
-                        "**t/1\n"
-                        "- **"])
+        self.ParseTest([(u"--exclude-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"1", u"3")],
+                       [u"**/1/1/1\n"
+                        u"+ **t/1/1\n"
+                        u"**t/1\n"
+                        u"- **"])
 
     def test_exclude_filelist_single_asterisk_at_beginning(self):
         """Exclude filelist testing limited functionality of functional test"""
         # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
-        self.root = Path("testfiles/select/1")
-        self.ParseTest([("--exclude-filelist", "file")],
-                       [(), ('2',), ('2', '1')],
-                       ["+ */select/1/2/1\n"
-                        "- testfiles/select/1/2\n"
-                        "- testfiles/*/1/1\n"
-                        "- testfiles/select/1/3"])
+        self.root = Path(u"testfiles/select/1")
+        self.ParseTest([(u"--exclude-filelist", u"file")],
+                       [(), (u"2",), (u"2", u"1")],
+                       [u"+ */select/1/2/1\n"
+                        u"- testfiles/select/1/2\n"
+                        u"- testfiles/*/1/1\n"
+                        u"- testfiles/select/1/3"])
 
     def test_commandline_asterisks_double_both(self):
         """Unit test the functional test TestAsterisks.test_commandline_asterisks_double_both"""
-        self.root = Path("testfiles/select/1")
-        self.ParseTest([("--include", "**/1/2/1"),
-                        ("--exclude", "**t/1/2"),
-                        ("--exclude", "**t/1/1"),
-                        ("--exclude", "**t/1/3")],
-                       [(), ('2',), ('2', '1')])
+        self.root = Path(u"testfiles/select/1")
+        self.ParseTest([(u"--include", u"**/1/2/1"),
+                        (u"--exclude", u"**t/1/2"),
+                        (u"--exclude", u"**t/1/1"),
+                        (u"--exclude", u"**t/1/3")],
+                       [(), (u"2",), (u"2", u"1")])
 
     def test_includes_files(self):
         """Unit test the functional test test_includes_files"""
         # Test for Bug 1624725
         # https://bugs.launchpad.net/duplicity/+bug/1624725
-        self.root = Path("testfiles/select2/1/1sub1")
-        self.ParseTest([("--include", "testfiles/select2/1/1sub1/1sub1sub1"),
-                        ("--exclude", "**")],
-                       [(), ('1sub1sub1',), ('1sub1sub1',
-                                             '1sub1sub1_file.txt')])
+        self.root = Path(u"testfiles/select2/1/1sub1")
+        self.ParseTest([(u"--include", u"testfiles/select2/1/1sub1/1sub1sub1"),
+                        (u"--exclude", u"**")],
+                       [(), (u"1sub1sub1",), (u"1sub1sub1",
+                                             u"1sub1sub1_file.txt")])
 
     def test_includes_files_trailing_slash(self):
         """Unit test the functional test test_includes_files_trailing_slash"""
         # Test for Bug 1624725
         # https://bugs.launchpad.net/duplicity/+bug/1624725
-        self.root = Path("testfiles/select2/1/1sub1")
-        self.ParseTest([("--include", "testfiles/select2/1/1sub1/1sub1sub1/"),
-                        ("--exclude", "**")],
-                       [(), ('1sub1sub1',), ('1sub1sub1',
-                                             '1sub1sub1_file.txt')])
+        self.root = Path(u"testfiles/select2/1/1sub1")
+        self.ParseTest([(u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/"),
+                        (u"--exclude", u"**")],
+                       [(), (u"1sub1sub1",), (u"1sub1sub1",
+                                             u"1sub1sub1_file.txt")])
 
     def test_includes_files_trailing_slash_globbing_chars(self):
         """Unit test functional test_includes_files_trailing_slash_globbing_chars"""
         # Test for Bug 1624725
         # https://bugs.launchpad.net/duplicity/+bug/1624725
-        self.root = Path("testfiles/select2/1/1sub1")
-        self.ParseTest([("--include", "testfiles/s?lect2/1/1sub1/1sub1sub1/"),
-                        ("--exclude", "**")],
-                       [(), ('1sub1sub1',), ('1sub1sub1',
-                                             '1sub1sub1_file.txt')])
+        self.root = Path(u"testfiles/select2/1/1sub1")
+        self.ParseTest([(u"--include", u"testfiles/s?lect2/1/1sub1/1sub1sub1/"),
+                        (u"--exclude", u"**")],
+                       [(), (u"1sub1sub1",), (u"1sub1sub1",
+                                             u"1sub1sub1_file.txt")])
 
     def test_glob(self):
         """Test globbing expression"""
-        self.ParseTest([("--exclude", "**[3-5]"),
-                        ("--include", "testfiles/select/1"),
-                        ("--exclude", "**")],
-                       [(), ('1',), ('1', '1'),
-                        ('1', '1', '1'), ('1', '1', '2'),
-                        ('1', '2'), ('1', '2', '1'), ('1', '2', '2')])
-        self.ParseTest([("--include", "testfiles/select**/2"),
-                        ("--exclude", "**")],
-                       [(), ('1',), ('1', '1'),
-                        ('1', '1', '2'),
-                        ('1', '2'),
-                        ('1', '2', '1'), ('1', '2', '2'), ('1', '2', '3'),
-                        ('1', '3'),
-                        ('1', '3', '2'),
-                        ('2',), ('2', '1'),
-                        ('2', '1', '1'), ('2', '1', '2'), ('2', '1', '3'),
-                        ('2', '2'),
-                        ('2', '2', '1'), ('2', '2', '2'), ('2', '2', '3'),
-                        ('2', '3'),
-                        ('2', '3', '1'), ('2', '3', '2'), ('2', '3', '3'),
-                        ('3',), ('3', '1'),
-                        ('3', '1', '2'),
-                        ('3', '2'),
-                        ('3', '2', '1'), ('3', '2', '2'), ('3', '2', '3'),
-                        ('3', '3'),
-                        ('3', '3', '2')])
+        self.ParseTest([(u"--exclude", u"**[3-5]"),
+                        (u"--include", u"testfiles/select/1"),
+                        (u"--exclude", u"**")],
+                       [(), (u"1",), (u"1", u"1"),
+                        (u"1", u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"2"), (u"1", u"2", u"1"), (u"1", u"2", u"2")])
+        self.ParseTest([(u"--include", u"testfiles/select**/2"),
+                        (u"--exclude", u"**")],
+                       [(), (u"1",), (u"1", u"1"),
+                        (u"1", u"1", u"2"),
+                        (u"1", u"2"),
+                        (u"1", u"2", u"1"), (u"1", u"2", u"2"), (u"1", u"2", u"3"),
+                        (u"1", u"3"),
+                        (u"1", u"3", u"2"),
+                        (u"2",), (u"2", u"1"),
+                        (u"2", u"1", u"1"), (u"2", u"1", u"2"), (u"2", u"1", u"3"),
+                        (u"2", u"2"),
+                        (u"2", u"2", u"1"), (u"2", u"2", u"2"), (u"2", u"2", u"3"),
+                        (u"2", u"3"),
+                        (u"2", u"3", u"1"), (u"2", u"3", u"2"), (u"2", u"3", u"3"),
+                        (u"3",), (u"3", u"1"),
+                        (u"3", u"1", u"2"),
+                        (u"3", u"2"),
+                        (u"3", u"2", u"1"), (u"3", u"2", u"2"), (u"3", u"2", u"3"),
+                        (u"3", u"3"),
+                        (u"3", u"3", u"2")])
 
     def test_filelist2(self):
         """Filelist glob test similar to above testGlob"""
-        self.ParseTest([("--exclude-filelist", "asoeuth")],
-                       [(), ('1',), ('1', '1'),
-                        ('1', '1', '1'), ('1', '1', '2'),
-                        ('1', '2'), ('1', '2', '1'), ('1', '2', '2')],
-                       ["""
+        self.ParseTest([(u"--exclude-filelist", u"asoeuth")],
+                       [(), (u"1",), (u"1", u"1"),
+                        (u"1", u"1", u"1"), (u"1", u"1", u"2"),
+                        (u"1", u"2"), (u"1", u"2", u"1"), (u"1", u"2", u"2")],
+                       [u"""
 **[3-5]
 + testfiles/select/1
 **
 """])
-        self.ParseTest([("--include-filelist", "file")],
-                       [(), ('1',), ('1', '1'),
-                        ('1', '1', '2'),
-                        ('1', '2'),
-                        ('1', '2', '1'), ('1', '2', '2'), ('1', '2', '3'),
-                        ('1', '3'),
-                        ('1', '3', '2'),
-                        ('2',), ('2', '1'),
-                        ('2', '1', '1'), ('2', '1', '2'), ('2', '1', '3'),
-                        ('2', '2'),
-                        ('2', '2', '1'), ('2', '2', '2'), ('2', '2', '3'),
-                        ('2', '3'),
-                        ('2', '3', '1'), ('2', '3', '2'), ('2', '3', '3'),
-                        ('3',), ('3', '1'),
-                        ('3', '1', '2'),
-                        ('3', '2'),
-                        ('3', '2', '1'), ('3', '2', '2'), ('3', '2', '3'),
-                        ('3', '3'),
-                        ('3', '3', '2')],
-                       ["""
+        self.ParseTest([(u"--include-filelist", u"file")],
+                       [(), (u"1",), (u"1", u"1"),
+                        (u"1", u"1", u"2"),
+                        (u"1", u"2"),
+                        (u"1", u"2", u"1"), (u"1", u"2", u"2"), (u"1", u"2", u"3"),
+                        (u"1", u"3"),
+                        (u"1", u"3", u"2"),
+                        (u"2",), (u"2", u"1"),
+                        (u"2", u"1", u"1"), (u"2", u"1", u"2"), (u"2", u"1", u"3"),
+                        (u"2", u"2"),
+                        (u"2", u"2", u"1"), (u"2", u"2", u"2"), (u"2", u"2", u"3"),
+                        (u"2", u"3"),
+                        (u"2", u"3", u"1"), (u"2", u"3", u"2"), (u"2", u"3", u"3"),
+                        (u"3",), (u"3", u"1"),
+                        (u"3", u"1", u"2"),
+                        (u"3", u"2"),
+                        (u"3", u"2", u"1"), (u"3", u"2", u"2"), (u"3", u"2", u"3"),
+                        (u"3", u"3"),
+                        (u"3", u"3", u"2")],
+                       [u"""
 testfiles/select**/2
 - **
 """])
 
     def test_glob2(self):
         """Test more globbing functions"""
-        self.ParseTest([("--include", "testfiles/select/*foo*/p*"),
-                        ("--exclude", "**")],
-                       [(), ('efools',), ('efools', 'ping'),
-                        ('foobar',), ('foobar', 'pong')])
-        self.ParseTest([("--exclude", "testfiles/select/1/1/*"),
-                        ("--exclude", "testfiles/select/1/2/**"),
-                        ("--exclude", "testfiles/select/1/3**"),
-                        ("--include", "testfiles/select/1"),
-                        ("--exclude", "**")],
-                       [(), ('1',), ('1', '1'), ('1', '2')])
+        self.ParseTest([(u"--include", u"testfiles/select/*foo*/p*"),
+                        (u"--exclude", u"**")],
+                       [(), (u"efools",), (u"efools", u"ping"),
+                        (u"foobar",), (u"foobar", u"pong")])
+        self.ParseTest([(u"--exclude", u"testfiles/select/1/1/*"),
+                        (u"--exclude", u"testfiles/select/1/2/**"),
+                        (u"--exclude", u"testfiles/select/1/3**"),
+                        (u"--include", u"testfiles/select/1"),
+                        (u"--exclude", u"**")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"2")])
 
     def test_glob3(self):
         """ regression test for bug 25230 """
-        self.ParseTest([("--include", "testfiles/select/**1"),
-                        ("--include", "testfiles/select/**2"),
-                        ("--exclude", "**")],
-                       [(), ('1',), ('1', '1'),
-                        ('1', '1', '1'), ('1', '1', '2'), ('1', '1', '3'),
-                        ('1', '2'),
-                        ('1', '2', '1'), ('1', '2', '2'), ('1', '2', '3'),
-                        ('1', '3'),
-                        ('1', '3', '1'), ('1', '3', '2'), ('1', '3', '3'),
-                        ('2',), ('2', '1'),
-                        ('2', '1', '1'), ('2', '1', '2'), ('2', '1', '3'),
-                        ('2', '2'),
-                        ('2', '2', '1'), ('2', '2', '2'), ('2', '2', '3'),
-                        ('2', '3'),
-                        ('2', '3', '1'), ('2', '3', '2'), ('2', '3', '3'),
-                        ('3',), ('3', '1'),
-                        ('3', '1', '1'), ('3', '1', '2'), ('3', '1', '3'),
-                        ('3', '2'),
-                        ('3', '2', '1'), ('3', '2', '2'), ('3', '2', '3'),
-                        ('3', '3'),
-                        ('3', '3', '1'), ('3', '3', '2')])
+        self.ParseTest([(u"--include", u"testfiles/select/**1"),
+                        (u"--include", u"testfiles/select/**2"),
+                        (u"--exclude", u"**")],
+                       [(), (u"1",), (u"1", u"1"),
+                        (u"1", u"1", u"1"), (u"1", u"1", u"2"), (u"1", u"1", u"3"),
+                        (u"1", u"2"),
+                        (u"1", u"2", u"1"), (u"1", u"2", u"2"), (u"1", u"2", u"3"),
+                        (u"1", u"3"),
+                        (u"1", u"3", u"1"), (u"1", u"3", u"2"), (u"1", u"3", u"3"),
+                        (u"2",), (u"2", u"1"),
+                        (u"2", u"1", u"1"), (u"2", u"1", u"2"), (u"2", u"1", u"3"),
+                        (u"2", u"2"),
+                        (u"2", u"2", u"1"), (u"2", u"2", u"2"), (u"2", u"2", u"3"),
+                        (u"2", u"3"),
+                        (u"2", u"3", u"1"), (u"2", u"3", u"2"), (u"2", u"3", u"3"),
+                        (u"3",), (u"3", u"1"),
+                        (u"3", u"1", u"1"), (u"3", u"1", u"2"), (u"3", u"1", u"3"),
+                        (u"3", u"2"),
+                        (u"3", u"2", u"1"), (u"3", u"2", u"2"), (u"3", u"2", u"3"),
+                        (u"3", u"3"),
+                        (u"3", u"3", u"1"), (u"3", u"3", u"2")])
 
     def test_alternate_root(self):
         """Test select with different root"""
-        self.root = Path("testfiles/select/1")
-        self.ParseTest([("--exclude", "testfiles/select/1/[23]")],
-                       [(), ('1',), ('1', '1'), ('1', '2'), ('1', '3')])
+        self.root = Path(u"testfiles/select/1")
+        self.ParseTest([(u"--exclude", u"testfiles/select/1/[23]")],
+                       [(), (u"1",), (u"1", u"1"), (u"1", u"2"), (u"1", u"3")])
 
-        self.root = Path("/")
-        self.ParseTest([("--exclude", "/tmp/*"),
-                        ("--include", "/tmp"),
-                        ("--exclude", "/")],
-                       [(), ("tmp",)])
+        self.root = Path(u"/")
+        self.ParseTest([(u"--exclude", u"/tmp/*"),
+                        (u"--include", u"/tmp"),
+                        (u"--exclude", u"/")],
+                       [(), (u"tmp",)])
 
     def test_exclude_after_scan(self):
         """Test select with an exclude after a pattern that would return a scan for that file"""
-        self.root = Path("testfiles/select2/3")
-        self.ParseTest([("--include", "testfiles/select2/3/**file.txt"),
-                        ("--exclude", "testfiles/select2/3/3sub2"),
-                        ("--include", "testfiles/select2/3/3sub1"),
-                        ("--exclude", "**")],
-                       [(), ('3sub1',), ('3sub1', '3sub1sub1'), ('3sub1', '3sub1sub2'), ('3sub1', '3sub1sub3'),
-                        ('3sub3',), ('3sub3', '3sub3sub2'), ('3sub3', '3sub3sub2', '3sub3sub2_file.txt')])
+        self.root = Path(u"testfiles/select2/3")
+        self.ParseTest([(u"--include", u"testfiles/select2/3/**file.txt"),
+                        (u"--exclude", u"testfiles/select2/3/3sub2"),
+                        (u"--include", u"testfiles/select2/3/3sub1"),
+                        (u"--exclude", u"**")],
+                       [(), (u"3sub1",), (u"3sub1", u"3sub1sub1"), (u"3sub1", u"3sub1sub2"), (u"3sub1", u"3sub1sub3"),
+                        (u"3sub3",), (u"3sub3", u"3sub3sub2"), (u"3sub3", u"3sub3sub2", u"3sub3sub2_file.txt")])
 
     def test_include_exclude_basic(self):
         """Test functional test test_include_exclude_basic as a unittest"""
-        self.root = Path("testfiles/select2")
-        self.ParseTest([("--include", "testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt"),
-                        ("--exclude", "testfiles/select2/3/3sub3/3sub3sub2"),
-                        ("--include", "testfiles/select2/3/3sub2/3sub2sub2"),
-                        ("--include", "testfiles/select2/3/3sub3"),
-                        ("--exclude", "testfiles/select2/3/3sub1"),
-                        ("--exclude", "testfiles/select2/2/2sub1/2sub1sub3"),
-                        ("--exclude", "testfiles/select2/2/2sub1/2sub1sub2"),
-                        ("--include", "testfiles/select2/2/2sub1"),
-                        ("--exclude", "testfiles/select2/1/1sub3/1sub3sub2"),
-                        ("--exclude", "testfiles/select2/1/1sub3/1sub3sub1"),
-                        ("--exclude", "testfiles/select2/1/1sub2/1sub2sub3"),
-                        ("--include", "testfiles/select2/1/1sub2/1sub2sub1"),
-                        ("--exclude", "testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt"),
-                        ("--exclude", "testfiles/select2/1/1sub1/1sub1sub2"),
-                        ("--exclude", "testfiles/select2/1/1sub2"),
-                        ("--include", "testfiles/select2/1.py"),
-                        ("--include", "testfiles/select2/3"),
-                        ("--include", "testfiles/select2/1"),
-                        ("--exclude", "testfiles/select2/**")],
+        self.root = Path(u"testfiles/select2")
+        self.ParseTest([(u"--include", u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt"),
+                        (u"--exclude", u"testfiles/select2/3/3sub3/3sub3sub2"),
+                        (u"--include", u"testfiles/select2/3/3sub2/3sub2sub2"),
+                        (u"--include", u"testfiles/select2/3/3sub3"),
+                        (u"--exclude", u"testfiles/select2/3/3sub1"),
+                        (u"--exclude", u"testfiles/select2/2/2sub1/2sub1sub3"),
+                        (u"--exclude", u"testfiles/select2/2/2sub1/2sub1sub2"),
+                        (u"--include", u"testfiles/select2/2/2sub1"),
+                        (u"--exclude", u"testfiles/select2/1/1sub3/1sub3sub2"),
+                        (u"--exclude", u"testfiles/select2/1/1sub3/1sub3sub1"),
+                        (u"--exclude", u"testfiles/select2/1/1sub2/1sub2sub3"),
+                        (u"--include", u"testfiles/select2/1/1sub2/1sub2sub1"),
+                        (u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt"),
+                        (u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub2"),
+                        (u"--exclude", u"testfiles/select2/1/1sub2"),
+                        (u"--include", u"testfiles/select2/1.py"),
+                        (u"--include", u"testfiles/select2/3"),
+                        (u"--include", u"testfiles/select2/1"),
+                        (u"--exclude", u"testfiles/select2/**")],
                        self.expected_restored_tree)
 
     def test_globbing_replacement(self):
         """Test functional test test_globbing_replacement as a unittest"""
-        self.root = Path("testfiles/select2")
-        self.ParseTest([("--include", "testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt"),
-                        ("--exclude", "testfiles/select2/*/3s*1"),
-                        ("--exclude", "testfiles/select2/**/2sub1sub3"),
-                        ("--exclude", "ignorecase:testfiles/select2/2/2sub1/2Sub1Sub2"),
-                        ("--include", "ignorecase:testfiles/sel[w,u,e,q]ct2/2/2S?b1"),
-                        ("--exclude", "testfiles/select2/1/1sub3/1s[w,u,p,q]b3sub2"),
-                        ("--exclude", "testfiles/select2/1/1sub[1-4]/1sub3sub1"),
-                        ("--include", "testfiles/select2/1/1sub2/1sub2sub1"),
-                        ("--exclude", "testfiles/select2/1/1sub1/1sub1sub3/1su?1sub3_file.txt"),
-                        ("--exclude", "testfiles/select2/1/1*1/1sub1sub2"),
-                        ("--exclude", "testfiles/select2/1/1sub2"),
-                        ("--include", "testfiles/select[2-4]/*.py"),
-                        ("--include", "testfiles/*2/3"),
-                        ("--include", "**/select2/1"),
-                        ("--exclude", "testfiles/select2/**")],
+        self.root = Path(u"testfiles/select2")
+        self.ParseTest([(u"--include", u"testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt"),
+                        (u"--exclude", u"testfiles/select2/*/3s*1"),
+                        (u"--exclude", u"testfiles/select2/**/2sub1sub3"),
+                        (u"--exclude", u"ignorecase:testfiles/select2/2/2sub1/2Sub1Sub2"),
+                        (u"--include", u"ignorecase:testfiles/sel[w,u,e,q]ct2/2/2S?b1"),
+                        (u"--exclude", u"testfiles/select2/1/1sub3/1s[w,u,p,q]b3sub2"),
+                        (u"--exclude", u"testfiles/select2/1/1sub[1-4]/1sub3sub1"),
+                        (u"--include", u"testfiles/select2/1/1sub2/1sub2sub1"),
+                        (u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3/1su?1sub3_file.txt"),
+                        (u"--exclude", u"testfiles/select2/1/1*1/1sub1sub2"),
+                        (u"--exclude", u"testfiles/select2/1/1sub2"),
+                        (u"--include", u"testfiles/select[2-4]/*.py"),
+                        (u"--include", u"testfiles/*2/3"),
+                        (u"--include", u"**/select2/1"),
+                        (u"--exclude", u"testfiles/select2/**")],
                        self.expected_restored_tree)
 
+    def test_unicode_paths_non_globbing(self):
+        """Test functional test test_unicode_paths_non_globbing as a unittest"""
+        self.root = Path(u"testfiles/select-unicode")
+        self.ParseTest([(u"--exclude", u"testfiles/select-unicode/прыклад/пример/例/Παράδειγμα/उदाहरण.txt"),
+                        (u"--exclude", u"testfiles/select-unicode/прыклад/пример/例/Παράδειγμα/דוגמא.txt"),
+                        (u"--exclude", u"testfiles/select-unicode/прыклад/пример/例/მაგალითი/"),
+                        (u"--include", u"testfiles/select-unicode/прыклад/пример/例/"),
+                        (u"--exclude", u"testfiles/select-unicode/прыклад/пример/"),
+                        (u"--include", u"testfiles/select-unicode/прыклад/"),
+                        (u"--include", u"testfiles/select-unicode/օրինակ.txt"),
+                        (u"--exclude", u"testfiles/select-unicode/**")],
+                       [(), (u"прыклад",), (u"прыклад", u"пример"), (u"прыклад", u"пример", u"例"),
+                        (u"прыклад", u"пример", u"例", u"Παράδειγμα"),
+                        (u"прыклад", u"пример", u"例", u"Παράδειγμα", u"ઉદાહરણ.log"),
+                        (u"прыклад", u"উদাহরণ"), (u"օրինակ.txt",)])
+
 
 class TestGlobGetNormalSf(UnitTestCase):
     """Test glob parsing of the test_glob_get_normal_sf function. Indirectly test behaviour of glob_to_re."""
@@ -877,152 +904,152 @@
         path = Path(path)
         return selection_function(path)
 
-    def include_glob_tester(self, path, glob_string, root_path="/"):
+    def include_glob_tester(self, path, glob_string, root_path=u"/"):
         return self.glob_tester(path, glob_string, 1, root_path)
 
-    def exclude_glob_tester(self, path, glob_string, root_path="/"):
+    def exclude_glob_tester(self, path, glob_string, root_path=u"/"):
         return self.glob_tester(path, glob_string, 0, root_path)
 
     def test_glob_get_normal_sf_exclude(self):
         """Test simple exclude."""
-        self.assertEqual(self.exclude_glob_tester("/testfiles/select2/3", "/testfiles/select2"), 0)
-        self.assertEqual(self.exclude_glob_tester("/testfiles/.git", "/testfiles"), 0)
+        self.assertEqual(self.exclude_glob_tester(u"/testfiles/select2/3", u"/testfiles/select2"), 0)
+        self.assertEqual(self.exclude_glob_tester(u"/testfiles/.git", u"/testfiles"), 0)
 
     def test_glob_get_normal_sf_exclude_root(self):
         """Test simple exclude with / as the glob."""
-        self.assertEqual(self.exclude_glob_tester("/.git", "/"), 0)
-        self.assertEqual(self.exclude_glob_tester("/testfile", "/"), 0)
+        self.assertEqual(self.exclude_glob_tester(u"/.git", u"/"), 0)
+        self.assertEqual(self.exclude_glob_tester(u"/testfile", u"/"), 0)
 
     def test_glob_get_normal_sf_2(self):
         """Test same behaviour as the functional test test_globbing_replacement."""
-        self.assertEqual(self.include_glob_tester("/testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt",
-                                                  "/testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt"), 1)
-        self.assertEqual(self.include_glob_tester("/testfiles/select2/3/3sub1", "/testfiles/select2/*/3s*1"), 1)
-        self.assertEqual(self.include_glob_tester("/testfiles/select2/2/2sub1/2sub1sub3",
-                                                  "/testfiles/select2/**/2sub1sub3"), 1)
-        self.assertEqual(self.include_glob_tester("/testfiles/select2/2/2sub1",
-                                                  "/testfiles/sel[w,u,e,q]ct2/2/2s?b1"), 1)
-        self.assertEqual(self.include_glob_tester("/testfiles/select2/1/1sub3/1sub3sub2",
-                                                  "/testfiles/select2/1/1sub3/1s[w,u,p,q]b3sub2"), 1)
-        self.assertEqual(self.exclude_glob_tester("/testfiles/select2/1/1sub3/1sub3sub1",
-                                                  "/testfiles/select2/1/1sub[1-4]/1sub3sub1"), 0)
-        self.assertEqual(self.include_glob_tester("/testfiles/select2/1/1sub2/1sub2sub1",
-                                                  "/testfiles/select2/*/1sub2/1s[w,u,p,q]b2sub1"), 1)
-        self.assertEqual(self.include_glob_tester("/testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt",
-                                                  "/testfiles/select2/1/1sub1/1sub1sub3/1su?1sub3_file.txt"), 1)
-        self.assertEqual(self.exclude_glob_tester("/testfiles/select2/1/1sub1/1sub1sub2",
-                                                  "/testfiles/select2/1/1*1/1sub1sub2"), 0)
-        self.assertEqual(self.include_glob_tester("/testfiles/select2/1/1sub2", "/testfiles/select2/1/1sub2"), 1)
-        self.assertEqual(self.include_glob_tester("/testfiles/select2/1.py", "/testfiles/select[2-4]/*.py"), 1)
-        self.assertEqual(self.exclude_glob_tester("/testfiles/select2/3", "/testfiles/*2/3"), 0)
-        self.assertEqual(self.include_glob_tester("/testfiles/select2/1", "**/select2/1"), 1)
+        self.assertEqual(self.include_glob_tester(u"/testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt",
+                                                  u"/testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt"), 1)
+        self.assertEqual(self.include_glob_tester(u"/testfiles/select2/3/3sub1", u"/testfiles/select2/*/3s*1"), 1)
+        self.assertEqual(self.include_glob_tester(u"/testfiles/select2/2/2sub1/2sub1sub3",
+                                                  u"/testfiles/select2/**/2sub1sub3"), 1)
+        self.assertEqual(self.include_glob_tester(u"/testfiles/select2/2/2sub1",
+                                                  u"/testfiles/sel[w,u,e,q]ct2/2/2s?b1"), 1)
+        self.assertEqual(self.include_glob_tester(u"/testfiles/select2/1/1sub3/1sub3sub2",
+                                                  u"/testfiles/select2/1/1sub3/1s[w,u,p,q]b3sub2"), 1)
+        self.assertEqual(self.exclude_glob_tester(u"/testfiles/select2/1/1sub3/1sub3sub1",
+                                                  u"/testfiles/select2/1/1sub[1-4]/1sub3sub1"), 0)
+        self.assertEqual(self.include_glob_tester(u"/testfiles/select2/1/1sub2/1sub2sub1",
+                                                  u"/testfiles/select2/*/1sub2/1s[w,u,p,q]b2sub1"), 1)
+        self.assertEqual(self.include_glob_tester(u"/testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt",
+                                                  u"/testfiles/select2/1/1sub1/1sub1sub3/1su?1sub3_file.txt"), 1)
+        self.assertEqual(self.exclude_glob_tester(u"/testfiles/select2/1/1sub1/1sub1sub2",
+                                                  u"/testfiles/select2/1/1*1/1sub1sub2"), 0)
+        self.assertEqual(self.include_glob_tester(u"/testfiles/select2/1/1sub2", u"/testfiles/select2/1/1sub2"), 1)
+        self.assertEqual(self.include_glob_tester(u"/testfiles/select2/1.py", u"/testfiles/select[2-4]/*.py"), 1)
+        self.assertEqual(self.exclude_glob_tester(u"/testfiles/select2/3", u"/testfiles/*2/3"), 0)
+        self.assertEqual(self.include_glob_tester(u"/testfiles/select2/1", u"**/select2/1"), 1)
 
     def test_glob_get_normal_sf_negative_square_brackets_specified(self):
         """Test negative square bracket (specified) [!a,b,c] replacement in get_normal_sf."""
         # As in a normal shell, [!...] expands to any single character but those specified
-        self.assertEqual(self.include_glob_tester("/test/hello1.txt", "/test/hello[!2,3,4].txt"), 1)
-        self.assertEqual(self.include_glob_tester("/test/hello.txt", "/t[!w,f,h]st/hello.txt"), 1)
-        self.assertEqual(self.exclude_glob_tester("/long/example/path/hello.txt",
-                                                  "/lon[!w,e,f]/e[!p]ample/path/hello.txt"), 0)
-        self.assertEqual(self.include_glob_tester("/test/hello1.txt", "/test/hello[!2,1,3,4].txt"), None)
-        self.assertEqual(self.include_glob_tester("/test/hello.txt", "/t[!e,f,h]st/hello.txt"), None)
-        self.assertEqual(self.exclude_glob_tester("/long/example/path/hello.txt",
-                                                  "/lon[!w,e,g,f]/e[!p,x]ample/path/hello.txt"), None)
+        self.assertEqual(self.include_glob_tester(u"/test/hello1.txt", u"/test/hello[!2,3,4].txt"), 1)
+        self.assertEqual(self.include_glob_tester(u"/test/hello.txt", u"/t[!w,f,h]st/hello.txt"), 1)
+        self.assertEqual(self.exclude_glob_tester(u"/long/example/path/hello.txt",
+                                                  u"/lon[!w,e,f]/e[!p]ample/path/hello.txt"), 0)
+        self.assertEqual(self.include_glob_tester(u"/test/hello1.txt", u"/test/hello[!2,1,3,4].txt"), None)
+        self.assertEqual(self.include_glob_tester(u"/test/hello.txt", u"/t[!e,f,h]st/hello.txt"), None)
+        self.assertEqual(self.exclude_glob_tester(u"/long/example/path/hello.txt",
+                                                  u"/lon[!w,e,g,f]/e[!p,x]ample/path/hello.txt"), None)
 
     def test_glob_get_normal_sf_negative_square_brackets_range(self):
         """Test negative square bracket (range) [!a,b,c] replacement in get_normal_sf."""
         # As in a normal shell, [!1-5] or [!a-f] expands to any single character not in the range specified
-        self.assertEqual(self.include_glob_tester("/test/hello1.txt", "/test/hello[!2-4].txt"), 1)
-        self.assertEqual(self.include_glob_tester("/test/hello.txt", "/t[!f-h]st/hello.txt"), 1)
-        self.assertEqual(self.exclude_glob_tester("/long/example/path/hello.txt",
-                                                  "/lon[!w,e,f]/e[!p-s]ample/path/hello.txt"), 0)
-        self.assertEqual(self.include_glob_tester("/test/hello1.txt", "/test/hello[!1-4].txt"), None)
-        self.assertEqual(self.include_glob_tester("/test/hello.txt", "/t[!b-h]st/hello.txt"), None)
-        self.assertEqual(self.exclude_glob_tester("/long/example/path/hello.txt",
-                                                  "/lon[!f-p]/e[!p]ample/path/hello.txt"), None)
+        self.assertEqual(self.include_glob_tester(u"/test/hello1.txt", u"/test/hello[!2-4].txt"), 1)
+        self.assertEqual(self.include_glob_tester(u"/test/hello.txt", u"/t[!f-h]st/hello.txt"), 1)
+        self.assertEqual(self.exclude_glob_tester(u"/long/example/path/hello.txt",
+                                                  u"/lon[!w,e,f]/e[!p-s]ample/path/hello.txt"), 0)
+        self.assertEqual(self.include_glob_tester(u"/test/hello1.txt", u"/test/hello[!1-4].txt"), None)
+        self.assertEqual(self.include_glob_tester(u"/test/hello.txt", u"/t[!b-h]st/hello.txt"), None)
+        self.assertEqual(self.exclude_glob_tester(u"/long/example/path/hello.txt",
+                                                  u"/lon[!f-p]/e[!p]ample/path/hello.txt"), None)
 
     def test_glob_get_normal_sf_2_ignorecase(self):
         """Test same behaviour as the functional test test_globbing_replacement, ignorecase tests."""
-        self.assertEqual(self.include_glob_tester("testfiles/select2/2/2sub1",
-                                                  "ignorecase:testfiles/sel[w,u,e,q]ct2/2/2S?b1",
-                                                  "testfiles/select2"), 1)
-        self.assertEqual(self.include_glob_tester("testfiles/select2/2/2sub1/2sub1sub2",
-                                                  "ignorecase:testfiles/select2/2/2sub1/2Sub1Sub2",
-                                                  "testfiles/select2"), 1)
+        self.assertEqual(self.include_glob_tester(u"testfiles/select2/2/2sub1",
+                                                  u"ignorecase:testfiles/sel[w,u,e,q]ct2/2/2S?b1",
+                                                  u"testfiles/select2"), 1)
+        self.assertEqual(self.include_glob_tester(u"testfiles/select2/2/2sub1/2sub1sub2",
+                                                  u"ignorecase:testfiles/select2/2/2sub1/2Sub1Sub2",
+                                                  u"testfiles/select2"), 1)
 
     def test_glob_get_normal_sf_3_double_asterisks_dirs_to_scan(self):
         """Test double asterisk (**) replacement in glob_get_normal_sf with directories that should be scanned"""
         # The new special pattern, **, expands to any string of characters whether or not it contains "/".
-        self.assertEqual(self.include_glob_tester("/long/example/path", "/**/hello.txt"), 2)
+        self.assertEqual(self.include_glob_tester(u"/long/example/path", u"/**/hello.txt"), 2)
 
     def test_glob_get_normal_sf_3_ignorecase(self):
         """Test ignorecase in glob_get_normal_sf"""
         # If the pattern starts with "ignorecase:" (case insensitive), then this prefix will be removed and any
         # character in the string can be replaced with an upper- or lowercase version of itself.
-        self.assertEqual(self.include_glob_tester("testfiles/select2/2", "ignorecase:testfiles/select2/2",
-                                                  "testfiles/select2"), 1)
-        self.assertEqual(self.include_glob_tester("testfiles/select2/2", "ignorecase:testFiles/Select2/2",
-                                                  "testfiles/select2"), 1)
-        self.assertEqual(self.include_glob_tester("tEstfiles/seLect2/2", "ignorecase:testFiles/Select2/2",
-                                                  "testfiles/select2"), 1)
-        self.assertEqual(self.include_glob_tester("TEstfiles/SeLect2/2", "ignorecase:t?stFiles/S*ect2/2",
-                                                  "testfiles/select2"), 1)
-        self.assertEqual(self.include_glob_tester("TEstfiles/SeLect2/2", "ignorecase:t?stFil**ect2/2",
-                                                  "testfiles/select2"), 1)
-        self.assertEqual(self.exclude_glob_tester("TEstfiles/SeLect2/2", "ignorecase:t?stFiles/S*ect2/2",
-                                                  "testfiles/select2"), 0)
-        self.assertEqual(self.exclude_glob_tester("TEstFiles/SeLect2/2", "ignorecase:t?stFile**ect2/2",
-                                                  "testfiles/select2"), 0)
+        self.assertEqual(self.include_glob_tester(u"testfiles/select2/2", u"ignorecase:testfiles/select2/2",
+                                                  u"testfiles/select2"), 1)
+        self.assertEqual(self.include_glob_tester(u"testfiles/select2/2", u"ignorecase:testFiles/Select2/2",
+                                                  u"testfiles/select2"), 1)
+        self.assertEqual(self.include_glob_tester(u"tEstfiles/seLect2/2", u"ignorecase:testFiles/Select2/2",
+                                                  u"testfiles/select2"), 1)
+        self.assertEqual(self.include_glob_tester(u"TEstfiles/SeLect2/2", u"ignorecase:t?stFiles/S*ect2/2",
+                                                  u"testfiles/select2"), 1)
+        self.assertEqual(self.include_glob_tester(u"TEstfiles/SeLect2/2", u"ignorecase:t?stFil**ect2/2",
+                                                  u"testfiles/select2"), 1)
+        self.assertEqual(self.exclude_glob_tester(u"TEstfiles/SeLect2/2", u"ignorecase:t?stFiles/S*ect2/2",
+                                                  u"testfiles/select2"), 0)
+        self.assertEqual(self.exclude_glob_tester(u"TEstFiles/SeLect2/2", u"ignorecase:t?stFile**ect2/2",
+                                                  u"testfiles/select2"), 0)
 
     def test_glob_dirs_to_scan(self):
         """Test parent directories are marked as needing to be scanned"""
-        with patch('duplicity.path.Path.isdir') as mock_isdir:
+        with patch(u"duplicity.path.Path.isdir") as mock_isdir:
             mock_isdir.return_value = True
             self.assertEqual(
-                self.glob_tester("parent", "parent/hello.txt", 1, "parent"), 2)
+                self.glob_tester(u"parent", u"parent/hello.txt", 1, u"parent"), 2)
 
     def test_glob_dirs_to_scan_glob(self):
         """Test parent directories are marked as needing to be scanned - globs"""
-        with patch('duplicity.path.Path.isdir') as mock_isdir:
+        with patch(u"duplicity.path.Path.isdir") as mock_isdir:
             mock_isdir.return_value = True
             self.assertEqual(
-                self.glob_tester("testfiles/select/1", "*/select/1/1", 1,
-                                 "testfiles/select"), 2)
-            self.assertEqual(
-                self.glob_tester("testfiles/select/1/2",
-                                 "*/select/1/2/1", 1, "testfiles/select"), 2)
-            self.assertEqual(
-                self.glob_tester("parent", "parent/hel?o.txt", 1, "parent"), 2)
-            self.assertEqual(
-                self.glob_tester("test/parent/folder",
-                                 "test/par*t/folder/hello.txt", 1, "test"), 2)
-            self.assertEqual(
-                self.glob_tester("testfiles/select/1/1",
-                                 "**/1/2/1", 1, "testfiles"), 2)
-            self.assertEqual(
-                self.glob_tester("testfiles/select2/3/3sub2",
-                                 "testfiles/select2/3/**file.txt", 1,
-                                 "testfiles"), 2)
-            self.assertEqual(
-                self.glob_tester("testfiles/select/1/2",
-                                 "*/select/1/2/1", 1, "testfiles"), 2)
-            self.assertEqual(
-                self.glob_tester("testfiles/select/1",
-                                 "testfiles/select**/2", 1, "testfiles"), 2)
-            self.assertEqual(
-                self.glob_tester("testfiles/select/efools",
-                                 "testfiles/select/*foo*/p*", 1,
-                                 "testfiles"), 2)
-            self.assertEqual(
-                self.glob_tester("testfiles/select/3",
-                                 "testfiles/select/**2", 1, "testfiles"), 2)
-            self.assertEqual(
-                self.glob_tester("testfiles/select2/1/1sub1/1sub1sub2",
-                                 "testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt",
-                                 1, "testfiles"), 2)
-            self.assertEqual(
-                self.glob_tester("testfiles/select/1",
-                                 "*/select/1/1", 1, "testfiles"), 2)
+                self.glob_tester(u"testfiles/select/1", u"*/select/1/1", 1,
+                                 u"testfiles/select"), 2)
+            self.assertEqual(
+                self.glob_tester(u"testfiles/select/1/2",
+                                 u"*/select/1/2/1", 1, u"testfiles/select"), 2)
+            self.assertEqual(
+                self.glob_tester(u"parent", u"parent/hel?o.txt", 1, u"parent"), 2)
+            self.assertEqual(
+                self.glob_tester(u"test/parent/folder",
+                                 u"test/par*t/folder/hello.txt", 1, u"test"), 2)
+            self.assertEqual(
+                self.glob_tester(u"testfiles/select/1/1",
+                                 u"**/1/2/1", 1, u"testfiles"), 2)
+            self.assertEqual(
+                self.glob_tester(u"testfiles/select2/3/3sub2",
+                                 u"testfiles/select2/3/**file.txt", 1,
+                                 u"testfiles"), 2)
+            self.assertEqual(
+                self.glob_tester(u"testfiles/select/1/2",
+                                 u"*/select/1/2/1", 1, u"testfiles"), 2)
+            self.assertEqual(
+                self.glob_tester(u"testfiles/select/1",
+                                 u"testfiles/select**/2", 1, u"testfiles"), 2)
+            self.assertEqual(
+                self.glob_tester(u"testfiles/select/efools",
+                                 u"testfiles/select/*foo*/p*", 1,
+                                 u"testfiles"), 2)
+            self.assertEqual(
+                self.glob_tester(u"testfiles/select/3",
+                                 u"testfiles/select/**2", 1, u"testfiles"), 2)
+            self.assertEqual(
+                self.glob_tester(u"testfiles/select2/1/1sub1/1sub1sub2",
+                                 u"testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt",
+                                 1, u"testfiles"), 2)
+            self.assertEqual(
+                self.glob_tester(u"testfiles/select/1",
+                                 u"*/select/1/1", 1, u"testfiles"), 2)
 
 if __name__ == "__main__":
     unittest.main()

=== modified file 'tox.ini'
--- tox.ini	2017-07-11 14:55:38 +0000
+++ tox.ini	2017-12-01 23:01:42 +0000
@@ -7,6 +7,7 @@
 deps=
     boto
     coverage
+    future
     jottalib
     mock
     pexpect
@@ -20,6 +21,7 @@
 setenv=
     RUN_CODE_TESTS=0
 deps=
+    future
     jottalib
     mock==1.0.1
     pexpect==3.1


Follow ups