|
7 | 7 | from test import support, test_genericpath
|
8 | 8 | from tempfile import TemporaryFile
|
9 | 9 |
|
| 10 | + |
10 | 11 | try:
|
11 | 12 | import nt
|
12 | 13 | except ImportError:
|
13 | 14 | # Most tests can complete without the nt module,
|
14 | 15 | # but for those that require it we import here.
|
15 | 16 | nt = None
|
16 | 17 |
|
| 18 | +try: |
| 19 | + ntpath._getfinalpathname |
| 20 | +except AttributeError: |
| 21 | + HAVE_GETFINALPATHNAME = False |
| 22 | +else: |
| 23 | + HAVE_GETFINALPATHNAME = True |
| 24 | + |
| 25 | + |
17 | 26 | def tester(fn, wantResult):
|
18 | 27 | fn = fn.replace("\\", "\\\\")
|
19 | 28 | gotResult = eval(fn)
|
@@ -194,6 +203,189 @@ def test_normpath(self):
|
194 | 203 | tester("ntpath.normpath('\\\\.\\NUL')", r'\\.\NUL')
|
195 | 204 | tester("ntpath.normpath('\\\\?\\D:/XY\\Z')", r'\\?\D:/XY\Z')
|
196 | 205 |
|
| 206 | + def test_realpath_curdir(self): |
| 207 | + expected = ntpath.normpath(os.getcwd()) |
| 208 | + tester("ntpath.realpath('.')", expected) |
| 209 | + tester("ntpath.realpath('./.')", expected) |
| 210 | + tester("ntpath.realpath('/'.join(['.'] * 100))", expected) |
| 211 | + tester("ntpath.realpath('.\\.')", expected) |
| 212 | + tester("ntpath.realpath('\\'.join(['.'] * 100))", expected) |
| 213 | + |
| 214 | + def test_realpath_pardir(self): |
| 215 | + expected = ntpath.normpath(os.getcwd()) |
| 216 | + tester("ntpath.realpath('..')", ntpath.dirname(expected)) |
| 217 | + tester("ntpath.realpath('../..')", |
| 218 | + ntpath.dirname(ntpath.dirname(expected))) |
| 219 | + tester("ntpath.realpath('/'.join(['..'] * 50))", |
| 220 | + ntpath.splitdrive(expected)[0] + '\\') |
| 221 | + tester("ntpath.realpath('..\\..')", |
| 222 | + ntpath.dirname(ntpath.dirname(expected))) |
| 223 | + tester("ntpath.realpath('\\'.join(['..'] * 50))", |
| 224 | + ntpath.splitdrive(expected)[0] + '\\') |
| 225 | + |
| 226 | + @support.skip_unless_symlink |
| 227 | + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') |
| 228 | + def test_realpath_basic(self): |
| 229 | + ABSTFN = ntpath.abspath(support.TESTFN) |
| 230 | + open(ABSTFN, "wb").close() |
| 231 | + self.addCleanup(support.unlink, ABSTFN) |
| 232 | + self.addCleanup(support.unlink, ABSTFN + "1") |
| 233 | + |
| 234 | + os.symlink(ABSTFN, ABSTFN + "1") |
| 235 | + self.assertEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN) |
| 236 | + self.assertEqual(ntpath.realpath(os.fsencode(ABSTFN + "1")), |
| 237 | + os.fsencode(ABSTFN)) |
| 238 | + |
| 239 | + @support.skip_unless_symlink |
| 240 | + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') |
| 241 | + def test_realpath_relative(self): |
| 242 | + ABSTFN = ntpath.abspath(support.TESTFN) |
| 243 | + open(ABSTFN, "wb").close() |
| 244 | + self.addCleanup(support.unlink, ABSTFN) |
| 245 | + self.addCleanup(support.unlink, ABSTFN + "1") |
| 246 | + |
| 247 | + os.symlink(ABSTFN, ntpath.relpath(ABSTFN + "1")) |
| 248 | + self.assertEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN) |
| 249 | + |
| 250 | + @support.skip_unless_symlink |
| 251 | + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') |
| 252 | + def test_realpath_broken_symlinks(self): |
| 253 | + ABSTFN = ntpath.abspath(support.TESTFN) |
| 254 | + os.mkdir(ABSTFN) |
| 255 | + self.addCleanup(support.rmtree, ABSTFN) |
| 256 | + |
| 257 | + with support.change_cwd(ABSTFN): |
| 258 | + os.mkdir("subdir") |
| 259 | + os.chdir("subdir") |
| 260 | + os.symlink(".", "recursive") |
| 261 | + os.symlink("..", "parent") |
| 262 | + os.chdir("..") |
| 263 | + os.symlink(".", "self") |
| 264 | + os.symlink("missing", "broken") |
| 265 | + os.symlink(r"broken\bar", "broken1") |
| 266 | + os.symlink(r"self\self\broken", "broken2") |
| 267 | + os.symlink(r"subdir\parent\subdir\parent\broken", "broken3") |
| 268 | + os.symlink(ABSTFN + r"\broken", "broken4") |
| 269 | + os.symlink(r"recursive\..\broken", "broken5") |
| 270 | + |
| 271 | + self.assertEqual(ntpath.realpath("broken"), |
| 272 | + ABSTFN + r"\missing") |
| 273 | + self.assertEqual(ntpath.realpath(r"broken\foo"), |
| 274 | + ABSTFN + r"\missing\foo") |
| 275 | + self.assertEqual(ntpath.realpath(r"broken1"), |
| 276 | + ABSTFN + r"\missing\bar") |
| 277 | + self.assertEqual(ntpath.realpath(r"broken1\baz"), |
| 278 | + ABSTFN + r"\missing\bar\baz") |
| 279 | + self.assertEqual(ntpath.realpath("broken2"), |
| 280 | + ABSTFN + r"\missing") |
| 281 | + self.assertEqual(ntpath.realpath("broken3"), |
| 282 | + ABSTFN + r"\missing") |
| 283 | + self.assertEqual(ntpath.realpath("broken4"), |
| 284 | + ABSTFN + r"\missing") |
| 285 | + self.assertEqual(ntpath.realpath("broken5"), |
| 286 | + ABSTFN + r"\missing") |
| 287 | + |
| 288 | + self.assertEqual(ntpath.realpath(b"broken"), |
| 289 | + os.fsencode(ABSTFN + r"\missing")) |
| 290 | + self.assertEqual(ntpath.realpath(rb"broken\foo"), |
| 291 | + os.fsencode(ABSTFN + r"\missing\foo")) |
| 292 | + self.assertEqual(ntpath.realpath(rb"broken1"), |
| 293 | + os.fsencode(ABSTFN + r"\missing\bar")) |
| 294 | + self.assertEqual(ntpath.realpath(rb"broken1\baz"), |
| 295 | + os.fsencode(ABSTFN + r"\missing\bar\baz")) |
| 296 | + self.assertEqual(ntpath.realpath(b"broken2"), |
| 297 | + os.fsencode(ABSTFN + r"\missing")) |
| 298 | + self.assertEqual(ntpath.realpath(rb"broken3"), |
| 299 | + os.fsencode(ABSTFN + r"\missing")) |
| 300 | + self.assertEqual(ntpath.realpath(b"broken4"), |
| 301 | + os.fsencode(ABSTFN + r"\missing")) |
| 302 | + self.assertEqual(ntpath.realpath(b"broken5"), |
| 303 | + os.fsencode(ABSTFN + r"\missing")) |
| 304 | + |
| 305 | + @support.skip_unless_symlink |
| 306 | + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') |
| 307 | + def test_realpath_symlink_loops(self): |
| 308 | + # Bug #930024, return the path unchanged if we get into an infinite |
| 309 | + # symlink loop. |
| 310 | + ABSTFN = ntpath.abspath(support.TESTFN) |
| 311 | + self.addCleanup(support.unlink, ABSTFN) |
| 312 | + self.addCleanup(support.unlink, ABSTFN + "1") |
| 313 | + self.addCleanup(support.unlink, ABSTFN + "2") |
| 314 | + self.addCleanup(support.unlink, ABSTFN + "y") |
| 315 | + self.addCleanup(support.unlink, ABSTFN + "c") |
| 316 | + self.addCleanup(support.unlink, ABSTFN + "a") |
| 317 | + |
| 318 | + P = "\\\\?\\" |
| 319 | + |
| 320 | + os.symlink(ABSTFN, ABSTFN) |
| 321 | + self.assertEqual(ntpath.realpath(ABSTFN), P + ABSTFN) |
| 322 | + |
| 323 | + # cycles are non-deterministic as to which path is returned, but |
| 324 | + # it will always be the fully resolved path of one member of the cycle |
| 325 | + os.symlink(ABSTFN + "1", ABSTFN + "2") |
| 326 | + os.symlink(ABSTFN + "2", ABSTFN + "1") |
| 327 | + expected = (P + ABSTFN + "1", P + ABSTFN + "2") |
| 328 | + self.assertIn(ntpath.realpath(ABSTFN + "1"), expected) |
| 329 | + self.assertIn(ntpath.realpath(ABSTFN + "2"), expected) |
| 330 | + |
| 331 | + self.assertIn(ntpath.realpath(ABSTFN + "1\\x"), |
| 332 | + (ntpath.join(r, "x") for r in expected)) |
| 333 | + self.assertEqual(ntpath.realpath(ABSTFN + "1\\.."), |
| 334 | + ntpath.dirname(ABSTFN)) |
| 335 | + self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\x"), |
| 336 | + ntpath.dirname(P + ABSTFN) + "\\x") |
| 337 | + os.symlink(ABSTFN + "x", ABSTFN + "y") |
| 338 | + self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\" |
| 339 | + + ntpath.basename(ABSTFN) + "y"), |
| 340 | + P + ABSTFN + "x") |
| 341 | + self.assertIn(ntpath.realpath(ABSTFN + "1\\..\\" |
| 342 | + + ntpath.basename(ABSTFN) + "1"), |
| 343 | + expected) |
| 344 | + |
| 345 | + os.symlink(ntpath.basename(ABSTFN) + "a\\b", ABSTFN + "a") |
| 346 | + self.assertEqual(ntpath.realpath(ABSTFN + "a"), P + ABSTFN + "a") |
| 347 | + |
| 348 | + os.symlink("..\\" + ntpath.basename(ntpath.dirname(ABSTFN)) |
| 349 | + + "\\" + ntpath.basename(ABSTFN) + "c", ABSTFN + "c") |
| 350 | + self.assertEqual(ntpath.realpath(ABSTFN + "c"), P + ABSTFN + "c") |
| 351 | + |
| 352 | + # Test using relative path as well. |
| 353 | + self.assertEqual(ntpath.realpath(ntpath.basename(ABSTFN)), P + ABSTFN) |
| 354 | + |
| 355 | + @support.skip_unless_symlink |
| 356 | + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') |
| 357 | + def test_realpath_symlink_prefix(self): |
| 358 | + ABSTFN = ntpath.abspath(support.TESTFN) |
| 359 | + self.addCleanup(support.unlink, ABSTFN + "3") |
| 360 | + self.addCleanup(support.unlink, "\\\\?\\" + ABSTFN + "3.") |
| 361 | + self.addCleanup(support.unlink, ABSTFN + "3link") |
| 362 | + self.addCleanup(support.unlink, ABSTFN + "3.link") |
| 363 | + |
| 364 | + with open(ABSTFN + "3", "wb") as f: |
| 365 | + f.write(b'0') |
| 366 | + os.symlink(ABSTFN + "3&
10000
quot;, ABSTFN + "3link") |
| 367 | + |
| 368 | + with open("\\\\?\\" + ABSTFN + "3.", "wb") as f: |
| 369 | + f.write(b'1') |
| 370 | + os.symlink("\\\\?\\" + ABSTFN + "3.", ABSTFN + "3.link") |
| 371 | + |
| 372 | + self.assertEqual(ntpath.realpath(ABSTFN + "3link"), |
| 373 | + ABSTFN + "3") |
| 374 | + self.assertEqual(ntpath.realpath(ABSTFN + "3.link"), |
| 375 | + "\\\\?\\" + ABSTFN + "3.") |
| 376 | + |
| 377 | + # Resolved paths should be usable to open target files |
| 378 | + with open(ntpath.realpath(ABSTFN + "3link"), "rb") as f: |
| 379 | + self.assertEqual(f.read(), b'0') |
| 380 | + with open(ntpath.realpath(ABSTFN + "3.link"), "rb") as f: |
| 381 | + self.assertEqual(f.read(), b'1') |
| 382 | + |
| 383 | + # When the prefix is included, it is not stripped |
| 384 | + self.assertEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3link"), |
| 385 | + "\\\\?\\" + ABSTFN + "3") |
| 386 | + self.assertEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3.link"), |
| 387 | + "\\\\?\\" + ABSTFN + "3.") |
| 388 | + |
197 | 389 | def test_expandvars(self):
|
198 | 390 | with support.EnvironmentVarGuard() as env:
|
199 | 391 | env.clear()
|
@@ -288,11 +480,11 @@ def test_abspath(self):
|
288 | 480 |
|
289 | 481 | def test_relpath(self):
|
290 | 482 | tester('ntpath.relpath("a")', 'a')
|
291 |
| - tester('ntpath.relpath(os.path.abspath("a"))', 'a') |
| 483 | + tester('ntpath.relpath(ntpath.abspath("a"))', 'a') |
292 | 484 | tester('ntpath.relpath("a/b")', 'a\\b')
|
293 | 485 | tester('ntpath.relpath("../a/b")', '..\\a\\b')
|
294 | 486 | with support.temp_cwd(support.TESTFN) as cwd_dir:
|
295 |
| - currentdir = os.path.basename(cwd_dir) |
| 487 | + currentdir = ntpath.basename(cwd_dir) |
296 | 488 | tester('ntpath.relpath("a", "../b")', '..\\'+currentdir+'\\a')
|
297 | 489 | tester('ntpath.relpath("a/b", "../c")', '..\\'+currentdir+'\\a\\b')
|
298 | 490 | tester('ntpath.relpath("a", "b/c")', '..\\..\\a')
|
@@ -417,7 +609,7 @@ def test_ismount(self):
|
417 | 609 | # locations below cannot then refer to mount points
|
418 | 610 | #
|
419 | 611 | drive, path = ntpath.splitdrive(sys.executable)
|
420 |
| - with support.change_cwd(os.path.dirname(sys.executable)): |
| 612 | + with support.change_cwd(ntpath.dirname(sys.executable)): |
421 | 613 | self.assertFalse(ntpath.ismount(drive.lower()))
|
422 | 614 | self.assertFalse(ntpath.ismount(drive.upper()))
|
423 | 615 |
|
|
0 commit comments