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