GH-126766: url2pathname(): handle 'localhost' authority (#127129) · python/cpython@ebf564a (original) (raw)

4 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -15,14 +15,17 @@ def url2pathname(url):
15 15 # become
16 16 # C:\foo\bar\spam.foo
17 17 import string, urllib.parse
18 +if url[:3] == '///':
19 +# URL has an empty authority section, so the path begins on the third
20 +# character.
21 +url = url[2:]
22 +elif url[:12] == '//localhost/':
23 +# Skip past 'localhost' authority.
24 +url = url[11:]
18 25 # Windows itself uses ":" even in URLs.
19 26 url = url.replace(':', '|')
20 27 if not '|' in url:
21 28 # No drive specifier, just convert slashes
22 -if url[:3] == '///':
23 -# URL has an empty authority section, so the path begins on the
24 -# third character.
25 -url = url[2:]
26 29 # make sure not to convert quoted slashes :-)
27 30 return urllib.parse.unquote(url.replace('/', '\\'))
28 31 comp = url.split('|')
Original file line number Diff line number Diff line change
@@ -1496,6 +1496,8 @@ def test_url2pathname_win(self):
1496 1496 # Localhost paths
1497 1497 self.assertEqual(fn('//localhost/C:/path/to/file'), 'C:\\path\\to\\file')
1498 1498 self.assertEqual(fn('//localhost/C|/path/to/file'), 'C:\\path\\to\\file')
1499 +self.assertEqual(fn('//localhost/path/to/file'), '\\path\\to\\file')
1500 +self.assertEqual(fn('//localhost//server/path/to/file'), '\\\\server\\path\\to\\file')
1499 1501 # Percent-encoded forward slashes are preserved for backwards compatibility
1500 1502 self.assertEqual(fn('C:/foo%2fbar'), 'C:\\foo/bar')
1501 1503 self.assertEqual(fn('//server/share/foo%2fbar'), '\\\\server\\share\\foo/bar')
@@ -1514,7 +1516,7 @@ def test_url2pathname_posix(self):
1514 1516 self.assertEqual(fn('//foo/bar'), '//foo/bar')
1515 1517 self.assertEqual(fn('///foo/bar'), '/foo/bar')
1516 1518 self.assertEqual(fn('////foo/bar'), '//foo/bar')
1517 -self.assertEqual(fn('//localhost/foo/bar'), '//localhost/foo/bar')
1519 +self.assertEqual(fn('//localhost/foo/bar'), '/foo/bar')
1518 1520
1519 1521 @unittest.skipUnless(os_helper.FS_NONASCII, 'need os_helper.FS_NONASCII')
1520 1522 def test_url2pathname_nonascii(self):
Original file line number Diff line number Diff line change
@@ -1657,6 +1657,9 @@ def url2pathname(pathname):
1657 1657 # URL has an empty authority section, so the path begins on the
1658 1658 # third character.
1659 1659 pathname = pathname[2:]
1660 +elif pathname[:12] == '//localhost/':
1661 +# Skip past 'localhost' authority.
1662 +pathname = pathname[11:]
1660 1663 encoding = sys.getfilesystemencoding()
1661 1664 errors = sys.getfilesystemencodeerrors()
1662 1665 return unquote(pathname, encoding=encoding, errors=errors)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1 +Fix issue where :func:`urllib.request.url2pathname` failed to discard any
2 +'localhost' authority present in the URL.