]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-119826: Improved fallback for ntpath.abspath() on Windows (GH-119938)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 2 Dec 2024 20:03:44 +0000 (21:03 +0100)
committerGitHub <noreply@github.com>
Mon, 2 Dec 2024 20:03:44 +0000 (20:03 +0000)
(cherry picked from commit 4b00aba42e4d9440d22e399ec2122fe8601bbe54)

Co-authored-by: Nice Zombies <nineteendo19d0@gmail.com>
Lib/ntpath.py
Lib/test/test_ntpath.py
Misc/NEWS.d/next/Library/2024-06-02-11-48-19.gh-issue-119826.N1obGa.rst [new file with mode: 0644]

index 2e290dcf9de9daec09dacd90ac64ac5190f535cc..c05e965fcb91d18dbf1a23eb93609f973f6f1404 100644 (file)
@@ -561,28 +561,21 @@ except ImportError:
         return prefix + sep.join(comps)
 
 
-def _abspath_fallback(path):
-    """Return the absolute version of a path as a fallback function in case
-    `nt._getfullpathname` is not available or raises OSError. See bpo-31047 for
-    more.
-
-    """
-
-    path = os.fspath(path)
-    if not isabs(path):
-        if isinstance(path, bytes):
-            cwd = os.getcwdb()
-        else:
-            cwd = os.getcwd()
-        path = join(cwd, path)
-    return normpath(path)
-
 # Return an absolute path.
 try:
     from nt import _getfullpathname
 
 except ImportError: # not running on Windows - mock up something sensible
-    abspath = _abspath_fallback
+    def abspath(path):
+        """Return the absolute version of a path."""
+        path = os.fspath(path)
+        if not isabs(path):
+            if isinstance(path, bytes):
+                cwd = os.getcwdb()
+            else:
+                cwd = os.getcwd()
+            path = join(cwd, path)
+        return normpath(path)
 
 else:  # use native Windows method on Windows
     def abspath(path):
@@ -590,7 +583,27 @@ else:  # use native Windows method on Windows
         try:
             return _getfullpathname(normpath(path))
         except (OSError, ValueError):
-            return _abspath_fallback(path)
+            # See gh-75230, handle outside for cleaner traceback
+            pass
+        path = os.fspath(path)
+        if not isabs(path):
+            if isinstance(path, bytes):
+                sep = b'\\'
+                getcwd = os.getcwdb
+            else:
+                sep = '\\'
+                getcwd = os.getcwd
+            drive, root, path = splitroot(path)
+            # Either drive or root can be nonempty, but not both.
+            if drive or root:
+                try:
+                    path = join(_getfullpathname(drive + root), path)
+                except (OSError, ValueError):
+                    # Drive "\0:" cannot exist; use the root directory.
+                    path = drive + sep + path
+            else:
+                path = join(getcwd(), path)
+        return normpath(path)
 
 try:
     from nt import _getfinalpathname, readlink as _nt_readlink
index 9c6715b2cc37b438332474558f33130f383b2c89..4924db983b568f84333945bcc45b2c208dbeed29 100644 (file)
@@ -743,6 +743,9 @@ class TestNtpath(NtpathTestCase):
         tester('ntpath.abspath("C:\\spam. . .")', "C:\\spam")
         tester('ntpath.abspath("C:/nul")',  "\\\\.\\nul")
         tester('ntpath.abspath("C:\\nul")', "\\\\.\\nul")
+        self.assertTrue(ntpath.isabs(ntpath.abspath("C:spam")))
+        self.assertEqual(ntpath.abspath("C:\x00"), ntpath.join(ntpath.abspath("C:"), "\x00"))
+        self.assertEqual(ntpath.abspath("\x00:spam"), "\x00:\\spam")
         tester('ntpath.abspath("//..")',           "\\\\")
         tester('ntpath.abspath("//../")',          "\\\\..\\")
         tester('ntpath.abspath("//../..")',        "\\\\..\\")
diff --git a/Misc/NEWS.d/next/Library/2024-06-02-11-48-19.gh-issue-119826.N1obGa.rst b/Misc/NEWS.d/next/Library/2024-06-02-11-48-19.gh-issue-119826.N1obGa.rst
new file mode 100644 (file)
index 0000000..6901e74
--- /dev/null
@@ -0,0 +1 @@
+Always return an absolute path for :func:`os.path.abspath` on Windows.