3030 "ismount" , "expanduser" ,"expandvars" ,"normpath" ,"abspath" ,
3131 "curdir" ,"pardir" ,"sep" ,"pathsep" ,"defpath" ,"altsep" ,
3232 "extsep" ,"devnull" ,"realpath" ,"supports_unicode_filenames" ,"relpath" ,
33- "samefile" , "sameopenfile" , "samestat" , "commonpath" , "isjunction" ]
33+ "samefile" , "sameopenfile" , "samestat" , "commonpath" , "isjunction" ,
34+ "ALLOW_MISSING" ]
3435
3536def _get_bothseps (path ):
3637 if isinstance (path , bytes ):
@@ -609,9 +610,10 @@ def abspath(path):
609610 from nt import _getfinalpathname , readlink as _nt_readlink
610611except ImportError :
611612 # realpath is a no-op on systems without _getfinalpathname support.
612- realpath = abspath
613+ def realpath (path , * , strict = False ):
614+ return abspath (path )
613615else :
614- def _readlink_deep (path ):
616+ def _readlink_deep (path , ignored_error = OSError ):
615617 # These error codes indicate that we should stop reading links and
616618 # return the path we currently have.
617619 # 1: ERROR_INVALID_FUNCTION
@@ -644,7 +646,7 @@ def _readlink_deep(path):
644646 path = old_path
645647 break
646648 path = normpath (join (dirname (old_path ), path ))
647- except OSError as ex :
649+ except ignored_error as ex :
648650 if ex .winerror in allowed_winerror :
649651 break
650652 raise
@@ -653,7 +655,7 @@ def _readlink_deep(path):
653655 break
654656 return path
655657
656- def _getfinalpathname_nonstrict (path ):
658+ def _getfinalpathname_nonstrict (path , ignored_error = OSError ):
657659 # These error codes indicate that we should stop resolving the path
658660 # and return the value we currently have.
659661 # 1: ERROR_INVALID_FUNCTION
@@ -680,17 +682,18 @@ def _getfinalpathname_nonstrict(path):
680682 try :
681683 path = _getfinalpathname (path )
682684 return join (path , tail ) if tail else path
683- except OSError as ex :
685+ except ignored_error as ex :
684686 if ex .winerror not in allowed_winerror :
685687 raise
686688 try :
687689 # The OS could not resolve this path fully, so we attempt
688690 # to follow the link ourselves. If we succeed, join the tail
689691 # and return.
690- new_path = _readlink_deep (path )
692+ new_path = _readlink_deep (path ,
693+ ignored_error = ignored_error )
691694 if new_path != path :
692695 return join (new_path , tail ) if tail else new_path
693- except OSError :
696+ except ignored_error :
694697 # If we fail to readlink(), let's keep traversing
695698 pass
696699 path , name = split (path )
@@ -721,24 +724,32 @@ def realpath(path, *, strict=False):
721724 if normcase (path ) == normcase (devnull ):
722725 return '\\ \\ .\\ NUL'
723726 had_prefix = path .startswith (prefix )
727+
728+ if strict is ALLOW_MISSING :
729+ ignored_error = FileNotFoundError
730+ strict = True
731+ elif strict :
732+ ignored_error = ()
733+ else :
734+ ignored_error = OSError
735+
724736 if not had_prefix and not isabs (path ):
725737 path = join (cwd , path )
726738 try :
727739 path = _getfinalpathname (path )
728740 initial_winerror = 0
729741 except ValueError as ex :
730742 # gh-106242: Raised for embedded null characters
731- # In strict mode , we convert into an OSError.
743+ # In strict modes , we convert into an OSError.
732744 # Non-strict mode returns the path as-is, since we've already
733745 # made it absolute.
734746 if strict :
735747 raise OSError (str (ex )) from None
736748 path = normpath (path )
737- except OSError as ex :
738- if strict :
739- raise
749+ except ignored_error as ex :
740750 initial_winerror = ex .winerror
741- path = _getfinalpathname_nonstrict (path )
751+ path = _getfinalpathname_nonstrict (path ,
752+ ignored_error = ignored_error )
742753 # The path returned by _getfinalpathname will always start with \\?\ -
743754 # strip off that prefix unless it was already provided on the original
744755 # path.
0 commit comments