[Checkins] SVN: zope.app.wsgi/trunk/ - Moved `wsgi_intercept` support to ``zope.testbrowser.wsgi``, thus

Michael Howitz mh at gocept.com
Mon Jan 24 09:48:29 EST 2011


Log message for revision 119878:
  - Moved `wsgi_intercept` support to ``zope.testbrowser.wsgi``, thus
    requiring at least version 3.11 of this package:
  
    - Moved ``zope.app.wsgi.testlayer.Browser`` to
      ``zope.testbrowser.wsgi.Browser``, but left BBB import here.
  
    - Split up ``zope.app.wsgi.testlayer.BrowserLayer`` into generic WSGI
      browser layer (``zope.testbrowser.wsgi.Layer``) and ZODB/ZOPE specific
      part (``zope.app.wsgi.testlayer.BrowserLayer`` as before).
  

Changed:
  U   zope.app.wsgi/trunk/CHANGES.txt
  U   zope.app.wsgi/trunk/setup.py
  U   zope.app.wsgi/trunk/src/zope/app/wsgi/testlayer.py

-=-
Modified: zope.app.wsgi/trunk/CHANGES.txt
===================================================================
--- zope.app.wsgi/trunk/CHANGES.txt	2011-01-24 14:47:12 UTC (rev 119877)
+++ zope.app.wsgi/trunk/CHANGES.txt	2011-01-24 14:48:29 UTC (rev 119878)
@@ -6,9 +6,17 @@
 3.10.1 (unreleased)
 -------------------
 
-- Nothing changed yet.
+- Moved `wsgi_intercept` support to ``zope.testbrowser.wsgi``, thus
+  requiring at least version 3.11 of this package:
 
+  - Moved ``zope.app.wsgi.testlayer.Browser`` to
+    ``zope.testbrowser.wsgi.Browser``, but left BBB import here.
 
+  - Split up ``zope.app.wsgi.testlayer.BrowserLayer`` into generic WSGI
+    browser layer (``zope.testbrowser.wsgi.Layer``) and ZODB/ZOPE specific
+    part (``zope.app.wsgi.testlayer.BrowserLayer`` as before).
+
+
 3.10.0 (2010-11-18)
 -------------------
 
@@ -18,7 +26,7 @@
 3.9.3 (2010-10-14)
 ------------------
 
-- Python2.7 compatibility for xmlrpc. Transplant of zope.app.testing r116141.
+- Python 2.7 compatibility for xmlrpc. Transplant of zope.app.testing r116141.
 
 
 3.9.2 (2010-05-23)

Modified: zope.app.wsgi/trunk/setup.py
===================================================================
--- zope.app.wsgi/trunk/setup.py	2011-01-24 14:47:12 UTC (rev 119877)
+++ zope.app.wsgi/trunk/setup.py	2011-01-24 14:48:29 UTC (rev 119878)
@@ -74,7 +74,7 @@
           'zope.lifecycleevent',
           'zope.session',
           'zope.site',
-          'zope.testbrowser',
+          'zope.testbrowser >= 3.11',
           'zope.testing',
           'zope.traversing',
           ],

Modified: zope.app.wsgi/trunk/src/zope/app/wsgi/testlayer.py
===================================================================
--- zope.app.wsgi/trunk/src/zope/app/wsgi/testlayer.py	2011-01-24 14:47:12 UTC (rev 119877)
+++ zope.app.wsgi/trunk/src/zope/app/wsgi/testlayer.py	2011-01-24 14:48:29 UTC (rev 119878)
@@ -17,86 +17,48 @@
 import httplib
 import xmlrpclib
 
-from transaction import commit
-from wsgi_intercept.mechanize_intercept import Browser as BaseInterceptBrowser
+import transaction
 from zope.app.appsetup.testlayer import ZODBLayer
-from zope.app.publication.httpfactory import HTTPPublicationRequestFactory
 from zope.app.wsgi import WSGIPublisherApplication
-from zope.testbrowser.browser import Browser as ZopeTestbrowser
 import wsgi_intercept
+import zope.testbrowser.wsgi
 
-# List of hostname where the test browser/http function replies to
-TEST_HOSTS = ['localhost', '127.0.0.1']
+# BBB
+from zope.testbrowser.wsgi import Browser
 
+class TransactionMiddleware(object):
+    """This middleware makes the WSGI application compatible with the
+    HTTPCaller behavior defined in zope.app.testing.functional:
+    - It commits and synchronises the current transaction before and
+      after the test.
 
-class InterceptBrowser(BaseInterceptBrowser):
-
-    default_schemes = ['http']
-    default_others = ['_http_error',
-                      '_http_default_error']
-    default_features = ['_redirect', '_cookies', '_referer', '_refresh',
-                        '_equiv', '_basicauth', '_digestauth']
-
-
-class Browser(ZopeTestbrowser):
-    """Override the zope.testbrowser.browser.Browser interface so that it
-    uses PatchedMechanizeBrowser
     """
+    def __init__(self, root_factory, wsgi_stack):
+        # ZODBLayer creates DB in testSetUp method, but the middleware is
+        # set up already in the `setUp` method, so we have only the
+        # `root_factory` not the root itself:
+        self.root_factory = root_factory
+        self.wsgi_stack = wsgi_stack
 
-    def __init__(self, *args, **kwargs):
-        kwargs['mech_browser'] = InterceptBrowser()
-        ZopeTestbrowser.__init__(self, *args, **kwargs)
+    def __call__(self, environ, start_response):
+        transaction.commit()
+        for entry in self.wsgi_stack(environ, start_response):
+            yield entry
+        self.root_factory()._p_jar.sync()
 
 
-# Compatibility helpers to behave like zope.app.testing
-
-basicre = re.compile('Basic (.+)?:(.+)?$')
-
-
-def auth_header(header):
-    """This function takes an authorization HTTP header and encode the
-    couple user, password into base 64 like the HTTP protocol wants
-    it.
-    """
-    match = basicre.match(header)
-    if match:
-        u, p = match.group(1, 2)
-        if u is None:
-            u = ''
-        if p is None:
-            p = ''
-        auth = base64.encodestring('%s:%s' % (u, p))
-        return 'Basic %s' % auth[:-1]
-    return header
-
-
-def is_wanted_header(header):
-    """Return True if the given HTTP header key is unwanted.
-    """
-    key, value = header
-    return key.lower() not in ('x-content-type-warning', 'x-powered-by')
-
-
-class TestBrowserMiddleware(object):
+class HandleErrorsMiddleware(object):
     """This middleware makes the WSGI application compatible with the
     HTTPCaller behavior defined in zope.app.testing.functional:
-    - It commits and synchronises the current transaction before and
-      after the test.
     - It honors the X-zope-handle-errors header in order to support
       zope.testbrowser Browser handleErrors flag.
-    - It modifies the HTTP Authorization header to encode user and
-      password into base 64 if it is Basic authentication.
     """
 
-    def __init__(self, app, wsgi_stack, root, handle_errors):
-        # Passing in both an app and a WSGI stack may seem like a duplication
-        # but we want to keep a reference to the app that may be arbitrarily
-        # deep in the WSGI stack.
-        assert isinstance(handle_errors, bool)
+    default_handle_errors = 'True'
+
+    def __init__(self, app, wsgi_stack):
         self.app = app
-        self.root = root
         self.wsgi_stack = wsgi_stack
-        self.default_handle_errors = str(handle_errors)
 
     def __call__(self, environ, start_response):
         # Handle debug mode
@@ -104,23 +66,11 @@
             'HTTP_X_ZOPE_HANDLE_ERRORS', self.default_handle_errors)
         self.app.handleErrors = handle_errors == 'True'
 
-        # Handle authorization
-        auth_key = 'HTTP_AUTHORIZATION'
-        if auth_key in environ:
-            environ[auth_key] = auth_header(environ[auth_key])
-
-        # Remove unwanted headers
-        def application_start_response(status, headers, exc_info=None):
-            headers = filter(is_wanted_header, headers)
-            start_response(status, headers)
-
-        commit()
-        for entry in self.wsgi_stack(environ, application_start_response):
+        for entry in self.wsgi_stack(environ, start_response):
             yield entry
-        self.root._p_jar.sync()
 
 
-class BrowserLayer(ZODBLayer):
+class BrowserLayer(zope.testbrowser.wsgi.Layer, ZODBLayer):
     """This create a test layer with a test database and register a wsgi
     application to use that test database.
 
@@ -134,26 +84,26 @@
         # WSGI middleware.
         return app
 
+    def make_wsgi_app(self):
+        # Since the request factory class is only a parameter default of
+        # WSGIPublisherApplication and not easily accessible otherwise, we fake
+        # it into creating a requestFactory instance, so we can read the class
+        # off of that in testSetUp()
+        fake_db = object()
+        self._application = WSGIPublisherApplication(fake_db)
+        return HandleErrorsMiddleware(
+            self._application,
+            TransactionMiddleware(
+                self.getRootFolder,
+                self.setup_middleware(self._application)))
+
     def testSetUp(self):
         super(BrowserLayer, self).testSetUp()
-        wsgi_app = WSGIPublisherApplication(
-            self.db, HTTPPublicationRequestFactory, True)
+        # Tell the publisher to use ZODBLayer's current database
+        factory = type(self._application.requestFactory)
+        self._application.requestFactory = factory(self.db)
 
-        def factory(handle_errors=True):
-            return TestBrowserMiddleware(wsgi_app,
-                                         self.setup_middleware(wsgi_app),
-                                         self.getRootFolder(),
-                                         handle_errors)
 
-        for host in TEST_HOSTS:
-            wsgi_intercept.add_wsgi_intercept(host, 80, factory)
-
-    def testTearDown(self):
-        for host in TEST_HOSTS:
-            wsgi_intercept.remove_wsgi_intercept(host, 80)
-        super(BrowserLayer, self).testTearDown()
-
-
 class NotInBrowserLayer(Exception):
     """The current test is not running in a layer inheriting from
     BrowserLayer.



More information about the checkins mailing list