29
29
"ismount" , "expanduser" ,"expandvars" ,"normpath" ,"abspath" ,
30
30
"curdir" ,"pardir" ,"sep" ,"pathsep" ,"defpath" ,"altsep" ,
31
31
"extsep" ,"devnull" ,"realpath" ,"supports_unicode_filenames" ,"relpath" ,
32
- "samefile" , "sameopenfile" , "samestat" , "commonpath" ]
32
+ "samefile" , "sameopenfile" , "samestat" , "commonpath" ,
33
+ "ALLOW_MISSING" ]
33
34
34
35
def _get_bothseps (path ):
35
36
if isinstance (path , bytes ):
@@ -532,9 +533,10 @@ def abspath(path):
532
533
from nt import _getfinalpathname , readlink as _nt_readlink
533
534
except ImportError :
534
535
# realpath is a no-op on systems without _getfinalpathname support.
535
- realpath = abspath
536
+ def realpath (path , * , strict = False ):
537
+ return abspath (path )
536
538
else :
537
- def _readlink_deep (path ):
539
+ def _readlink_deep (path , ignored_error = OSError ):
538
540
# These error codes indicate that we should stop reading links and
539
541
# return the path we currently have.
540
542
# 1: ERROR_INVALID_FUNCTION
@@ -567,7 +569,7 @@ def _readlink_deep(path):
567
569
path = old_path
568
570
break
569
571
path = normpath (join (dirname (old_path ), path ))
570
- except OSError as ex :
572
+ except ignored_error as ex :
571
573
if ex .winerror in allowed_winerror :
572
574
break
573
575
raise
@@ -576,7 +578,7 @@ def _readlink_deep(path):
576
578
break
577
579
return path
578
580
579
- def _getfinalpathname_nonstrict (path ):
581
+ def _getfinalpathname_nonstrict (path , ignored_error = OSError ):
580
582
# These error codes indicate that we should stop resolving the path
581
583
# and return the value we currently have.
582
584
# 1: ERROR_INVALID_FUNCTION
@@ -600,17 +602,18 @@ def _getfinalpathname_nonstrict(path):
600
602
try :
601
603
path = _getfinalpathname (path )
602
604
return join (path , tail ) if tail else path
603
- except OSError as ex :
605
+ except ignored_error as ex :
604
606
if ex .winerror not in allowed_winerror :
605
607
raise
606
608
try :
607
609
# The OS could not resolve this path fully, so we attempt
608
610
# to follow the link ourselves. If we succeed, join the tail
609
611
# and return.
610
- new_path = _readlink_deep (path )
612
+ new_path = _readlink_deep (path ,
613
+ ignored_error = ignored_error )
611
614
if new_path != path :
612
615
return join (new_path , tail ) if tail else new_path
613
- except OSError :
616
+ except ignored_error :
614
617
# If we fail to readlink(), let's keep traversing
615
618
pass
616
619
path , name = split (path )
@@ -641,16 +644,24 @@ def realpath(path, *, strict=False):
641
644
if normcase (path ) == normcase (devnull ):
642
645
return '\\ \\ .\\ NUL'
643
646
had_prefix = path .startswith (prefix )
647
+
648
+ if strict is ALLOW_MISSING :
649
+ ignored_error = FileNotFoundError
650
+ strict = True
651
+ elif strict :
652
+ ignored_error = ()
653
+ else :
654
+ ignored_error = OSError
655
+
644
656
if not had_prefix and not isabs (path ):
645
657
path = join (cwd , path )
646
658
try :
647
659
path = _getfinalpathname (path )
648
660
initial_winerror = 0
649
- except OSError as ex :
650
- if strict :
651
- raise
661
+ except ignored_error as ex :
652
662
initial_winerror = ex .winerror
653
- path = _getfinalpathname_nonstrict (path )
663
+ path = _getfinalpathname_nonstrict (path ,
664
+ ignored_error = ignored_error )
654
665
# The path returned by _getfinalpathname will always start with \\?\ -
655
666
# strip off that prefix unless it was already provided on the original
656
667
# path.
0 commit comments