[Repoze-checkins] r795 - in repoze.zope2/trunk: . repoze/zope2 repoze/zope2/tests

Chris McDonough chrism at agendaless.com
Mon Mar 10 05:12:02 UTC 2008


Author: Chris McDonough <chrism at agendaless.com>
Date: Mon Mar 10 00:12:02 2008
New Revision: 795

Log:
  - repoze.zope2 now properly respects virtual host directives
    provided to it by repoze.vhm xheaders middleware >= 0.4.  Zope's
    VHM can still be used as necessary, but is no longer required.



Modified:
   repoze.zope2/trunk/CHANGES.txt
   repoze.zope2/trunk/repoze/zope2/tests/base.py
   repoze.zope2/trunk/repoze/zope2/tests/test_z2bob.py
   repoze.zope2/trunk/repoze/zope2/z2bob.py
   repoze.zope2/trunk/setup.py

Modified: repoze.zope2/trunk/CHANGES.txt
==============================================================================
--- repoze.zope2/trunk/CHANGES.txt	(original)
+++ repoze.zope2/trunk/CHANGES.txt	Mon Mar 10 00:12:02 2008
@@ -1,3 +1,9 @@
+0.3.3 (2008-03-10)
+
+  - repoze.zope2 now properly respects virtual host directives
+    provided to it by repoze.vhm xheaders middleware >= 0.4.  Zope's
+    VHM can still be used as necessary, but is no longer required.
+
 0.3.2 (2008-03-03)
 
   - Fix bug reported by Martin Aspeli: repoze.zope2 would choke on

Modified: repoze.zope2/trunk/repoze/zope2/tests/base.py
==============================================================================
--- repoze.zope2/trunk/repoze/zope2/tests/base.py	(original)
+++ repoze.zope2/trunk/repoze/zope2/tests/base.py	Mon Mar 10 00:12:02 2008
@@ -110,6 +110,9 @@
             raise self.exception
         return self.result
 
+    def getPhysicalPath(self):
+        return ('', 'foo')
+
 class DummyPublishedObjectWithRoles(DummyPublishedObject):
     __roles__ = ('Manager',)
 

Modified: repoze.zope2/trunk/repoze/zope2/tests/test_z2bob.py
==============================================================================
--- repoze.zope2/trunk/repoze/zope2/tests/test_z2bob.py	(original)
+++ repoze.zope2/trunk/repoze/zope2/tests/test_z2bob.py	Mon Mar 10 00:12:02 2008
@@ -170,6 +170,50 @@
                          'http://www.example.com/foo')
         self.assertEqual(helper.webdav_client, False)
         self.assertEqual(helper.default_page, 'index_html')
+        self.assertEqual(helper.vroot_stack, None)
+
+    def test_setup_with_vroot(self):
+        from zope.security.management import queryInteraction
+        from zope.security.management import endInteraction
+        env = _makeEnviron()
+        env['SERVER_NAME'] = 'www.example.com'
+        env['SERVER_PORT'] = '80'
+        env['repoze.vhm.virtual_root'] = '/cms'
+        helper = self._makeOne(env)
+        if queryInteraction() is not None:
+            endInteraction()
+        helper.setup()
+        self.assertEqual(env['SERVER_URL'], 'http://www.example.com')
+        from zope.publisher.interfaces.browser import IDefaultBrowserLayer
+        self.failUnless(IDefaultBrowserLayer.providedBy(helper.request))
+        self.assertNotEqual(queryInteraction(), None)
+        self.assertEqual(helper.request['URL'], 'http://www.example.com')
+        self.assertEqual(helper.request['ACTUAL_URL'],
+                         'http://www.example.com/foo')
+        self.assertEqual(helper.webdav_client, False)
+        self.assertEqual(helper.default_page, 'index_html')
+        self.assertEqual(helper.vroot_stack, ['cms'])
+        self.assertEqual(helper.request['TraversalRequestNameStack'],
+                         ['foo', '_rvh:cms'])
+
+    def test_setup_with_empty_vroot(self):
+        from zope.security.management import queryInteraction
+        from zope.security.management import endInteraction
+        env = _makeEnviron()
+        env['SERVER_NAME'] = 'www.example.com'
+        env['SERVER_PORT'] = '80'
+        env['repoze.vhm.virtual_root'] = '//'
+        helper = self._makeOne(env)
+        if queryInteraction() is not None:
+            endInteraction()
+        helper.setup()
+        self.assertEqual(env['SERVER_URL'], 'http://www.example.com')
+        from zope.publisher.interfaces.browser import IDefaultBrowserLayer
+        self.failUnless(IDefaultBrowserLayer.providedBy(helper.request))
+        self.assertNotEqual(queryInteraction(), None)
+        self.assertEqual(helper.vroot_stack, None)
+        self.assertEqual(helper.request['TraversalRequestNameStack'],
+                         ['foo'])
 
     def test_setup_dav(self):
         from zope.security.management import queryInteraction
@@ -212,6 +256,23 @@
         self.assertEqual(helper.next_name(), 'bar')
         self.assertEqual(helper.next_name(), None)
 
+    def test_next_name_with_rvh_novhost(self):
+        helper = self._makeOne()
+        helper.request['TraversalRequestNameStack'] = ['bar', '_rvh:foo']
+        helper.vroot_stack = None
+        self.assertEqual(helper.next_name(), '_rvh:foo')
+        self.assertEqual(helper.next_name(), 'bar')
+        self.assertEqual(helper.next_name(), None)
+
+    def test_next_name_with_rvh_vhost(self):
+        helper = self._makeOne()
+        helper.request['TraversalRequestNameStack'] = ['bar', '_rvh:foo']
+        helper.vroot_stack = ['_rvh:foo']
+        self.assertEqual(helper.next_name(), 'foo')
+        self.assertEqual(helper.vroot_stack, [])
+        self.assertEqual(helper.next_name(), 'bar')
+        self.assertEqual(helper.next_name(), None)
+
     def test_before_traverse_calls_bpth(self):
         published = DummyPublishedObject()
         L = []
@@ -262,6 +323,42 @@
         self.assertEqual(helper.user_folders,
                          [('', published.__allow_groups__)])
 
+    def test_traverse_with_empty_vroot_stack(self):
+        published = DummyGetitemPublishedObject()
+        foo = DummyPublishedObject()
+        foo.__doc__ = 'hello'
+        published.subs['foo'] = foo
+        published.__allow_groups__ = object()
+        env = _makeEnviron()
+        helper = self._makeOne()
+        helper.user_folders = []
+        helper.request.steps = []
+        helper.request._steps = ['bar']
+        helper.vroot_stack = []
+        helper.traverse(published, 'foo')
+        self.assertEqual(helper.request.other['VirtualRootPhysicalPath'],
+                         ('', 'foo'))
+        self.assertEqual(helper.request._steps, [])
+        self.assertEqual(helper.vroot_stack, None)
+
+    def test_traverse_with_nonempty_vroot_stack(self):
+        published = DummyGetitemPublishedObject()
+        foo = DummyPublishedObject()
+        foo.__doc__ = 'hello'
+        published.subs['foo'] = foo
+        published.__allow_groups__ = object()
+        env = _makeEnviron()
+        helper = self._makeOne()
+        helper.user_folders = []
+        helper.request.steps = []
+        helper.request._steps = ['bar']
+        helper.vroot_stack = ['buz']
+        helper.traverse(published, 'foo')
+        request = helper.request
+        self.assertEqual(request.other.get('VirtualRootPhysicalPath'), None)
+        self.assertEqual(helper.request._steps, ['bar'])
+        self.assertEqual(helper.vroot_stack, ['buz'])
+
     def test_traverse_nslookup_to_bad_viewname_raises_HTTPNotFound(self):
         published = DummyPublishedObject()
         helper = self._makeOne()

Modified: repoze.zope2/trunk/repoze/zope2/z2bob.py
==============================================================================
--- repoze.zope2/trunk/repoze/zope2/z2bob.py	(original)
+++ repoze.zope2/trunk/repoze/zope2/z2bob.py	Mon Mar 10 00:12:02 2008
@@ -75,8 +75,10 @@
 
 def cleanPath(path):
     # Cleanup the path list
-    if path[:1]=='/':  path=path[1:]
-    if path[-1:]=='/': path=path[:-1]
+    if path[:1]=='/':
+        path=path[1:]
+    if path[-1:]=='/':
+        path=path[:-1]
     clean=[]
     for item in path.split('/'):
         # Make sure that certain things that dont make sense
@@ -128,6 +130,7 @@
         self.traversed = []
         self.webdav_client = False
         self.default_page = 'index_html'
+        self.vroot_stack = None
 
     def _configure(self, config):
         self._config = config
@@ -149,7 +152,8 @@
                 pass
 
     def setup(self):
-        from repoze.vhm.zope2 import setServerURL
+        self.vroot_stack = None
+        from repoze.vhm.utils import setServerURL
         # dictate what SERVER_URL is instead of allowing the request
         # constructor to compute it
         setServerURL(self.environ) 
@@ -177,6 +181,7 @@
         self.browser_path = path = request['PATH_INFO']
         request['ACTUAL_URL'] = request['URL'] + path
         request.steps = request._steps = []
+        path = self._setVirtualRoot(self.environ, path)
         self.clean = cleanPath(path)
         # We need to continue respecting this silly stack to account
         # for hooks that modify it
@@ -185,7 +190,7 @@
         request.path = request['TraversalRequestNameStack'] = trns
         request.roles = getRoles(None, None, self.root, UNSPECIFIED_ROLES)
         self.request = request
-        
+
     def teardown(self):
         endInteraction()
         if self.request is not None:
@@ -196,6 +201,13 @@
         trns = self.request['TraversalRequestNameStack']
         if trns:
             name =  trns.pop()
+            if name.startswith('_rvh:') and self.vroot_stack is not None:
+                # this is a repoze.vhm.virtual_root-defined name; pop
+                # it off the vroot stack too; when the vroot stack is
+                # empty, we'll be able to set VirtualRootPhysicalPath
+                # in the request.
+                self.vroot_stack.pop()
+                name = name[len('_rvh:'):]
             return name
 
     def before_traverse(self, ob):
@@ -237,6 +249,22 @@
         request.roles = getRoles(ob, name, ob2, request.roles)
         self.traversed.append(name)
 
+        if self.vroot_stack is not None:
+            # there was a virtual root specified during this request
+            # (via 'repoze.vhm.virtual_root')
+            if not self.vroot_stack:
+                # the virtual root stack has been popped until empty,
+                # which means the object we just traversed is the
+                # virtual root; set its physical path in
+                # request.other's VirtualRootPhysicalPath.
+                request.other['VirtualRootPhysicalPath'] = ob2.getPhysicalPath()
+                # clear _steps: URLs computed subsequently won't have
+                # any names in them from objects we've traversed thus
+                # far.
+                del request._steps[:]
+                # gate; we don't want to do this again
+                self.vroot_stack = None
+
         return ob2
 
     def before_invoke(self, published):
@@ -508,6 +536,39 @@
             path = '/'.join([''] + self.traversed)
             self.user_folders.insert(0, (path, user_folder))
 
+    def _setVirtualRoot(self, environ, path):
+        from repoze.vhm.utils import getVirtualRoot
+        vroot = getVirtualRoot(self.environ)
+        # vroot will be the value of 'repoze.vhm.virtual_root' in the
+        # environment
+        if vroot:
+            split_vroot = cleanPath(vroot)
+            if split_vroot:
+                # The vroot isn't the real root.
+
+                # Munge the vroot path names
+                vroot_path = [ '_rvh:%s' % name for name in split_vroot ]
+                vroot_path = '/'.join(vroot_path)
+                # Names prefixed with '_rvh:' will be popped off the
+                # both the traversal request name stack and the
+                # self.vroot stack within next_name() (which unmunges
+                # the '_rvh:' names); we do this because the trns can
+                # be mutated arbitrarily by app code and we can't just
+                # count the number of pops to figure out when we've
+                # popped the virtual root in order to detect when
+                # we're allowed to set VirtualRootPhysicalPath at the
+                # ass end of traverse().
+                if not path.startswith('/'):
+                    path = '/' + path
+                # path will now contain the vroot steps
+                path = vroot_path + path
+                self.vroot_stack = split_vroot
+                # We reverse this simply because trns is also reversed
+                # (presumably so lazy people wouldn't have to type
+                # pop(0); might as well ape the pattern)
+                self.vroot_stack.reverse()
+        return path
+
 lock = threading.Lock()
 db = None
 
@@ -545,3 +606,11 @@
     helper.root = root
 
     return root
+
+def vhmtest(app, global_conf):
+    def test(environ, start_response):
+        environ['HTTP_X_VHM_HOST'] = 'http://127.0.0.1:8080'
+        environ['HTTP_X_VHM_ROOT'] = '/siteroot'
+        return app(environ, start_response)
+    return test
+    

Modified: repoze.zope2/trunk/setup.py
==============================================================================
--- repoze.zope2/trunk/setup.py	(original)
+++ repoze.zope2/trunk/setup.py	Mon Mar 10 00:12:02 2008
@@ -12,7 +12,7 @@
 #
 ##############################################################################
 
-__version__ = '0.3.2'
+__version__ = '0.3.3'
 
 from ez_setup import use_setuptools
 use_setuptools()
@@ -52,7 +52,7 @@
                'ZODB3 >= 3.7.2, < 3.8.0a',
                'repoze.tm >= 0.8',
                'repoze.errorlog >= 0.5',
-               'repoze.vhm >=0.3',
+               'repoze.vhm >= 0.4',
                'repoze.retry >=0.6',
                'repoze.obob >= 0.2',
                ],


More information about the Repoze-checkins mailing list