1import ntpath 2import os 3import sys 4import unittest 5import warnings 6from test.support import os_helper 7from test.support import TestFailed 8from test.support.os_helper import FakePath 9from test import test_genericpath 10from tempfile import TemporaryFile 11 12 13try: 14 import nt 15except ImportError: 16 # Most tests can complete without the nt module, 17 # but for those that require it we import here. 18 nt = None 19 20try: 21 ntpath._getfinalpathname 22except AttributeError: 23 HAVE_GETFINALPATHNAME = False 24else: 25 HAVE_GETFINALPATHNAME = True 26 27try: 28 import ctypes 29except ImportError: 30 HAVE_GETSHORTPATHNAME = False 31else: 32 HAVE_GETSHORTPATHNAME = True 33 def _getshortpathname(path): 34 GSPN = ctypes.WinDLL("kernel32", use_last_error=True).GetShortPathNameW 35 GSPN.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32] 36 GSPN.restype = ctypes.c_uint32 37 result_len = GSPN(path, None, 0) 38 if not result_len: 39 raise OSError("failed to get short path name 0x{:08X}" 40 .format(ctypes.get_last_error())) 41 result = ctypes.create_unicode_buffer(result_len) 42 result_len = GSPN(path, result, result_len) 43 return result[:result_len] 44 45def _norm(path): 46 if isinstance(path, (bytes, str, os.PathLike)): 47 return ntpath.normcase(os.fsdecode(path)) 48 elif hasattr(path, "__iter__"): 49 return tuple(ntpath.normcase(os.fsdecode(p)) for p in path) 50 return path 51 52 53def tester(fn, wantResult): 54 fn = fn.replace("\\", "\\\\") 55 gotResult = eval(fn) 56 if wantResult != gotResult and _norm(wantResult) != _norm(gotResult): 57 raise TestFailed("%s should return: %s but returned: %s" \ 58 %(str(fn), str(wantResult), str(gotResult))) 59 60 # then with bytes 61 fn = fn.replace("('", "(b'") 62 fn = fn.replace('("', '(b"') 63 fn = fn.replace("['", "[b'") 64 fn = fn.replace('["', '[b"') 65 fn = fn.replace(", '", ", b'") 66 fn = fn.replace(', "', ', b"') 67 fn = os.fsencode(fn).decode('latin1') 68 fn = fn.encode('ascii', 'backslashreplace').decode('ascii') 69 with warnings.catch_warnings(): 70 warnings.simplefilter("ignore", DeprecationWarning) 71 gotResult = eval(fn) 72 if _norm(wantResult) != _norm(gotResult): 73 raise TestFailed("%s should return: %s but returned: %s" \ 74 %(str(fn), str(wantResult), repr(gotResult))) 75 76 77class NtpathTestCase(unittest.TestCase): 78 def assertPathEqual(self, path1, path2): 79 if path1 == path2 or _norm(path1) == _norm(path2): 80 return 81 self.assertEqual(path1, path2) 82 83 def assertPathIn(self, path, pathset): 84 self.assertIn(_norm(path), _norm(pathset)) 85 86 87class TestNtpath(NtpathTestCase): 88 def test_splitext(self): 89 tester('ntpath.splitext("foo.ext")', ('foo', '.ext')) 90 tester('ntpath.splitext("/foo/foo.ext")', ('/foo/foo', '.ext')) 91 tester('ntpath.splitext(".ext")', ('.ext', '')) 92 tester('ntpath.splitext("\\foo.ext\\foo")', ('\\foo.ext\\foo', '')) 93 tester('ntpath.splitext("foo.ext\\")', ('foo.ext\\', '')) 94 tester('ntpath.splitext("")', ('', '')) 95 tester('ntpath.splitext("foo.bar.ext")', ('foo.bar', '.ext')) 96 tester('ntpath.splitext("xx/foo.bar.ext")', ('xx/foo.bar', '.ext')) 97 tester('ntpath.splitext("xx\\foo.bar.ext")', ('xx\\foo.bar', '.ext')) 98 tester('ntpath.splitext("c:a/b\\c.d")', ('c:a/b\\c', '.d')) 99 100 def test_splitdrive(self): 101 tester('ntpath.splitdrive("c:\\foo\\bar")', 102 ('c:', '\\foo\\bar')) 103 tester('ntpath.splitdrive("c:/foo/bar")', 104 ('c:', '/foo/bar')) 105 tester('ntpath.splitdrive("\\\\conky\\mountpoint\\foo\\bar")', 106 ('\\\\conky\\mountpoint', '\\foo\\bar')) 107 tester('ntpath.splitdrive("//conky/mountpoint/foo/bar")', 108 ('//conky/mountpoint', '/foo/bar')) 109 tester('ntpath.splitdrive("\\\\\\conky\\mountpoint\\foo\\bar")', 110 ('', '\\\\\\conky\\mountpoint\\foo\\bar')) 111 tester('ntpath.splitdrive("///conky/mountpoint/foo/bar")', 112 ('', '///conky/mountpoint/foo/bar')) 113 tester('ntpath.splitdrive("\\\\conky\\\\mountpoint\\foo\\bar")', 114 ('', '\\\\conky\\\\mountpoint\\foo\\bar')) 115 tester('ntpath.splitdrive("//conky//mountpoint/foo/bar")', 116 ('', '//conky//mountpoint/foo/bar')) 117 # Issue #19911: UNC part containing U+0130 118 self.assertEqual(ntpath.splitdrive('//conky/MOUNTPOİNT/foo/bar'), 119 ('//conky/MOUNTPOİNT', '/foo/bar')) 120 121 def test_split(self): 122 tester('ntpath.split("c:\\foo\\bar")', ('c:\\foo', 'bar')) 123 tester('ntpath.split("\\\\conky\\mountpoint\\foo\\bar")', 124 ('\\\\conky\\mountpoint\\foo', 'bar')) 125 126 tester('ntpath.split("c:\\")', ('c:\\', '')) 127 tester('ntpath.split("\\\\conky\\mountpoint\\")', 128 ('\\\\conky\\mountpoint\\', '')) 129 130 tester('ntpath.split("c:/")', ('c:/', '')) 131 tester('ntpath.split("//conky/mountpoint/")', ('//conky/mountpoint/', '')) 132 133 def test_isabs(self): 134 tester('ntpath.isabs("c:\\")', 1) 135 tester('ntpath.isabs("\\\\conky\\mountpoint\\")', 1) 136 tester('ntpath.isabs("\\foo")', 1) 137 tester('ntpath.isabs("\\foo\\bar")', 1) 138 139 def test_commonprefix(self): 140 tester('ntpath.commonprefix(["/home/swenson/spam", "/home/swen/spam"])', 141 "/home/swen") 142 tester('ntpath.commonprefix(["\\home\\swen\\spam", "\\home\\swen\\eggs"])', 143 "\\home\\swen\\") 144 tester('ntpath.commonprefix(["/home/swen/spam", "/home/swen/spam"])', 145 "/home/swen/spam") 146 147 def test_join(self): 148 tester('ntpath.join("")', '') 149 tester('ntpath.join("", "", "")', '') 150 tester('ntpath.join("a")', 'a') 151 tester('ntpath.join("/a")', '/a') 152 tester('ntpath.join("\\a")', '\\a') 153 tester('ntpath.join("a:")', 'a:') 154 tester('ntpath.join("a:", "\\b")', 'a:\\b') 155 tester('ntpath.join("a", "\\b")', '\\b') 156 tester('ntpath.join("a", "b", "c")', 'a\\b\\c') 157 tester('ntpath.join("a\\", "b", "c")', 'a\\b\\c') 158 tester('ntpath.join("a", "b\\", "c")', 'a\\b\\c') 159 tester('ntpath.join("a", "b", "\\c")', '\\c') 160 tester('ntpath.join("d:\\", "\\pleep")', 'd:\\pleep') 161 tester('ntpath.join("d:\\", "a", "b")', 'd:\\a\\b') 162 163 tester("ntpath.join('', 'a')", 'a') 164 tester("ntpath.join('', '', '', '', 'a')", 'a') 165 tester("ntpath.join('a', '')", 'a\\') 166 tester("ntpath.join('a', '', '', '', '')", 'a\\') 167 tester("ntpath.join('a\\', '')", 'a\\') 168 tester("ntpath.join('a\\', '', '', '', '')", 'a\\') 169 tester("ntpath.join('a/', '')", 'a/') 170 171 tester("ntpath.join('a/b', 'x/y')", 'a/b\\x/y') 172 tester("ntpath.join('/a/b', 'x/y')", '/a/b\\x/y') 173 tester("ntpath.join('/a/b/', 'x/y')", '/a/b/x/y') 174 tester("ntpath.join('c:', 'x/y')", 'c:x/y') 175 tester("ntpath.join('c:a/b', 'x/y')", 'c:a/b\\x/y') 176 tester("ntpath.join('c:a/b/', 'x/y')", 'c:a/b/x/y') 177 tester("ntpath.join('c:/', 'x/y')", 'c:/x/y') 178 tester("ntpath.join('c:/a/b', 'x/y')", 'c:/a/b\\x/y') 179 tester("ntpath.join('c:/a/b/', 'x/y')", 'c:/a/b/x/y') 180 tester("ntpath.join('//computer/share', 'x/y')", '//computer/share\\x/y') 181 tester("ntpath.join('//computer/share/', 'x/y')", '//computer/share/x/y') 182 tester("ntpath.join('//computer/share/a/b', 'x/y')", '//computer/share/a/b\\x/y') 183 184 tester("ntpath.join('a/b', '/x/y')", '/x/y') 185 tester("ntpath.join('/a/b', '/x/y')", '/x/y') 186 tester("ntpath.join('c:', '/x/y')", 'c:/x/y') 187 tester("ntpath.join('c:a/b', '/x/y')", 'c:/x/y') 188 tester("ntpath.join('c:/', '/x/y')", 'c:/x/y') 189 tester("ntpath.join('c:/a/b', '/x/y')", 'c:/x/y') 190 tester("ntpath.join('//computer/share', '/x/y')", '//computer/share/x/y') 191 tester("ntpath.join('//computer/share/', '/x/y')", '//computer/share/x/y') 192 tester("ntpath.join('//computer/share/a', '/x/y')", '//computer/share/x/y') 193 194 tester("ntpath.join('c:', 'C:x/y')", 'C:x/y') 195 tester("ntpath.join('c:a/b', 'C:x/y')", 'C:a/b\\x/y') 196 tester("ntpath.join('c:/', 'C:x/y')", 'C:/x/y') 197 tester("ntpath.join('c:/a/b', 'C:x/y')", 'C:/a/b\\x/y') 198 199 for x in ('', 'a/b', '/a/b', 'c:', 'c:a/b', 'c:/', 'c:/a/b', 200 '//computer/share', '//computer/share/', '//computer/share/a/b'): 201 for y in ('d:', 'd:x/y', 'd:/', 'd:/x/y', 202 '//machine/common', '//machine/common/', '//machine/common/x/y'): 203 tester("ntpath.join(%r, %r)" % (x, y), y) 204 205 tester("ntpath.join('\\\\computer\\share\\', 'a', 'b')", '\\\\computer\\share\\a\\b') 206 tester("ntpath.join('\\\\computer\\share', 'a', 'b')", '\\\\computer\\share\\a\\b') 207 tester("ntpath.join('\\\\computer\\share', 'a\\b')", '\\\\computer\\share\\a\\b') 208 tester("ntpath.join('//computer/share/', 'a', 'b')", '//computer/share/a\\b') 209 tester("ntpath.join('//computer/share', 'a', 'b')", '//computer/share\\a\\b') 210 tester("ntpath.join('//computer/share', 'a/b')", '//computer/share\\a/b') 211 212 def test_normpath(self): 213 tester("ntpath.normpath('A//////././//.//B')", r'A\B') 214 tester("ntpath.normpath('A/./B')", r'A\B') 215 tester("ntpath.normpath('A/foo/../B')", r'A\B') 216 tester("ntpath.normpath('C:A//B')", r'C:A\B') 217 tester("ntpath.normpath('D:A/./B')", r'D:A\B') 218 tester("ntpath.normpath('e:A/foo/../B')", r'e:A\B') 219 220 tester("ntpath.normpath('C:///A//B')", r'C:\A\B') 221 tester("ntpath.normpath('D:///A/./B')", r'D:\A\B') 222 tester("ntpath.normpath('e:///A/foo/../B')", r'e:\A\B') 223 224 tester("ntpath.normpath('..')", r'..') 225 tester("ntpath.normpath('.')", r'.') 226 tester("ntpath.normpath('')", r'.') 227 tester("ntpath.normpath('/')", '\\') 228 tester("ntpath.normpath('c:/')", 'c:\\') 229 tester("ntpath.normpath('/../.././..')", '\\') 230 tester("ntpath.normpath('c:/../../..')", 'c:\\') 231 tester("ntpath.normpath('../.././..')", r'..\..\..') 232 tester("ntpath.normpath('K:../.././..')", r'K:..\..\..') 233 tester("ntpath.normpath('C:////a/b')", r'C:\a\b') 234 tester("ntpath.normpath('//machine/share//a/b')", r'\\machine\share\a\b') 235 236 tester("ntpath.normpath('\\\\.\\NUL')", r'\\.\NUL') 237 tester("ntpath.normpath('\\\\?\\D:/XY\\Z')", r'\\?\D:/XY\Z') 238 239 def test_realpath_curdir(self): 240 expected = ntpath.normpath(os.getcwd()) 241 tester("ntpath.realpath('.')", expected) 242 tester("ntpath.realpath('./.')", expected) 243 tester("ntpath.realpath('/'.join(['.'] * 100))", expected) 244 tester("ntpath.realpath('.\\.')", expected) 245 tester("ntpath.realpath('\\'.join(['.'] * 100))", expected) 246 247 def test_realpath_pardir(self): 248 expected = ntpath.normpath(os.getcwd()) 249 tester("ntpath.realpath('..')", ntpath.dirname(expected)) 250 tester("ntpath.realpath('../..')", 251 ntpath.dirname(ntpath.dirname(expected))) 252 tester("ntpath.realpath('/'.join(['..'] * 50))", 253 ntpath.splitdrive(expected)[0] + '\\') 254 tester("ntpath.realpath('..\\..')", 255 ntpath.dirname(ntpath.dirname(expected))) 256 tester("ntpath.realpath('\\'.join(['..'] * 50))", 257 ntpath.splitdrive(expected)[0] + '\\') 258 259 @os_helper.skip_unless_symlink 260 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') 261 def test_realpath_basic(self): 262 ABSTFN = ntpath.abspath(os_helper.TESTFN) 263 open(ABSTFN, "wb").close() 264 self.addCleanup(os_helper.unlink, ABSTFN) 265 self.addCleanup(os_helper.unlink, ABSTFN + "1") 266 267 os.symlink(ABSTFN, ABSTFN + "1") 268 self.assertPathEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN) 269 self.assertPathEqual(ntpath.realpath(os.fsencode(ABSTFN + "1")), 270 os.fsencode(ABSTFN)) 271 272 @os_helper.skip_unless_symlink 273 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') 274 def test_realpath_strict(self): 275 # Bug #43757: raise FileNotFoundError in strict mode if we encounter 276 # a path that does not exist. 277 ABSTFN = ntpath.abspath(os_helper.TESTFN) 278 os.symlink(ABSTFN + "1", ABSTFN) 279 self.addCleanup(os_helper.unlink, ABSTFN) 280 self.assertRaises(FileNotFoundError, ntpath.realpath, ABSTFN, strict=True) 281 self.assertRaises(FileNotFoundError, ntpath.realpath, ABSTFN + "2", strict=True) 282 283 @os_helper.skip_unless_symlink 284 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') 285 def test_realpath_relative(self): 286 ABSTFN = ntpath.abspath(os_helper.TESTFN) 287 open(ABSTFN, "wb").close() 288 self.addCleanup(os_helper.unlink, ABSTFN) 289 self.addCleanup(os_helper.unlink, ABSTFN + "1") 290 291 os.symlink(ABSTFN, ntpath.relpath(ABSTFN + "1")) 292 self.assertPathEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN) 293 294 @os_helper.skip_unless_symlink 295 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') 296 def test_realpath_broken_symlinks(self): 297 ABSTFN = ntpath.abspath(os_helper.TESTFN) 298 os.mkdir(ABSTFN) 299 self.addCleanup(os_helper.rmtree, ABSTFN) 300 301 with os_helper.change_cwd(ABSTFN): 302 os.mkdir("subdir") 303 os.chdir("subdir") 304 os.symlink(".", "recursive") 305 os.symlink("..", "parent") 306 os.chdir("..") 307 os.symlink(".", "self") 308 os.symlink("missing", "broken") 309 os.symlink(r"broken\bar", "broken1") 310 os.symlink(r"self\self\broken", "broken2") 311 os.symlink(r"subdir\parent\subdir\parent\broken", "broken3") 312 os.symlink(ABSTFN + r"\broken", "broken4") 313 os.symlink(r"recursive\..\broken", "broken5") 314 315 self.assertPathEqual(ntpath.realpath("broken"), 316 ABSTFN + r"\missing") 317 self.assertPathEqual(ntpath.realpath(r"broken\foo"), 318 ABSTFN + r"\missing\foo") 319 # bpo-38453: We no longer recursively resolve segments of relative 320 # symlinks that the OS cannot resolve. 321 self.assertPathEqual(ntpath.realpath(r"broken1"), 322 ABSTFN + r"\broken\bar") 323 self.assertPathEqual(ntpath.realpath(r"broken1\baz"), 324 ABSTFN + r"\broken\bar\baz") 325 self.assertPathEqual(ntpath.realpath("broken2"), 326 ABSTFN + r"\self\self\missing") 327 self.assertPathEqual(ntpath.realpath("broken3"), 328 ABSTFN + r"\subdir\parent\subdir\parent\missing") 329 self.assertPathEqual(ntpath.realpath("broken4"), 330 ABSTFN + r"\missing") 331 self.assertPathEqual(ntpath.realpath("broken5"), 332 ABSTFN + r"\missing") 333 334 self.assertPathEqual(ntpath.realpath(b"broken"), 335 os.fsencode(ABSTFN + r"\missing")) 336 self.assertPathEqual(ntpath.realpath(rb"broken\foo"), 337 os.fsencode(ABSTFN + r"\missing\foo")) 338 self.assertPathEqual(ntpath.realpath(rb"broken1"), 339 os.fsencode(ABSTFN + r"\broken\bar")) 340 self.assertPathEqual(ntpath.realpath(rb"broken1\baz"), 341 os.fsencode(ABSTFN + r"\broken\bar\baz")) 342 self.assertPathEqual(ntpath.realpath(b"broken2"), 343 os.fsencode(ABSTFN + r"\self\self\missing")) 344 self.assertPathEqual(ntpath.realpath(rb"broken3"), 345 os.fsencode(ABSTFN + r"\subdir\parent\subdir\parent\missing")) 346 self.assertPathEqual(ntpath.realpath(b"broken4"), 347 os.fsencode(ABSTFN + r"\missing")) 348 self.assertPathEqual(ntpath.realpath(b"broken5"), 349 os.fsencode(ABSTFN + r"\missing")) 350 351 @os_helper.skip_unless_symlink 352 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') 353 def test_realpath_symlink_loops(self): 354 # Symlink loops in non-strict mode are non-deterministic as to which 355 # path is returned, but it will always be the fully resolved path of 356 # one member of the cycle 357 ABSTFN = ntpath.abspath(os_helper.TESTFN) 358 self.addCleanup(os_helper.unlink, ABSTFN) 359 self.addCleanup(os_helper.unlink, ABSTFN + "1") 360 self.addCleanup(os_helper.unlink, ABSTFN + "2") 361 self.addCleanup(os_helper.unlink, ABSTFN + "y") 362 self.addCleanup(os_helper.unlink, ABSTFN + "c") 363 self.addCleanup(os_helper.unlink, ABSTFN + "a") 364 365 os.symlink(ABSTFN, ABSTFN) 366 self.assertPathEqual(ntpath.realpath(ABSTFN), ABSTFN) 367 368 os.symlink(ABSTFN + "1", ABSTFN + "2") 369 os.symlink(ABSTFN + "2", ABSTFN + "1") 370 expected = (ABSTFN + "1", ABSTFN + "2") 371 self.assertPathIn(ntpath.realpath(ABSTFN + "1"), expected) 372 self.assertPathIn(ntpath.realpath(ABSTFN + "2"), expected) 373 374 self.assertPathIn(ntpath.realpath(ABSTFN + "1\\x"), 375 (ntpath.join(r, "x") for r in expected)) 376 self.assertPathEqual(ntpath.realpath(ABSTFN + "1\\.."), 377 ntpath.dirname(ABSTFN)) 378 self.assertPathEqual(ntpath.realpath(ABSTFN + "1\\..\\x"), 379 ntpath.dirname(ABSTFN) + "\\x") 380 os.symlink(ABSTFN + "x", ABSTFN + "y") 381 self.assertPathEqual(ntpath.realpath(ABSTFN + "1\\..\\" 382 + ntpath.basename(ABSTFN) + "y"), 383 ABSTFN + "x") 384 self.assertPathIn(ntpath.realpath(ABSTFN + "1\\..\\" 385 + ntpath.basename(ABSTFN) + "1"), 386 expected) 387 388 os.symlink(ntpath.basename(ABSTFN) + "a\\b", ABSTFN + "a") 389 self.assertPathEqual(ntpath.realpath(ABSTFN + "a"), ABSTFN + "a") 390 391 os.symlink("..\\" + ntpath.basename(ntpath.dirname(ABSTFN)) 392 + "\\" + ntpath.basename(ABSTFN) + "c", ABSTFN + "c") 393 self.assertPathEqual(ntpath.realpath(ABSTFN + "c"), ABSTFN + "c") 394 395 # Test using relative path as well. 396 self.assertPathEqual(ntpath.realpath(ntpath.basename(ABSTFN)), ABSTFN) 397 398 @os_helper.skip_unless_symlink 399 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') 400 def test_realpath_symlink_loops_strict(self): 401 # Symlink loops raise OSError in strict mode 402 ABSTFN = ntpath.abspath(os_helper.TESTFN) 403 self.addCleanup(os_helper.unlink, ABSTFN) 404 self.addCleanup(os_helper.unlink, ABSTFN + "1") 405 self.addCleanup(os_helper.unlink, ABSTFN + "2") 406 self.addCleanup(os_helper.unlink, ABSTFN + "y") 407 self.addCleanup(os_helper.unlink, ABSTFN + "c") 408 self.addCleanup(os_helper.unlink, ABSTFN + "a") 409 410 os.symlink(ABSTFN, ABSTFN) 411 self.assertRaises(OSError, ntpath.realpath, ABSTFN, strict=True) 412 413 os.symlink(ABSTFN + "1", ABSTFN + "2") 414 os.symlink(ABSTFN + "2", ABSTFN + "1") 415 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "1", strict=True) 416 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "2", strict=True) 417 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "1\\x", strict=True) 418 # Windows eliminates '..' components before resolving links, so the 419 # following call is not expected to raise. 420 self.assertPathEqual(ntpath.realpath(ABSTFN + "1\\..", strict=True), 421 ntpath.dirname(ABSTFN)) 422 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "1\\..\\x", strict=True) 423 os.symlink(ABSTFN + "x", ABSTFN + "y") 424 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "1\\..\\" 425 + ntpath.basename(ABSTFN) + "y", 426 strict=True) 427 self.assertRaises(OSError, ntpath.realpath, 428 ABSTFN + "1\\..\\" + ntpath.basename(ABSTFN) + "1", 429 strict=True) 430 431 os.symlink(ntpath.basename(ABSTFN) + "a\\b", ABSTFN + "a") 432 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "a", strict=True) 433 434 os.symlink("..\\" + ntpath.basename(ntpath.dirname(ABSTFN)) 435 + "\\" + ntpath.basename(ABSTFN) + "c", ABSTFN + "c") 436 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "c", strict=True) 437 438 # Test using relative path as well. 439 self.assertRaises(OSError, ntpath.realpath, ntpath.basename(ABSTFN), 440 strict=True) 441 442 @os_helper.skip_unless_symlink 443 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') 444 def test_realpath_symlink_prefix(self): 445 ABSTFN = ntpath.abspath(os_helper.TESTFN) 446 self.addCleanup(os_helper.unlink, ABSTFN + "3") 447 self.addCleanup(os_helper.unlink, "\\\\?\\" + ABSTFN + "3.") 448 self.addCleanup(os_helper.unlink, ABSTFN + "3link") 449 self.addCleanup(os_helper.unlink, ABSTFN + "3.link") 450 451 with open(ABSTFN + "3", "wb") as f: 452 f.write(b'0') 453 os.symlink(ABSTFN + "3", ABSTFN + "3link") 454 455 with open("\\\\?\\" + ABSTFN + "3.", "wb") as f: 456 f.write(b'1') 457 os.symlink("\\\\?\\" + ABSTFN + "3.", ABSTFN + "3.link") 458 459 self.assertPathEqual(ntpath.realpath(ABSTFN + "3link"), 460 ABSTFN + "3") 461 self.assertPathEqual(ntpath.realpath(ABSTFN + "3.link"), 462 "\\\\?\\" + ABSTFN + "3.") 463 464 # Resolved paths should be usable to open target files 465 with open(ntpath.realpath(ABSTFN + "3link"), "rb") as f: 466 self.assertEqual(f.read(), b'0') 467 with open(ntpath.realpath(ABSTFN + "3.link"), "rb") as f: 468 self.assertEqual(f.read(), b'1') 469 470 # When the prefix is included, it is not stripped 471 self.assertPathEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3link"), 472 "\\\\?\\" + ABSTFN + "3") 473 self.assertPathEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3.link"), 474 "\\\\?\\" + ABSTFN + "3.") 475 476 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') 477 def test_realpath_nul(self): 478 tester("ntpath.realpath('NUL')", r'\\.\NUL') 479 480 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') 481 @unittest.skipUnless(HAVE_GETSHORTPATHNAME, 'need _getshortpathname') 482 def test_realpath_cwd(self): 483 ABSTFN = ntpath.abspath(os_helper.TESTFN) 484 485 os_helper.unlink(ABSTFN) 486 os_helper.rmtree(ABSTFN) 487 os.mkdir(ABSTFN) 488 self.addCleanup(os_helper.rmtree, ABSTFN) 489 490 test_dir_long = ntpath.join(ABSTFN, "MyVeryLongDirectoryName") 491 os.mkdir(test_dir_long) 492 493 test_dir_short = _getshortpathname(test_dir_long) 494 test_file_long = ntpath.join(test_dir_long, "file.txt") 495 test_file_short = ntpath.join(test_dir_short, "file.txt") 496 497 with open(test_file_long, "wb") as f: 498 f.write(b"content") 499 500 self.assertPathEqual(test_file_long, ntpath.realpath(test_file_short)) 501 502 with os_helper.change_cwd(test_dir_long): 503 self.assertPathEqual(test_file_long, ntpath.realpath("file.txt")) 504 with os_helper.change_cwd(test_dir_long.lower()): 505 self.assertPathEqual(test_file_long, ntpath.realpath("file.txt")) 506 with os_helper.change_cwd(test_dir_short): 507 self.assertPathEqual(test_file_long, ntpath.realpath("file.txt")) 508 509 def test_expandvars(self): 510 with os_helper.EnvironmentVarGuard() as env: 511 env.clear() 512 env["foo"] = "bar" 513 env["{foo"] = "baz1" 514 env["{foo}"] = "baz2" 515 tester('ntpath.expandvars("foo")', "foo") 516 tester('ntpath.expandvars("$foo bar")', "bar bar") 517 tester('ntpath.expandvars("${foo}bar")', "barbar") 518 tester('ntpath.expandvars("$[foo]bar")', "$[foo]bar") 519 tester('ntpath.expandvars("$bar bar")', "$bar bar") 520 tester('ntpath.expandvars("$?bar")', "$?bar") 521 tester('ntpath.expandvars("$foo}bar")', "bar}bar") 522 tester('ntpath.expandvars("${foo")', "${foo") 523 tester('ntpath.expandvars("${{foo}}")', "baz1}") 524 tester('ntpath.expandvars("$foo$foo")', "barbar") 525 tester('ntpath.expandvars("$bar$bar")', "$bar$bar") 526 tester('ntpath.expandvars("%foo% bar")', "bar bar") 527 tester('ntpath.expandvars("%foo%bar")', "barbar") 528 tester('ntpath.expandvars("%foo%%foo%")', "barbar") 529 tester('ntpath.expandvars("%%foo%%foo%foo%")', "%foo%foobar") 530 tester('ntpath.expandvars("%?bar%")', "%?bar%") 531 tester('ntpath.expandvars("%foo%%bar")', "bar%bar") 532 tester('ntpath.expandvars("\'%foo%\'%bar")', "\'%foo%\'%bar") 533 tester('ntpath.expandvars("bar\'%foo%")', "bar\'%foo%") 534 535 @unittest.skipUnless(os_helper.FS_NONASCII, 'need os_helper.FS_NONASCII') 536 def test_expandvars_nonascii(self): 537 def check(value, expected): 538 tester('ntpath.expandvars(%r)' % value, expected) 539 with os_helper.EnvironmentVarGuard() as env: 540 env.clear() 541 nonascii = os_helper.FS_NONASCII 542 env['spam'] = nonascii 543 env[nonascii] = 'ham' + nonascii 544 check('$spam bar', '%s bar' % nonascii) 545 check('$%s bar' % nonascii, '$%s bar' % nonascii) 546 check('${spam}bar', '%sbar' % nonascii) 547 check('${%s}bar' % nonascii, 'ham%sbar' % nonascii) 548 check('$spam}bar', '%s}bar' % nonascii) 549 check('$%s}bar' % nonascii, '$%s}bar' % nonascii) 550 check('%spam% bar', '%s bar' % nonascii) 551 check('%{}% bar'.format(nonascii), 'ham%s bar' % nonascii) 552 check('%spam%bar', '%sbar' % nonascii) 553 check('%{}%bar'.format(nonascii), 'ham%sbar' % nonascii) 554 555 def test_expanduser(self): 556 tester('ntpath.expanduser("test")', 'test') 557 558 with os_helper.EnvironmentVarGuard() as env: 559 env.clear() 560 tester('ntpath.expanduser("~test")', '~test') 561 562 env['HOMEDRIVE'] = 'C:\\' 563 env['HOMEPATH'] = 'Users\\eric' 564 env['USERNAME'] = 'eric' 565 tester('ntpath.expanduser("~test")', 'C:\\Users\\test') 566 tester('ntpath.expanduser("~")', 'C:\\Users\\eric') 567 568 del env['HOMEDRIVE'] 569 tester('ntpath.expanduser("~test")', 'Users\\test') 570 tester('ntpath.expanduser("~")', 'Users\\eric') 571 572 env.clear() 573 env['USERPROFILE'] = 'C:\\Users\\eric' 574 env['USERNAME'] = 'eric' 575 tester('ntpath.expanduser("~test")', 'C:\\Users\\test') 576 tester('ntpath.expanduser("~")', 'C:\\Users\\eric') 577 tester('ntpath.expanduser("~test\\foo\\bar")', 578 'C:\\Users\\test\\foo\\bar') 579 tester('ntpath.expanduser("~test/foo/bar")', 580 'C:\\Users\\test/foo/bar') 581 tester('ntpath.expanduser("~\\foo\\bar")', 582 'C:\\Users\\eric\\foo\\bar') 583 tester('ntpath.expanduser("~/foo/bar")', 584 'C:\\Users\\eric/foo/bar') 585 586 # bpo-36264: ignore `HOME` when set on windows 587 env.clear() 588 env['HOME'] = 'F:\\' 589 env['USERPROFILE'] = 'C:\\Users\\eric' 590 env['USERNAME'] = 'eric' 591 tester('ntpath.expanduser("~test")', 'C:\\Users\\test') 592 tester('ntpath.expanduser("~")', 'C:\\Users\\eric') 593 594 # bpo-39899: don't guess another user's home directory if 595 # `%USERNAME% != basename(%USERPROFILE%)` 596 env.clear() 597 env['USERPROFILE'] = 'C:\\Users\\eric' 598 env['USERNAME'] = 'idle' 599 tester('ntpath.expanduser("~test")', '~test') 600 tester('ntpath.expanduser("~")', 'C:\\Users\\eric') 601 602 603 604 @unittest.skipUnless(nt, "abspath requires 'nt' module") 605 def test_abspath(self): 606 tester('ntpath.abspath("C:\\")', "C:\\") 607 with os_helper.temp_cwd(os_helper.TESTFN) as cwd_dir: # bpo-31047 608 tester('ntpath.abspath("")', cwd_dir) 609 tester('ntpath.abspath(" ")', cwd_dir + "\\ ") 610 tester('ntpath.abspath("?")', cwd_dir + "\\?") 611 drive, _ = ntpath.splitdrive(cwd_dir) 612 tester('ntpath.abspath("/abc/")', drive + "\\abc") 613 614 def test_relpath(self): 615 tester('ntpath.relpath("a")', 'a') 616 tester('ntpath.relpath(ntpath.abspath("a"))', 'a') 617 tester('ntpath.relpath("a/b")', 'a\\b') 618 tester('ntpath.relpath("../a/b")', '..\\a\\b') 619 with os_helper.temp_cwd(os_helper.TESTFN) as cwd_dir: 620 currentdir = ntpath.basename(cwd_dir) 621 tester('ntpath.relpath("a", "../b")', '..\\'+currentdir+'\\a') 622 tester('ntpath.relpath("a/b", "../c")', '..\\'+currentdir+'\\a\\b') 623 tester('ntpath.relpath("a", "b/c")', '..\\..\\a') 624 tester('ntpath.relpath("c:/foo/bar/bat", "c:/x/y")', '..\\..\\foo\\bar\\bat') 625 tester('ntpath.relpath("//conky/mountpoint/a", "//conky/mountpoint/b/c")', '..\\..\\a') 626 tester('ntpath.relpath("a", "a")', '.') 627 tester('ntpath.relpath("/foo/bar/bat", "/x/y/z")', '..\\..\\..\\foo\\bar\\bat') 628 tester('ntpath.relpath("/foo/bar/bat", "/foo/bar")', 'bat') 629 tester('ntpath.relpath("/foo/bar/bat", "/")', 'foo\\bar\\bat') 630 tester('ntpath.relpath("/", "/foo/bar/bat")', '..\\..\\..') 631 tester('ntpath.relpath("/foo/bar/bat", "/x")', '..\\foo\\bar\\bat') 632 tester('ntpath.relpath("/x", "/foo/bar/bat")', '..\\..\\..\\x') 633 tester('ntpath.relpath("/", "/")', '.') 634 tester('ntpath.relpath("/a", "/a")', '.') 635 tester('ntpath.relpath("/a/b", "/a/b")', '.') 636 tester('ntpath.relpath("c:/foo", "C:/FOO")', '.') 637 638 def test_commonpath(self): 639 def check(paths, expected): 640 tester(('ntpath.commonpath(%r)' % paths).replace('\\\\', '\\'), 641 expected) 642 def check_error(exc, paths): 643 self.assertRaises(exc, ntpath.commonpath, paths) 644 self.assertRaises(exc, ntpath.commonpath, 645 [os.fsencode(p) for p in paths]) 646 647 self.assertRaises(ValueError, ntpath.commonpath, []) 648 check_error(ValueError, ['C:\\Program Files', 'Program Files']) 649 check_error(ValueError, ['C:\\Program Files', 'C:Program Files']) 650 check_error(ValueError, ['\\Program Files', 'Program Files']) 651 check_error(ValueError, ['Program Files', 'C:\\Program Files']) 652 check(['C:\\Program Files'], 'C:\\Program Files') 653 check(['C:\\Program Files', 'C:\\Program Files'], 'C:\\Program Files') 654 check(['C:\\Program Files\\', 'C:\\Program Files'], 655 'C:\\Program Files') 656 check(['C:\\Program Files\\', 'C:\\Program Files\\'], 657 'C:\\Program Files') 658 check(['C:\\\\Program Files', 'C:\\Program Files\\\\'], 659 'C:\\Program Files') 660 check(['C:\\.\\Program Files', 'C:\\Program Files\\.'], 661 'C:\\Program Files') 662 check(['C:\\', 'C:\\bin'], 'C:\\') 663 check(['C:\\Program Files', 'C:\\bin'], 'C:\\') 664 check(['C:\\Program Files', 'C:\\Program Files\\Bar'], 665 'C:\\Program Files') 666 check(['C:\\Program Files\\Foo', 'C:\\Program Files\\Bar'], 667 'C:\\Program Files') 668 check(['C:\\Program Files', 'C:\\Projects'], 'C:\\') 669 check(['C:\\Program Files\\', 'C:\\Projects'], 'C:\\') 670 671 check(['C:\\Program Files\\Foo', 'C:/Program Files/Bar'], 672 'C:\\Program Files') 673 check(['C:\\Program Files\\Foo', 'c:/program files/bar'], 674 'C:\\Program Files') 675 check(['c:/program files/bar', 'C:\\Program Files\\Foo'], 676 'c:\\program files') 677 678 check_error(ValueError, ['C:\\Program Files', 'D:\\Program Files']) 679 680 check(['spam'], 'spam') 681 check(['spam', 'spam'], 'spam') 682 check(['spam', 'alot'], '') 683 check(['and\\jam', 'and\\spam'], 'and') 684 check(['and\\\\jam', 'and\\spam\\\\'], 'and') 685 check(['and\\.\\jam', '.\\and\\spam'], 'and') 686 check(['and\\jam', 'and\\spam', 'alot'], '') 687 check(['and\\jam', 'and\\spam', 'and'], 'and') 688 check(['C:and\\jam', 'C:and\\spam'], 'C:and') 689 690 check([''], '') 691 check(['', 'spam\\alot'], '') 692 check_error(ValueError, ['', '\\spam\\alot']) 693 694 self.assertRaises(TypeError, ntpath.commonpath, 695 [b'C:\\Program Files', 'C:\\Program Files\\Foo']) 696 self.assertRaises(TypeError, ntpath.commonpath, 697 [b'C:\\Program Files', 'Program Files\\Foo']) 698 self.assertRaises(TypeError, ntpath.commonpath, 699 [b'Program Files', 'C:\\Program Files\\Foo']) 700 self.assertRaises(TypeError, ntpath.commonpath, 701 ['C:\\Program Files', b'C:\\Program Files\\Foo']) 702 self.assertRaises(TypeError, ntpath.commonpath, 703 ['C:\\Program Files', b'Program Files\\Foo']) 704 self.assertRaises(TypeError, ntpath.commonpath, 705 ['Program Files', b'C:\\Program Files\\Foo']) 706 707 def test_sameopenfile(self): 708 with TemporaryFile() as tf1, TemporaryFile() as tf2: 709 # Make sure the same file is really the same 710 self.assertTrue(ntpath.sameopenfile(tf1.fileno(), tf1.fileno())) 711 # Make sure different files are really different 712 self.assertFalse(ntpath.sameopenfile(tf1.fileno(), tf2.fileno())) 713 # Make sure invalid values don't cause issues on win32 714 if sys.platform == "win32": 715 with self.assertRaises(OSError): 716 # Invalid file descriptors shouldn't display assert 717 # dialogs (#4804) 718 ntpath.sameopenfile(-1, -1) 719 720 def test_ismount(self): 721 self.assertTrue(ntpath.ismount("c:\\")) 722 self.assertTrue(ntpath.ismount("C:\\")) 723 self.assertTrue(ntpath.ismount("c:/")) 724 self.assertTrue(ntpath.ismount("C:/")) 725 self.assertTrue(ntpath.ismount("\\\\.\\c:\\")) 726 self.assertTrue(ntpath.ismount("\\\\.\\C:\\")) 727 728 self.assertTrue(ntpath.ismount(b"c:\\")) 729 self.assertTrue(ntpath.ismount(b"C:\\")) 730 self.assertTrue(ntpath.ismount(b"c:/")) 731 self.assertTrue(ntpath.ismount(b"C:/")) 732 self.assertTrue(ntpath.ismount(b"\\\\.\\c:\\")) 733 self.assertTrue(ntpath.ismount(b"\\\\.\\C:\\")) 734 735 with os_helper.temp_dir() as d: 736 self.assertFalse(ntpath.ismount(d)) 737 738 if sys.platform == "win32": 739 # 740 # Make sure the current folder isn't the root folder 741 # (or any other volume root). The drive-relative 742 # locations below cannot then refer to mount points 743 # 744 drive, path = ntpath.splitdrive(sys.executable) 745 with os_helper.change_cwd(ntpath.dirname(sys.executable)): 746 self.assertFalse(ntpath.ismount(drive.lower())) 747 self.assertFalse(ntpath.ismount(drive.upper())) 748 749 self.assertTrue(ntpath.ismount("\\\\localhost\\c$")) 750 self.assertTrue(ntpath.ismount("\\\\localhost\\c$\\")) 751 752 self.assertTrue(ntpath.ismount(b"\\\\localhost\\c$")) 753 self.assertTrue(ntpath.ismount(b"\\\\localhost\\c$\\")) 754 755 def assertEqualCI(self, s1, s2): 756 """Assert that two strings are equal ignoring case differences.""" 757 self.assertEqual(s1.lower(), s2.lower()) 758 759 @unittest.skipUnless(nt, "OS helpers require 'nt' module") 760 def test_nt_helpers(self): 761 # Trivial validation that the helpers do not break, and support both 762 # unicode and bytes (UTF-8) paths 763 764 executable = nt._getfinalpathname(sys.executable) 765 766 for path in executable, os.fsencode(executable): 767 volume_path = nt._getvolumepathname(path) 768 path_drive = ntpath.splitdrive(path)[0] 769 volume_path_drive = ntpath.splitdrive(volume_path)[0] 770 self.assertEqualCI(path_drive, volume_path_drive) 771 772 cap, free = nt._getdiskusage(sys.exec_prefix) 773 self.assertGreater(cap, 0) 774 self.assertGreater(free, 0) 775 b_cap, b_free = nt._getdiskusage(sys.exec_prefix.encode()) 776 # Free space may change, so only test the capacity is equal 777 self.assertEqual(b_cap, cap) 778 self.assertGreater(b_free, 0) 779 780 for path in [sys.prefix, sys.executable]: 781 final_path = nt._getfinalpathname(path) 782 self.assertIsInstance(final_path, str) 783 self.assertGreater(len(final_path), 0) 784 785 b_final_path = nt._getfinalpathname(path.encode()) 786 self.assertIsInstance(b_final_path, bytes) 787 self.assertGreater(len(b_final_path), 0) 788 789class NtCommonTest(test_genericpath.CommonTest, unittest.TestCase): 790 pathmodule = ntpath 791 attributes = ['relpath'] 792 793 794class PathLikeTests(NtpathTestCase): 795 796 path = ntpath 797 798 def setUp(self): 799 self.file_name = os_helper.TESTFN 800 self.file_path = FakePath(os_helper.TESTFN) 801 self.addCleanup(os_helper.unlink, self.file_name) 802 with open(self.file_name, 'xb', 0) as file: 803 file.write(b"test_ntpath.PathLikeTests") 804 805 def _check_function(self, func): 806 self.assertPathEqual(func(self.file_path), func(self.file_name)) 807 808 def test_path_normcase(self): 809 self._check_function(self.path.normcase) 810 811 def test_path_isabs(self): 812 self._check_function(self.path.isabs) 813 814 def test_path_join(self): 815 self.assertEqual(self.path.join('a', FakePath('b'), 'c'), 816 self.path.join('a', 'b', 'c')) 817 818 def test_path_split(self): 819 self._check_function(self.path.split) 820 821 def test_path_splitext(self): 822 self._check_function(self.path.splitext) 823 824 def test_path_splitdrive(self): 825 self._check_function(self.path.splitdrive) 826 827 def test_path_basename(self): 828 self._check_function(self.path.basename) 829 830 def test_path_dirname(self): 831 self._check_function(self.path.dirname) 832 833 def test_path_islink(self): 834 self._check_function(self.path.islink) 835 836 def test_path_lexists(self): 837 self._check_function(self.path.lexists) 838 839 def test_path_ismount(self): 840 self._check_function(self.path.ismount) 841 842 def test_path_expanduser(self): 843 self._check_function(self.path.expanduser) 844 845 def test_path_expandvars(self): 846 self._check_function(self.path.expandvars) 847 848 def test_path_normpath(self): 849 self._check_function(self.path.normpath) 850 851 def test_path_abspath(self): 852 self._check_function(self.path.abspath) 853 854 def test_path_realpath(self): 855 self._check_function(self.path.realpath) 856 857 def test_path_relpath(self): 858 self._check_function(self.path.relpath) 859 860 def test_path_commonpath(self): 861 common_path = self.path.commonpath([self.file_path, self.file_name]) 862 self.assertPathEqual(common_path, self.file_name) 863 864 def test_path_isdir(self): 865 self._check_function(self.path.isdir) 866 867 868if __name__ == "__main__": 869 unittest.main() 870