diff options
author | Brett Cannon <brett@python.org> | 2016-08-26 21:44:48 (GMT) |
---|---|---|
committer | Brett Cannon <brett@python.org> | 2016-08-26 21:44:48 (GMT) |
commit | 3f9183b5aca568867f37c38501fca63911580c66 (patch) | |
tree | 77dbe8fa7c0381c665ed259a94620a860a8f73d7 /Lib | |
parent | 6ed442c48dd7f8d3097e688a36bc027df3271621 (diff) | |
download | cpython-3f9183b5aca568867f37c38501fca63911580c66.zip cpython-3f9183b5aca568867f37c38501fca63911580c66.tar.gz cpython-3f9183b5aca568867f37c38501fca63911580c66.tar.bz2 |
Issue #26027, #27524: Add PEP 519/__fspath__() support to os and
os.path.
Thanks to Jelle Zijlstra for the initial patch against posixmodule.c.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/genericpath.py | 6 | ||||
-rw-r--r-- | Lib/ntpath.py | 18 | ||||
-rw-r--r-- | Lib/os.py | 4 | ||||
-rw-r--r-- | Lib/posixpath.py | 19 | ||||
-rw-r--r-- | Lib/test/test_genericpath.py | 64 | ||||
-rw-r--r-- | Lib/test/test_ntpath.py | 83 | ||||
-rw-r--r-- | Lib/test/test_os.py | 83 | ||||
-rw-r--r-- | Lib/test/test_posix.py | 10 | ||||
-rw-r--r-- | Lib/test/test_posixpath.py | 80 |
9 files changed, 345 insertions, 22 deletions
diff --git a/Lib/genericpath.py b/Lib/genericpath.py index 6714061..303b3b3 100644 --- a/Lib/genericpath.py +++ b/Lib/genericpath.py @@ -69,6 +69,12 @@ def getctime(filename): def commonprefix(m): "Given a list of pathnames, returns the longest common leading component" if not m: return '' + # Some people pass in a list of pathname parts to operate in an OS-agnostic + # fashion; don't try to translate in that case as that's an abuse of the + # API and they are already doing what they need to be OS-agnostic and so + # they most likely won't be using an os.PathLike object in the sublists. + if not isinstance(m[0], (list, tuple)): + m = tuple(map(os.fspath, m)) s1 = min(m) s2 = max(m) for i, c in enumerate(s1): diff --git a/Lib/ntpath.py b/Lib/ntpath.py index af6a709..1fa4448 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -46,6 +46,7 @@ def normcase(s): """Normalize case of pathname. Makes all characters lowercase and all slashes into backslashes.""" + s = os.fspath(s) try: if isinstance(s, bytes): return s.replace(b'/', b'\\').lower() @@ -66,12 +67,14 @@ def normcase(s): def isabs(s): """Test whether a path is absolute""" + s = os.fspath(s) s = splitdrive(s)[1] return len(s) > 0 and s[0] in _get_bothseps(s) # Join two (or more) paths. def join(path, *paths): + path = os.fspath(path) if isinstance(path, bytes): sep = b'\\' seps = b'\\/' @@ -84,7 +87,7 @@ def join(path, *paths): if not paths: path[:0] + sep #23780: Ensure compatible data type even if p is null. result_drive, result_path = splitdrive(path) - for p in paths: + for p in map(os.fspath, paths): p_drive, p_path = splitdrive(p) if p_path and p_path[0] in seps: # Second path is absolute @@ -136,6 +139,7 @@ def splitdrive(p): Paths cannot contain both a drive letter and a UNC path. """ + p = os.fspath(p) if len(p) >= 2: if isinstance(p, bytes): sep = b'\\' @@ -199,7 +203,7 @@ def split(p): Return tuple (head, tail) where tail is everything after the final slash. Either part may be empty.""" - + p = os.fspath(p) seps = _get_bothseps(p) d, p = splitdrive(p) # set i to index beyond p's last slash @@ -218,6 +222,7 @@ def split(p): # It is always true that root + ext == p. def splitext(p): + p = os.fspath(p) if isinstance(p, bytes): return genericpath._splitext(p, b'\\', b'/', b'.') else: @@ -278,6 +283,7 @@ except ImportError: def ismount(path): """Test whether a path is a mount point (a drive root, the root of a share, or a mounted volume)""" + path = os.fspath(path) seps = _get_bothseps(path) path = abspath(path) root, rest = splitdrive(path) @@ -305,6 +311,7 @@ def expanduser(path): """Expand ~ and ~user constructs. If user or $HOME is unknown, do nothing.""" + path = os.fspath(path) if isinstance(path, bytes): tilde = b'~' else: @@ -354,6 +361,7 @@ def expandvars(path): """Expand shell variables of the forms $var, ${var} and %var%. Unknown variables are left unchanged.""" + path = os.fspath(path) if isinstance(path, bytes): if b'$' not in path and b'%' not in path: return path @@ -464,6 +472,7 @@ def expandvars(path): def normpath(path): """Normalize path, eliminating double slashes, etc.""" + path = os.fspath(path) if isinstance(path, bytes): sep = b'\\' altsep = b'/' @@ -518,6 +527,7 @@ try: except ImportError: # not running on Windows - mock up something sensible def abspath(path): """Return the absolute version of a path.""" + path = os.fspath(path) if not isabs(path): if isinstance(path, bytes): cwd = os.getcwdb() @@ -531,6 +541,7 @@ else: # use native Windows method on Windows """Return the absolute version of a path.""" if path: # Empty path must return current working directory. + path = os.fspath(path) try: path = _getfullpathname(path) except OSError: @@ -549,6 +560,7 @@ supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and def relpath(path, start=None): """Return a relative version of a path""" + path = os.fspath(path) if isinstance(path, bytes): sep = b'\\' curdir = b'.' @@ -564,6 +576,7 @@ def relpath(path, start=None): if not path: raise ValueError("no path specified") + start = os.fspath(start) try: start_abs = abspath(normpath(start)) path_abs = abspath(normpath(path)) @@ -607,6 +620,7 @@ def commonpath(paths): if not paths: raise ValueError('commonpath() arg is an empty sequence') + paths = tuple(map(os.fspath, paths)) if isinstance(paths[0], bytes): sep = b'\\' altsep = b'/' @@ -353,7 +353,7 @@ def walk(top, topdown=True, onerror=None, followlinks=False): dirs.remove('CVS') # don't visit CVS directories """ - + top = fspath(top) dirs = [] nondirs = [] walk_dirs = [] @@ -536,6 +536,8 @@ if {open, stat} <= supports_dir_fd and {listdir, stat} <= supports_fd: if 'CVS' in dirs: dirs.remove('CVS') # don't visit CVS directories """ + if not isinstance(top, int) or not hasattr(top, '__index__'): + top = fspath(top) # Note: To guard against symlink races, we use the standard # lstat()/open()/fstat() trick. orig_st = stat(top, follow_symlinks=False, dir_fd=dir_fd) diff --git a/Lib/posixpath.py b/Lib/posixpath.py index d9f3f99..6dbdab2 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -49,6 +49,7 @@ def _get_sep(path): def normcase(s): """Normalize case of pathname. Has no effect under Posix""" + s = os.fspath(s) if not isinstance(s, (bytes, str)): raise TypeError("normcase() argument must be str or bytes, " "not '{}'".format(s.__class__.__name__)) @@ -60,6 +61,7 @@ def normcase(s): def isabs(s): """Test whether a path is absolute""" + s = os.fspath(s) sep = _get_sep(s) return s.startswith(sep) @@ -73,12 +75,13 @@ def join(a, *p): If any component is an absolute path, all previous path components will be discarded. An empty last part will result in a path that ends with a separator.""" + a = os.fspath(a) sep = _get_sep(a) path = a try: if not p: path[:0] + sep #23780: Ensure compatible data type even if p is null. - for b in p: + for b in map(os.fspath, p): if b.startswith(sep): path = b elif not path or path.endswith(sep): @@ -99,6 +102,7 @@ def join(a, *p): def split(p): """Split a pathname. Returns tuple "(head, tail)" where "tail" is everything after the final slash. Either part may be empty.""" + p = os.fspath(p) sep = _get_sep(p) i = p.rfind(sep) + 1 head, tail = p[:i], p[i:] @@ -113,6 +117,7 @@ def split(p): # It is always true that root + ext == p. def splitext(p): + p = os.fspath(p) if isinstance(p, bytes): sep = b'/' extsep = b'.' @@ -128,6 +133,7 @@ splitext.__doc__ = genericpath._splitext.__doc__ def splitdrive(p): """Split a pathname into drive and path. On Posix, drive is always empty.""" + p = os.fspath(p) return p[:0], p @@ -135,6 +141,7 @@ def splitdrive(p): def basename(p): """Returns the final component of a pathname""" + p = os.fspath(p) sep = _get_sep(p) i = p.rfind(sep) + 1 return p[i:] @@ -144,6 +151,7 @@ def basename(p): def dirname(p): """Returns the directory component of a pathname""" + p = os.fspath(p) sep = _get_sep(p) i = p.rfind(sep) + 1 head = p[:i] @@ -222,6 +230,7 @@ def ismount(path): def expanduser(path): """Expand ~ and ~user constructions. If user or $HOME is unknown, do nothing.""" + path = os.fspath(path) if isinstance(path, bytes): tilde = b'~' else: @@ -267,6 +276,7 @@ _varprogb = None def expandvars(path): """Expand shell variables of form $var and ${var}. Unknown variables are left unchanged.""" + path = os.fspath(path) global _varprog, _varprogb if isinstance(path, bytes): if b'$' not in path: @@ -318,6 +328,7 @@ def expandvars(path): def normpath(path): """Normalize path, eliminating double slashes, etc.""" + path = os.fspath(path) if isinstance(path, bytes): sep = b'/' empty = b'' @@ -355,6 +366,7 @@ def normpath(path): def abspath(path): """Return an absolute path.""" + path = os.fspath(path) if not isabs(path): if isinstance(path, bytes): cwd = os.getcwdb() @@ -370,6 +382,7 @@ def abspath(path): def realpath(filename): """Return the canonical path of the specified filename, eliminating any symbolic links encountered in the path.""" + filename = os.fspath(filename) path, ok = _joinrealpath(filename[:0], filename, {}) return abspath(path) @@ -434,6 +447,7 @@ def relpath(path, start=None): if not path: raise ValueError("no path specified") + path = os.fspath(path) if isinstance(path, bytes): curdir = b'.' sep = b'/' @@ -445,6 +459,8 @@ def relpath(path, start=None): if start is None: start = curdir + else: + start = os.fspath(start) try: start_list = [x for x in abspath(start).split(sep) if x] @@ -472,6 +488,7 @@ def commonpath(paths): if not paths: raise ValueError('commonpath() arg is an empty sequence') + paths = tuple(map(os.fspath, paths)) if isinstance(paths[0], bytes): sep = b'/' curdir = b'.' diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py index 5331b24..c8f158d 100644 --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -450,16 +450,15 @@ class CommonTest(GenericTest): with self.assertRaisesRegex(TypeError, errmsg): self.pathmodule.join('str', b'bytes') # regression, see #15377 - errmsg = r'join\(\) argument must be str or bytes, not %r' - with self.assertRaisesRegex(TypeError, errmsg % 'int'): + with self.assertRaisesRegex(TypeError, 'int'): self.pathmodule.join(42, 'str') - with self.assertRaisesRegex(TypeError, errmsg % 'int'): + with self.assertRaisesRegex(TypeError, 'int'): self.pathmodule.join('str', 42) - with self.assertRaisesRegex(TypeError, errmsg % 'int'): + with self.assertRaisesRegex(TypeError, 'int'): self.pathmodule.join(42) - with self.assertRaisesRegex(TypeError, errmsg % 'list'): + with self.assertRaisesRegex(TypeError, 'list'): self.pathmodule.join([]) - with self.assertRaisesRegex(TypeError, errmsg % 'bytearray'): + with self.assertRaisesRegex(TypeError, 'bytearray'): self.pathmodule.join(bytearray(b'foo'), bytearray(b'bar')) def test_relpath_errors(self): @@ -471,14 +470,59 @@ class CommonTest(GenericTest): self.pathmodule.relpath(b'bytes', 'str') with self.assertRaisesRegex(TypeError, errmsg): self.pathmodule.relpath('str', b'bytes') - errmsg = r'relpath\(\) argument must be str or bytes, not %r' - with self.assertRaisesRegex(TypeError, errmsg % 'int'): + with self.assertRaisesRegex(TypeError, 'int'): self.pathmodule.relpath(42, 'str') - with self.assertRaisesRegex(TypeError, errmsg % 'int'): + with self.assertRaisesRegex(TypeError, 'int'): self.pathmodule.relpath('str', 42) - with self.assertRaisesRegex(TypeError, errmsg % 'bytearray'): + with self.assertRaisesRegex(TypeError, 'bytearray'): self.pathmodule.relpath(bytearray(b'foo'), bytearray(b'bar')) +class PathLikeTests(unittest.TestCase): + + class PathLike: + def __init__(self, path=''): + self.path = path + def __fspath__(self): + if isinstance(self.path, BaseException): + raise self.path + else: + return self.path + + def setUp(self): + self.file_name = support.TESTFN.lower() + self.file_path = self.PathLike(support.TESTFN) + self.addCleanup(support.unlink, self.file_name) + create_file(self.file_name, b"test_genericpath.PathLikeTests") + + def assertPathEqual(self, func): + self.assertEqual(func(self.file_path), func(self.file_name)) + + def test_path_exists(self): + self.assertPathEqual(os.path.exists) + + def test_path_isfile(self): + self.assertPathEqual(os.path.isfile) + + def test_path_isdir(self): + self.assertPathEqual(os.path.isdir) + + def test_path_commonprefix(self): + self.assertEqual(os.path.commonprefix([self.file_path, self.file_name]), + self.file_name) + + def test_path_getsize(self): + self.assertPathEqual(os.path.getsize) + + def test_path_getmtime(self): + self.assertPathEqual(os.path.getatime) + + def test_path_getctime(self): + self.assertPathEqual(os.path.getctime) + + def test_path_samefile(self): + self.assertTrue(os.path.samefile(self.file_path, self.file_name)) + + if __name__=="__main__": unittest.main() diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 580f203..90edb6d 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -452,5 +452,88 @@ class NtCommonTest(test_genericpath.CommonTest, unittest.TestCase): attributes = ['relpath', 'splitunc'] +class PathLikeTests(unittest.TestCase): + + path = ntpath + + class PathLike: + def __init__(self, path=''): + self.path = path + def __fspath__(self): + if isinstance(self.path, BaseException): + raise self.path + else: + return self.path + + def setUp(self): + self.file_name = support.TESTFN.lower() + self.file_path = self.PathLike(support.TESTFN) + self.addCleanup(support.unlink, self.file_name) + with open(self.file_name, 'xb', 0) as file: + file.write(b"test_ntpath.PathLikeTests") + + def assertPathEqual(self, func): + self.assertEqual(func(self.file_path), func(self.file_name)) + + def test_path_normcase(self): + self.assertPathEqual(self.path.normcase) + + def test_path_isabs(self): + self.assertPathEqual(self.path.isabs) + + def test_path_join(self): + self.assertEqual(self.path.join('a', self.PathLike('b'), 'c'), + self.path.join('a', 'b', 'c')) + + def test_path_split(self): + self.assertPathEqual(self.path.split) + + def test_path_splitext(self): + self.assertPathEqual(self.path.splitext) + + def test_path_splitdrive(self): + self.assertPathEqual(self.path.splitdrive) + + def test_path_basename(self): + self.assertPathEqual(self.path.basename) + + def test_path_dirname(self): + self.assertPathEqual(self.path.dirname) + + def test_path_islink(self): + self.assertPathEqual(self.path.islink) + + def test_path_lexists(self): + self.assertPathEqual(self.path.lexists) + + def test_path_ismount(self): + self.assertPathEqual(self.path.ismount) + + def test_path_expanduser(self): + self.assertPathEqual(self.path.expanduser) + + def test_path_expandvars(self): + self.assertPathEqual(self.path.expandvars) + + def test_path_normpath(self): + self.assertPathEqual(self.path.normpath) + + def test_path_abspath(self): + self.assertPathEqual(self.path.abspath) + + def test_path_realpath(self): + self.assertPathEqual(self.path.realpath) + + def test_path_relpath(self): + self.assertPathEqual(self.path.relpath) + + def test_path_commonpath(self): + common_path = self.path.commonpath([self.file_path, self.file_name]) + self.assertEqual(common_path, self.file_name) + + def test_path_isdir(self): + self.assertPathEqual(self.path.isdir) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index d8920d9..5ac4d64 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -874,10 +874,12 @@ class WalkTests(unittest.TestCase): self.assertEqual(all[2 + flipped], (self.sub11_path, [], [])) self.assertEqual(all[3 - 2 * flipped], self.sub2_tree) - def test_walk_prune(self): + def test_walk_prune(self, walk_path=None): + if walk_path is None: + walk_path = self.walk_path # Prune the search. all = [] - for root, dirs, files in self.walk(self.walk_path): + for root, dirs, files in self.walk(walk_path): all.append((root, dirs, files)) # Don't descend into SUB1. if 'SUB1' in dirs: @@ -886,11 +888,22 @@ class WalkTests(unittest.TestCase): self.assertEqual(len(all), 2) self.assertEqual(all[0], - (self.walk_path, ["SUB2"], ["tmp1"])) + (str(walk_path), ["SUB2"], ["tmp1"])) all[1][-1].sort() self.assertEqual(all[1], self.sub2_tree) + def test_file_like_path(self): + class FileLike: + def __init__(self, path): + self._path = path + def __str__(self): + return str(self._path) + def __fspath__(self): + return self._path + + self.test_walk_prune(FileLike(self.walk_path)) + def test_walk_bottom_up(self): # Walk bottom-up. all = list(self.walk(self.walk_path, topdown=False)) @@ -2807,6 +2820,70 @@ class FDInheritanceTests(unittest.TestCase): self.assertEqual(os.get_inheritable(slave_fd), False) +class PathTConverterTests(unittest.TestCase): + # tuples of (function name, allows fd arguments, additional arguments to + # function, cleanup function) + functions = [ + ('stat', True, (), None), + ('lstat', False, (), None), + ('access', True, (os.F_OK,), None), + ('chflags', False, (0,), None), + ('lchflags', False, (0,), None), + ('open', False, (0,), getattr(os, 'close', None)), + ] + + def test_path_t_converter(self): + class PathLike: + def __init__(self, path): + self.path = path + + def __fspath__(self): + return self.path + + str_filename = support.TESTFN + bytes_filename = support.TESTFN.encode('ascii') + bytearray_filename = bytearray(bytes_filename) + fd = os.open(PathLike(str_filename), os.O_WRONLY|os.O_CREAT) + self.addCleanup(os.close, fd) + self.addCleanup(support.unlink, support.TESTFN) + + int_fspath = PathLike(fd) + str_fspath = PathLike(str_filename) + bytes_fspath = PathLike(bytes_filename) + bytearray_fspath = PathLike(bytearray_filename) + + for name, allow_fd, extra_args, cleanup_fn in self.functions: + with self.subTest(name=name): + try: + fn = getattr(os, name) + except AttributeError: + continue + + for path in (str_filename, bytes_filename, bytearray_filename, + str_fspath, bytes_fspath): + with self.subTest(name=name, path=path): + result = fn(path, *extra_args) + if cleanup_fn is not None: + cleanup_fn(result) + + with self.assertRaisesRegex( + TypeError, 'should be string, bytes'): + fn(int_fspath, *extra_args) + with self.assertRaisesRegex( + TypeError, 'should be string, bytes'): + fn(bytearray_fspath, *extra_args) + + if allow_fd: + result = fn(fd, *extra_args) # should not fail + if cleanup_fn is not None: + cleanup_fn(result) + else: + with self.assertRaisesRegex( + TypeError, + 'os.PathLike'): + fn(fd, *extra_args) + + @unittest.skipUnless(hasattr(os, 'get_blocking'), 'needs os.get_blocking() and os.set_blocking()') class BlockingTests(unittest.TestCase): diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index de22513..d2f58ba 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -397,7 +397,7 @@ class PosixTester(unittest.TestCase): self.assertTrue(posix.stat(fp.fileno())) self.assertRaisesRegex(TypeError, - 'should be string, bytes or integer, not', + 'should be string, bytes, os.PathLike or integer, not', posix.stat, float(fp.fileno())) finally: fp.close() @@ -409,16 +409,16 @@ class PosixTester(unittest.TestCase): self.assertTrue(posix.stat(os.fsencode(support.TESTFN))) self.assertWarnsRegex(DeprecationWarning, - 'should be string, bytes or integer, not', + 'should be string, bytes, os.PathLike or integer, not', posix.stat, bytearray(os.fsencode(support.TESTFN))) self.assertRaisesRegex(TypeError, - 'should be string, bytes or integer, not', + 'should be string, bytes, os.PathLike or integer, not', posix.stat, None) self.assertRaisesRegex(TypeError, - 'should be string, bytes or integer, not', + 'should be string, bytes, os.PathLike or integer, not', posix.stat, list(support.TESTFN)) self.assertRaisesRegex(TypeError, - 'should be string, bytes or integer, not', + 'should be string, bytes, os.PathLike or integer, not', posix.stat, list(os.fsencode(support.TESTFN))) @unittest.skipUnless(hasattr(posix, 'mkfifo'), "don't have mkfifo()") diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py index 0783c36..8a1e33b 100644 --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -596,5 +596,85 @@ class PosixCommonTest(test_genericpath.CommonTest, unittest.TestCase): attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat'] +class PathLikeTests(unittest.TestCase): + + path = posixpath + + class PathLike: + def __init__(self, path=''): + self.path = path + def __fspath__(self): + if isinstance(self.path, BaseException): + raise self.path + else: + return self.path + + def setUp(self): + self.file_name = support.TESTFN.lower() + self.file_path = self.PathLike(support.TESTFN) + self.addCleanup(support.unlink, self.file_name) + with open(self.file_name, 'xb', 0) as file: + file.write(b"test_posixpath.PathLikeTests") + + def assertPathEqual(self, func): + self.assertEqual(func(self.file_path), func(self.file_name)) + + def test_path_normcase(self): + self.assertPathEqual(self.path.normcase) + + def test_path_isabs(self): + self.assertPathEqual(self.path.isabs) + + def test_path_join(self): + self.assertEqual(self.path.join('a', self.PathLike('b'), 'c'), + self.path.join('a', 'b', 'c')) + + def test_path_split(self): + self.assertPathEqual(self.path.split) + + def test_path_splitext(self): + self.assertPathEqual(self.path.splitext) + + def test_path_splitdrive(self): + self.assertPathEqual(self.path.splitdrive) + + def test_path_basename(self): + self.assertPathEqual(self.path.basename) + + def test_path_dirname(self): + self.assertPathEqual(self.path.dirname) + + def test_path_islink(self): + self.assertPathEqual(self.path.islink) + + def test_path_lexists(self): + self.assertPathEqual(self.path.lexists) + + def test_path_ismount(self): + self.assertPathEqual(self.path.ismount) + + def test_path_expanduser(self): + self.assertPathEqual(self.path.expanduser) + + def test_path_expandvars(self): + self.assertPathEqual(self.path.expandvars) + + def test_path_normpath(self): + self.assertPathEqual(self.path.normpath) + + def test_path_abspath(self): + self.assertPathEqual(self.path.abspath) + + def test_path_realpath(self): + self.assertPathEqual(self.path.realpath) + + def test_path_relpath(self): + self.assertPathEqual(self.path.relpath) + + def test_path_commonpath(self): + common_path = self.path.commonpath([self.file_path, self.file_name]) + self.assertEqual(common_path, self.file_name) + + if __name__=="__main__": unittest.main() |