1import os 2import posixpath 3import unittest 4import warnings 5from posixpath import realpath, abspath, dirname, basename 6from test import support, test_genericpath 7 8try: 9 import posix 10except ImportError: 11 posix = None 12 13# An absolute path to a temporary filename for testing. We can't rely on TESTFN 14# being an absolute path, so we need this. 15 16ABSTFN = abspath(support.TESTFN) 17 18def skip_if_ABSTFN_contains_backslash(test): 19 """ 20 On Windows, posixpath.abspath still returns paths with backslashes 21 instead of posix forward slashes. If this is the case, several tests 22 fail, so skip them. 23 """ 24 found_backslash = '\\' in ABSTFN 25 msg = "ABSTFN is not a posix path - tests fail" 26 return [test, unittest.skip(msg)(test)][found_backslash] 27 28def safe_rmdir(dirname): 29 try: 30 os.rmdir(dirname) 31 except OSError: 32 pass 33 34class PosixPathTest(unittest.TestCase): 35 36 def setUp(self): 37 self.tearDown() 38 39 def tearDown(self): 40 for suffix in ["", "1", "2"]: 41 support.unlink(support.TESTFN + suffix) 42 safe_rmdir(support.TESTFN + suffix) 43 44 def test_join(self): 45 self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"), 46 "/bar/baz") 47 self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz") 48 self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"), 49 "/foo/bar/baz/") 50 51 self.assertEqual(posixpath.join(b"/foo", b"bar", b"/bar", b"baz"), 52 b"/bar/baz") 53 self.assertEqual(posixpath.join(b"/foo", b"bar", b"baz"), 54 b"/foo/bar/baz") 55 self.assertEqual(posixpath.join(b"/foo/", b"bar/", b"baz/"), 56 b"/foo/bar/baz/") 57 58 def test_split(self): 59 self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar")) 60 self.assertEqual(posixpath.split("/"), ("/", "")) 61 self.assertEqual(posixpath.split("foo"), ("", "foo")) 62 self.assertEqual(posixpath.split("////foo"), ("////", "foo")) 63 self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar")) 64 65 self.assertEqual(posixpath.split(b"/foo/bar"), (b"/foo", b"bar")) 66 self.assertEqual(posixpath.split(b"/"), (b"/", b"")) 67 self.assertEqual(posixpath.split(b"foo"), (b"", b"foo")) 68 self.assertEqual(posixpath.split(b"////foo"), (b"////", b"foo")) 69 self.assertEqual(posixpath.split(b"//foo//bar"), (b"//foo", b"bar")) 70 71 def splitextTest(self, path, filename, ext): 72 self.assertEqual(posixpath.splitext(path), (filename, ext)) 73 self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext)) 74 self.assertEqual(posixpath.splitext("abc/" + path), 75 ("abc/" + filename, ext)) 76 self.assertEqual(posixpath.splitext("abc.def/" + path), 77 ("abc.def/" + filename, ext)) 78 self.assertEqual(posixpath.splitext("/abc.def/" + path), 79 ("/abc.def/" + filename, ext)) 80 self.assertEqual(posixpath.splitext(path + "/"), 81 (filename + ext + "/", "")) 82 83 path = bytes(path, "ASCII") 84 filename = bytes(filename, "ASCII") 85 ext = bytes(ext, "ASCII") 86 87 self.assertEqual(posixpath.splitext(path), (filename, ext)) 88 self.assertEqual(posixpath.splitext(b"/" + path), 89 (b"/" + filename, ext)) 90 self.assertEqual(posixpath.splitext(b"abc/" + path), 91 (b"abc/" + filename, ext)) 92 self.assertEqual(posixpath.splitext(b"abc.def/" + path), 93 (b"abc.def/" + filename, ext)) 94 self.assertEqual(posixpath.splitext(b"/abc.def/" + path), 95 (b"/abc.def/" + filename, ext)) 96 self.assertEqual(posixpath.splitext(path + b"/"), 97 (filename + ext + b"/", b"")) 98 99 def test_splitext(self): 100 self.splitextTest("foo.bar", "foo", ".bar") 101 self.splitextTest("foo.boo.bar", "foo.boo", ".bar") 102 self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar") 103 self.splitextTest(".csh.rc", ".csh", ".rc") 104 self.splitextTest("nodots", "nodots", "") 105 self.splitextTest(".cshrc", ".cshrc", "") 106 self.splitextTest("...manydots", "...manydots", "") 107 self.splitextTest("...manydots.ext", "...manydots", ".ext") 108 self.splitextTest(".", ".", "") 109 self.splitextTest("..", "..", "") 110 self.splitextTest("........", "........", "") 111 self.splitextTest("", "", "") 112 113 def test_isabs(self): 114 self.assertIs(posixpath.isabs(""), False) 115 self.assertIs(posixpath.isabs("/"), True) 116 self.assertIs(posixpath.isabs("/foo"), True) 117 self.assertIs(posixpath.isabs("/foo/bar"), True) 118 self.assertIs(posixpath.isabs("foo/bar"), False) 119 120 self.assertIs(posixpath.isabs(b""), False) 121 self.assertIs(posixpath.isabs(b"/"), True) 122 self.assertIs(posixpath.isabs(b"/foo"), True) 123 self.assertIs(posixpath.isabs(b"/foo/bar"), True) 124 self.assertIs(posixpath.isabs(b"foo/bar"), False) 125 126 def test_basename(self): 127 self.assertEqual(posixpath.basename("/foo/bar"), "bar") 128 self.assertEqual(posixpath.basename("/"), "") 129 self.assertEqual(posixpath.basename("foo"), "foo") 130 self.assertEqual(posixpath.basename("////foo"), "foo") 131 self.assertEqual(posixpath.basename("//foo//bar"), "bar") 132 133 self.assertEqual(posixpath.basename(b"/foo/bar"), b"bar") 134 self.assertEqual(posixpath.basename(b"/"), b"") 135 self.assertEqual(posixpath.basename(b"foo"), b"foo") 136 self.assertEqual(posixpath.basename(b"////foo"), b"foo") 137 self.assertEqual(posixpath.basename(b"//foo//bar"), b"bar") 138 139 def test_dirname(self): 140 self.assertEqual(posixpath.dirname("/foo/bar"), "/foo") 141 self.assertEqual(posixpath.dirname("/"), "/") 142 self.assertEqual(posixpath.dirname("foo"), "") 143 self.assertEqual(posixpath.dirname("////foo"), "////") 144 self.assertEqual(posixpath.dirname("//foo//bar"), "//foo") 145 146 self.assertEqual(posixpath.dirname(b"/foo/bar"), b"/foo") 147 self.assertEqual(posixpath.dirname(b"/"), b"/") 148 self.assertEqual(posixpath.dirname(b"foo"), b"") 149 self.assertEqual(posixpath.dirname(b"////foo"), b"////") 150 self.assertEqual(posixpath.dirname(b"//foo//bar"), b"//foo") 151 152 def test_islink(self): 153 self.assertIs(posixpath.islink(support.TESTFN + "1"), False) 154 self.assertIs(posixpath.lexists(support.TESTFN + "2"), False) 155 f = open(support.TESTFN + "1", "wb") 156 try: 157 f.write(b"foo") 158 f.close() 159 self.assertIs(posixpath.islink(support.TESTFN + "1"), False) 160 if support.can_symlink(): 161 os.symlink(support.TESTFN + "1", support.TESTFN + "2") 162 self.assertIs(posixpath.islink(support.TESTFN + "2"), True) 163 os.remove(support.TESTFN + "1") 164 self.assertIs(posixpath.islink(support.TESTFN + "2"), True) 165 self.assertIs(posixpath.exists(support.TESTFN + "2"), False) 166 self.assertIs(posixpath.lexists(support.TESTFN + "2"), True) 167 finally: 168 if not f.close(): 169 f.close() 170 171 def test_ismount(self): 172 self.assertIs(posixpath.ismount("/"), True) 173 with warnings.catch_warnings(): 174 warnings.simplefilter("ignore", DeprecationWarning) 175 self.assertIs(posixpath.ismount(b"/"), True) 176 177 def test_ismount_non_existent(self): 178 # Non-existent mountpoint. 179 self.assertIs(posixpath.ismount(ABSTFN), False) 180 try: 181 os.mkdir(ABSTFN) 182 self.assertIs(posixpath.ismount(ABSTFN), False) 183 finally: 184 safe_rmdir(ABSTFN) 185 186 @unittest.skipUnless(support.can_symlink(), 187 "Test requires symlink support") 188 def test_ismount_symlinks(self): 189 # Symlinks are never mountpoints. 190 try: 191 os.symlink("/", ABSTFN) 192 self.assertIs(posixpath.ismount(ABSTFN), False) 193 finally: 194 os.unlink(ABSTFN) 195 196 @unittest.skipIf(posix is None, "Test requires posix module") 197 def test_ismount_different_device(self): 198 # Simulate the path being on a different device from its parent by 199 # mocking out st_dev. 200 save_lstat = os.lstat 201 def fake_lstat(path): 202 st_ino = 0 203 st_dev = 0 204 if path == ABSTFN: 205 st_dev = 1 206 st_ino = 1 207 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0)) 208 try: 209 os.lstat = fake_lstat 210 self.assertIs(posixpath.ismount(ABSTFN), True) 211 finally: 212 os.lstat = save_lstat 213 214 @unittest.skipIf(posix is None, "Test requires posix module") 215 def test_ismount_directory_not_readable(self): 216 # issue #2466: Simulate ismount run on a directory that is not 217 # readable, which used to return False. 218 save_lstat = os.lstat 219 def fake_lstat(path): 220 st_ino = 0 221 st_dev = 0 222 if path.startswith(ABSTFN) and path != ABSTFN: 223 # ismount tries to read something inside the ABSTFN directory; 224 # simulate this being forbidden (no read permission). 225 raise OSError("Fake [Errno 13] Permission denied") 226 if path == ABSTFN: 227 st_dev = 1 228 st_ino = 1 229 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0)) 230 try: 231 os.lstat = fake_lstat 232 self.assertIs(posixpath.ismount(ABSTFN), True) 233 finally: 234 os.lstat = save_lstat 235 236 def test_expanduser(self): 237 self.assertEqual(posixpath.expanduser("foo"), "foo") 238 self.assertEqual(posixpath.expanduser(b"foo"), b"foo") 239 with support.EnvironmentVarGuard() as env: 240 for home in '/', '', '//', '///': 241 with self.subTest(home=home): 242 env['HOME'] = home 243 self.assertEqual(posixpath.expanduser("~"), "/") 244 self.assertEqual(posixpath.expanduser("~/"), "/") 245 self.assertEqual(posixpath.expanduser("~/foo"), "/foo") 246 try: 247 import pwd 248 except ImportError: 249 pass 250 else: 251 self.assertIsInstance(posixpath.expanduser("~/"), str) 252 self.assertIsInstance(posixpath.expanduser(b"~/"), bytes) 253 # if home directory == root directory, this test makes no sense 254 if posixpath.expanduser("~") != '/': 255 self.assertEqual( 256 posixpath.expanduser("~") + "/", 257 posixpath.expanduser("~/") 258 ) 259 self.assertEqual( 260 posixpath.expanduser(b"~") + b"/", 261 posixpath.expanduser(b"~/") 262 ) 263 self.assertIsInstance(posixpath.expanduser("~root/"), str) 264 self.assertIsInstance(posixpath.expanduser("~foo/"), str) 265 self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes) 266 self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes) 267 268 with support.EnvironmentVarGuard() as env: 269 # expanduser should fall back to using the password database 270 del env['HOME'] 271 home = pwd.getpwuid(os.getuid()).pw_dir 272 # $HOME can end with a trailing /, so strip it (see #17809) 273 home = home.rstrip("/") or '/' 274 self.assertEqual(posixpath.expanduser("~"), home) 275 276 def test_normpath(self): 277 self.assertEqual(posixpath.normpath(""), ".") 278 self.assertEqual(posixpath.normpath("/"), "/") 279 self.assertEqual(posixpath.normpath("//"), "//") 280 self.assertEqual(posixpath.normpath("///"), "/") 281 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar") 282 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"), 283 "/foo/baz") 284 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar") 285 286 self.assertEqual(posixpath.normpath(b""), b".") 287 self.assertEqual(posixpath.normpath(b"/"), b"/") 288 self.assertEqual(posixpath.normpath(b"//"), b"//") 289 self.assertEqual(posixpath.normpath(b"///"), b"/") 290 self.assertEqual(posixpath.normpath(b"///foo/.//bar//"), b"/foo/bar") 291 self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"), 292 b"/foo/baz") 293 self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"), 294 b"/foo/bar") 295 296 @skip_if_ABSTFN_contains_backslash 297 def test_realpath_curdir(self): 298 self.assertEqual(realpath('.'), os.getcwd()) 299 self.assertEqual(realpath('./.'), os.getcwd()) 300 self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd()) 301 302 self.assertEqual(realpath(b'.'), os.getcwdb()) 303 self.assertEqual(realpath(b'./.'), os.getcwdb()) 304 self.assertEqual(realpath(b'/'.join([b'.'] * 100)), os.getcwdb()) 305 306 @skip_if_ABSTFN_contains_backslash 307 def test_realpath_pardir(self): 308 self.assertEqual(realpath('..'), dirname(os.getcwd())) 309 self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd()))) 310 self.assertEqual(realpath('/'.join(['..'] * 100)), '/') 311 312 self.assertEqual(realpath(b'..'), dirname(os.getcwdb())) 313 self.assertEqual(realpath(b'../..'), dirname(dirname(os.getcwdb()))) 314 self.assertEqual(realpath(b'/'.join([b'..'] * 100)), b'/') 315 316 @unittest.skipUnless(hasattr(os, "symlink"), 317 "Missing symlink implementation") 318 @skip_if_ABSTFN_contains_backslash 319 def test_realpath_basic(self): 320 # Basic operation. 321 try: 322 os.symlink(ABSTFN+"1", ABSTFN) 323 self.assertEqual(realpath(ABSTFN), ABSTFN+"1") 324 finally: 325 support.unlink(ABSTFN) 326 327 @unittest.skipUnless(hasattr(os, "symlink"), 328 "Missing symlink implementation") 329 @skip_if_ABSTFN_contains_backslash 330 def test_realpath_relative(self): 331 try: 332 os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN) 333 self.assertEqual(realpath(ABSTFN), ABSTFN+"1") 334 finally: 335 support.unlink(ABSTFN) 336 337 @unittest.skipUnless(hasattr(os, "symlink"), 338 "Missing symlink implementation") 339 @skip_if_ABSTFN_contains_backslash 340 def test_realpath_symlink_loops(self): 341 # Bug #930024, return the path unchanged if we get into an infinite 342 # symlink loop. 343 try: 344 os.symlink(ABSTFN, ABSTFN) 345 self.assertEqual(realpath(ABSTFN), ABSTFN) 346 347 os.symlink(ABSTFN+"1", ABSTFN+"2") 348 os.symlink(ABSTFN+"2", ABSTFN+"1") 349 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1") 350 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2") 351 352 self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x") 353 self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN)) 354 self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x") 355 os.symlink(ABSTFN+"x", ABSTFN+"y") 356 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"), 357 ABSTFN + "y") 358 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"), 359 ABSTFN + "1") 360 361 os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a") 362 self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b") 363 364 os.symlink("../" + basename(dirname(ABSTFN)) + "/" + 365 basename(ABSTFN) + "c", ABSTFN+"c") 366 self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c") 367 368 # Test using relative path as well. 369 with support.change_cwd(dirname(ABSTFN)): 370 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN) 371 finally: 372 support.unlink(ABSTFN) 373 support.unlink(ABSTFN+"1") 374 support.unlink(ABSTFN+"2") 375 support.unlink(ABSTFN+"y") 376 support.unlink(ABSTFN+"c") 377 support.unlink(ABSTFN+"a") 378 379 @unittest.skipUnless(hasattr(os, "symlink"), 380 "Missing symlink implementation") 381 @skip_if_ABSTFN_contains_backslash 382 def test_realpath_repeated_indirect_symlinks(self): 383 # Issue #6975. 384 try: 385 os.mkdir(ABSTFN) 386 os.symlink('../' + basename(ABSTFN), ABSTFN + '/self') 387 os.symlink('self/self/self', ABSTFN + '/link') 388 self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN) 389 finally: 390 support.unlink(ABSTFN + '/self') 391 support.unlink(ABSTFN + '/link') 392 safe_rmdir(ABSTFN) 393 394 @unittest.skipUnless(hasattr(os, "symlink"), 395 "Missing symlink implementation") 396 @skip_if_ABSTFN_contains_backslash 397 def test_realpath_deep_recursion(self): 398 depth = 10 399 try: 400 os.mkdir(ABSTFN) 401 for i in range(depth): 402 os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1)) 403 os.symlink('.', ABSTFN + '/0') 404 self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN) 405 406 # Test using relative path as well. 407 with support.change_cwd(ABSTFN): 408 self.assertEqual(realpath('%d' % depth), ABSTFN) 409 finally: 410 for i in range(depth + 1): 411 support.unlink(ABSTFN + '/%d' % i) 412 safe_rmdir(ABSTFN) 413 414 @unittest.skipUnless(hasattr(os, "symlink"), 415 "Missing symlink implementation") 416 @skip_if_ABSTFN_contains_backslash 417 def test_realpath_resolve_parents(self): 418 # We also need to resolve any symlinks in the parents of a relative 419 # path passed to realpath. E.g.: current working directory is 420 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call 421 # realpath("a"). This should return /usr/share/doc/a/. 422 try: 423 os.mkdir(ABSTFN) 424 os.mkdir(ABSTFN + "/y") 425 os.symlink(ABSTFN + "/y", ABSTFN + "/k") 426 427 with support.change_cwd(ABSTFN + "/k"): 428 self.assertEqual(realpath("a"), ABSTFN + "/y/a") 429 finally: 430 support.unlink(ABSTFN + "/k") 431 safe_rmdir(ABSTFN + "/y") 432 safe_rmdir(ABSTFN) 433 434 @unittest.skipUnless(hasattr(os, "symlink"), 435 "Missing symlink implementation") 436 @skip_if_ABSTFN_contains_backslash 437 def test_realpath_resolve_before_normalizing(self): 438 # Bug #990669: Symbolic links should be resolved before we 439 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y' 440 # in the following hierarchy: 441 # a/k/y 442 # 443 # and a symbolic link 'link-y' pointing to 'y' in directory 'a', 444 # then realpath("link-y/..") should return 'k', not 'a'. 445 try: 446 os.mkdir(ABSTFN) 447 os.mkdir(ABSTFN + "/k") 448 os.mkdir(ABSTFN + "/k/y") 449 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y") 450 451 # Absolute path. 452 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k") 453 # Relative path. 454 with support.change_cwd(dirname(ABSTFN)): 455 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."), 456 ABSTFN + "/k") 457 finally: 458 support.unlink(ABSTFN + "/link-y") 459 safe_rmdir(ABSTFN + "/k/y") 460 safe_rmdir(ABSTFN + "/k") 461 safe_rmdir(ABSTFN) 462 463 @unittest.skipUnless(hasattr(os, "symlink"), 464 "Missing symlink implementation") 465 @skip_if_ABSTFN_contains_backslash 466 def test_realpath_resolve_first(self): 467 # Bug #1213894: The first component of the path, if not absolute, 468 # must be resolved too. 469 470 try: 471 os.mkdir(ABSTFN) 472 os.mkdir(ABSTFN + "/k") 473 os.symlink(ABSTFN, ABSTFN + "link") 474 with support.change_cwd(dirname(ABSTFN)): 475 base = basename(ABSTFN) 476 self.assertEqual(realpath(base + "link"), ABSTFN) 477 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k") 478 finally: 479 support.unlink(ABSTFN + "link") 480 safe_rmdir(ABSTFN + "/k") 481 safe_rmdir(ABSTFN) 482 483 def test_relpath(self): 484 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar") 485 try: 486 curdir = os.path.split(os.getcwd())[-1] 487 self.assertRaises(ValueError, posixpath.relpath, "") 488 self.assertEqual(posixpath.relpath("a"), "a") 489 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a") 490 self.assertEqual(posixpath.relpath("a/b"), "a/b") 491 self.assertEqual(posixpath.relpath("../a/b"), "../a/b") 492 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a") 493 self.assertEqual(posixpath.relpath("a/b", "../c"), 494 "../"+curdir+"/a/b") 495 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a") 496 self.assertEqual(posixpath.relpath("a", "a"), ".") 497 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat') 498 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat') 499 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat') 500 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..') 501 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat') 502 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x') 503 self.assertEqual(posixpath.relpath("/", "/"), '.') 504 self.assertEqual(posixpath.relpath("/a", "/a"), '.') 505 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.') 506 finally: 507 os.getcwd = real_getcwd 508 509 def test_relpath_bytes(self): 510 (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar") 511 try: 512 curdir = os.path.split(os.getcwdb())[-1] 513 self.assertRaises(ValueError, posixpath.relpath, b"") 514 self.assertEqual(posixpath.relpath(b"a"), b"a") 515 self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a") 516 self.assertEqual(posixpath.relpath(b"a/b"), b"a/b") 517 self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b") 518 self.assertEqual(posixpath.relpath(b"a", b"../b"), 519 b"../"+curdir+b"/a") 520 self.assertEqual(posixpath.relpath(b"a/b", b"../c"), 521 b"../"+curdir+b"/a/b") 522 self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a") 523 self.assertEqual(posixpath.relpath(b"a", b"a"), b".") 524 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat') 525 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat') 526 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat') 527 self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..') 528 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat') 529 self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x') 530 self.assertEqual(posixpath.relpath(b"/", b"/"), b'.') 531 self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.') 532 self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.') 533 534 self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str") 535 self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes") 536 finally: 537 os.getcwdb = real_getcwdb 538 539 def test_commonpath(self): 540 def check(paths, expected): 541 self.assertEqual(posixpath.commonpath(paths), expected) 542 self.assertEqual(posixpath.commonpath([os.fsencode(p) for p in paths]), 543 os.fsencode(expected)) 544 def check_error(exc, paths): 545 self.assertRaises(exc, posixpath.commonpath, paths) 546 self.assertRaises(exc, posixpath.commonpath, 547 [os.fsencode(p) for p in paths]) 548 549 self.assertRaises(ValueError, posixpath.commonpath, []) 550 check_error(ValueError, ['/usr', 'usr']) 551 check_error(ValueError, ['usr', '/usr']) 552 553 check(['/usr/local'], '/usr/local') 554 check(['/usr/local', '/usr/local'], '/usr/local') 555 check(['/usr/local/', '/usr/local'], '/usr/local') 556 check(['/usr/local/', '/usr/local/'], '/usr/local') 557 check(['/usr//local', '//usr/local'], '/usr/local') 558 check(['/usr/./local', '/./usr/local'], '/usr/local') 559 check(['/', '/dev'], '/') 560 check(['/usr', '/dev'], '/') 561 check(['/usr/lib/', '/usr/lib/python3'], '/usr/lib') 562 check(['/usr/lib/', '/usr/lib64/'], '/usr') 563 564 check(['/usr/lib', '/usr/lib64'], '/usr') 565 check(['/usr/lib/', '/usr/lib64'], '/usr') 566 567 check(['spam'], 'spam') 568 check(['spam', 'spam'], 'spam') 569 check(['spam', 'alot'], '') 570 check(['and/jam', 'and/spam'], 'and') 571 check(['and//jam', 'and/spam//'], 'and') 572 check(['and/./jam', './and/spam'], 'and') 573 check(['and/jam', 'and/spam', 'alot'], '') 574 check(['and/jam', 'and/spam', 'and'], 'and') 575 576 check([''], '') 577 check(['', 'spam/alot'], '') 578 check_error(ValueError, ['', '/spam/alot']) 579 580 self.assertRaises(TypeError, posixpath.commonpath, 581 [b'/usr/lib/', '/usr/lib/python3']) 582 self.assertRaises(TypeError, posixpath.commonpath, 583 [b'/usr/lib/', 'usr/lib/python3']) 584 self.assertRaises(TypeError, posixpath.commonpath, 585 [b'usr/lib/', '/usr/lib/python3']) 586 self.assertRaises(TypeError, posixpath.commonpath, 587 ['/usr/lib/', b'/usr/lib/python3']) 588 self.assertRaises(TypeError, posixpath.commonpath, 589 ['/usr/lib/', b'usr/lib/python3']) 590 self.assertRaises(TypeError, posixpath.commonpath, 591 ['usr/lib/', b'/usr/lib/python3']) 592 593 594class PosixCommonTest(test_genericpath.CommonTest, unittest.TestCase): 595 pathmodule = posixpath 596 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat'] 597 598 599class PathLikeTests(unittest.TestCase): 600 601 path = posixpath 602 603 class PathLike: 604 def __init__(self, path=''): 605 self.path = path 606 def __fspath__(self): 607 if isinstance(self.path, BaseException): 608 raise self.path 609 else: 610 return self.path 611 612 def setUp(self): 613 self.file_name = support.TESTFN.lower() 614 self.file_path = self.PathLike(support.TESTFN) 615 self.addCleanup(support.unlink, self.file_name) 616 with open(self.file_name, 'xb', 0) as file: 617 file.write(b"test_posixpath.PathLikeTests") 618 619 def assertPathEqual(self, func): 620 self.assertEqual(func(self.file_path), func(self.file_name)) 621 622 def test_path_normcase(self): 623 self.assertPathEqual(self.path.normcase) 624 625 def test_path_isabs(self): 626 self.assertPathEqual(self.path.isabs) 627 628 def test_path_join(self): 629 self.assertEqual(self.path.join('a', self.PathLike('b'), 'c'), 630 self.path.join('a', 'b', 'c')) 631 632 def test_path_split(self): 633 self.assertPathEqual(self.path.split) 634 635 def test_path_splitext(self): 636 self.assertPathEqual(self.path.splitext) 637 638 def test_path_splitdrive(self): 639 self.assertPathEqual(self.path.splitdrive) 640 641 def test_path_basename(self): 642 self.assertPathEqual(self.path.basename) 643 644 def test_path_dirname(self): 645 self.assertPathEqual(self.path.dirname) 646 647 def test_path_islink(self): 648 self.assertPathEqual(self.path.islink) 649 650 def test_path_lexists(self): 651 self.assertPathEqual(self.path.lexists) 652 653 def test_path_ismount(self): 654 self.assertPathEqual(self.path.ismount) 655 656 def test_path_expanduser(self): 657 self.assertPathEqual(self.path.expanduser) 658 659 def test_path_expandvars(self): 660 self.assertPathEqual(self.path.expandvars) 661 662 def test_path_normpath(self): 663 self.assertPathEqual(self.path.normpath) 664 665 def test_path_abspath(self): 666 self.assertPathEqual(self.path.abspath) 667 668 def test_path_realpath(self): 669 self.assertPathEqual(self.path.realpath) 670 671 def test_path_relpath(self): 672 self.assertPathEqual(self.path.relpath) 673 674 def test_path_commonpath(self): 675 common_path = self.path.commonpath([self.file_path, self.file_name]) 676 self.assertEqual(common_path, self.file_name) 677 678 679if __name__=="__main__": 680 unittest.main() 681