30
30
"ismount" , "expanduser" ,"expandvars" ,"normpath" ,"abspath" ,
31
31
"curdir" ,"pardir" ,"sep" ,"pathsep" ,"defpath" ,"altsep" ,
32
32
"extsep" ,"devnull" ,"realpath" ,"supports_unicode_filenames" ,"relpath" ,
33
- "samefile" , "sameopenfile" , "samestat" , "commonpath" ]
33
+ "samefile" , "sameopenfile" , "samestat" , "commonpath" ,
34
+ "ALLOW_MISSING" ]
34
35
35
36
def _get_bothseps (path ):
36
37
if isinstance (path , bytes ):
@@ -571,9 +572,10 @@ def abspath(path):
571
572
from nt import _getfinalpathname , readlink as _nt_readlink
572
573
except ImportError :
573
574
# realpath is a no-op on systems without _getfinalpathname support.
574
- realpath = abspath
575
+ def realpath (path , * , strict = False ):
576
+ return abspath (path )
575
577
else :
576
- def _readlink_deep (path ):
578
+ def _readlink_deep (path , ignored_error = OSError ):
577
579
# These error codes indicate that we should stop reading links and
578
580
# return the path we currently have.
579
581
# 1: ERROR_INVALID_FUNCTION
@@ -606,7 +608,7 @@ def _readlink_deep(path):
606
608
path = old_path
607
609
break
608
610
path = normpath (join (dirname (old_path ), path ))
609
- except OSError as ex :
611
+ except ignored_error as ex :
610
612
if ex .winerror in allowed_winerror :
611
613
break
612
614
raise
@@ -615,7 +617,7 @@ def _readlink_deep(path):
615
617
break
616
618
return path
617
619
618
- def _getfinalpathname_nonstrict (path ):
620
+ def _getfinalpathname_nonstrict (path , ignored_error = OSError ):
619
621
# These error codes indicate that we should stop resolving the path
620
622
# and return the value we currently have.
621
623
# 1: ERROR_INVALID_FUNCTION
@@ -642,17 +644,18 @@ def _getfinalpathname_nonstrict(path):
642
644
try :
643
645
path = _getfinalpathname (path )
644
646
return join (path , tail ) if tail else path
645
- except OSError as ex :
647
+ except ignored_error as ex :
646
648
if ex .winerror not in allowed_winerror :
647
649
raise
648
650
try :
649
651
# The OS could not resolve this path fully, so we attempt
650
652
# to follow the link ourselves. If we succeed, join the tail
651
653
# and return.
652
- new_path = _readlink_deep (path )
654
+ new_path = _readlink_deep (path ,
655
+ ignored_error = ignored_error )
653
656
if new_path != path :
654
657
return join (new_path , tail ) if tail else new_path
655
- except OSError :
658
+ except ignored_error :
656
659
# If we fail to readlink(), let's keep traversing
657
660
pass
658
661
path , name = split (path )
@@ -683,16 +686,24 @@ def realpath(path, *, strict=False):
683
686
if normcase (path ) == normcase (devnull ):
684
687
return '\\ \\ .\\ NUL'
685
688
had_prefix = path .startswith (prefix )
689
+
690
+ if strict is ALLOW_MISSING :
691
+ ignored_error = FileNotFoundError
692
+ strict = True
693
+ elif strict :
694
+ ignored_error = ()
695
+ else :
696
+ ignored_error = OSError
697
+
686
698
if not had_prefix and not isabs (path ):
687
699
path = join (cwd , path )
688
700
try :
689
701
path = _getfinalpathname (path )
690
702
initial_winerror = 0
691
- except OSError as ex :
692
- if strict :
693
- raise
703
+ except ignored_error as ex :
694
704
initial_winerror = ex .winerror
695
- path = _getfinalpathname_nonstrict (path )
705
+ path = _getfinalpathname_nonstrict (path ,
706
+ ignored_error = ignored_error )
696
707
# The path returned by _getfinalpathname will always start with \\?\ -
697
708
# strip off that prefix unless it was already provided on the original
698
709
# path.
0 commit comments