diff options
author | Senthil Kumaran <orsenthil@gmail.com> | 2010-04-16 02:46:46 (GMT) |
---|---|---|
committer | Senthil Kumaran <orsenthil@gmail.com> | 2010-04-16 02:46:46 (GMT) |
commit | 8c6d9d7c8d6082e2168f2756c12638284d0f9206 (patch) | |
tree | 05a28701b5677b459cda9931be1783ad6e237cad | |
parent | b7b7c77eb3c62bab5dde55d5ad802df4c90645d5 (diff) | |
download | cpython-8c6d9d7c8d6082e2168f2756c12638284d0f9206.zip cpython-8c6d9d7c8d6082e2168f2756c12638284d0f9206.tar.gz cpython-8c6d9d7c8d6082e2168f2756c12638284d0f9206.tar.bz2 |
Fix issue2987: RFC2732 support for urlparse (IPv6 addresses)
-rw-r--r-- | Lib/test/test_urlparse.py | 34 | ||||
-rw-r--r-- | Lib/urlparse.py | 32 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
3 files changed, 57 insertions, 12 deletions
diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py index 92d19fb..4085de7 100644 --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -238,10 +238,44 @@ class UrlParseTestCase(unittest.TestCase): #self.checkJoin(RFC2396_BASE, '?y', 'http://a/b/c/?y') #self.checkJoin(RFC2396_BASE, ';x', 'http://a/b/c/;x') + def test_RFC3986(self): self.checkJoin(RFC3986_BASE, '?y','http://a/b/c/d;p?y') self.checkJoin(RFC2396_BASE, ';x', 'http://a/b/c/;x') + def test_RFC2732(self): + for url, hostname, port in [ + ('http://Test.python.org:5432/foo/', 'test.python.org', 5432), + ('http://12.34.56.78:5432/foo/', '12.34.56.78', 5432), + ('http://[::1]:5432/foo/', '::1', 5432), + ('http://[dead:beef::1]:5432/foo/', 'dead:beef::1', 5432), + ('http://[dead:beef::]:5432/foo/', 'dead:beef::', 5432), + ('http://[dead:beef:cafe:5417:affe:8FA3:deaf:feed]:5432/foo/', + 'dead:beef:cafe:5417:affe:8fa3:deaf:feed', 5432), + ('http://[::12.34.56.78]:5432/foo/', '::12.34.56.78', 5432), + ('http://[::ffff:12.34.56.78]:5432/foo/', + '::ffff:12.34.56.78', 5432), + ('http://Test.python.org/foo/', 'test.python.org', None), + ('http://12.34.56.78/foo/', '12.34.56.78', None), + ('http://[::1]/foo/', '::1', None), + ('http://[dead:beef::1]/foo/', 'dead:beef::1', None), + ('http://[dead:beef::]/foo/', 'dead:beef::', None), + ('http://[dead:beef:cafe:5417:affe:8FA3:deaf:feed]/foo/', + 'dead:beef:cafe:5417:affe:8fa3:deaf:feed', None), + ('http://[::12.34.56.78]/foo/', '::12.34.56.78', None), + ('http://[::ffff:12.34.56.78]/foo/', + '::ffff:12.34.56.78', None), + ]: + urlparsed = urlparse.urlparse(url) + self.assertEqual((urlparsed.hostname, urlparsed.port) , (hostname, port)) + + for invalid_url in [ + 'http://::12.34.56.78]/', + 'http://[::1/foo/', + 'http://[::ffff:12.34.56.78']: + self.assertRaises(ValueError, lambda : urlparse.urlparse(invalid_url).hostname) + self.assertRaises(ValueError, lambda : urlparse.urlparse(invalid_url)) + def test_urldefrag(self): for url, defrag, frag in [ ('http://python.org#frag', 'http://python.org', 'frag'), diff --git a/Lib/urlparse.py b/Lib/urlparse.py index f6e20af..c169f38 100644 --- a/Lib/urlparse.py +++ b/Lib/urlparse.py @@ -64,22 +64,26 @@ class ResultMixin(object): @property def hostname(self): - netloc = self.netloc - if "@" in netloc: - netloc = netloc.rsplit("@", 1)[1] - if ":" in netloc: - netloc = netloc.split(":", 1)[0] - return netloc.lower() or None + netloc = self.netloc.split('@')[-1] + if '[' in netloc and ']' in netloc: + return netloc.split(']')[0][1:].lower() + elif '[' in netloc or ']' in netloc: + raise ValueError("Invalid IPv6 hostname") + elif ':' in netloc: + return netloc.split(':')[0].lower() + elif netloc == '': + return None + else: + return netloc.lower() @property def port(self): - netloc = self.netloc - if "@" in netloc: - netloc = netloc.rsplit("@", 1)[1] - if ":" in netloc: - port = netloc.split(":", 1)[1] + netloc = self.netloc.split('@')[-1].split(']')[-1] + if ':' in netloc: + port = netloc.split(':')[1] return int(port, 10) - return None + else: + return None from collections import namedtuple @@ -124,6 +128,10 @@ def _splitparams(url): def _splitnetloc(url, start=0): delim = len(url) # position of end of domain part of url, default is end + if '[' in url: # check for invalid IPv6 URL + if not ']' in url: raise ValueError("Invalid IPv6 URL") + elif ']' in url: + if not '[' in url: raise ValueError("Invalid IPv6 URL") for c in '/?#': # look for delimiters; the order is NOT important wdelim = url.find(c, start) # find first of this delim if wdelim >= 0: # if found @@ -15,6 +15,9 @@ Core and Builtins Library ------- +- Issue #2987: RFC2732 support for urlparse (IPv6 addresses). Patch by Tony + Locke and Hans Ulrich Niedermann. + - Issue #7585: difflib context and unified diffs now place a tab between filename and date, conforming to the 'standards' they were originally designed to follow. This improves compatibility with patch tools. |