Back to index

python3.2  3.2.2
Classes | Functions
test.test_urllib2 Namespace Reference

Classes

class  TrivialTests
class  MockOpener
class  MockFile
class  MockHeaders
class  MockResponse
class  MockCookieJar
class  FakeMethod
class  MockHTTPResponse
class  MockHTTPClass
class  MockHandler
class  MockHTTPHandler
class  MockHTTPSHandler
class  MockPasswordManager
class  OpenerDirectorTests
class  HandlerTests
class  MiscTests
class  RequestTests

Functions

def test_request_headers_dict
def test_request_headers_methods
def test_password_manager
def test_password_manager_default_port
def add_ordered_mock_handlers
def build_test_opener
def test_http_error
 def test_error(self):

XXX this doesn't actually seem to be used in standard library,

but should really be tested anyway...


def test_processors
def sanepathname2url
def test_main

Function Documentation

def test.test_urllib2.add_ordered_mock_handlers (   opener,
  meth_spec 
)
Create MockHandlers and add them to an OpenerDirector.

meth_spec: list of lists of tuples and strings defining methods to define
on handlers.  eg:

[["http_error", "ftp_open"], ["http_open"]]

defines methods .http_error() and .ftp_open() on one handler, and
.http_open() on another.  These methods just record their arguments and
return None.  Using a tuple instead of a string causes the method to
perform some action (see MockHandler.handle()), eg:

[["http_error"], [("http_open", "return request")]]

defines .http_error() on one handler (which simply returns None), and
.http_open() on another handler, which returns a Request object.

Definition at line 367 of file test_urllib2.py.

00367 
00368 def add_ordered_mock_handlers(opener, meth_spec):
00369     """Create MockHandlers and add them to an OpenerDirector.
00370 
00371     meth_spec: list of lists of tuples and strings defining methods to define
00372     on handlers.  eg:
00373 
00374     [["http_error", "ftp_open"], ["http_open"]]
00375 
00376     defines methods .http_error() and .ftp_open() on one handler, and
00377     .http_open() on another.  These methods just record their arguments and
00378     return None.  Using a tuple instead of a string causes the method to
00379     perform some action (see MockHandler.handle()), eg:
00380 
00381     [["http_error"], [("http_open", "return request")]]
00382 
00383     defines .http_error() on one handler (which simply returns None), and
00384     .http_open() on another handler, which returns a Request object.
00385 
00386     """
00387     handlers = []
00388     count = 0
00389     for meths in meth_spec:
00390         class MockHandlerSubclass(MockHandler): pass
00391         h = MockHandlerSubclass(meths)
00392         h.handler_order += count
00393         h.add_parent(opener)
00394         count = count + 1
00395         handlers.append(h)
00396         opener.add_handler(h)
00397     return handlers

Here is the caller graph for this function:

def test.test_urllib2.build_test_opener (   handler_instances)

Definition at line 398 of file test_urllib2.py.

00398 
00399 def build_test_opener(*handler_instances):
00400     opener = OpenerDirector()
00401     for h in handler_instances:
00402         opener.add_handler(h)
00403     return opener

Here is the caller graph for this function:

Definition at line 606 of file test_urllib2.py.

00606 
00607 def sanepathname2url(path):
00608     try:
00609         path.encode("utf8")
00610     except UnicodeEncodeError:
00611         raise unittest.SkipTest("path is not encodable to utf8")
00612     urlpath = urllib.request.pathname2url(path)
00613     if os.name == "nt" and urlpath.startswith("///"):
00614         urlpath = urlpath[2:]
00615     # XXX don't ask me about the mac...
00616     return urlpath

Here is the call graph for this function:

Here is the caller graph for this function:

def test_error(self):

XXX this doesn't actually seem to be used in standard library,

but should really be tested anyway...

Definition at line 543 of file test_urllib2.py.

00543 
00544     def test_http_error(self):
00545         # XXX http_error_default
00546         # http errors are a special case
00547         o = OpenerDirector()
00548         meth_spec = [
00549             [("http_open", "error 302")],
00550             [("http_error_400", "raise"), "http_open"],
00551             [("http_error_302", "return response"), "http_error_303",
00552              "http_error"],
00553             [("http_error_302")],
00554             ]
00555         handlers = add_ordered_mock_handlers(o, meth_spec)
00556 
00557         class Unknown:
00558             def __eq__(self, other): return True
00559 
00560         req = Request("http://example.com/")
00561         r = o.open(req)
00562         assert len(o.calls) == 2
00563         calls = [(handlers[0], "http_open", (req,)),
00564                  (handlers[2], "http_error_302",
00565                   (req, Unknown(), 302, "", {}))]
00566         for expected, got in zip(calls, o.calls):
00567             handler, method_name, args = expected
00568             self.assertEqual((handler, method_name), got[:2])
00569             self.assertEqual(args, got[2])

Here is the call graph for this function:

def test.test_urllib2.test_main (   verbose = None)

Definition at line 1412 of file test_urllib2.py.

01412 
01413 def test_main(verbose=None):
01414     from test import test_urllib2
01415     support.run_doctest(test_urllib2, verbose)
01416     support.run_doctest(urllib.request, verbose)
01417     tests = (TrivialTests,
01418              OpenerDirectorTests,
01419              HandlerTests,
01420              MiscTests,
01421              RequestTests)
01422     support.run_unittest(*tests)

>>> mgr = urllib.request.HTTPPasswordMgr()
>>> add = mgr.add_password
>>> add("Some Realm", "http://example.com/", "joe", "password")
>>> add("Some Realm", "http://example.com/ni", "ni", "ni")
>>> add("c", "http://example.com/foo", "foo", "ni")
>>> add("c", "http://example.com/bar", "bar", "nini")
>>> add("b", "http://example.com/", "first", "blah")
>>> add("b", "http://example.com/", "second", "spam")
>>> add("a", "http://example.com", "1", "a")
>>> add("Some Realm", "http://c.example.com:3128", "3", "c")
>>> add("Some Realm", "d.example.com", "4", "d")
>>> add("Some Realm", "e.example.com:3128", "5", "e")

>>> mgr.find_user_password("Some Realm", "example.com")
('joe', 'password')
>>> mgr.find_user_password("Some Realm", "http://example.com")
('joe', 'password')
>>> mgr.find_user_password("Some Realm", "http://example.com/")
('joe', 'password')
>>> mgr.find_user_password("Some Realm", "http://example.com/spam")
('joe', 'password')
>>> mgr.find_user_password("Some Realm", "http://example.com/spam/spam")
('joe', 'password')
>>> mgr.find_user_password("c", "http://example.com/foo")
('foo', 'ni')
>>> mgr.find_user_password("c", "http://example.com/bar")
('bar', 'nini')

Actually, this is really undefined ATM
##     Currently, we use the highest-level path where more than one match:

##     >>> mgr.find_user_password("Some Realm", "http://example.com/ni")
##     ('joe', 'password')

Use latest add_password() in case of conflict:

>>> mgr.find_user_password("b", "http://example.com/")
('second', 'spam')

No special relationship between a.example.com and example.com:

>>> mgr.find_user_password("a", "http://example.com/")
('1', 'a')
>>> mgr.find_user_password("a", "http://a.example.com/")
(None, None)

Ports:

>>> mgr.find_user_password("Some Realm", "c.example.com")
(None, None)
>>> mgr.find_user_password("Some Realm", "c.example.com:3128")
('3', 'c')
>>> mgr.find_user_password("Some Realm", "http://c.example.com:3128")
('3', 'c')
>>> mgr.find_user_password("Some Realm", "d.example.com")
('4', 'd')
>>> mgr.find_user_password("Some Realm", "e.example.com:3128")
('5', 'e')

Definition at line 113 of file test_urllib2.py.

00113 
00114 def test_password_manager(self):
00115     """
00116     >>> mgr = urllib.request.HTTPPasswordMgr()
00117     >>> add = mgr.add_password
00118     >>> add("Some Realm", "http://example.com/", "joe", "password")
00119     >>> add("Some Realm", "http://example.com/ni", "ni", "ni")
00120     >>> add("c", "http://example.com/foo", "foo", "ni")
00121     >>> add("c", "http://example.com/bar", "bar", "nini")
00122     >>> add("b", "http://example.com/", "first", "blah")
00123     >>> add("b", "http://example.com/", "second", "spam")
00124     >>> add("a", "http://example.com", "1", "a")
00125     >>> add("Some Realm", "http://c.example.com:3128", "3", "c")
00126     >>> add("Some Realm", "d.example.com", "4", "d")
00127     >>> add("Some Realm", "e.example.com:3128", "5", "e")
00128 
00129     >>> mgr.find_user_password("Some Realm", "example.com")
00130     ('joe', 'password')
00131     >>> mgr.find_user_password("Some Realm", "http://example.com")
00132     ('joe', 'password')
00133     >>> mgr.find_user_password("Some Realm", "http://example.com/")
00134     ('joe', 'password')
00135     >>> mgr.find_user_password("Some Realm", "http://example.com/spam")
00136     ('joe', 'password')
00137     >>> mgr.find_user_password("Some Realm", "http://example.com/spam/spam")
00138     ('joe', 'password')
00139     >>> mgr.find_user_password("c", "http://example.com/foo")
00140     ('foo', 'ni')
00141     >>> mgr.find_user_password("c", "http://example.com/bar")
00142     ('bar', 'nini')
00143 
00144     Actually, this is really undefined ATM
00145 ##     Currently, we use the highest-level path where more than one match:
00146 
00147 ##     >>> mgr.find_user_password("Some Realm", "http://example.com/ni")
00148 ##     ('joe', 'password')
00149 
00150     Use latest add_password() in case of conflict:
00151 
00152     >>> mgr.find_user_password("b", "http://example.com/")
00153     ('second', 'spam')
00154 
00155     No special relationship between a.example.com and example.com:
00156 
00157     >>> mgr.find_user_password("a", "http://example.com/")
00158     ('1', 'a')
00159     >>> mgr.find_user_password("a", "http://a.example.com/")
00160     (None, None)
00161 
00162     Ports:
00163 
00164     >>> mgr.find_user_password("Some Realm", "c.example.com")
00165     (None, None)
00166     >>> mgr.find_user_password("Some Realm", "c.example.com:3128")
00167     ('3', 'c')
00168     >>> mgr.find_user_password("Some Realm", "http://c.example.com:3128")
00169     ('3', 'c')
00170     >>> mgr.find_user_password("Some Realm", "d.example.com")
00171     ('4', 'd')
00172     >>> mgr.find_user_password("Some Realm", "e.example.com:3128")
00173     ('5', 'e')
00174 
00175     """
00176     pass
00177 

>>> mgr = urllib.request.HTTPPasswordMgr()
>>> add = mgr.add_password

The point to note here is that we can't guess the default port if there's
no scheme.  This applies to both add_password and find_user_password.

>>> add("f", "http://g.example.com:80", "10", "j")
>>> add("g", "http://h.example.com", "11", "k")
>>> add("h", "i.example.com:80", "12", "l")
>>> add("i", "j.example.com", "13", "m")
>>> mgr.find_user_password("f", "g.example.com:100")
(None, None)
>>> mgr.find_user_password("f", "g.example.com:80")
('10', 'j')
>>> mgr.find_user_password("f", "g.example.com")
(None, None)
>>> mgr.find_user_password("f", "http://g.example.com:100")
(None, None)
>>> mgr.find_user_password("f", "http://g.example.com:80")
('10', 'j')
>>> mgr.find_user_password("f", "http://g.example.com")
('10', 'j')
>>> mgr.find_user_password("g", "h.example.com")
('11', 'k')
>>> mgr.find_user_password("g", "h.example.com:80")
('11', 'k')
>>> mgr.find_user_password("g", "http://h.example.com:80")
('11', 'k')
>>> mgr.find_user_password("h", "i.example.com")
(None, None)
>>> mgr.find_user_password("h", "i.example.com:80")
('12', 'l')
>>> mgr.find_user_password("h", "http://i.example.com:80")
('12', 'l')
>>> mgr.find_user_password("i", "j.example.com")
('13', 'm')
>>> mgr.find_user_password("i", "j.example.com:80")
(None, None)
>>> mgr.find_user_password("i", "http://j.example.com")
('13', 'm')
>>> mgr.find_user_password("i", "http://j.example.com:80")
(None, None)

Definition at line 178 of file test_urllib2.py.

00178 
00179 def test_password_manager_default_port(self):
00180     """
00181     >>> mgr = urllib.request.HTTPPasswordMgr()
00182     >>> add = mgr.add_password
00183 
00184     The point to note here is that we can't guess the default port if there's
00185     no scheme.  This applies to both add_password and find_user_password.
00186 
00187     >>> add("f", "http://g.example.com:80", "10", "j")
00188     >>> add("g", "http://h.example.com", "11", "k")
00189     >>> add("h", "i.example.com:80", "12", "l")
00190     >>> add("i", "j.example.com", "13", "m")
00191     >>> mgr.find_user_password("f", "g.example.com:100")
00192     (None, None)
00193     >>> mgr.find_user_password("f", "g.example.com:80")
00194     ('10', 'j')
00195     >>> mgr.find_user_password("f", "g.example.com")
00196     (None, None)
00197     >>> mgr.find_user_password("f", "http://g.example.com:100")
00198     (None, None)
00199     >>> mgr.find_user_password("f", "http://g.example.com:80")
00200     ('10', 'j')
00201     >>> mgr.find_user_password("f", "http://g.example.com")
00202     ('10', 'j')
00203     >>> mgr.find_user_password("g", "h.example.com")
00204     ('11', 'k')
00205     >>> mgr.find_user_password("g", "h.example.com:80")
00206     ('11', 'k')
00207     >>> mgr.find_user_password("g", "http://h.example.com:80")
00208     ('11', 'k')
00209     >>> mgr.find_user_password("h", "i.example.com")
00210     (None, None)
00211     >>> mgr.find_user_password("h", "i.example.com:80")
00212     ('12', 'l')
00213     >>> mgr.find_user_password("h", "http://i.example.com:80")
00214     ('12', 'l')
00215     >>> mgr.find_user_password("i", "j.example.com")
00216     ('13', 'm')
00217     >>> mgr.find_user_password("i", "j.example.com:80")
00218     (None, None)
00219     >>> mgr.find_user_password("i", "http://j.example.com")
00220     ('13', 'm')
00221     >>> mgr.find_user_password("i", "http://j.example.com:80")
00222     (None, None)
00223 
00224     """

Definition at line 570 of file test_urllib2.py.

00570 
00571     def test_processors(self):
00572         # *_request / *_response methods get called appropriately
00573         o = OpenerDirector()
00574         meth_spec = [
00575             [("http_request", "return request"),
00576              ("http_response", "return response")],
00577             [("http_request", "return request"),
00578              ("http_response", "return response")],
00579             ]
00580         handlers = add_ordered_mock_handlers(o, meth_spec)
00581 
00582         req = Request("http://example.com/")
00583         r = o.open(req)
00584         # processor methods are called on *all* handlers that define them,
00585         # not just the first handler that handles the request
00586         calls = [
00587             (handlers[0], "http_request"), (handlers[1], "http_request"),
00588             (handlers[0], "http_response"), (handlers[1], "http_response")]
00589 
00590         for i, (handler, name, args, kwds) in enumerate(o.calls):
00591             if i < 2:
00592                 # *_request
00593                 self.assertEqual((handler, name), calls[i])
00594                 self.assertEqual(len(args), 1)
00595                 self.assertIsInstance(args[0], Request)
00596             else:
00597                 # *_response
00598                 self.assertEqual((handler, name), calls[i])
00599                 self.assertEqual(len(args), 2)
00600                 self.assertIsInstance(args[0], Request)
00601                 # response from opener.open is None, because there's no
00602                 # handler that defines http_open to handle it
00603                 self.assertTrue(args[1] is None or
00604                              isinstance(args[1], MockResponse))
00605 

Here is the call graph for this function:

The Request.headers dictionary is not a documented interface.  It should
stay that way, because the complete set of headers are only accessible
through the .get_header(), .has_header(), .header_items() interface.
However, .headers pre-dates those methods, and so real code will be using
the dictionary.

The introduction in 2.4 of those methods was a mistake for the same reason:
code that previously saw all (urllib2 user)-provided headers in .headers
now sees only a subset (and the function interface is ugly and incomplete).
A better change would have been to replace .headers dict with a dict
subclass (or UserDict.DictMixin instance?)  that preserved the .headers
interface and also provided access to the "unredirected" headers.  It's
probably too late to fix that, though.


Check .capitalize() case normalization:

>>> url = "http://example.com"
>>> Request(url, headers={"Spam-eggs": "blah"}).headers["Spam-eggs"]
'blah'
>>> Request(url, headers={"spam-EggS": "blah"}).headers["Spam-eggs"]
'blah'

Currently, Request(url, "Spam-eggs").headers["Spam-Eggs"] raises KeyError,
but that could be changed in future.

Definition at line 51 of file test_urllib2.py.

00051 
00052 def test_request_headers_dict():
00053     """
00054     The Request.headers dictionary is not a documented interface.  It should
00055     stay that way, because the complete set of headers are only accessible
00056     through the .get_header(), .has_header(), .header_items() interface.
00057     However, .headers pre-dates those methods, and so real code will be using
00058     the dictionary.
00059 
00060     The introduction in 2.4 of those methods was a mistake for the same reason:
00061     code that previously saw all (urllib2 user)-provided headers in .headers
00062     now sees only a subset (and the function interface is ugly and incomplete).
00063     A better change would have been to replace .headers dict with a dict
00064     subclass (or UserDict.DictMixin instance?)  that preserved the .headers
00065     interface and also provided access to the "unredirected" headers.  It's
00066     probably too late to fix that, though.
00067 
00068 
00069     Check .capitalize() case normalization:
00070 
00071     >>> url = "http://example.com"
00072     >>> Request(url, headers={"Spam-eggs": "blah"}).headers["Spam-eggs"]
00073     'blah'
00074     >>> Request(url, headers={"spam-EggS": "blah"}).headers["Spam-eggs"]
00075     'blah'
00076 
00077     Currently, Request(url, "Spam-eggs").headers["Spam-Eggs"] raises KeyError,
00078     but that could be changed in future.
00079 
00080     """

Note the case normalization of header names here, to .capitalize()-case.
This should be preserved for backwards-compatibility.  (In the HTTP case,
normalization to .title()-case is done by urllib2 before sending headers to
http.client).

>>> url = "http://example.com"
>>> r = Request(url, headers={"Spam-eggs": "blah"})
>>> r.has_header("Spam-eggs")
True
>>> r.header_items()
[('Spam-eggs', 'blah')]
>>> r.add_header("Foo-Bar", "baz")
>>> items = sorted(r.header_items())
>>> items
[('Foo-bar', 'baz'), ('Spam-eggs', 'blah')]

Note that e.g. r.has_header("spam-EggS") is currently False, and
r.get_header("spam-EggS") returns None, but that could be changed in
future.

>>> r.has_header("Not-there")
False
>>> print(r.get_header("Not-there"))
None
>>> r.get_header("Not-there", "default")
'default'

Definition at line 81 of file test_urllib2.py.

00081 
00082 def test_request_headers_methods():
00083     """
00084     Note the case normalization of header names here, to .capitalize()-case.
00085     This should be preserved for backwards-compatibility.  (In the HTTP case,
00086     normalization to .title()-case is done by urllib2 before sending headers to
00087     http.client).
00088 
00089     >>> url = "http://example.com"
00090     >>> r = Request(url, headers={"Spam-eggs": "blah"})
00091     >>> r.has_header("Spam-eggs")
00092     True
00093     >>> r.header_items()
00094     [('Spam-eggs', 'blah')]
00095     >>> r.add_header("Foo-Bar", "baz")
00096     >>> items = sorted(r.header_items())
00097     >>> items
00098     [('Foo-bar', 'baz'), ('Spam-eggs', 'blah')]
00099 
00100     Note that e.g. r.has_header("spam-EggS") is currently False, and
00101     r.get_header("spam-EggS") returns None, but that could be changed in
00102     future.
00103 
00104     >>> r.has_header("Not-there")
00105     False
00106     >>> print(r.get_header("Not-there"))
00107     None
00108     >>> r.get_header("Not-there", "default")
00109     'default'
00110 
00111     """
00112