duplicity-team team mailing list archive
-
duplicity-team team
-
Mailing list archive
-
Message #04640
[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