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