diff options
-rw-r--r-- | Lib/test/test_urllib2.py | 2 | ||||
-rw-r--r-- | Lib/test/test_urllib2net.py | 92 | ||||
-rw-r--r-- | Lib/urllib2.py | 16 |
3 files changed, 108 insertions, 2 deletions
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py index 6e9901f..c68d244 100644 --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -423,6 +423,8 @@ class HandlerTests(unittest.TestCase): self.msg = msg self.status = status self.reason = reason + def read(self): + return '' class MockHTTPClass: def __init__(self): self.req_headers = [] diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py new file mode 100644 index 0000000..3c23246 --- /dev/null +++ b/Lib/test/test_urllib2net.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python + +import unittest +from test import test_support + +import socket +import urllib2 +import sys +import os +import mimetools + +class URLTimeoutTest(unittest.TestCase): + + TIMEOUT = 10.0 + + def setUp(self): + socket.setdefaulttimeout(self.TIMEOUT) + + def tearDown(self): + socket.setdefaulttimeout(None) + + def testURLread(self): + f = urllib2.urlopen("http://www.python.org/") + x = f.read() + +class urlopenNetworkTests(unittest.TestCase): + """Tests urllib2.urlopen using the network. + + These tests are not exhaustive. Assuming that testing using files does a + good job overall of some of the basic interface features. There are no + tests exercising the optional 'data' and 'proxies' arguments. No tests + for transparent redirection have been written. + + setUp is not used for always constructing a connection to + http://www.python.org/ since there a few tests that don't use that address + and making a connection is expensive enough to warrant minimizing unneeded + connections. + + """ + + def test_basic(self): + # Simple test expected to pass. + open_url = urllib2.urlopen("http://www.python.org/") + for attr in ("read", "close", "info", "geturl"): + self.assert_(hasattr(open_url, attr), "object returned from " + "urlopen lacks the %s attribute" % attr) + try: + self.assert_(open_url.read(), "calling 'read' failed") + finally: + open_url.close() + + def test_info(self): + # Test 'info'. + open_url = urllib2.urlopen("http://www.python.org/") + try: + info_obj = open_url.info() + finally: + open_url.close() + self.assert_(isinstance(info_obj, mimetools.Message), + "object returned by 'info' is not an instance of " + "mimetools.Message") + self.assertEqual(info_obj.getsubtype(), "html") + + def test_geturl(self): + # Make sure same URL as opened is returned by geturl. + URL = "http://www.python.org/" + open_url = urllib2.urlopen(URL) + try: + gotten_url = open_url.geturl() + finally: + open_url.close() + self.assertEqual(gotten_url, URL) + + def test_bad_address(self): + # Make sure proper exception is raised when connecting to a bogus + # address. + self.assertRaises(IOError, + # SF patch 809915: In Sep 2003, VeriSign started + # highjacking invalid .com and .net addresses to + # boost traffic to their own site. This test + # started failing then. One hopes the .invalid + # domain will be spared to serve its defined + # purpose. + # urllib2.urlopen, "http://www.sadflkjsasadf.com/") + urllib2.urlopen, "http://www.python.invalid/") + +def test_main(): + test_support.requires("network") + test_support.run_unittest(URLTimeoutTest, urlopenNetworkTests) + +if __name__ == "__main__": + test_main() diff --git a/Lib/urllib2.py b/Lib/urllib2.py index c525f8c..9ec8b9b 100644 --- a/Lib/urllib2.py +++ b/Lib/urllib2.py @@ -997,8 +997,20 @@ class AbstractHTTPHandler(BaseHandler): raise URLError(err) # Pick apart the HTTPResponse object to get the addinfourl - # object initialized properly - resp = addinfourl(r.fp, r.msg, req.get_full_url()) + # object initialized properly. + + # Wrap the HTTPResponse object in socket's file object adapter + # for Windows. That adapter calls recv(), so delegate recv() + # to read(). This weird wrapping allows the returned object to + # have readline() and readlines() methods. + + # XXX It might be better to extract the read buffering code + # out of socket._fileobject() and into a base class. + + r.recv = r.read + fp = socket._fileobject(r) + + resp = addinfourl(fp, r.msg, req.get_full_url()) resp.code = r.status resp.msg = r.reason return resp |