[wwwsearch-commits] r32987 - in wwwsearch/mechanize/trunk: mechanize test

jjlee at codespeak.net jjlee at codespeak.net
Sat Oct 7 14:53:15 CEST 2006


Author: jjlee
Date: Sat Oct  7 14:53:13 2006
New Revision: 32987

Added:
   wwwsearch/mechanize/trunk/test/test_browser.doctest
Modified:
   wwwsearch/mechanize/trunk/mechanize/_html.py
   wwwsearch/mechanize/trunk/mechanize/_mechanize.py
   wwwsearch/mechanize/trunk/mechanize/_seek.py
   wwwsearch/mechanize/trunk/mechanize/_upgrade.py
   wwwsearch/mechanize/trunk/test/test_browser.py
Log:
Fix a bunch of problems with Browser and Factory not handling None responses correctly; Add some tests

Modified: wwwsearch/mechanize/trunk/mechanize/_html.py
==============================================================================
--- wwwsearch/mechanize/trunk/mechanize/_html.py	(original)
+++ wwwsearch/mechanize/trunk/mechanize/_html.py	Sat Oct  7 14:53:13 2006
@@ -480,8 +480,8 @@
     def set_response(self, response):
         """Set response.
 
-        The response must implement the same interface as objects returned by
-        urllib2.urlopen().
+        The response must either be None or implement the same interface as
+        objects returned by urllib2.urlopen().
 
         """
         self._response = response

Modified: wwwsearch/mechanize/trunk/mechanize/_mechanize.py
==============================================================================
--- wwwsearch/mechanize/trunk/mechanize/_mechanize.py	(original)
+++ wwwsearch/mechanize/trunk/mechanize/_mechanize.py	Sat Oct  7 14:53:13 2006
@@ -98,8 +98,6 @@
         if history is None:
             history = History()
         self._history = history
-        self.request = self._response = None
-        self.form = None
 
         if request_class is None:
             if not hasattr(urllib2.Request, "add_unredirected_header"):
@@ -113,6 +111,9 @@
         self._factory = factory
         self.request_class = request_class
 
+        self.request = None
+        self.set_response(None)
+
         UserAgent.__init__(self)  # do this last to avoid __getattr__ problems
 
     def close(self):
@@ -208,15 +209,23 @@
         return copy.copy(self._response)
 
     def set_response(self, response):
-        """Replace current response with (a copy of) response."""
+        """Replace current response with (a copy of) response.
+
+        response may be None.
+        """
         # sanity check, necessary but far from sufficient
-        if not (hasattr(response, "info") and hasattr(response, "geturl") and
-                hasattr(response, "read")):
+        if not (response is None or
+                (hasattr(response, "info") and hasattr(response, "geturl") and
+                 hasattr(response, "read")
+                 )
+                ):
             raise ValueError("not a response object")
 
         self.form = None
-        self._response = _upgrade.upgrade_response(response)
-        self._factory.set_response(self._response)
+        if response is not None:
+            response = _upgrade.upgrade_response(response)
+        self._response = response
+        self._factory.set_response(response)
 
     def geturl(self):
         """Get URL of current document."""

Modified: wwwsearch/mechanize/trunk/mechanize/_seek.py
==============================================================================
--- wwwsearch/mechanize/trunk/mechanize/_seek.py	(original)
+++ wwwsearch/mechanize/trunk/mechanize/_seek.py	Sat Oct  7 14:53:13 2006
@@ -6,6 +6,6 @@
     """Make responses seekable."""
 
     def any_response(self, request, response):
-        if not hasattr(response, "seek"):
+        if response is not None and not hasattr(response, "seek"):
             return response_seek_wrapper(response)
         return response

Modified: wwwsearch/mechanize/trunk/mechanize/_upgrade.py
==============================================================================
--- wwwsearch/mechanize/trunk/mechanize/_upgrade.py	(original)
+++ wwwsearch/mechanize/trunk/mechanize/_upgrade.py	Sat Oct  7 14:53:13 2006
@@ -27,6 +27,7 @@
     # upgrade responses to be .close()able without becoming unusable
     handler_order = 0  # before anything else
     def any_response(self, request, response):
-        if not hasattr(response, 'closeable_response'):
+        if (response is not None and
+            not hasattr(response, 'closeable_response')):
             response = upgrade_response(response)
         return response

Added: wwwsearch/mechanize/trunk/test/test_browser.doctest
==============================================================================
--- (empty file)
+++ wwwsearch/mechanize/trunk/test/test_browser.doctest	Sat Oct  7 14:53:13 2006
@@ -0,0 +1,32 @@
+>>> from test_browser import TestBrowser, TestBrowser2
+
+Warn early about some mistakes setting a response object
+
+>>> import StringIO
+>>> br = TestBrowser()
+>>> br.set_response("blah")
+Traceback (most recent call last):
+...
+ValueError: not a response object
+>>> br.set_response(StringIO.StringIO())
+Traceback (most recent call last):
+...
+ValueError: not a response object
+
+
+.open() without an appropriate scheme handler should fail with
+URLError
+
+>>> br = TestBrowser2()
+>>> br.open("http://example.com")
+Traceback (most recent call last):
+...
+URLError: <urlopen error unknown url type: http>
+
+Reload after failed .open() should fail due to failure to open, not
+with BrowserStateError
+
+>>> br.reload()
+Traceback (most recent call last):
+...
+URLError: <urlopen error unknown url type: http>

Modified: wwwsearch/mechanize/trunk/test/test_browser.py
==============================================================================
--- wwwsearch/mechanize/trunk/test/test_browser.py	(original)
+++ wwwsearch/mechanize/trunk/test/test_browser.py	Sat Oct  7 14:53:13 2006
@@ -105,6 +105,15 @@
     default_others = []
     default_schemes = []
 
+class TestBrowser2(mechanize.Browser):
+    # XXX better name!
+    # As TestBrowser, this is neutered so doesn't know about protocol handling,
+    # but still knows what to do with unknown schemes, etc., because
+    # UserAgent's default_others list is left intact, including classes like
+    # UnknownHandler
+    default_features = ["_seek"]
+    default_schemes = []
+
 
 class BrowserTests(TestCase):
 
@@ -328,17 +337,44 @@
         url = "http://example.com/"
 
         b = TestBrowser()
-        b.add_handler(make_mock_handler()([("http_open", MockResponse(url, "", {}))]))
+
+        self.assert_(b.response() is None)
+
+        # To open a relative reference (often called a "relative URL"), you
+        # have to have already opened a URL for it "to be relative to".
+        self.assertRaises(mechanize.BrowserStateError, b.open, "relative_ref")
+
+        # we can still clear the history even if we've not visited any URL
+        b.clear_history()
+
+        # most methods raise BrowserStateError...
+        def test_state_error(method_names):
+            for attr in method_names:
+                method = getattr(b, attr)
+                #print attr
+                self.assertRaises(mechanize.BrowserStateError, method)
+            self.assertRaises(mechanize.BrowserStateError, b.select_form,
+                              name="blah")
+            self.assertRaises(mechanize.BrowserStateError, b.find_link,
+                              name="blah")
+        # ...if not visiting a URL...
+        test_state_error(("geturl reload back viewing_html encoding "
+                          "click links forms title select_form".split()))
+        self.assertRaises(mechanize.BrowserStateError, b.set_cookie, "foo=bar")
+        self.assertRaises(mechanize.BrowserStateError, b.submit, nr=0)
+        self.assertRaises(mechanize.BrowserStateError, b.click_link, nr=0)
+        self.assertRaises(mechanize.BrowserStateError, b.follow_link, nr=0)
+        self.assertRaises(mechanize.BrowserStateError, b.find_link, nr=0)
+        # ...and lots do so if visiting a non-HTML URL
+        b.add_handler(make_mock_handler()(
+            [("http_open", MockResponse(url, "", {}))]))
         r = b.open(url)
         self.assert_(not b.viewing_html())
-        self.assertRaises(mechanize.BrowserStateError, b.links)
-        self.assertRaises(mechanize.BrowserStateError, b.forms)
-        self.assertRaises(mechanize.BrowserStateError, b.title)
-        self.assertRaises(mechanize.BrowserStateError, b.select_form)
-        self.assertRaises(mechanize.BrowserStateError, b.select_form,
-                          name="blah")
-        self.assertRaises(mechanize.BrowserStateError, b.find_link,
-                          name="blah")
+        test_state_error("click links forms title select_form".split())
+        self.assertRaises(mechanize.BrowserStateError, b.submit, nr=0)
+        self.assertRaises(mechanize.BrowserStateError, b.click_link, nr=0)
+        self.assertRaises(mechanize.BrowserStateError, b.follow_link, nr=0)
+        self.assertRaises(mechanize.BrowserStateError, b.find_link, nr=0)
 
         b = TestBrowser()
         r = MockResponse(url,


More information about the wwwsearch-commits mailing list