| >>> import mechanize |
| >>> from mechanize._response import test_response |
| >>> from test_browser import TestBrowser2, make_mock_handler |
| |
| |
| Opening a new response should close the old one. |
| |
| >>> class TestHttpHandler(mechanize.BaseHandler): |
| ... def http_open(self, request): |
| ... return test_response(url=request.get_full_url()) |
| >>> class TestHttpBrowser(TestBrowser2): |
| ... handler_classes = TestBrowser2.handler_classes.copy() |
| ... handler_classes["http"] = TestHttpHandler |
| ... default_schemes = ["http"] |
| >>> def response_impl(response): |
| ... return response.wrapped.fp.__class__.__name__ |
| |
| >>> br = TestHttpBrowser() |
| >>> r = br.open("http://example.com") |
| >>> print response_impl(r) |
| StringI |
| >>> r2 = br.open("http://example.com") |
| >>> print response_impl(r2) |
| StringI |
| >>> print response_impl(r) |
| eofresponse |
| |
| So should .set_response() |
| |
| >>> br.set_response(test_response()) |
| >>> print response_impl(r2) |
| eofresponse |
| |
| |
| .visit_response() works very similarly to .open() |
| |
| >>> br = TestHttpBrowser() |
| >>> r = br.open("http://example.com") |
| >>> r2 = test_response(url="http://example.com/2") |
| >>> print response_impl(r2) |
| StringI |
| >>> br.visit_response(r2) |
| >>> print response_impl(r) |
| eofresponse |
| >>> br.geturl() == br.request.get_full_url() == "http://example.com/2" |
| True |
| >>> junk = br.back() |
| >>> br.geturl() == br.request.get_full_url() == "http://example.com" |
| True |
| |
| |
| .back() may reload if the complete response was not read. If so, it |
| should return the new response, not the old one |
| |
| >>> class ReloadCheckBrowser(TestHttpBrowser): |
| ... reloaded = False |
| ... def reload(self): |
| ... self.reloaded = True |
| ... return TestHttpBrowser.reload(self) |
| >>> br = ReloadCheckBrowser() |
| >>> old = br.open("http://example.com") |
| >>> junk = br.open("http://example.com/2") |
| >>> new = br.back() |
| >>> br.reloaded |
| True |
| >>> new.wrapped is not old.wrapped |
| True |
| |
| |
| Warn early about some mistakes setting a response object |
| |
| >>> import StringIO |
| >>> br = TestBrowser2() |
| >>> 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> |
| |
| |
| .clear_history() should do what it says on the tin. Note that the |
| history does not include the current response! |
| |
| >>> br = TestBrowser2() |
| >>> br.add_handler(make_mock_handler(test_response)([("http_open", None)])) |
| |
| >>> br.response() is None |
| True |
| >>> len(br._history._history) |
| 0 |
| |
| >>> r = br.open("http://example.com/1") |
| >>> br.response() is not None |
| True |
| >>> len(br._history._history) |
| 0 |
| |
| >>> br.clear_history() |
| >>> br.response() is not None |
| True |
| >>> len(br._history._history) |
| 0 |
| |
| >>> r = br.open("http://example.com/2") |
| >>> br.response() is not None |
| True |
| >>> len(br._history._history) |
| 1 |
| |
| >>> br.clear_history() |
| >>> br.response() is not None |
| True |
| >>> len(br._history._history) |
| 0 |
| |
| |
| .open()ing a Request with False .visit does not affect Browser state. |
| Redirections during such a non-visiting request should also be |
| non-visiting. |
| |
| >>> from mechanize import BrowserStateError, Request, HTTPRedirectHandler |
| >>> from test_urllib2 import MockHTTPHandler |
| |
| >>> def make_browser_with_redirect(): |
| ... br = TestBrowser2() |
| ... hh = MockHTTPHandler(302, "Location: http://example.com/\r\n\r\n") |
| ... br.add_handler(hh) |
| ... br.add_handler(HTTPRedirectHandler()) |
| ... return br |
| >>> def raises(exc_class, fn, *args, **kwds): |
| ... try: |
| ... fn(*args, **kwds) |
| ... except exc_class, exc: |
| ... return True |
| ... return False |
| >>> def test_state(br): |
| ... return (br.request is None and |
| ... br.response() is None and |
| ... raises(BrowserStateError, br.back) |
| ... ) |
| >>> br = make_browser_with_redirect() |
| >>> test_state(br) |
| True |
| >>> req = Request("http://example.com") |
| >>> req.visit = False |
| >>> r = br.open(req) |
| >>> test_state(br) |
| True |
| |
| .open_novisit() mutates the request object |
| |
| >>> br = make_browser_with_redirect() |
| >>> test_state(br) |
| True |
| >>> req = Request("http://example.com") |
| >>> print req.visit |
| None |
| >>> r = br.open_novisit(req) |
| >>> test_state(br) |
| True |
| >>> req.visit |
| False |
| |
| |
| ...in fact, any redirection (but not refresh), proxy request, basic or |
| digest auth request, or robots.txt request should be non-visiting, |
| even if .visit is True: |
| |
| >>> from test_urllib2 import MockPasswordManager |
| >>> def test_one_visit(handlers): |
| ... br = TestBrowser2() |
| ... for handler in handlers: br.add_handler(handler) |
| ... req = Request("http://example.com") |
| ... req.visit = True |
| ... br.open(req) |
| ... return br |
| >>> def test_state(br): |
| ... # XXX the _history._history check is needed because of the weird |
| ... # throwing-away of history entries by .back() where response is |
| ... # None, which makes the .back() check insufficient to tell if a |
| ... # history entry was .add()ed. I don't want to change this until |
| ... # post-stable. |
| ... return ( |
| ... br.response() and |
| ... br.request and |
| ... len(br._history._history) == 0 and |
| ... raises(BrowserStateError, br.back)) |
| |
| >>> hh = MockHTTPHandler(302, "Location: http://example.com/\r\n\r\n") |
| >>> br = test_one_visit([hh, HTTPRedirectHandler()]) |
| >>> test_state(br) |
| True |
| |
| >>> class MockPasswordManager: |
| ... def add_password(self, realm, uri, user, password): pass |
| ... def find_user_password(self, realm, authuri): return '', '' |
| |
| >>> ah = mechanize.HTTPBasicAuthHandler(MockPasswordManager()) |
| >>> hh = MockHTTPHandler( |
| ... 401, 'WWW-Authenticate: Basic realm="realm"\r\n\r\n') |
| >>> test_state(test_one_visit([hh, ah])) |
| True |
| |
| >>> ph = mechanize.ProxyHandler(dict(http="proxy.example.com:3128")) |
| >>> ah = mechanize.ProxyBasicAuthHandler(MockPasswordManager()) |
| >>> hh = MockHTTPHandler( |
| ... 407, 'Proxy-Authenticate: Basic realm="realm"\r\n\r\n') |
| >>> test_state(test_one_visit([ph, hh, ah])) |
| True |
| |
| XXX Can't really fix this one properly without significant changes -- |
| the refresh should go onto the history *after* the call, but currently |
| all redirects, including refreshes, are done by recursive .open() |
| calls, which gets the history wrong in this case. Will have to wait |
| until after stable release: |
| |
| #>>> hh = MockHTTPHandler( |
| #... "refresh", 'Location: http://example.com/\r\n\r\n') |
| #>>> br = test_one_visit([hh, HTTPRedirectHandler()]) |
| #>>> br.response() is not None |
| #True |
| #>>> br.request is not None |
| #True |
| #>>> r = br.back() |
| |
| XXX digest, robots |
| |
| |
| .global_form() is separate from the other forms (partly for backwards- |
| compatibility reasons). |
| |
| >>> from mechanize._response import test_response |
| >>> br = TestBrowser2() |
| >>> html = """\ |
| ... <html><body> |
| ... <input type="text" name="a" /> |
| ... <form><input type="text" name="b" /></form> |
| ... </body></html> |
| ... """ |
| >>> response = test_response(html, headers=[("Content-type", "text/html")]) |
| >>> br.global_form() |
| Traceback (most recent call last): |
| BrowserStateError: not viewing any document |
| >>> br.set_response(response) |
| >>> br.global_form().find_control(nr=0).name |
| 'a' |
| >>> len(list(br.forms())) |
| 1 |
| >>> iter(br.forms()).next().find_control(nr=0).name |
| 'b' |
| |
| |
| |
| .select_form() works with the global form |
| |
| >>> from mechanize._response import test_html_response |
| >>> br = TestBrowser2() |
| >>> br.visit_response(test_html_response("""\ |
| ... <html><head><title></title></head><body> |
| ... <input type="text" name="a" value="b"></input> |
| ... <form> |
| ... <input type="text" name="p" value="q"></input> |
| ... </form> |
| ... </body></html>""")) |
| >>> def has_a(form): |
| ... try: |
| ... form.find_control(name="a") |
| ... except mechanize.ControlNotFoundError: |
| ... return False |
| ... else: |
| ... return True |
| >>> br.select_form(predicate=has_a) |
| >>> br.form.find_control(name="a").value |
| 'b' |