bpo-38355: Fix ntpath.realpath failing on sys.executable (GH-16551)
This commit is contained in:
parent
098e25672f
commit
a0e3d27e4e
|
@ -560,13 +560,6 @@ else:
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def _getfinalpathname_nonstrict(path):
|
def _getfinalpathname_nonstrict(path):
|
||||||
# Fast path to get the final path name. If this succeeds, there
|
|
||||||
# is no need to go any further.
|
|
||||||
try:
|
|
||||||
return _getfinalpathname(path)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# These error codes indicate that we should stop resolving the path
|
# These error codes indicate that we should stop resolving the path
|
||||||
# and return the value we currently have.
|
# and return the value we currently have.
|
||||||
# 1: ERROR_INVALID_FUNCTION
|
# 1: ERROR_INVALID_FUNCTION
|
||||||
|
@ -579,8 +572,9 @@ else:
|
||||||
# 67: ERROR_BAD_NET_NAME (implies remote server unavailable)
|
# 67: ERROR_BAD_NET_NAME (implies remote server unavailable)
|
||||||
# 87: ERROR_INVALID_PARAMETER
|
# 87: ERROR_INVALID_PARAMETER
|
||||||
# 123: ERROR_INVALID_NAME
|
# 123: ERROR_INVALID_NAME
|
||||||
|
# 1920: ERROR_CANT_ACCESS_FILE
|
||||||
# 1921: ERROR_CANT_RESOLVE_FILENAME (implies unfollowable symlink)
|
# 1921: ERROR_CANT_RESOLVE_FILENAME (implies unfollowable symlink)
|
||||||
allowed_winerror = 1, 2, 3, 5, 21, 32, 50, 67, 87, 123, 1921
|
allowed_winerror = 1, 2, 3, 5, 21, 32, 50, 67, 87, 123, 1920, 1921
|
||||||
|
|
||||||
# Non-strict algorithm is to find as much of the target directory
|
# Non-strict algorithm is to find as much of the target directory
|
||||||
# as we can and join the rest.
|
# as we can and join the rest.
|
||||||
|
@ -615,9 +609,13 @@ else:
|
||||||
unc_prefix = '\\\\?\\UNC\\'
|
unc_prefix = '\\\\?\\UNC\\'
|
||||||
new_unc_prefix = '\\\\'
|
new_unc_prefix = '\\\\'
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
did_not_exist = not exists(path)
|
|
||||||
had_prefix = path.startswith(prefix)
|
had_prefix = path.startswith(prefix)
|
||||||
path = _getfinalpathname_nonstrict(path)
|
try:
|
||||||
|
path = _getfinalpathname(path)
|
||||||
|
initial_winerror = 0
|
||||||
|
except OSError as ex:
|
||||||
|
initial_winerror = ex.winerror
|
||||||
|
path = _getfinalpathname_nonstrict(path)
|
||||||
# The path returned by _getfinalpathname will always start with \\?\ -
|
# The path returned by _getfinalpathname will always start with \\?\ -
|
||||||
# strip off that prefix unless it was already provided on the original
|
# strip off that prefix unless it was already provided on the original
|
||||||
# path.
|
# path.
|
||||||
|
@ -635,7 +633,7 @@ else:
|
||||||
except OSError as ex:
|
except OSError as ex:
|
||||||
# If the path does not exist and originally did not exist, then
|
# If the path does not exist and originally did not exist, then
|
||||||
# strip the prefix anyway.
|
# strip the prefix anyway.
|
||||||
if ex.winerror in {2, 3} and did_not_exist:
|
if ex.winerror == initial_winerror:
|
||||||
path = spath
|
path = spath
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
|
@ -329,16 +329,14 @@ class TestNtpath(NtpathTestCase):
|
||||||
self.addCleanup(support.unlink, ABSTFN + "c")
|
self.addCleanup(support.unlink, ABSTFN + "c")
|
||||||
self.addCleanup(support.unlink, ABSTFN + "a")
|
self.addCleanup(support.unlink, ABSTFN + "a")
|
||||||
|
|
||||||
P = "\\\\?\\"
|
|
||||||
|
|
||||||
os.symlink(ABSTFN, ABSTFN)
|
os.symlink(ABSTFN, ABSTFN)
|
||||||
self.assertPathEqual(ntpath.realpath(ABSTFN), P + ABSTFN)
|
self.assertPathEqual(ntpath.realpath(ABSTFN), ABSTFN)
|
||||||
|
|
||||||
# cycles are non-deterministic as to which path is returned, but
|
# cycles are non-deterministic as to which path is returned, but
|
||||||
# it will always be the fully resolved path of one member of the cycle
|
# it will always be the fully resolved path of one member of the cycle
|
||||||
os.symlink(ABSTFN + "1", ABSTFN + "2")
|
os.symlink(ABSTFN + "1", ABSTFN + "2")
|
||||||
os.symlink(ABSTFN + "2", ABSTFN + "1")
|
os.symlink(ABSTFN + "2", ABSTFN + "1")
|
||||||
expected = (P + ABSTFN + "1", P + ABSTFN + "2")
|
expected = (ABSTFN + "1", ABSTFN + "2")
|
||||||
self.assertPathIn(ntpath.realpath(ABSTFN + "1"), expected)
|
self.assertPathIn(ntpath.realpath(ABSTFN + "1"), expected)
|
||||||
self.assertPathIn(ntpath.realpath(ABSTFN + "2"), expected)
|
self.assertPathIn(ntpath.realpath(ABSTFN + "2"), expected)
|
||||||
|
|
||||||
|
@ -357,14 +355,14 @@ class TestNtpath(NtpathTestCase):
|
||||||
expected)
|
expected)
|
||||||
|
|
||||||
os.symlink(ntpath.basename(ABSTFN) + "a\\b", ABSTFN + "a")
|
os.symlink(ntpath.basename(ABSTFN) + "a\\b", ABSTFN + "a")
|
||||||
self.assertPathEqual(ntpath.realpath(ABSTFN + "a"), P + ABSTFN + "a")
|
self.assertPathEqual(ntpath.realpath(ABSTFN + "a"), ABSTFN + "a")
|
||||||
|
|
||||||
os.symlink("..\\" + ntpath.basename(ntpath.dirname(ABSTFN))
|
os.symlink("..\\" + ntpath.basename(ntpath.dirname(ABSTFN))
|
||||||
+ "\\" + ntpath.basename(ABSTFN) + "c", ABSTFN + "c")
|
+ "\\" + ntpath.basename(ABSTFN) + "c", ABSTFN + "c")
|
||||||
self.assertPathEqual(ntpath.realpath(ABSTFN + "c"), P + ABSTFN + "c")
|
self.assertPathEqual(ntpath.realpath(ABSTFN + "c"), ABSTFN + "c")
|
||||||
|
|
||||||
# Test using relative path as well.
|
# Test using relative path as well.
|
||||||
self.assertPathEqual(ntpath.realpath(ntpath.basename(ABSTFN)), P + ABSTFN)
|
self.assertPathEqual(ntpath.realpath(ntpath.basename(ABSTFN)), ABSTFN)
|
||||||
|
|
||||||
@support.skip_unless_symlink
|
@support.skip_unless_symlink
|
||||||
@unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
|
@unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fixes ``ntpath.realpath`` failing on ``sys.executable``.
|
Loading…
Reference in New Issue