GH-136874: url2pathname(): discard query and fragment components (#136875)

In `urllib.request.url2pathname()`, ignore any query or fragment components
in the given URL.
This commit is contained in:
Barney Gale 2025-07-21 18:33:20 +01:00 committed by GitHub
parent 4b68289ca6
commit 80b2d60a51
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 18 additions and 5 deletions

View file

@ -210,6 +210,9 @@ The :mod:`urllib.request` module defines the following functions:
Windows a UNC path is returned (as before), and on other platforms a Windows a UNC path is returned (as before), and on other platforms a
:exc:`~urllib.error.URLError` is raised. :exc:`~urllib.error.URLError` is raised.
.. versionchanged:: 3.14
The URL query and fragment components are discarded if present.
.. versionchanged:: 3.14 .. versionchanged:: 3.14
The *require_scheme* and *resolve_host* parameters were added. The *require_scheme* and *resolve_host* parameters were added.

View file

@ -2192,6 +2192,7 @@ urllib
- Discard URL authority if it matches the local hostname. - Discard URL authority if it matches the local hostname.
- Discard URL authority if it resolves to a local IP address when the new - Discard URL authority if it resolves to a local IP address when the new
*resolve_host* argument is set to true. *resolve_host* argument is set to true.
- Discard URL query and fragment components.
- Raise :exc:`~urllib.error.URLError` if a URL authority isn't local, - Raise :exc:`~urllib.error.URLError` if a URL authority isn't local,
except on Windows where we return a UNC path as before. except on Windows where we return a UNC path as before.

View file

@ -1526,6 +1526,14 @@ def test_url2pathname(self):
self.assertEqual(fn('////foo/bar'), f'{sep}{sep}foo{sep}bar') self.assertEqual(fn('////foo/bar'), f'{sep}{sep}foo{sep}bar')
self.assertEqual(fn('data:blah'), 'data:blah') self.assertEqual(fn('data:blah'), 'data:blah')
self.assertEqual(fn('data://blah'), f'data:{sep}{sep}blah') self.assertEqual(fn('data://blah'), f'data:{sep}{sep}blah')
self.assertEqual(fn('foo?bar'), 'foo')
self.assertEqual(fn('foo#bar'), 'foo')
self.assertEqual(fn('foo?bar=baz'), 'foo')
self.assertEqual(fn('foo?bar#baz'), 'foo')
self.assertEqual(fn('foo%3Fbar'), 'foo?bar')
self.assertEqual(fn('foo%23bar'), 'foo#bar')
self.assertEqual(fn('foo%3Fbar%3Dbaz'), 'foo?bar=baz')
self.assertEqual(fn('foo%3Fbar%23baz'), 'foo?bar#baz')
def test_url2pathname_require_scheme(self): def test_url2pathname_require_scheme(self):
sep = os.path.sep sep = os.path.sep

View file

@ -1654,11 +1654,11 @@ def url2pathname(url, *, require_scheme=False, resolve_host=False):
The URL authority may be resolved with gethostbyname() if The URL authority may be resolved with gethostbyname() if
*resolve_host* is set to true. *resolve_host* is set to true.
""" """
if require_scheme: if not require_scheme:
scheme, url = _splittype(url) url = 'file:' + url
if scheme != 'file': scheme, authority, url = urlsplit(url)[:3] # Discard query and fragment.
raise URLError("URL is missing a 'file:' scheme") if scheme != 'file':
authority, url = _splithost(url) raise URLError("URL is missing a 'file:' scheme")
if os.name == 'nt': if os.name == 'nt':
if not _is_local_authority(authority, resolve_host): if not _is_local_authority(authority, resolve_host):
# e.g. file://server/share/file.txt # e.g. file://server/share/file.txt

View file

@ -0,0 +1 @@
Discard URL query and fragment in :func:`urllib.request.url2pathname`.