diff --git a/Lib/locale.py b/Lib/locale.py --- a/Lib/locale.py +++ b/Lib/locale.py @@ -442,13 +442,17 @@ No aliasing or normalizing takes place. """ - language, encoding = localetuple - if language is None: - language = 'C' - if encoding is None: - return language - else: - return language + '.' + encoding + try: + language, encoding = localetuple + + if language is None: + language = 'C' + if encoding is None: + return language + else: + return language + '.' + encoding + except (TypeError, ValueError): + raise Error('Locale must be None, a string, or an iterable of two strings -- language code, encoding.') def getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -409,6 +409,20 @@ locale.setlocale(locale.LC_CTYPE, loc) self.assertEqual(loc, locale.getlocale(locale.LC_CTYPE)) + def test_invalid_locale_format_in_localetuple(self): + with self.assertRaises(locale.Error) as e: + locale.setlocale(locale.LC_ALL, b'fi_FI') + self.assertEquals(str(e.exception), + 'Locale must be None, a string, or an iterable of two strings -- language code, encoding.' + ) + + def test_invalid_iterable_in_localetuple(self): + with self.assertRaises(locale.Error) as e: + locale.setlocale(locale.LC_ALL, (b'not', b'valid')) + self.assertEquals(str(e.exception), + 'Locale must be None, a string, or an iterable of two strings -- language code, encoding.' + ) + def test_main(): tests = [ diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -36,6 +36,44 @@ else: return opener.open(url, data) + +class FakeHTTPMixin(object): + def fakehttp(self, fakedata): + class FakeSocket(io.BytesIO): + io_refs = 1 + + def sendall(self, str): + pass + + def makefile(self, *args, **kwds): + self.io_refs += 1 + return self + + def read(self, amt=None): + if self.closed: + return b"" + return io.BytesIO.read(self, amt) + + def readline(self, length=None): + if self.closed: + return b"" + return io.BytesIO.readline(self, length) + + def close(self): + self.io_refs -= 1 + if self.io_refs == 0: + io.BytesIO.close(self) + + class FakeHTTPConnection(http.client.HTTPConnection): + def connect(self): + self.sock = FakeSocket(fakedata) + self._connection_class = http.client.HTTPConnection + http.client.HTTPConnection = FakeHTTPConnection + + def unfakehttp(self): + http.client.HTTPConnection = self._connection_class + + class urlopen_FileTests(unittest.TestCase): """Test urlopen() opening a temporary file. @@ -139,35 +177,9 @@ self.env.set('NO_PROXY', 'localhost, anotherdomain.com, newdomain.com') self.assertTrue(urllib.request.proxy_bypass_environment('anotherdomain.com')) -class urlopen_HttpTests(unittest.TestCase): +class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin): """Test urlopen() opening a fake http connection.""" - def fakehttp(self, fakedata): - class FakeSocket(io.BytesIO): - io_refs = 1 - def sendall(self, str): pass - def makefile(self, *args, **kwds): - self.io_refs += 1 - return self - def read(self, amt=None): - if self.closed: return b"" - return io.BytesIO.read(self, amt) - def readline(self, length=None): - if self.closed: return b"" - return io.BytesIO.readline(self, length) - def close(self): - self.io_refs -= 1 - if self.io_refs == 0: - io.BytesIO.close(self) - class FakeHTTPConnection(http.client.HTTPConnection): - def connect(self): - self.sock = FakeSocket(fakedata) - self._connection_class = http.client.HTTPConnection - http.client.HTTPConnection = FakeHTTPConnection - - def unfakehttp(self): - http.client.HTTPConnection = self._connection_class - def check_read(self, ver): self.fakehttp(b"HTTP/" + ver + b" 200 OK\r\n\r\nHello!") try: @@ -394,6 +406,48 @@ self.assertEqual(report[0][1], 8192) self.assertEqual(report[0][2], 8193) + +class urlretrieve_HttpTests(unittest.TestCase, FakeHTTPMixin): + """Test urllib.urlretrieve() using fake http connections""" + + def test_short_content_raises_ContentTooShortError(self): + self.fakehttp(b'''HTTP/1.1 200 OK +Date: Wed, 02 Jan 2008 03:03:54 GMT +Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e +Connection: close +Content-Length: 100 +Content-Type: text/html; charset=iso-8859-1 + +FF +''') + + def _reporthook(par1, par2, par3): + pass + + with self.assertRaises(urllib.error.ContentTooShortError): + try: + urllib.request.urlretrieve('http://example.com/', + reporthook=_reporthook) + finally: + self.unfakehttp() + + def test_short_content_raises_ContentTooShortError_without_reporthook(self): + self.fakehttp(b'''HTTP/1.1 200 OK +Date: Wed, 02 Jan 2008 03:03:54 GMT +Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e +Connection: close +Content-Length: 100 +Content-Type: text/html; charset=iso-8859-1 + +FF +''') + with self.assertRaises(urllib.error.ContentTooShortError): + try: + urllib.request.urlretrieve('http://example.com/') + finally: + self.unfakehttp() + + class QuotingTests(unittest.TestCase): """Tests for urllib.quote() and urllib.quote_plus() @@ -1186,6 +1240,7 @@ urlopen_FileTests, urlopen_HttpTests, urlretrieve_FileTests, + urlretrieve_HttpTests, ProxyTests, QuotingTests, UnquotingTests, diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -1606,9 +1606,9 @@ size = -1 read = 0 blocknum = 0 + if "content-length" in headers: + size = int(headers["Content-Length"]) if reporthook: - if "content-length" in headers: - size = int(headers["Content-Length"]) reporthook(blocknum, bs, size) while 1: block = fp.read(bs)