bpo-9949: Call normpath() in realpath() and avoid unnecessary prefixes (GH-15369)
authorSteve Dower <steve.dower@python.org>
Wed, 21 Aug 2019 23:45:02 +0000 (16:45 -0700)
committerGitHub <noreply@github.com>
Wed, 21 Aug 2019 23:45:02 +0000 (16:45 -0700)
Lib/ntpath.py
Lib/test/test_ntpath.py

index ef4999e1473acb00b80e9c8acc61948232ea2189..1d22d5f1dc2ab5d26ec157cd754e2afea881d887 100644 (file)
@@ -458,7 +458,8 @@ def normpath(path):
         # in the case of paths with these prefixes:
         # \\.\ -> device names
         # \\?\ -> literal paths
-        # do not do any normalization, but return the path unchanged
+        # do not do any normalization, but return the path
+        # unchanged apart from the call to os.fspath()
         return path
     path = path.replace(altsep, sep)
     prefix, path = splitdrive(path)
@@ -575,7 +576,7 @@ else:
         return abspath(tail)
 
     def realpath(path):
-        path = os.fspath(path)
+        path = normpath(path)
         if isinstance(path, bytes):
             prefix = b'\\\\?\\'
             unc_prefix = b'\\\\?\\UNC\\'
@@ -586,6 +587,7 @@ else:
             unc_prefix = '\\\\?\\UNC\\'
             new_unc_prefix = '\\\\'
             cwd = os.getcwd()
+        did_not_exist = not exists(path)
         had_prefix = path.startswith(prefix)
         path = _getfinalpathname_nonstrict(path)
         # The path returned by _getfinalpathname will always start with \\?\ -
@@ -603,7 +605,10 @@ else:
                 if _getfinalpathname(spath) == path:
                     path = spath
             except OSError as ex:
-                pass
+                # If the path does not exist and originally did not exist, then
+                # strip the prefix anyway.
+                if ex.winerror in {2, 3} and did_not_exist:
+                    path = spath
         return path
 
 
index 74dc8c378e2746d657a3baf1e122493a84a7739e..285fb69dc1e88f51a99657b67054580c92570a86 100644 (file)
@@ -333,11 +333,11 @@ class TestNtpath(unittest.TestCase):
         self.assertEqual(ntpath.realpath(ABSTFN + "1\\.."),
                          ntpath.dirname(ABSTFN))
         self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\x"),
-                         ntpath.dirname(P + ABSTFN) + "\\x")
+                         ntpath.dirname(ABSTFN) + "\\x")
         os.symlink(ABSTFN + "x", ABSTFN + "y")
         self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\"
                                          + ntpath.basename(ABSTFN) + "y"),
-                         P + ABSTFN + "x")
+                         ABSTFN + "x")
         self.assertIn(ntpath.realpath(ABSTFN + "1\\..\\"
                                       + ntpath.basename(ABSTFN) + "1"),
                       expected)