Skip to content

Commit

Permalink
Add documentation. A tiny bit of cleanup.
Browse files Browse the repository at this point in the history
  • Loading branch information
strichter committed Jul 27, 2005
1 parent 8be868d commit fff9740
Showing 1 changed file with 137 additions and 0 deletions.
137 changes: 137 additions & 0 deletions testbrowser/testing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
##############################################################################
#
# Copyright (c) 2005 Zope Corporation. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Visible Source
# License, Version 1.0 (ZVSL). A copy of the ZVSL should accompany this
# distribution.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Publisher Hook to ``mechanize``
$Id$
"""
import httplib
import urllib2
from cStringIO import StringIO

import mechanize
import ClientCookie

from zope.app.testing.functional import HTTPCaller
from zope.app.testing.testbrowser import browser


class PublisherConnection(object):
"""A ``urllib2`` compatible connection obejct."""

def __init__(self, host):
self.host = host
self.caller = HTTPCaller()

def set_debuglevel(self, level):
pass

def request(self, method, url, body=None, headers=None):
"""Send a request to the publisher.
The response will be stored in ``self.response``.
"""
if body is None:
body = ''

# Construct the headers.
header_chunks = []
if headers is not None:
for header in headers.items():
header_chunks.append('%s: %s' % header)
headers = '\n'.join(header_chunks) + '\n'
else:
headers = ''

# Construct the full HTTP request string, since that is what the
# ``HTTPCaller`` wants.
request_string = (method + ' ' + url + ' HTTP/1.1\n'
+ headers + '\n' + body)

self.response = self.caller(request_string)

def getresponse(self):
"""Return a ``urllib2`` compatible response.
The goal of ths method is to convert the Zope Publisher's reseponse to
a ``urllib2`` compatible response, which is also understood by
mechanize.
"""
headers = self.response.header_output.headers
real_response = self.response._response
status = real_response.getStatus()
reason = real_response._reason # XXX should add a getReason method
output = (real_response.getHeaderText(real_response.getHeaders()) +
self.response.getBody())
return PublisherResponse(output, status, reason)


class PublisherResponse(object):
"""``urllib2`` compatible response object."""

def __init__(self, content, status, reason):
self.content = content
self.status = status
self.reason = reason
self.msg = httplib.HTTPMessage(StringIO(content), 0)
self.content_as_file = StringIO(content)

def read(self, amt=None):
return self.content_as_file.read(amt)


class PublisherHTTPHandler(urllib2.HTTPHandler):
"""Special HTTP handler to use the Zope Publisher."""

http_request = urllib2.AbstractHTTPHandler.do_request_

def http_open(self, req):
"""Open an HTTP connection having a ``urllib2`` request."""
# Here we connect to the publisher.
return self.do_open(PublisherConnection, req)


class PublisherMechanizeBrowser(mechanize.Browser):
"""Special ``mechanize`` browser using the Zope Publisher HTTP handler."""

handler_classes = {
# scheme handlers
"http": PublisherHTTPHandler,

"_http_error": ClientCookie.HTTPErrorProcessor,
"_http_request_upgrade": ClientCookie.HTTPRequestUpgradeProcessor,
"_http_default_error": urllib2.HTTPDefaultErrorHandler,

# feature handlers
"_authen": urllib2.HTTPBasicAuthHandler,
"_redirect": ClientCookie.HTTPRedirectHandler,
"_cookies": ClientCookie.HTTPCookieProcessor,
"_refresh": ClientCookie.HTTPRefreshProcessor,
"_referer": mechanize.Browser.handler_classes['_referer'],
"_equiv": ClientCookie.HTTPEquivProcessor,
"_seek": ClientCookie.SeekableProcessor,
}

default_schemes = ["http"]
default_others = ["_http_error", "_http_request_upgrade",
"_http_default_error"]
default_features = ["_authen", "_redirect", "_cookies", "_seek"]


class Browser(browser.Browser):
"""A Zope ``testbrowser` Browser that uses the Zope Publisher."""

def __init__(self, url=None):
mech_browser = PublisherMechanizeBrowser()
super(Browser, self).__init__(url=url, mech_browser=mech_browser)

0 comments on commit fff9740

Please sign in to comment.