@@ -269,6 +269,17 @@ def test_realpath_basic(self):
269
269
self .assertPathEqual (ntpath .realpath (os .fsencode (ABSTFN + "1" )),
270
270
os .fsencode (ABSTFN ))
271
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
+
272
283
@os_helper .skip_unless_symlink
273
284
@unittest .skipUnless (HAVE_GETFINALPATHNAME , 'need _getfinalpathname' )
274
285
def test_realpath_relative (self ):
@@ -343,8 +354,9 @@ def test_realpath_broken_symlinks(self):
343
354
@os_helper .skip_unless_symlink
344
355
@unittest .skipUnless (HAVE_GETFINALPATHNAME , 'need _getfinalpathname' )
345
356
def test_realpath_symlink_loops (self ):
346
- # Symlink loops are non-deterministic as to which path is returned, but
347
- # it will always be the fully resolved path of one member of the cycle
357
+ # Symlink loops in non-strict mode are non-deterministic as to which
358
+ # path is returned, but it will always be the fully resolved path of
359
+ # one member of the cycle
348
360
ABSTFN = ntpath .abspath (os_helper .TESTFN )
349
361
self .addCleanup (os_helper .unlink , ABSTFN )
350
362
self .addCleanup (os_helper .unlink , ABSTFN + "1" )
@@ -386,6 +398,50 @@ def test_realpath_symlink_loops(self):
386
398
# Test using relative path as well.
387
399
self .assertPathEqual (ntpath .realpath (ntpath .basename (ABSTFN )), ABSTFN )
388
400
401
+ @os_helper .skip_unless_symlink
402
+ @unittest .skipUnless (HAVE_GETFINALPATHNAME , 'need _getfinalpathname' )
403
+ def test_realpath_symlink_loops_strict (self ):
404
+ # Symlink loops raise OSError in strict mode
405
+ ABSTFN = ntpath .abspath (os_helper .TESTFN )
406
+ self .addCleanup (os_helper .unlink , ABSTFN )
407
+ self .addCleanup (os_helper .unlink , ABSTFN + "1" )
408
+ self .addCleanup (os_helper .unlink , ABSTFN + "2" )
409
+ self .addCleanup (os_helper .unlink , ABSTFN + "y" )
410
+ self .addCleanup (os_helper .unlink , ABSTFN + "c" )
411
+ self .addCleanup (os_helper .unlink , ABSTFN + "a" )
412
+
413
+ os .symlink (ABSTFN , ABSTFN )
414
+ self .assertRaises (OSError , ntpath .realpath , ABSTFN , strict = True )
415
+
416
+ os .symlink (ABSTFN + "1" , ABSTFN + "2" )
417
+ os .symlink (ABSTFN + "2" , ABSTFN + "1" )
418
+ self .assertRaises (OSError , ntpath .realpath , ABSTFN + "1" , strict = True )
419
+ self .assertRaises (OSError , ntpath .realpath , ABSTFN + "2" , strict = True )
420
+ self .assertRaises (OSError , ntpath .realpath , ABSTFN + "1\\ x" , strict = True )
421
+ # Windows eliminates '..' components before resolving links, so the
422
+ # following call is not expected to raise.
423
+ self .assertPathEqual (ntpath .realpath (ABSTFN + "1\\ .." , strict = True ),
424
+ ntpath .dirname (ABSTFN ))
425
+ self .assertRaises (OSError , ntpath .realpath , ABSTFN + "1\\ ..\\ x" , strict = True )
426
+ os .symlink (ABSTFN + "x" , ABSTFN + "y" )
427
+ self .assertRaises (OSError , ntpath .realpath , ABSTFN + "1\\ ..\\ "
428
+ + ntpath .basename (ABSTFN ) + "y" ,
429
+ strict = True )
430
+ self .assertRaises (OSError , ntpath .realpath ,
431
+ ABSTFN + "1\\ ..\\ " + ntpath .basename (ABSTFN ) + "1" ,
432
+ strict = True )
433
+
434
+ os .symlink (ntpath .basename (ABSTFN ) + "a\\ b" , ABSTFN + "a" )
435
+ self .assertRaises (OSError , ntpath .realpath , ABSTFN + "a" , strict = True )
436
+
437
+ os .symlink ("..\\ " + ntpath .basename (ntpath .dirname (ABSTFN ))
438
+ + "\\ " + ntpath .basename (ABSTFN ) + "c" , ABSTFN + "c" )
439
+ self .assertRaises (OSError , ntpath .realpath , ABSTFN + "c" , strict = True )
440
+
441
+ # Test using relative path as well.
442
+ self .assertRaises (OSError , ntpath .realpath , ntpath .basename (ABSTFN ),
443
+ strict = True )
444
+
389
445
@os_helper .skip_unless_symlink
390
446
@unittest .skipUnless (HAVE_GETFINALPATHNAME , 'need _getfinalpathname' )
391
447
def test_realpath_symlink_prefix (self ):
@@ -506,34 +562,47 @@ def test_expanduser(self):
506
562
env .clear ()
507
563
tester ('ntpath.expanduser("~test")' , '~test' )
508
564
509
- env ['HOMEPATH' ] = 'eric\\ idle'
510
565
env ['HOMEDRIVE' ] = 'C:\\ '
511
- tester ('ntpath.expanduser("~test")' , 'C:\\ eric\\ test' )
512
- tester ('ntpath.expanduser("~")' , 'C:\\ eric\\ idle' )
566
+ env ['HOMEPATH' ] = 'Users\\ eric'
567
+ env ['USERNAME' ] = 'eric'
568
+ tester ('ntpath.expanduser("~test")' , 'C:\\ Users\\ test' )
569
+ tester ('ntpath.expanduser("~")' , 'C:\\ Users\\ eric' )
513
570
514
571
del env ['HOMEDRIVE' ]
515
- tester ('ntpath.expanduser("~test")' , 'eric \\ test' )
516
- tester ('ntpath.expanduser("~")' , 'eric \\ idle ' )
572
+ tester ('ntpath.expanduser("~test")' , 'Users \\ test' )
573
+ tester ('ntpath.expanduser("~")' , 'Users \\ eric ' )
517
574
518
575
env .clear ()
519
- env ['USERPROFILE' ] = 'C:\\ eric\\ idle'
520
- tester ('ntpath.expanduser("~test")' , 'C:\\ eric\\ test' )
521
- tester ('ntpath.expanduser("~")' , 'C:\\ eric\\ idle' )
576
+ env ['USERPROFILE' ] = 'C:\\ Users\\ eric'
577
+ env ['USERNAME' ] = 'eric'
578
+ tester ('ntpath.expanduser("~test")' , 'C:\\ Users\\ test' )
579
+ tester ('ntpath.expanduser("~")' , 'C:\\ Users\\ eric' )
522
580
tester ('ntpath.expanduser("~test\\ foo\\ bar")' ,
523
- 'C:\\ eric \\ test\\ foo\\ bar' )
581
+ 'C:\\ Users \\ test\\ foo\\ bar' )
524
582
tester ('ntpath.expanduser("~test/foo/bar")' ,
525
- 'C:\\ eric \\ test/foo/bar' )
583
+ 'C:\\ Users \\ test/foo/bar' )
526
584
tester ('ntpath.expanduser("~\\ foo\\ bar")' ,
527
- 'C:\\ eric \\ idle \\ foo\\ bar' )
585
+ 'C:\\ Users \\ eric \\ foo\\ bar' )
528
586
tester ('ntpath.expanduser("~/foo/bar")' ,
529
- 'C:\\ eric \\ idle /foo/bar' )
587
+ 'C:\\ Users \\ eric /foo/bar' )
530
588
531
589
# bpo-36264: ignore `HOME` when set on windows
532
590
env .clear ()
533
591
env ['HOME' ] = 'F:\\ '
534
- env ['USERPROFILE' ] = 'C:\\ eric\\ idle'
535
- tester ('ntpath.expanduser("~test")' , 'C:\\ eric\\ test' )
536
- tester ('ntpath.expanduser("~")' , 'C:\\ eric\\ idle' )
592
+ env ['USERPROFILE' ] = 'C:\\ Users\\ eric'
593
+ env ['USERNAME' ] = 'eric'
594
+ tester ('ntpath.expanduser("~test")' , 'C:\\ Users\\ test' )
595
+ tester ('ntpath.expanduser("~")' , 'C:\\ Users\\ eric' )
596
+
597
+ # bpo-39899: don't guess another user's home directory if
598
+ # `%USERNAME% != basename(%USERPROFILE%)`
599
+ env .clear ()
600
+ env ['USERPROFILE' ] = 'C:\\ Users\\ eric'
601
+ env ['USERNAME' ] = 'idle'
602
+ tester ('ntpath.expanduser("~test")' , '~test' )
603
+ tester ('ntpath.expanduser("~")' , 'C:\\ Users\\ eric' )
604
+
605
+
537
606
538
607
@unittest .skipUnless (nt , "abspath requires 'nt' module" )
539
608
def test_abspath (self ):
@@ -728,9 +797,6 @@ class NtCommonTest(test_genericpath.CommonTest, unittest.TestCase):
728
797
pathmodule = ntpath
729
798
attributes = ['relpath' ]
730
799
731
- def test_expandvars_nonascii (self ):
732
- super ().test_expandvars_nonascii ()
733
-
734
800
# TODO: RUSTPYTHON
735
801
if sys .platform == "linux" :
736
802
@unittest .expectedFailure
@@ -767,7 +833,7 @@ class PathLikeTests(NtpathTestCase):
767
833
path = ntpath
768
834
769
835
def setUp (self ):
770
- self .file_name = os_helper .TESTFN . lower ()
836
+ self .file_name = os_helper .TESTFN
771
837
self .file_path = FakePath (os_helper .TESTFN )
772
838
self .addCleanup (os_helper .unlink , self .file_name )
773
839
with open (self .file_name , 'xb' , 0 ) as file :
@@ -778,6 +844,8 @@ def _check_function(self, func):
778
844
779
845
def test_path_normcase (self ):
780
846
self ._check_function (self .path .normcase )
847
+ if sys .platform == 'win32' :
848
+ self .assertEqual (ntpath .normcase ('\u03a9 \u2126 ' ), 'ωΩ' )
781
849
782
850
def test_path_isabs (self ):
783
851
self ._check_function (self .path .isabs )
0 commit comments