1import unittest 2from test import test_support, test_genericpath 3 4import posixpath, os 5from posixpath import realpath, abspath, dirname, basename 6 7# An absolute path to a temporary filename for testing. We can't rely on TESTFN 8# being an absolute path, so we need this. 9 10ABSTFN = abspath(test_support.TESTFN) 11 12def skip_if_ABSTFN_contains_backslash(test): 13 """ 14 On Windows, posixpath.abspath still returns paths with backslashes 15 instead of posix forward slashes. If this is the case, several tests 16 fail, so skip them. 17 """ 18 found_backslash = '\\' in ABSTFN 19 msg = "ABSTFN is not a posix path - tests fail" 20 return [test, unittest.skip(msg)(test)][found_backslash] 21 22def safe_rmdir(dirname): 23 try: 24 os.rmdir(dirname) 25 except OSError: 26 pass 27 28class PosixPathTest(unittest.TestCase): 29 30 def setUp(self): 31 self.tearDown() 32 33 def tearDown(self): 34 for suffix in ["", "1", "2"]: 35 test_support.unlink(test_support.TESTFN + suffix) 36 safe_rmdir(test_support.TESTFN + suffix) 37 38 def test_join(self): 39 self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"), "/bar/baz") 40 self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz") 41 self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"), "/foo/bar/baz/") 42 43 def test_split(self): 44 self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar")) 45 self.assertEqual(posixpath.split("/"), ("/", "")) 46 self.assertEqual(posixpath.split("foo"), ("", "foo")) 47 self.assertEqual(posixpath.split("////foo"), ("////", "foo")) 48 self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar")) 49 50 def splitextTest(self, path, filename, ext): 51 self.assertEqual(posixpath.splitext(path), (filename, ext)) 52 self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext)) 53 self.assertEqual(posixpath.splitext("abc/" + path), ("abc/" + filename, ext)) 54 self.assertEqual(posixpath.splitext("abc.def/" + path), ("abc.def/" + filename, ext)) 55 self.assertEqual(posixpath.splitext("/abc.def/" + path), ("/abc.def/" + filename, ext)) 56 self.assertEqual(posixpath.splitext(path + "/"), (filename + ext + "/", "")) 57 58 def test_splitext(self): 59 self.splitextTest("foo.bar", "foo", ".bar") 60 self.splitextTest("foo.boo.bar", "foo.boo", ".bar") 61 self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar") 62 self.splitextTest(".csh.rc", ".csh", ".rc") 63 self.splitextTest("nodots", "nodots", "") 64 self.splitextTest(".cshrc", ".cshrc", "") 65 self.splitextTest("...manydots", "...manydots", "") 66 self.splitextTest("...manydots.ext", "...manydots", ".ext") 67 self.splitextTest(".", ".", "") 68 self.splitextTest("..", "..", "") 69 self.splitextTest("........", "........", "") 70 self.splitextTest("", "", "") 71 72 def test_isabs(self): 73 self.assertIs(posixpath.isabs(""), False) 74 self.assertIs(posixpath.isabs("/"), True) 75 self.assertIs(posixpath.isabs("/foo"), True) 76 self.assertIs(posixpath.isabs("/foo/bar"), True) 77 self.assertIs(posixpath.isabs("foo/bar"), False) 78 79 def test_basename(self): 80 self.assertEqual(posixpath.basename("/foo/bar"), "bar") 81 self.assertEqual(posixpath.basename("/"), "") 82 self.assertEqual(posixpath.basename("foo"), "foo") 83 self.assertEqual(posixpath.basename("////foo"), "foo") 84 self.assertEqual(posixpath.basename("//foo//bar"), "bar") 85 86 def test_dirname(self): 87 self.assertEqual(posixpath.dirname("/foo/bar"), "/foo") 88 self.assertEqual(posixpath.dirname("/"), "/") 89 self.assertEqual(posixpath.dirname("foo"), "") 90 self.assertEqual(posixpath.dirname("////foo"), "////") 91 self.assertEqual(posixpath.dirname("//foo//bar"), "//foo") 92 93 def test_islink(self): 94 self.assertIs(posixpath.islink(test_support.TESTFN + "1"), False) 95 f = open(test_support.TESTFN + "1", "wb") 96 try: 97 f.write("foo") 98 f.close() 99 self.assertIs(posixpath.islink(test_support.TESTFN + "1"), False) 100 if hasattr(os, "symlink"): 101 os.symlink(test_support.TESTFN + "1", test_support.TESTFN + "2") 102 self.assertIs(posixpath.islink(test_support.TESTFN + "2"), True) 103 os.remove(test_support.TESTFN + "1") 104 self.assertIs(posixpath.islink(test_support.TESTFN + "2"), True) 105 self.assertIs(posixpath.exists(test_support.TESTFN + "2"), False) 106 self.assertIs(posixpath.lexists(test_support.TESTFN + "2"), True) 107 finally: 108 if not f.close(): 109 f.close() 110 111 def test_samefile(self): 112 f = open(test_support.TESTFN + "1", "wb") 113 try: 114 f.write("foo") 115 f.close() 116 self.assertIs( 117 posixpath.samefile( 118 test_support.TESTFN + "1", 119 test_support.TESTFN + "1" 120 ), 121 True 122 ) 123 124 # If we don't have links, assume that os.stat doesn't return 125 # reasonable inode information and thus, that samefile() doesn't 126 # work. 127 if hasattr(os, "symlink"): 128 os.symlink( 129 test_support.TESTFN + "1", 130 test_support.TESTFN + "2" 131 ) 132 self.assertIs( 133 posixpath.samefile( 134 test_support.TESTFN + "1", 135 test_support.TESTFN + "2" 136 ), 137 True 138 ) 139 os.remove(test_support.TESTFN + "2") 140 f = open(test_support.TESTFN + "2", "wb") 141 f.write("bar") 142 f.close() 143 self.assertIs( 144 posixpath.samefile( 145 test_support.TESTFN + "1", 146 test_support.TESTFN + "2" 147 ), 148 False 149 ) 150 finally: 151 if not f.close(): 152 f.close() 153 154 def test_samestat(self): 155 f = open(test_support.TESTFN + "1", "wb") 156 try: 157 f.write("foo") 158 f.close() 159 self.assertIs( 160 posixpath.samestat( 161 os.stat(test_support.TESTFN + "1"), 162 os.stat(test_support.TESTFN + "1") 163 ), 164 True 165 ) 166 # If we don't have links, assume that os.stat() doesn't return 167 # reasonable inode information and thus, that samestat() doesn't 168 # work. 169 if hasattr(os, "symlink"): 170 os.symlink(test_support.TESTFN + "1", test_support.TESTFN + "2") 171 self.assertIs( 172 posixpath.samestat( 173 os.stat(test_support.TESTFN + "1"), 174 os.stat(test_support.TESTFN + "2") 175 ), 176 True 177 ) 178 os.remove(test_support.TESTFN + "2") 179 f = open(test_support.TESTFN + "2", "wb") 180 f.write("bar") 181 f.close() 182 self.assertIs( 183 posixpath.samestat( 184 os.stat(test_support.TESTFN + "1"), 185 os.stat(test_support.TESTFN + "2") 186 ), 187 False 188 ) 189 finally: 190 if not f.close(): 191 f.close() 192 193 def test_ismount(self): 194 self.assertIs(posixpath.ismount("/"), True) 195 196 def test_expanduser(self): 197 self.assertEqual(posixpath.expanduser("foo"), "foo") 198 try: 199 import pwd 200 except ImportError: 201 pass 202 else: 203 self.assertIsInstance(posixpath.expanduser("~/"), basestring) 204 # if home directory == root directory, this test makes no sense 205 if posixpath.expanduser("~") != '/': 206 self.assertEqual( 207 posixpath.expanduser("~") + "/", 208 posixpath.expanduser("~/") 209 ) 210 self.assertIsInstance(posixpath.expanduser("~root/"), basestring) 211 self.assertIsInstance(posixpath.expanduser("~foo/"), basestring) 212 213 with test_support.EnvironmentVarGuard() as env: 214 env['HOME'] = '/' 215 self.assertEqual(posixpath.expanduser("~"), "/") 216 self.assertEqual(posixpath.expanduser("~/foo"), "/foo") 217 218 def test_normpath(self): 219 self.assertEqual(posixpath.normpath(""), ".") 220 self.assertEqual(posixpath.normpath("/"), "/") 221 self.assertEqual(posixpath.normpath("//"), "//") 222 self.assertEqual(posixpath.normpath("///"), "/") 223 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar") 224 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"), "/foo/baz") 225 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar") 226 227 @skip_if_ABSTFN_contains_backslash 228 def test_realpath_curdir(self): 229 self.assertEqual(realpath('.'), os.getcwd()) 230 self.assertEqual(realpath('./.'), os.getcwd()) 231 self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd()) 232 233 @skip_if_ABSTFN_contains_backslash 234 def test_realpath_pardir(self): 235 self.assertEqual(realpath('..'), dirname(os.getcwd())) 236 self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd()))) 237 self.assertEqual(realpath('/'.join(['..'] * 100)), '/') 238 239 if hasattr(os, "symlink"): 240 def test_realpath_basic(self): 241 # Basic operation. 242 try: 243 os.symlink(ABSTFN+"1", ABSTFN) 244 self.assertEqual(realpath(ABSTFN), ABSTFN+"1") 245 finally: 246 test_support.unlink(ABSTFN) 247 248 def test_realpath_symlink_loops(self): 249 # Bug #930024, return the path unchanged if we get into an infinite 250 # symlink loop. 251 try: 252 old_path = abspath('.') 253 os.symlink(ABSTFN, ABSTFN) 254 self.assertEqual(realpath(ABSTFN), ABSTFN) 255 256 os.symlink(ABSTFN+"1", ABSTFN+"2") 257 os.symlink(ABSTFN+"2", ABSTFN+"1") 258 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1") 259 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2") 260 261 self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x") 262 self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN)) 263 self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x") 264 os.symlink(ABSTFN+"x", ABSTFN+"y") 265 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"), 266 ABSTFN + "y") 267 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"), 268 ABSTFN + "1") 269 270 os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a") 271 self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b") 272 273 os.symlink("../" + basename(dirname(ABSTFN)) + "/" + 274 basename(ABSTFN) + "c", ABSTFN+"c") 275 self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c") 276 277 # Test using relative path as well. 278 os.chdir(dirname(ABSTFN)) 279 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN) 280 finally: 281 os.chdir(old_path) 282 test_support.unlink(ABSTFN) 283 test_support.unlink(ABSTFN+"1") 284 test_support.unlink(ABSTFN+"2") 285 test_support.unlink(ABSTFN+"y") 286 test_support.unlink(ABSTFN+"c") 287 test_support.unlink(ABSTFN+"a") 288 289 def test_realpath_repeated_indirect_symlinks(self): 290 # Issue #6975. 291 try: 292 os.mkdir(ABSTFN) 293 os.symlink('../' + basename(ABSTFN), ABSTFN + '/self') 294 os.symlink('self/self/self', ABSTFN + '/link') 295 self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN) 296 finally: 297 test_support.unlink(ABSTFN + '/self') 298 test_support.unlink(ABSTFN + '/link') 299 safe_rmdir(ABSTFN) 300 301 def test_realpath_deep_recursion(self): 302 depth = 10 303 old_path = abspath('.') 304 try: 305 os.mkdir(ABSTFN) 306 for i in range(depth): 307 os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1)) 308 os.symlink('.', ABSTFN + '/0') 309 self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN) 310 311 # Test using relative path as well. 312 os.chdir(ABSTFN) 313 self.assertEqual(realpath('%d' % depth), ABSTFN) 314 finally: 315 os.chdir(old_path) 316 for i in range(depth + 1): 317 test_support.unlink(ABSTFN + '/%d' % i) 318 safe_rmdir(ABSTFN) 319 320 def test_realpath_resolve_parents(self): 321 # We also need to resolve any symlinks in the parents of a relative 322 # path passed to realpath. E.g.: current working directory is 323 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call 324 # realpath("a"). This should return /usr/share/doc/a/. 325 try: 326 old_path = abspath('.') 327 os.mkdir(ABSTFN) 328 os.mkdir(ABSTFN + "/y") 329 os.symlink(ABSTFN + "/y", ABSTFN + "/k") 330 331 os.chdir(ABSTFN + "/k") 332 self.assertEqual(realpath("a"), ABSTFN + "/y/a") 333 finally: 334 os.chdir(old_path) 335 test_support.unlink(ABSTFN + "/k") 336 safe_rmdir(ABSTFN + "/y") 337 safe_rmdir(ABSTFN) 338 339 def test_realpath_resolve_before_normalizing(self): 340 # Bug #990669: Symbolic links should be resolved before we 341 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y' 342 # in the following hierarchy: 343 # a/k/y 344 # 345 # and a symbolic link 'link-y' pointing to 'y' in directory 'a', 346 # then realpath("link-y/..") should return 'k', not 'a'. 347 try: 348 old_path = abspath('.') 349 os.mkdir(ABSTFN) 350 os.mkdir(ABSTFN + "/k") 351 os.mkdir(ABSTFN + "/k/y") 352 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y") 353 354 # Absolute path. 355 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k") 356 # Relative path. 357 os.chdir(dirname(ABSTFN)) 358 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."), 359 ABSTFN + "/k") 360 finally: 361 os.chdir(old_path) 362 test_support.unlink(ABSTFN + "/link-y") 363 safe_rmdir(ABSTFN + "/k/y") 364 safe_rmdir(ABSTFN + "/k") 365 safe_rmdir(ABSTFN) 366 367 def test_realpath_resolve_first(self): 368 # Bug #1213894: The first component of the path, if not absolute, 369 # must be resolved too. 370 371 try: 372 old_path = abspath('.') 373 os.mkdir(ABSTFN) 374 os.mkdir(ABSTFN + "/k") 375 os.symlink(ABSTFN, ABSTFN + "link") 376 os.chdir(dirname(ABSTFN)) 377 378 base = basename(ABSTFN) 379 self.assertEqual(realpath(base + "link"), ABSTFN) 380 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k") 381 finally: 382 os.chdir(old_path) 383 test_support.unlink(ABSTFN + "link") 384 safe_rmdir(ABSTFN + "/k") 385 safe_rmdir(ABSTFN) 386 387 def test_relpath(self): 388 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar") 389 try: 390 curdir = os.path.split(os.getcwd())[-1] 391 self.assertRaises(ValueError, posixpath.relpath, "") 392 self.assertEqual(posixpath.relpath("a"), "a") 393 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a") 394 self.assertEqual(posixpath.relpath("a/b"), "a/b") 395 self.assertEqual(posixpath.relpath("../a/b"), "../a/b") 396 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a") 397 self.assertEqual(posixpath.relpath("a/b", "../c"), "../"+curdir+"/a/b") 398 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a") 399 self.assertEqual(posixpath.relpath("a", "a"), ".") 400 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat') 401 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat') 402 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat') 403 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..') 404 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat') 405 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x') 406 self.assertEqual(posixpath.relpath("/", "/"), '.') 407 self.assertEqual(posixpath.relpath("/a", "/a"), '.') 408 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.') 409 finally: 410 os.getcwd = real_getcwd 411 412 413class PosixCommonTest(test_genericpath.CommonTest): 414 pathmodule = posixpath 415 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat'] 416 417 418def test_main(): 419 test_support.run_unittest(PosixPathTest, PosixCommonTest) 420 421 422if __name__=="__main__": 423 test_main() 424