diff -r fb70ea8b7b2d Lib/test/test_urlparse.py --- a/Lib/test/test_urlparse.py Tue Apr 26 09:31:11 2016 +0300 +++ b/Lib/test/test_urlparse.py Tue Apr 26 15:28:20 2016 +0300 @@ -748,7 +748,6 @@ class UrlParseTestCase(unittest.TestCase self.assertEqual(func(b"path", scheme=b"ftp").scheme, b"ftp") self.assertEqual(func("path").scheme, "") self.assertEqual(func(b"path").scheme, b"") - self.assertEqual(func(b"path", "").scheme, b"") def test_parse_fragments(self): # Exercise the allow_fragments parameter of urlparse() and urlsplit() @@ -800,6 +799,113 @@ class UrlParseTestCase(unittest.TestCase with self.assertRaisesRegex(TypeError, "Cannot mix str"): urllib.parse.urljoin(b"http://python.org", "http://python.org") + def test_false_args(self): + from urllib.parse import (urlparse, urlsplit, urlunparse, urlunsplit, + urljoin, urldefrag, parse_qsl) + + self.assertRaises(TypeError, urlparse, None) + self.assertRaises(AttributeError, urlparse, ()) + self.assertRaises(TypeError, urlparse, b'www.python.org', '') + self.assertRaises(TypeError, urlparse, 'www.python.org', b'') + + self.assertRaises(TypeError, urlsplit, None) + self.assertRaises(AttributeError, urlsplit, ()) + self.assertRaises(TypeError, urlsplit, b'www.python.org', '') + self.assertRaises(TypeError, urlsplit, 'www.python.org', b'') + + with self.assertRaises(TypeError): + urlunparse((b"", "www.python.org", "", "", "", "")) + with self.assertRaises(TypeError): + urlunparse((None, "www.python.org", "", "", "", "")) + with self.assertRaises(TypeError): + urlunparse(("http", b"", "", "", "", "")) + with self.assertRaises(TypeError): + urlunparse(("http", None, "", "", "", "")) + with self.assertRaises(TypeError): + urlunparse(("http", "www.python.org", b"", "", "", "")) + with self.assertRaises(TypeError): + urlunparse(("http", "www.python.org", None, "", "", "")) + with self.assertRaises(TypeError): + urlunparse(("http", "www.python.org", "", b"", "", "")) + with self.assertRaises(TypeError): + urlunparse(("http", "www.python.org", "", None, "", "")) + with self.assertRaises(TypeError): + urlunparse(("http", "www.python.org", "", "", b"", "")) + with self.assertRaises(TypeError): + urlunparse(("http", "www.python.org", "", "", None, "")) + with self.assertRaises(TypeError): + urlunparse(("http", "www.python.org", "", "", "", b"")) + with self.assertRaises(TypeError): + urlunparse(("http", "www.python.org", "", "", "", None)) + with self.assertRaises(TypeError): + urlunparse(("", b"www.python.org", b"", b"", b"", b"")) + with self.assertRaises(AttributeError): + urlunparse((None, b"www.python.org", b"", b"", b"", b"")) + with self.assertRaises(TypeError): + urlunparse((b"http", "", b"", b"", b"", b"")) + with self.assertRaises(AttributeError): + urlunparse((b"http", None, b"", b"", b"", b"")) + with self.assertRaises(TypeError): + urlunparse((b"http", b"www.python.org", "", b"", b"", b"")) + with self.assertRaises(AttributeError): + urlunparse((b"http", b"www.python.org", None, b"", b"", b"")) + with self.assertRaises(TypeError): + urlunparse((b"http", b"www.python.org", b"", "", b"", b"")) + with self.assertRaises(AttributeError): + urlunparse((b"http", b"www.python.org", b"", None, b"", b"")) + with self.assertRaises(TypeError): + urlunparse((b"http", b"www.python.org", b"", b"", "", b"")) + with self.assertRaises(AttributeError): + urlunparse((b"http", b"www.python.org", b"", b"", None, b"")) + with self.assertRaises(TypeError): + urlunparse((b"http", b"www.python.org", b"", b"", b"", "")) + with self.assertRaises(AttributeError): + urlunparse((b"http", b"www.python.org", b"", b"", b"", None)) + + with self.assertRaises(TypeError): + urlunsplit((b"", "www.python.org", "", "", "")) + with self.assertRaises(TypeError): + urlunsplit((None, "www.python.org", "", "", "")) + with self.assertRaises(TypeError): + urlunsplit(("http", b"", "", "", "")) + with self.assertRaises(TypeError): + urlunsplit(("http", None, "", "", "")) + with self.assertRaises(TypeError): + urlunsplit(("http", "www.python.org", b"", "", "")) + with self.assertRaises(TypeError): + urlunsplit(("http", "www.python.org", None, "", "")) + with self.assertRaises(TypeError): + urlunsplit(("http", "www.python.org", "", b"", "")) + with self.assertRaises(TypeError): + urlunsplit(("http", "www.python.org", "", None, "")) + with self.assertRaises(TypeError): + urlunsplit(("http", "www.python.org", "", "", b"")) + with self.assertRaises(TypeError): + urlunsplit(("http", "www.python.org", "", "", None)) + with self.assertRaises(TypeError): + urlunsplit(("", b"www.python.org", b"", b"", b"")) + with self.assertRaises(AttributeError): + urlunsplit((None, b"www.python.org", b"", b"", b"")) + with self.assertRaises(TypeError): + urlunsplit((b"http", "", b"", b"", b"")) + with self.assertRaises(AttributeError): + urlunsplit((b"http", None, b"", b"", b"")) + with self.assertRaises(TypeError): + urlunsplit((b"http", b"www.python.org", "", b"", b"")) + with self.assertRaises(AttributeError): + urlunsplit((b"http", b"www.python.org", None, b"", b"")) + with self.assertRaises(TypeError): + urlunsplit((b"http", b"www.python.org", b"", "", b"")) + with self.assertRaises(AttributeError): + urlunsplit((b"http", b"www.python.org", b"", None, b"")) + with self.assertRaises(TypeError): + urlunsplit((b"http", b"www.python.org", b"", b"", "")) + with self.assertRaises(AttributeError): + urlunsplit((b"http", b"www.python.org", b"", b"", None)) + + self.assertRaises(AttributeError, urldefrag, None) + self.assertRaises(AttributeError, parse_qsl, None) + def _check_result_type(self, str_type): num_args = len(str_type._fields) bytes_type = str_type._encoded_counterpart diff -r fb70ea8b7b2d Lib/urllib/parse.py --- a/Lib/urllib/parse.py Tue Apr 26 09:31:11 2016 +0300 +++ b/Lib/urllib/parse.py Tue Apr 26 15:28:20 2016 +0300 @@ -95,7 +95,7 @@ def _encode_result(obj, encoding=_implic def _decode_args(args, encoding=_implicit_encoding, errors=_implicit_errors): - return tuple(x.decode(encoding, errors) if x else '' for x in args) + return tuple(x.decode(encoding, errors) for x in args) def _coerce_args(*args): # Invokes decode if necessary to create str args @@ -104,11 +104,11 @@ def _coerce_args(*args): # - noop for str inputs # - encoding function otherwise str_input = isinstance(args[0], str) + for arg in args[1:]: - # We special-case the empty string to support the - # "scheme=''" default argument to some functions - if arg and isinstance(arg, str) != str_input: + if isinstance(arg, str) != str_input: raise TypeError("Cannot mix str and non-str arguments") + if str_input: return args + (_noop,) return _decode_args(args) + (_encode_result,) @@ -347,12 +347,16 @@ def _fix_result_transcoding(): _fix_result_transcoding() del _fix_result_transcoding -def urlparse(url, scheme='', allow_fragments=True): +_sentinel = object() + +def urlparse(url, scheme=_sentinel, allow_fragments=True): """Parse a URL into 6 components: :///;?# Return a 6-tuple: (scheme, netloc, path, params, query, fragment). Note that we don't break the components up in smaller bits (e.g. netloc is a single string) and we don't expand % escapes.""" + if scheme is _sentinel: + scheme = url[:0] url, scheme, _coerce_result = _coerce_args(url, scheme) splitresult = urlsplit(url, scheme, allow_fragments) scheme, netloc, url, query, fragment = splitresult @@ -380,12 +384,14 @@ def _splitnetloc(url, start=0): delim = min(delim, wdelim) # use earliest delim position return url[start:delim], url[delim:] # return (domain, rest) -def urlsplit(url, scheme='', allow_fragments=True): +def urlsplit(url, scheme=_sentinel, allow_fragments=True): """Parse a URL into 5 components: :///?# Return a 5-tuple: (scheme, netloc, path, query, fragment). Note that we don't break the components up in smaller bits (e.g. netloc is a single string) and we don't expand % escapes.""" + if scheme is _sentinel: + scheme = url[:0] url, scheme, _coerce_result = _coerce_args(url, scheme) allow_fragments = bool(allow_fragments) key = url, scheme, allow_fragments, type(url), type(scheme)