Skip to content

Commit

Permalink
pythongh-85110: Preserve relative path in URL without netloc in urlli…
Browse files Browse the repository at this point in the history
…b.parse.urlunsplit() (pythonGH-123179)
  • Loading branch information
serhiy-storchaka authored Aug 21, 2024
1 parent 9dbd123 commit 90c892e
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 9 deletions.
37 changes: 30 additions & 7 deletions Lib/test/test_urlparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ def test_roundtrips(self):
('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', '', '')),
Expand All @@ -216,6 +219,18 @@ def test_roundtrips(self):
('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', '', '')),
Expand Down Expand Up @@ -260,7 +275,8 @@ def _encode(t):
('', '', 'schème:path/to/file', '', '')),
]
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):
str_cases = [
Expand Down Expand Up @@ -292,7 +308,8 @@ def _encode(t):
tuple(x.encode('ascii') for x in t[3]))
bytes_cases = [_encode(x) for x in str_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):
# urllib.parse.urlsplit treats 'http:' as an optimized special case,
Expand Down Expand Up @@ -333,11 +350,17 @@ def _encode(t):
self.checkRoundtrips(url, parsed, split)

def checkJoin(self, base, relurl, expected):
str_components = (base, relurl, expected)
self.assertEqual(urllib.parse.urljoin(base, relurl), expected)
bytes_components = baseb, relurlb, expectedb = [
x.encode('ascii') for x in str_components]
self.assertEqual(urllib.parse.urljoin(baseb, relurlb), expectedb)
with self.subTest(base=base, relurl=relurl):
self.assertEqual(urllib.parse.urljoin(base, relurl), expected)
baseb = base.encode('ascii')
relurlb = relurl.encode('ascii')
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):
str_cases = ['Python', './Python','x-newscheme://foo.com/stuff','x://y','x:/y','x:/','/',]
Expand Down
8 changes: 6 additions & 2 deletions Lib/urllib/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,9 +525,13 @@ def urlunsplit(components):
empty query; the RFC states that these are equivalent)."""
scheme, netloc, url, query, fragment, _coerce_result = (
_coerce_args(*components))
if netloc or (scheme and scheme in uses_netloc) or url[:2] == '//':
if netloc:
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:
url = scheme + ':' + url
if query:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Preserve relative path in URL without netloc in
:func:`urllib.parse.urlunsplit` and :func:`urllib.parse.urlunparse`.

0 comments on commit 90c892e

Please sign in to comment.