Skip to content

Commit a853610

Browse files
gh-119826: Improved fallback for ntpath.abspath() on Windows (GH-119938)
(cherry picked from commit 4b00aba) Co-authored-by: Nice Zombies <[email protected]>
1 parent 219b826 commit a853610

File tree

3 files changed

+35
-18
lines changed

3 files changed

+35
-18
lines changed

Lib/ntpath.py

+31-18
Original file line numberDiff line numberDiff line change
@@ -553,36 +553,49 @@ def normpath(path):
553553
return prefix + sep.join(comps)
554554

555555

556-
def _abspath_fallback(path):
557-
"""Return the absolute version of a path as a fallback function in case
558-
`nt._getfullpathname` is not available or raises OSError. See bpo-31047 for
559-
more.
560-
561-
"""
562-
563-
path = os.fspath(path)
564-
if not isabs(path):
565-
if isinstance(path, bytes):
566-
cwd = os.getcwdb()
567-
else:
568-
cwd = os.getcwd()
569-
path = join(cwd, path)
570-
return normpath(path)
571-
572556
# Return an absolute path.
573557
try:
574558
from nt import _getfullpathname
575559

576560
except ImportError: # not running on Windows - mock up something sensible
577-
abspath = _abspath_fallback
561+
def abspath(path):
562+
"""Return the absolute version of a path."""
563+
path = os.fspath(path)
564+
if not isabs(path):
565+
if isinstance(path, bytes):
566+
cwd = os.getcwdb()
567+
else:
568+
cwd = os.getcwd()
569+
path = join(cwd, path)
570+
return normpath(path)
578571

579572
else: # use native Windows method on Windows
580573
def abspath(path):
581574
"""Return the absolute version of a path."""
582575
try:
583576
return _getfullpathname(normpath(path))
584577
except (OSError, ValueError):
585-
return _abspath_fallback(path)
578+
# See gh-75230, handle outside for cleaner traceback
579+
pass
580+
path = os.fspath(path)
581+
if not isabs(path):
582+
if isinstance(path, bytes):
583+
sep = b'\\'
584+
getcwd = os.getcwdb
585+
else:
586+
sep = '\\'
587+
getcwd = os.getcwd
588+
drive, root, path = splitroot(path)
589+
# Either drive or root can be nonempty, but not both.
590+
if drive or root:
591+
try:
592+
path = join(_getfullpathname(drive + root), path)
593+
except (OSError, ValueError):
594+
# Drive "\0:" cannot exist; use the root directory.
595+
path = drive + sep + path
596+
else:
597+
path = join(getcwd(), path)
598+
return normpath(path)
586599

587600
try:
588601
from nt import _findfirstfile, _getfinalpathname, readlink as _nt_readlink

Lib/test/test_ntpath.py

+3
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,9 @@ def test_abspath(self):
811811
tester('ntpath.abspath("C:\\spam. . .")', "C:\\spam")
812812
tester('ntpath.abspath("C:/nul")', "\\\\.\\nul")
813813
tester('ntpath.abspath("C:\\nul")', "\\\\.\\nul")
814+
self.assertTrue(ntpath.isabs(ntpath.abspath("C:spam")))
815+
self.assertEqual(ntpath.abspath("C:\x00"), ntpath.join(ntpath.abspath("C:"), "\x00"))
816+
self.assertEqual(ntpath.abspath("\x00:spam"), "\x00:\\spam")
814817
tester('ntpath.abspath("//..")', "\\\\")
815818
tester('ntpath.abspath("//../")', "\\\\..\\")
816819
tester('ntpath.abspath("//../..")', "\\\\..\\")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Always return an absolute path for :func:`os.path.abspath` on Windows.

0 commit comments

Comments
 (0)