[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