Skip to content

Commit 32c6255

Browse files
committed
Fix CI. Handle the special case of file://C:\\ parsed by url2pathname
function where ":" should not be treated as port separator.
1 parent 315747a commit 32c6255

3 files changed

Lines changed: 31 additions & 3 deletions

File tree

‎Lib/test/test_urllib.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import email.message
88
import io
99
import unittest
10+
import unittest.mock
1011
from test import support
1112
from test.support import os_helper
1213
from test.support import socket_helper
@@ -1678,6 +1679,17 @@ def test_url2pathname_resolve_host(self):
16781679
self.assertEqual(fn(f'//{socket.gethostname()}/foo/bar'), f'{sep}foo{sep}bar')
16791680
self.assertEqual(fn(f'//{socket.gethostname()}/foo/bar', resolve_host=True), f'{sep}foo{sep}bar')
16801681

1682+
def test_url2pathname_win_netloc_not_validated_as_port(self):
1683+
# The Windows branch of url2pathname() stuffs things like drive
1684+
# letters into the netloc (e.g. '//C:\\' -> authority 'C:\\'),
1685+
# which is not a real host[:port] pair. url2pathname() must not
1686+
# reject it as an invalid port; run the Windows branch directly
1687+
# so this is exercised on every platform, not just win32.
1688+
with unittest.mock.patch('os.name', 'nt'):
1689+
fn = urllib.request.url2pathname
1690+
self.assertEqual(fn('//C:\\'), 'C:\\')
1691+
self.assertEqual(fn('//C:80/'), 'C:80\\')
1692+
16811693
@unittest.skipUnless(sys.platform == 'win32',
16821694
'test specific to Windows pathnames.')
16831695
def test_url2pathname_win(self):

‎Lib/urllib/request.py‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@
101101
from urllib.parse import (
102102
urlparse, urlsplit, urljoin, unwrap, quote, unquote,
103103
_splittype, _splithost, _splitport, _splituser, _splitpasswd,
104-
_splitattr, _splitvalue, _splittag,
104+
_splitattr, _splitvalue, _splittag, _splitnetloc,
105+
_WHATWG_C0_CONTROL_OR_SPACE, _UNSAFE_URL_BYTES_TO_REMOVE,
105106
unquote_to_bytes, urlunparse)
106107
from urllib.response import addinfourl, addclosehook
107108

@@ -1681,7 +1682,22 @@ def url2pathname(url, *, require_scheme=False, resolve_host=False):
16811682
"""
16821683
if not require_scheme:
16831684
url = 'file:' + url
1684-
scheme, authority, url = urlsplit(url)[:3] # Discard query and fragment.
1685+
# Match urlsplit()'s own control-character handling up front, so the
1686+
# except branch below can reuse this same cleaned-up string.
1687+
url = url.lstrip(_WHATWG_C0_CONTROL_OR_SPACE)
1688+
for b in _UNSAFE_URL_BYTES_TO_REMOVE:
1689+
url = url.replace(b, '')
1690+
try:
1691+
scheme, authority, url = urlsplit(url)[:3] # Discard query and fragment.
1692+
except ValueError:
1693+
# The authority here is not a real host[:port] pair -- it may
1694+
# hold a Windows drive letter (e.g. 'C:\\') -- so urlsplit()'s
1695+
# eager port check doesn't apply; split without it instead.
1696+
scheme, _, url = url.partition(':')
1697+
scheme = scheme.lower()
1698+
authority = ''
1699+
if url[:2] == '//':
1700+
authority, url = _splitnetloc(url, 2)
16851701
if scheme != 'file':
16861702
raise URLError("URL is missing a 'file:' scheme")
16871703
if os.name == 'nt':
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
:func:`urllib.parse.urlsplit` and :func:`urllib.parse.urlparse` now raise
22
:exc:`ValueError` for an invalid port when the URL is parsed, instead of
3-
when the :attr:`!port` attribute is read. Patch by Miguel Brito.
3+
when the :attr:`!port` attribute is read. Patch by Miguel Brito and Senthil Kumaran.

0 commit comments

Comments
 (0)