summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_urllib2.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_urllib2.py')
-rw-r--r--Lib/test/test_urllib2.py138
1 files changed, 114 insertions, 24 deletions
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index 62226b8..d8c302b 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -4,6 +4,7 @@ from test import support
import os
import io
import socket
+import array
import urllib.request
# The proxy bypass method imported below has logic specific to the OSX
@@ -25,11 +26,6 @@ class TrivialTests(unittest.TestCase):
# XXX Name hacking to get this to work on Windows.
fname = os.path.abspath(urllib.request.__file__).replace('\\', '/')
- # And more hacking to get it to work on MacOS. This assumes
- # urllib.pathname2url works, unfortunately...
- if os.name == 'mac':
- fname = '/' + fname.replace(':', '/')
-
if os.name == 'nt':
file_url = "file:///%s" % fname
else:
@@ -299,7 +295,7 @@ class MockHTTPClass:
def set_debuglevel(self, level):
self.level = level
- def _set_tunnel(self, host, port=None, headers=None):
+ def set_tunnel(self, host, port=None, headers=None):
self._tunnel_host = host
self._tunnel_port = port
if headers:
@@ -321,6 +317,9 @@ class MockHTTPClass:
def getresponse(self):
return MockHTTPResponse(MockFile(), {}, 200, "OK")
+ def close(self):
+ pass
+
class MockHandler:
# useful for testing handler machinery
# see add_ordered_mock_handlers() docstring
@@ -592,12 +591,12 @@ class OpenerDirectorTests(unittest.TestCase):
# *_request
self.assertEqual((handler, name), calls[i])
self.assertEqual(len(args), 1)
- self.assertTrue(isinstance(args[0], Request))
+ self.assertIsInstance(args[0], Request)
else:
# *_response
self.assertEqual((handler, name), calls[i])
self.assertEqual(len(args), 2)
- self.assertTrue(isinstance(args[0], Request))
+ self.assertIsInstance(args[0], Request)
# response from opener.open is None, because there's no
# handler that defines http_open to handle it
self.assertTrue(args[1] is None or
@@ -605,6 +604,10 @@ class OpenerDirectorTests(unittest.TestCase):
def sanepathname2url(path):
+ try:
+ path.encode("utf8")
+ except UnicodeEncodeError:
+ raise unittest.SkipTest("path is not encodable to utf8")
urlpath = urllib.request.pathname2url(path)
if os.name == "nt" and urlpath.startswith("///"):
urlpath = urlpath[2:]
@@ -619,6 +622,7 @@ class HandlerTests(unittest.TestCase):
def retrfile(self, filename, filetype):
self.filename, self.filetype = filename, filetype
return io.StringIO(self.data), len(self.data)
+ def close(self): pass
class NullFTPHandler(urllib.request.FTPHandler):
def __init__(self, data): self.data = data
@@ -745,11 +749,11 @@ class HandlerTests(unittest.TestCase):
# file:///blah.txt (a file)
# file://ftp.example.com/blah.txt (an ftp URL)
for url, ftp in [
- ("file://ftp.example.com//foo.txt", True),
+ ("file://ftp.example.com//foo.txt", False),
("file://ftp.example.com///foo.txt", False),
# XXXX bug: fails with OSError, should be URLError
("file://ftp.example.com/foo.txt", False),
- ("file://somehost//foo/something.txt", True),
+ ("file://somehost//foo/something.txt", False),
("file://localhost//foo/something.txt", False),
]:
req = Request(url)
@@ -769,7 +773,7 @@ class HandlerTests(unittest.TestCase):
o = h.parent = MockOpener()
url = "http://example.com/"
- for method, data in [("GET", None), ("POST", "blah")]:
+ for method, data in [("GET", None), ("POST", b"blah")]:
req = Request(url, data, {"Foo": "bar"})
req.timeout = None
req.add_unredirected_header("Spam", "eggs")
@@ -797,15 +801,19 @@ class HandlerTests(unittest.TestCase):
http.raise_on_endheaders = True
self.assertRaises(urllib.error.URLError, h.do_open, http, req)
+ # Check for TypeError on POST data which is str.
+ req = Request("http://example.com/","badpost")
+ self.assertRaises(TypeError, h.do_request_, req)
+
# check adding of standard headers
o.addheaders = [("Spam", "eggs")]
- for data in "", None: # POST, GET
+ for data in b"", None: # POST, GET
req = Request("http://example.com/", data)
r = MockResponse(200, "OK", {}, "")
newreq = h.do_request_(req)
if data is None: # GET
- self.assertTrue("Content-length" not in req.unredirected_hdrs)
- self.assertTrue("Content-type" not in req.unredirected_hdrs)
+ self.assertNotIn("Content-length", req.unredirected_hdrs)
+ self.assertNotIn("Content-type", req.unredirected_hdrs)
else: # POST
self.assertEqual(req.unredirected_hdrs["Content-length"], "0")
self.assertEqual(req.unredirected_hdrs["Content-type"],
@@ -825,14 +833,56 @@ class HandlerTests(unittest.TestCase):
self.assertEqual(req.unredirected_hdrs["Host"], "baz")
self.assertEqual(req.unredirected_hdrs["Spam"], "foo")
+ # Check iterable body support
+ def iterable_body():
+ yield b"one"
+ yield b"two"
+ yield b"three"
+
+ for headers in {}, {"Content-Length": 11}:
+ req = Request("http://example.com/", iterable_body(), headers)
+ if not headers:
+ # Having an iterable body without a Content-Length should
+ # raise an exception
+ self.assertRaises(ValueError, h.do_request_, req)
+ else:
+ newreq = h.do_request_(req)
+
+ # A file object.
+ # Test only Content-Length attribute of request.
+
+ file_obj = io.BytesIO()
+ file_obj.write(b"Something\nSomething\nSomething\n")
+
+ for headers in {}, {"Content-Length": 30}:
+ req = Request("http://example.com/", file_obj, headers)
+ if not headers:
+ # Having an iterable body without a Content-Length should
+ # raise an exception
+ self.assertRaises(ValueError, h.do_request_, req)
+ else:
+ newreq = h.do_request_(req)
+ self.assertEqual(int(newreq.get_header('Content-length')),30)
+
+ file_obj.close()
+
+ # array.array Iterable - Content Length is calculated
+
+ iterable_array = array.array("I",[1,2,3,4])
+
+ for headers in {}, {"Content-Length": 16}:
+ req = Request("http://example.com/", iterable_array, headers)
+ newreq = h.do_request_(req)
+ self.assertEqual(int(newreq.get_header('Content-length')),16)
+
def test_http_doubleslash(self):
# Checks the presence of any unnecessary double slash in url does not
# break anything. Previously, a double slash directly after the host
- # could could cause incorrect parsing.
+ # could cause incorrect parsing.
h = urllib.request.AbstractHTTPHandler()
o = h.parent = MockOpener()
- data = ""
+ data = b""
ds_urls = [
"http://example.com/foo/bar/baz.html",
"http://example.com//foo/bar/baz.html",
@@ -945,13 +995,13 @@ class HandlerTests(unittest.TestCase):
# now it's a GET, there should not be headers regarding content
# (possibly dragged from before being a POST)
headers = [x.lower() for x in o.req.headers]
- self.assertTrue("content-length" not in headers)
- self.assertTrue("content-type" not in headers)
+ self.assertNotIn("content-length", headers)
+ self.assertNotIn("content-type", headers)
self.assertEqual(o.req.headers["Nonsense"],
"viking=withhold")
- self.assertTrue("Spam" not in o.req.headers)
- self.assertTrue("Spam" not in o.req.unredirected_hdrs)
+ self.assertNotIn("Spam", o.req.headers)
+ self.assertNotIn("Spam", o.req.unredirected_hdrs)
# loop detection
req = Request(from_url)
@@ -1009,6 +1059,19 @@ class HandlerTests(unittest.TestCase):
MockHeaders({"location": valid_url}))
self.assertEqual(o.req.get_full_url(), valid_url)
+ def test_relative_redirect(self):
+ from_url = "http://example.com/a.html"
+ relative_url = "/b.html"
+ h = urllib.request.HTTPRedirectHandler()
+ o = h.parent = MockOpener()
+ req = Request(from_url)
+ req.timeout = socket._GLOBAL_DEFAULT_TIMEOUT
+
+ valid_url = urllib.parse.urljoin(from_url,relative_url)
+ h.http_error_302(req, MockFile(), 302, "That's fine",
+ MockHeaders({"location": valid_url}))
+ self.assertEqual(o.req.get_full_url(), valid_url)
+
def test_cookie_redirect(self):
# cookies shouldn't leak into redirected requests
from http.cookiejar import CookieJar
@@ -1108,10 +1171,10 @@ class HandlerTests(unittest.TestCase):
# Verify Proxy-Authorization gets tunneled to request.
# httpsconn req_headers do not have the Proxy-Authorization header but
# the req will have.
- self.assertFalse(("Proxy-Authorization","FooBar") in
+ self.assertNotIn(("Proxy-Authorization","FooBar"),
https_handler.httpconn.req_headers)
- self.assertTrue(("User-Agent","Grail") in
- https_handler.httpconn.req_headers)
+ self.assertIn(("User-Agent","Grail"),
+ https_handler.httpconn.req_headers)
self.assertIsNotNone(req._tunnel_host)
self.assertEqual(req.get_host(), "proxy.example.com:3128")
self.assertEqual(req.get_header("Proxy-authorization"),"FooBar")
@@ -1155,6 +1218,22 @@ class HandlerTests(unittest.TestCase):
def test_basic_auth_with_single_quoted_realm(self):
self.test_basic_auth(quote_char="'")
+ def test_basic_auth_with_unquoted_realm(self):
+ opener = OpenerDirector()
+ password_manager = MockPasswordManager()
+ auth_handler = urllib.request.HTTPBasicAuthHandler(password_manager)
+ realm = "ACME Widget Store"
+ http_handler = MockHTTPHandler(
+ 401, 'WWW-Authenticate: Basic realm=%s\r\n\r\n' % realm)
+ opener.add_handler(auth_handler)
+ opener.add_handler(http_handler)
+ with self.assertWarns(UserWarning):
+ self._test_basic_auth(opener, auth_handler, "Authorization",
+ realm, http_handler, password_manager,
+ "http://acme.example.com/protected",
+ "http://acme.example.com/protected",
+ )
+
def test_proxy_basic_auth(self):
opener = OpenerDirector()
ph = urllib.request.ProxyHandler(dict(http="proxy.example.com:3128"))
@@ -1173,7 +1252,7 @@ class HandlerTests(unittest.TestCase):
)
def test_basic_and_digest_auth_handlers(self):
- # HTTPDigestAuthHandler threw an exception if it couldn't handle a 40*
+ # HTTPDigestAuthHandler raised an exception if it couldn't handle a 40*
# response (http://python.org/sf/1479302), where it should instead
# return None to allow another handler (especially
# HTTPBasicAuthHandler) to handle the response.
@@ -1359,6 +1438,17 @@ class RequestTests(unittest.TestCase):
req = Request(url)
self.assertEqual(req.get_full_url(), url)
+def test_HTTPError_interface():
+ """
+ Issue 13211 reveals that HTTPError didn't implement the URLError
+ interface even though HTTPError is a subclass of URLError.
+
+ >>> err = urllib.error.HTTPError(msg='something bad happened', url=None, code=None, hdrs=None, fp=None)
+ >>> assert hasattr(err, 'reason')
+ >>> err.reason
+ 'something bad happened'
+ """
+
def test_main(verbose=None):
from test import test_urllib2
support.run_doctest(test_urllib2, verbose)