2929 "abspath" ,"curdir" ,"pardir" ,"sep" ,"pathsep" ,"defpath" ,"altsep" ,
3030 "extsep" ,"devnull" ,"realpath" ,"supports_unicode_filenames" ,"relpath" ,
3131 "samefile" , "sameopenfile" , "samestat" , "commonpath" , "isjunction" ,
32- "isdevdrive" ]
32+ "isdevdrive" , "ALLOW_MISSING" ]
3333
3434def _get_bothseps (path ):
3535 if isinstance (path , bytes ):
@@ -601,9 +601,10 @@ def abspath(path):
601601 from nt import _findfirstfile , _getfinalpathname , readlink as _nt_readlink
602602except ImportError :
603603 # realpath is a no-op on systems without _getfinalpathname support.
604- realpath = abspath
604+ def realpath (path , * , strict = False ):
605+ return abspath (path )
605606else :
606- def _readlink_deep (path ):
607+ def _readlink_deep (path , ignored_error = OSError ):
607608 # These error codes indicate that we should stop reading links and
608609 # return the path we currently have.
609610 # 1: ERROR_INVALID_FUNCTION
@@ -636,7 +637,7 @@ def _readlink_deep(path):
636637 path = old_path
637638 break
638639 path = normpath (join (dirname (old_path ), path ))
639- except OSError as ex :
640+ except ignored_error as ex :
640641 if ex .winerror in allowed_winerror :
641642 break
642643 raise
@@ -645,7 +646,7 @@ def _readlink_deep(path):
645646 break
646647 return path
647648
648- def _getfinalpathname_nonstrict (path ):
649+ def _getfinalpathname_nonstrict (path , ignored_error = OSError ):
649650 # These error codes indicate that we should stop resolving the path
650651 # and return the value we currently have.
651652 # 1: ERROR_INVALID_FUNCTION
@@ -673,25 +674,26 @@ def _getfinalpathname_nonstrict(path):
673674 try :
674675 path = _getfinalpathname (path )
675676 return join (path , tail ) if tail else path
676- except OSError as ex :
677+ except ignored_error as ex :
677678 if ex .winerror not in allowed_winerror :
678679 raise
679680 try :
680681 # The OS could not resolve this path fully, so we attempt
681682 # to follow the link ourselves. If we succeed, join the tail
682683 # and return.
683- new_path = _readlink_deep (path )
684+ new_path = _readlink_deep (path ,
685+ ignored_error = ignored_error )
684686 if new_path != path :
685687 return join (new_path , tail ) if tail else new_path
686- except OSError :
688+ except ignored_error :
687689 # If we fail to readlink(), let's keep traversing
688690 pass
689691 # If we get these errors, try to get the real name of the file without accessing it.
690692 if ex .winerror in (1 , 5 , 32 , 50 , 87 , 1920 , 1921 ):
691693 try :
692694 name = _findfirstfile (path )
693695 path , _ = split (path )
694- except OSError :
696+ except ignored_error :
695697 path , name = split (path )
696698 else :
697699 path , name = split (path )
@@ -721,24 +723,32 @@ def realpath(path, *, strict=False):
721723 if normcase (path ) == devnull :
722724 return '\\ \\ .\\ NUL'
723725 had_prefix = path .startswith (prefix )
726+
727+ if strict is ALLOW_MISSING :
728+ ignored_error = FileNotFoundError
729+ strict = True
730+ elif strict :
731+ ignored_error = ()
732+ else :
733+ ignored_error = OSError
734+
724735 if not had_prefix and not isabs (path ):
725736 path = join (cwd , path )
726737 try :
727738 path = _getfinalpathname (path )
728739 initial_winerror = 0
729740 except ValueError as ex :
730741 # gh-106242: Raised for embedded null characters
731- # In strict mode , we convert into an OSError.
742+ # In strict modes , we convert into an OSError.
732743 # Non-strict mode returns the path as-is, since we've already
733744 # made it absolute.
734745 if strict :
735746 raise OSError (str (ex )) from None
736747 path = normpath (path )
737- except OSError as ex :
738- if strict :
739- raise
748+ except ignored_error as ex :
740749 initial_winerror = ex .winerror
741- path = _getfinalpathname_nonstrict (path )
750+ path = _getfinalpathname_nonstrict (path ,
751+ ignored_error = ignored_error )
742752 # The path returned by _getfinalpathname will always start with \\?\ -
743753 # strip off that prefix unless it was already provided on the original
744754 # path.
0 commit comments