mirror of https://github.com/python/cpython
[3.13] gh-85110: Preserve relative path in URL without netloc in urllib.parse.urlunsplit() (GH-123179) (#123187)
gh-85110: Preserve relative path in URL without netloc in urllib.parse.urlunsplit() (GH-123179)
(cherry picked from commit 90c892efea
)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
2b4c31d87d
commit
4ea9c5ba78
|
@ -207,6 +207,9 @@ class UrlParseTestCase(unittest.TestCase):
|
||||||
('scheme://///path/to/file',
|
('scheme://///path/to/file',
|
||||||
('scheme', '', '///path/to/file', '', '', ''),
|
('scheme', '', '///path/to/file', '', '', ''),
|
||||||
('scheme', '', '///path/to/file', '', '')),
|
('scheme', '', '///path/to/file', '', '')),
|
||||||
|
('file:tmp/junk.txt',
|
||||||
|
('file', '', 'tmp/junk.txt', '', '', ''),
|
||||||
|
('file', '', 'tmp/junk.txt', '', '')),
|
||||||
('file:///tmp/junk.txt',
|
('file:///tmp/junk.txt',
|
||||||
('file', '', '/tmp/junk.txt', '', '', ''),
|
('file', '', '/tmp/junk.txt', '', '', ''),
|
||||||
('file', '', '/tmp/junk.txt', '', '')),
|
('file', '', '/tmp/junk.txt', '', '')),
|
||||||
|
@ -216,6 +219,18 @@ class UrlParseTestCase(unittest.TestCase):
|
||||||
('file://///tmp/junk.txt',
|
('file://///tmp/junk.txt',
|
||||||
('file', '', '///tmp/junk.txt', '', '', ''),
|
('file', '', '///tmp/junk.txt', '', '', ''),
|
||||||
('file', '', '///tmp/junk.txt', '', '')),
|
('file', '', '///tmp/junk.txt', '', '')),
|
||||||
|
('http:tmp/junk.txt',
|
||||||
|
('http', '', 'tmp/junk.txt', '', '', ''),
|
||||||
|
('http', '', 'tmp/junk.txt', '', '')),
|
||||||
|
('http://example.com/tmp/junk.txt',
|
||||||
|
('http', 'example.com', '/tmp/junk.txt', '', '', ''),
|
||||||
|
('http', 'example.com', '/tmp/junk.txt', '', '')),
|
||||||
|
('http:///example.com/tmp/junk.txt',
|
||||||
|
('http', '', '/example.com/tmp/junk.txt', '', '', ''),
|
||||||
|
('http', '', '/example.com/tmp/junk.txt', '', '')),
|
||||||
|
('http:////example.com/tmp/junk.txt',
|
||||||
|
('http', '', '//example.com/tmp/junk.txt', '', '', ''),
|
||||||
|
('http', '', '//example.com/tmp/junk.txt', '', '')),
|
||||||
('imap://mail.python.org/mbox1',
|
('imap://mail.python.org/mbox1',
|
||||||
('imap', 'mail.python.org', '/mbox1', '', '', ''),
|
('imap', 'mail.python.org', '/mbox1', '', '', ''),
|
||||||
('imap', 'mail.python.org', '/mbox1', '', '')),
|
('imap', 'mail.python.org', '/mbox1', '', '')),
|
||||||
|
@ -260,7 +275,8 @@ class UrlParseTestCase(unittest.TestCase):
|
||||||
('', '', 'schème:path/to/file', '', '')),
|
('', '', 'schème:path/to/file', '', '')),
|
||||||
]
|
]
|
||||||
for url, parsed, split in str_cases + bytes_cases:
|
for url, parsed, split in str_cases + bytes_cases:
|
||||||
self.checkRoundtrips(url, parsed, split)
|
with self.subTest(url):
|
||||||
|
self.checkRoundtrips(url, parsed, split)
|
||||||
|
|
||||||
def test_roundtrips_normalization(self):
|
def test_roundtrips_normalization(self):
|
||||||
str_cases = [
|
str_cases = [
|
||||||
|
@ -292,7 +308,8 @@ class UrlParseTestCase(unittest.TestCase):
|
||||||
tuple(x.encode('ascii') for x in t[3]))
|
tuple(x.encode('ascii') for x in t[3]))
|
||||||
bytes_cases = [_encode(x) for x in str_cases]
|
bytes_cases = [_encode(x) for x in str_cases]
|
||||||
for url, url2, parsed, split in str_cases + bytes_cases:
|
for url, url2, parsed, split in str_cases + bytes_cases:
|
||||||
self.checkRoundtrips(url, parsed, split, url2)
|
with self.subTest(url):
|
||||||
|
self.checkRoundtrips(url, parsed, split, url2)
|
||||||
|
|
||||||
def test_http_roundtrips(self):
|
def test_http_roundtrips(self):
|
||||||
# urllib.parse.urlsplit treats 'http:' as an optimized special case,
|
# urllib.parse.urlsplit treats 'http:' as an optimized special case,
|
||||||
|
@ -333,11 +350,17 @@ class UrlParseTestCase(unittest.TestCase):
|
||||||
self.checkRoundtrips(url, parsed, split)
|
self.checkRoundtrips(url, parsed, split)
|
||||||
|
|
||||||
def checkJoin(self, base, relurl, expected):
|
def checkJoin(self, base, relurl, expected):
|
||||||
str_components = (base, relurl, expected)
|
with self.subTest(base=base, relurl=relurl):
|
||||||
self.assertEqual(urllib.parse.urljoin(base, relurl), expected)
|
self.assertEqual(urllib.parse.urljoin(base, relurl), expected)
|
||||||
bytes_components = baseb, relurlb, expectedb = [
|
baseb = base.encode('ascii')
|
||||||
x.encode('ascii') for x in str_components]
|
relurlb = relurl.encode('ascii')
|
||||||
self.assertEqual(urllib.parse.urljoin(baseb, relurlb), expectedb)
|
expectedb = expected.encode('ascii')
|
||||||
|
self.assertEqual(urllib.parse.urljoin(baseb, relurlb), expectedb)
|
||||||
|
|
||||||
|
relurl = urllib.parse.urlunsplit(urllib.parse.urlsplit(relurl))
|
||||||
|
self.assertEqual(urllib.parse.urljoin(base, relurl), expected)
|
||||||
|
relurlb = urllib.parse.urlunsplit(urllib.parse.urlsplit(relurlb))
|
||||||
|
self.assertEqual(urllib.parse.urljoin(baseb, relurlb), expectedb)
|
||||||
|
|
||||||
def test_unparse_parse(self):
|
def test_unparse_parse(self):
|
||||||
str_cases = ['Python', './Python','x-newscheme://foo.com/stuff','x://y','x:/y','x:/','/',]
|
str_cases = ['Python', './Python','x-newscheme://foo.com/stuff','x://y','x:/y','x:/','/',]
|
||||||
|
|
|
@ -525,9 +525,13 @@ def urlunsplit(components):
|
||||||
empty query; the RFC states that these are equivalent)."""
|
empty query; the RFC states that these are equivalent)."""
|
||||||
scheme, netloc, url, query, fragment, _coerce_result = (
|
scheme, netloc, url, query, fragment, _coerce_result = (
|
||||||
_coerce_args(*components))
|
_coerce_args(*components))
|
||||||
if netloc or (scheme and scheme in uses_netloc) or url[:2] == '//':
|
if netloc:
|
||||||
if url and url[:1] != '/': url = '/' + url
|
if url and url[:1] != '/': url = '/' + url
|
||||||
url = '//' + (netloc or '') + url
|
url = '//' + netloc + url
|
||||||
|
elif url[:2] == '//':
|
||||||
|
url = '//' + url
|
||||||
|
elif scheme and scheme in uses_netloc and (not url or url[:1] == '/'):
|
||||||
|
url = '//' + url
|
||||||
if scheme:
|
if scheme:
|
||||||
url = scheme + ':' + url
|
url = scheme + ':' + url
|
||||||
if query:
|
if query:
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Preserve relative path in URL without netloc in
|
||||||
|
:func:`urllib.parse.urlunsplit` and :func:`urllib.parse.urlunparse`.
|
Loading…
Reference in New Issue