[wwwsearch-commits] r41252 - in wwwsearch/mechanize/trunk: mechanize test
jjlee at codespeak.net
jjlee at codespeak.net
Sat Mar 24 19:18:52 CET 2007
Author: jjlee
Date: Sat Mar 24 19:18:50 2007
New Revision: 41252
Modified:
wwwsearch/mechanize/trunk/mechanize/_http.py
wwwsearch/mechanize/trunk/mechanize/_opener.py
wwwsearch/mechanize/trunk/mechanize/_urllib2.py
wwwsearch/mechanize/trunk/test/test_browser.py
wwwsearch/mechanize/trunk/test/test_urllib2.py
Log:
Remove most ugly part of mock objects used in tests, and fix a multiple-response-wrapping bug that got revealed as a result
Modified: wwwsearch/mechanize/trunk/mechanize/_http.py
==============================================================================
--- wwwsearch/mechanize/trunk/mechanize/_http.py (original)
+++ wwwsearch/mechanize/trunk/mechanize/_http.py Sat Mar 24 19:18:50 2007
@@ -578,6 +578,23 @@
https_response = http_response
+class HTTPDefaultErrorHandler(BaseHandler):
+ def http_error_default(self, req, fp, code, msg, hdrs):
+ # why these error methods took the code, msg, headers args in the first
+ # place rather than a response object, I don't know, but to avoid
+ # multiple wrapping, we're discarding them
+
+ if isinstance(fp, urllib2.HTTPError):
+ response = fp
+ else:
+ response = urllib2.HTTPError(
+ req.get_full_url(), code, msg, hdrs, fp)
+ assert code == response.code
+ assert msg == response.msg
+ assert hdrs == response.hdrs
+ raise response
+
+
class AbstractHTTPHandler(BaseHandler):
def __init__(self, debuglevel=0):
Modified: wwwsearch/mechanize/trunk/mechanize/_opener.py
==============================================================================
--- wwwsearch/mechanize/trunk/mechanize/_opener.py (original)
+++ wwwsearch/mechanize/trunk/mechanize/_opener.py Sat Mar 24 19:18:50 2007
@@ -304,7 +304,7 @@
urllib2.ProxyHandler,
urllib2.UnknownHandler,
_http.HTTPHandler, # derived from new AbstractHTTPHandler
- urllib2.HTTPDefaultErrorHandler,
+ _http.HTTPDefaultErrorHandler,
_http.HTTPRedirectHandler, # bugfixed
urllib2.FTPHandler,
urllib2.FileHandler,
Modified: wwwsearch/mechanize/trunk/mechanize/_urllib2.py
==============================================================================
--- wwwsearch/mechanize/trunk/mechanize/_urllib2.py (original)
+++ wwwsearch/mechanize/trunk/mechanize/_urllib2.py Sat Mar 24 19:18:50 2007
@@ -28,7 +28,6 @@
# ...from urllib2...
from urllib2 import \
BaseHandler, \
- HTTPDefaultErrorHandler, \
UnknownHandler, \
FTPHandler, \
CacheFTPHandler, \
@@ -37,6 +36,7 @@
# ...and from mechanize
from _http import \
HTTPHandler, \
+ HTTPDefaultErrorHandler, \
HTTPRedirectHandler, \
HTTPEquivProcessor, \
HTTPCookieProcessor, \
Modified: wwwsearch/mechanize/trunk/test/test_browser.py
==============================================================================
--- wwwsearch/mechanize/trunk/test/test_browser.py (original)
+++ wwwsearch/mechanize/trunk/test/test_browser.py Sat Mar 24 19:18:50 2007
@@ -32,9 +32,6 @@
self.fp = StringIO.StringIO(data)
if info is None: info = {}
self._info = MockHeaders(info)
- self.source = "%d%d" % (id(self), random.randint(0, sys.maxint-1))
- # otherwise we can't test for "same_response" in test_history
- self.read_complete = True
def info(self): return self._info
def geturl(self): return self.url
def read(self, size=-1): return self.fp.read(size)
@@ -43,12 +40,6 @@
self.fp.seek(0)
def close(self): pass
def get_data(self): pass
- def __getstate__(self):
- state = self.__dict__
- state['source'] = self.source
- return state
- def __setstate__(self, state):
- self.__dict__ = state
def make_mock_handler(response_class=MockResponse):
class MockHandler:
@@ -189,12 +180,21 @@
def test_history(self):
import mechanize
+ from mechanize import _response
def same_response(ra, rb):
- return ra.source == rb.source
+ return ra.wrapped is rb.wrapped
- b = TestBrowser()
- b.add_handler(make_mock_handler()([("http_open", None)]))
+ class Handler(mechanize.BaseHandler):
+ def http_open(self, request):
+ r = _response.test_response(url=request.get_full_url())
+ # these tests aren't interested in auto-.reload() behaviour of
+ # .back(), so read the response to prevent that happening
+ r.get_data()
+ return r
+
+ b = TestBrowser2()
+ b.add_handler(Handler())
self.assertRaises(mechanize.BrowserStateError, b.back)
r1 = b.open("http://example.com/")
self.assertRaises(mechanize.BrowserStateError, b.back)
@@ -204,6 +204,7 @@
r4 = b.open("http://example.com/spam")
self.assert_(same_response(b.back(), r3))
self.assert_(same_response(b.back(), r1))
+ self.assertEquals(b.geturl(), "http://example.com/")
self.assertRaises(mechanize.BrowserStateError, b.back)
# reloading does a real HTTP fetch rather than using history cache
r5 = b.reload()
@@ -221,13 +222,17 @@
self.assertRaises(mechanize.BrowserStateError, b.back, 2)
r8 = b.open("/spam")
- # even if we get a HTTPError, history, .response() and .request should
+ # even if we get an HTTPError, history, .response() and .request should
# still get updated
- error = urllib2.HTTPError("http://example.com/bad", 503, "Oops",
- MockHeaders(), StringIO.StringIO())
- b.add_handler(make_mock_handler()([("https_open", error)]))
+ class Handler2(mechanize.BaseHandler):
+ def https_open(self, request):
+ r = urllib2.HTTPError(
+ "https://example.com/bad", 503, "Oops",
+ MockHeaders(), StringIO.StringIO())
+ return r
+ b.add_handler(Handler2())
self.assertRaises(urllib2.HTTPError, b.open, "https://example.com/badreq")
- self.assertEqual(b.response().geturl(), error.geturl())
+ self.assertEqual(b.response().geturl(), "https://example.com/bad")
self.assertEqual(b.request.get_full_url(), "https://example.com/badreq")
self.assert_(same_response(b.back(), r8))
Modified: wwwsearch/mechanize/trunk/test/test_urllib2.py
==============================================================================
--- wwwsearch/mechanize/trunk/test/test_urllib2.py (original)
+++ wwwsearch/mechanize/trunk/test/test_urllib2.py Sat Mar 24 19:18:50 2007
@@ -33,6 +33,10 @@
## l = getLogger("mechanize")
## l.setLevel(DEBUG)
+class AlwaysEqual:
+ def __cmp__(self, other):
+ return 0
+
class MockOpener:
addheaders = []
def open(self, req, data=None):
@@ -259,6 +263,20 @@
if expected_args[j] is not Unknown:
self.assert_(args[j] == expected_args[j])
+ def test_http_error_raised(self):
+ # should get an HTTPError if an HTTP handler raises a non-200 response
+ # XXX it worries me that this is the only test that excercises the else
+ # branch in HTTPDefaultErrorHandler
+ from mechanize import _response
+ o = mechanize.OpenerDirector()
+ o.add_handler(mechanize.HTTPErrorProcessor())
+ o.add_handler(mechanize.HTTPDefaultErrorHandler())
+ class HTTPHandler(AbstractHTTPHandler):
+ def http_open(self, req):
+ return _response.test_response(code=302)
+ o.add_handler(HTTPHandler())
+ self.assertRaises(mechanize.HTTPError, o.open, "http://example.com/")
+
def test_processors(self):
# *_request / *_response methods get called appropriately
o = OpenerDirector()
@@ -656,21 +674,52 @@
self.assert_(req.unredirected_hdrs["Referer"] == ref)
def test_errors(self):
+ from mechanize import _response
h = HTTPErrorProcessor()
o = h.parent = MockOpener()
- url = "http://example.com/"
- req = Request(url)
+ req = Request("http://example.com")
# 200 OK is passed through
- r = MockResponse(200, "OK", {}, "", url)
+ r = _response.test_response()
newr = h.http_response(req, r)
self.assert_(r is newr)
self.assert_(not hasattr(o, "proto")) # o.error not called
# anything else calls o.error (and MockOpener returns None, here)
- r = MockResponse(201, "Created", {}, "", url)
+ r = _response.test_response(code=201, msg="Created")
self.assert_(h.http_response(req, r) is None)
self.assert_(o.proto == "http") # o.error called
- self.assert_(o.args == (req, r, 201, "Created", {}))
+ self.assert_(o.args == (req, r, 201, "Created", AlwaysEqual()))
+
+ def test_raise_http_errors(self):
+ # HTTPDefaultErrorHandler should raise HTTPError if no error handler
+ # handled the error response
+ from mechanize import _response
+ h = mechanize.HTTPDefaultErrorHandler()
+
+ url = "http://example.com"; code = 500; msg = "Error"
+ request = mechanize.Request(url)
+ response = _response.test_response(url=url, code=code, msg=msg)
+
+ # case 1. it's not an HTTPError
+ try:
+ h.http_error_default(
+ request, response, code, msg, response.info())
+ except mechanize.HTTPError, exc:
+ self.assert_(exc is not response)
+ self.assert_(exc.fp is response)
+ else:
+ self.assert_(False)
+
+ # case 2. response object is already an HTTPError, so just re-raise it
+ error = mechanize.HTTPError(
+ url, code, msg, "fake headers", response)
+ try:
+ h.http_error_default(
+ request, error, code, msg, error.info())
+ except mechanize.HTTPError, exc:
+ self.assert_(exc is error)
+ else:
+ self.assert_(False)
def test_robots(self):
# XXX useragent
More information about the wwwsearch-commits
mailing list