mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	gh-85110: Preserve relative path in URL without netloc in urllib.parse.urlunsplit() (GH-123179)
This commit is contained in:
		
							parent
							
								
									9dbd123755
								
							
						
					
					
						commit
						90c892efea
					
				
					 3 changed files with 38 additions and 9 deletions
				
			
		|  | @ -207,6 +207,9 @@ def test_roundtrips(self): | ||||||
|             ('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 @@ def test_roundtrips(self): | ||||||
|             ('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 @@ def _encode(t): | ||||||
|              ('', '', '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 @@ def _encode(t): | ||||||
|                     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 @@ def _encode(t): | ||||||
|                     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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Serhiy Storchaka
						Serhiy Storchaka