https://github.com/python/cpython/commit/bf224bd7cef5d24eaff35945ebe7ffe14df7710f
commit: bf224bd7cef5d24eaff35945ebe7ffe14df7710f
branch: main
author: Barney Gale <[email protected]>
committer: barneygale <[email protected]>
date: 2024-11-12T19:52:30Z
summary:

GH-120423: `pathname2url()`: handle forward slashes in Windows paths (#126593)

Adjust `urllib.request.pathname2url()` so that forward slashes in Windows
paths are handled identically to backward slashes.

files:
A Misc/NEWS.d/next/Library/2024-11-08-17-05-10.gh-issue-120423.7rdLVV.rst
M Lib/nturl2path.py
M Lib/test/test_urllib.py

diff --git a/Lib/nturl2path.py b/Lib/nturl2path.py
index 2f9fec7893afd1..9ecabff21c33e1 100644
--- a/Lib/nturl2path.py
+++ b/Lib/nturl2path.py
@@ -44,20 +44,21 @@ def pathname2url(p):
     import urllib.parse
     # First, clean up some special forms. We are going to sacrifice
     # the additional information anyway
-    if p[:4] == '\\\\?\\':
+    p = p.replace('\\', '/')
+    if p[:4] == '//?/':
         p = p[4:]
-        if p[:4].upper() == 'UNC\\':
-            p = '\\\\' + p[4:]
+        if p[:4].upper() == 'UNC/':
+            p = '//' + p[4:]
         elif p[1:2] != ':':
             raise OSError('Bad path: ' + p)
     if not ':' in p:
-        # No drive specifier, just convert slashes and quote the name
-        return urllib.parse.quote(p.replace('\\', '/'))
+        # No DOS drive specified, just quote the pathname
+        return urllib.parse.quote(p)
     comp = p.split(':', maxsplit=2)
     if len(comp) != 2 or len(comp[0]) > 1:
         error = 'Bad path: ' + p
         raise OSError(error)
 
     drive = urllib.parse.quote(comp[0].upper())
-    tail = urllib.parse.quote(comp[1].replace('\\', '/'))
+    tail = urllib.parse.quote(comp[1])
     return '///' + drive + ':' + tail
diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py
index 28369b21db06d4..66e948fc3a06be 100644
--- a/Lib/test/test_urllib.py
+++ b/Lib/test/test_urllib.py
@@ -1542,6 +1542,11 @@ def test_pathname2url_win(self):
         self.assertEqual(fn('\\\\some\\share\\'), '//some/share/')
         self.assertEqual(fn('\\\\some\\share\\a\\b.c'), '//some/share/a/b.c')
         self.assertEqual(fn('\\\\some\\share\\a\\b%#c\xe9'), 
'//some/share/a/b%25%23c%C3%A9')
+        # Alternate path separator
+        self.assertEqual(fn('C:/a/b.c'), '///C:/a/b.c')
+        self.assertEqual(fn('//some/share/a/b.c'), '//some/share/a/b.c')
+        self.assertEqual(fn('//?/C:/dir'), '///C:/dir')
+        self.assertEqual(fn('//?/unc/server/share/dir'), '//server/share/dir')
         # Round-tripping
         urls = ['///C:',
                 '///folder/test/',
diff --git 
a/Misc/NEWS.d/next/Library/2024-11-08-17-05-10.gh-issue-120423.7rdLVV.rst 
b/Misc/NEWS.d/next/Library/2024-11-08-17-05-10.gh-issue-120423.7rdLVV.rst
new file mode 100644
index 00000000000000..b475257ceb6610
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-11-08-17-05-10.gh-issue-120423.7rdLVV.rst
@@ -0,0 +1,2 @@
+Fix issue where :func:`urllib.request.pathname2url` mishandled Windows paths
+with embedded forward slashes.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to