summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-06-22 04:59:31 +0000
committerChris McDonough <chrism@agendaless.com>2009-06-22 04:59:31 +0000
commit7fc6a3c63676637018c922e6f997b174639466f0 (patch)
tree9dc0fd27543e098bc27e8b47b9a176835976b27a
parentd70fd93e4b76369edea80ac1ded9da9ac0a93289 (diff)
downloadpyramid-7fc6a3c63676637018c922e6f997b174639466f0.tar.gz
pyramid-7fc6a3c63676637018c922e6f997b174639466f0.tar.bz2
pyramid-7fc6a3c63676637018c922e6f997b174639466f0.zip
We weren't computing the virtual root correctly in a corner case.
-rw-r--r--repoze/bfg/tests/test_traversal.py53
-rw-r--r--repoze/bfg/traversal.py63
2 files changed, 74 insertions, 42 deletions
diff --git a/repoze/bfg/tests/test_traversal.py b/repoze/bfg/tests/test_traversal.py
index da52ab968..7d24cb9bc 100644
--- a/repoze/bfg/tests/test_traversal.py
+++ b/repoze/bfg/tests/test_traversal.py
@@ -88,6 +88,7 @@ class ModelGraphTraverserTests(unittest.TestCase):
self.assertEqual(result['view_name'], '')
self.assertEqual(result['subpath'], ())
self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], policy.root)
self.assertEqual(result['virtual_root'], policy.root)
self.assertEqual(result['virtual_root_path'], ())
@@ -99,6 +100,7 @@ class ModelGraphTraverserTests(unittest.TestCase):
self.assertEqual(result['view_name'], 'foo')
self.assertEqual(result['subpath'], ('bar',))
self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], policy.root)
self.assertEqual(result['virtual_root'], policy.root)
self.assertEqual(result['virtual_root_path'], ())
@@ -111,6 +113,7 @@ class ModelGraphTraverserTests(unittest.TestCase):
self.assertEqual(result['view_name'], '')
self.assertEqual(result['subpath'], ())
self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], root)
self.assertEqual(result['virtual_root'], root)
self.assertEqual(result['virtual_root_path'], ())
@@ -124,6 +127,7 @@ class ModelGraphTraverserTests(unittest.TestCase):
self.assertEqual(result['view_name'], 'bar')
self.assertEqual(result['subpath'], ())
self.assertEqual(result['traversed'], (u'foo',))
+ self.assertEqual(result['root'], root)
self.assertEqual(result['virtual_root'], root)
self.assertEqual(result['virtual_root_path'], ())
@@ -137,6 +141,7 @@ class ModelGraphTraverserTests(unittest.TestCase):
self.assertEqual(result['view_name'], 'bar')
self.assertEqual(result['subpath'], ('baz', 'buz'))
self.assertEqual(result['traversed'], (u'foo',))
+ self.assertEqual(result['root'], root)
self.assertEqual(result['virtual_root'], root)
self.assertEqual(result['virtual_root_path'], ())
@@ -150,38 +155,41 @@ class ModelGraphTraverserTests(unittest.TestCase):
self.assertEqual(result['view_name'], 'foo')
self.assertEqual(result['subpath'], ())
self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], root)
self.assertEqual(result['virtual_root'], root)
self.assertEqual(result['virtual_root_path'], ())
def test_call_with_vh_root(self):
environ = self._getEnviron(PATH_INFO='/baz',
HTTP_X_VHM_ROOT='/foo/bar')
- baz = DummyContext()
- bar = DummyContext(baz)
- foo = DummyContext(bar)
- root = DummyContext(foo)
+ baz = DummyContext(None, 'baz')
+ bar = DummyContext(baz, 'bar')
+ foo = DummyContext(bar, 'foo')
+ root = DummyContext(foo, 'root')
policy = self._makeOne(root)
result = policy(environ)
self.assertEqual(result['context'], baz)
self.assertEqual(result['view_name'], '')
self.assertEqual(result['subpath'], ())
self.assertEqual(result['traversed'], (u'foo', u'bar', u'baz'))
+ self.assertEqual(result['root'], root)
self.assertEqual(result['virtual_root'], bar)
self.assertEqual(result['virtual_root_path'], (u'foo', u'bar'))
def test_call_with_vh_root2(self):
environ = self._getEnviron(PATH_INFO='/bar/baz',
HTTP_X_VHM_ROOT='/foo')
- baz = DummyContext()
- bar = DummyContext(baz)
- foo = DummyContext(bar)
- root = DummyContext(foo)
+ baz = DummyContext(None, 'baz')
+ bar = DummyContext(baz, 'bar')
+ foo = DummyContext(bar, 'foo')
+ root = DummyContext(foo, 'root')
policy = self._makeOne(root)
result = policy(environ)
self.assertEqual(result['context'], baz)
self.assertEqual(result['view_name'], '')
self.assertEqual(result['subpath'], ())
self.assertEqual(result['traversed'], (u'foo', u'bar', u'baz'))
+ self.assertEqual(result['root'], root)
self.assertEqual(result['virtual_root'], foo)
self.assertEqual(result['virtual_root_path'], (u'foo',))
@@ -198,9 +206,27 @@ class ModelGraphTraverserTests(unittest.TestCase):
self.assertEqual(result['view_name'], '')
self.assertEqual(result['subpath'], ())
self.assertEqual(result['traversed'], (u'foo', u'bar', u'baz'))
+ self.assertEqual(result['root'], root)
self.assertEqual(result['virtual_root'], root)
self.assertEqual(result['virtual_root_path'], ())
+ def test_call_with_vh_root4(self):
+ environ = self._getEnviron(PATH_INFO='/',
+ HTTP_X_VHM_ROOT='/foo/bar/baz')
+ baz = DummyContext(None, 'baz')
+ bar = DummyContext(baz, 'bar')
+ foo = DummyContext(bar, 'foo')
+ root = DummyContext(foo, 'root')
+ policy = self._makeOne(root)
+ result = policy(environ)
+ self.assertEqual(result['context'], baz)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], (u'foo', u'bar', u'baz'))
+ self.assertEqual(result['root'], root)
+ self.assertEqual(result['virtual_root'], baz)
+ self.assertEqual(result['virtual_root_path'], (u'foo', u'bar', u'baz'))
+
def test_call_with_vh_root_path_root(self):
policy = self._makeOne(None)
environ = self._getEnviron(HTTP_X_VHM_ROOT='/',
@@ -210,6 +236,7 @@ class ModelGraphTraverserTests(unittest.TestCase):
self.assertEqual(result['view_name'], '')
self.assertEqual(result['subpath'], ())
self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], policy.root)
self.assertEqual(result['virtual_root'], policy.root)
self.assertEqual(result['virtual_root_path'], ())
@@ -239,6 +266,7 @@ class ModelGraphTraverserTests(unittest.TestCase):
self.assertEqual(result['view_name'], '')
self.assertEqual(result['subpath'], ())
self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], model)
self.assertEqual(result['virtual_root'], model)
self.assertEqual(result['virtual_root_path'], ())
@@ -251,6 +279,7 @@ class ModelGraphTraverserTests(unittest.TestCase):
self.assertEqual(result['view_name'], '')
self.assertEqual(result['subpath'], ('a', 'b','c'))
self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], model)
self.assertEqual(result['virtual_root'], model)
self.assertEqual(result['virtual_root_path'], ())
@@ -263,6 +292,7 @@ class ModelGraphTraverserTests(unittest.TestCase):
self.assertEqual(result['view_name'], 'foo')
self.assertEqual(result['subpath'], ('bar',))
self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], model)
self.assertEqual(result['virtual_root'], model)
self.assertEqual(result['virtual_root_path'], ())
@@ -917,15 +947,18 @@ def make_traverser(result):
class DummyContext(object):
__parent__ = None
- __name__ = None
- def __init__(self, next=None):
+ def __init__(self, next=None, name=None):
self.next = next
+ self.__name__ = name
def __getitem__(self, name):
if self.next is None:
raise KeyError, name
return self.next
+ def __repr__(self):
+ return '<DummyContext with name %s at id %s>'%(self.__name__, id(self))
+
class DummyRequest:
application_url = 'http://example.com:5432' # app_url never ends with slash
def __init__(self, environ=None):
diff --git a/repoze/bfg/traversal.py b/repoze/bfg/traversal.py
index 59ad9115d..2b9a0e611 100644
--- a/repoze/bfg/traversal.py
+++ b/repoze/bfg/traversal.py
@@ -502,69 +502,68 @@ class ModelGraphTraverser(object):
# this request did not match a Routes route
subpath = ()
try:
- path = environ['PATH_INFO']
+ path = environ['PATH_INFO'] or '/'
except KeyError:
path = '/'
try:
- vroot_path_string = environ[VH_ROOT_KEY]
+ vroot_path = environ[VH_ROOT_KEY]
except KeyError:
- vroot_path = ()
- vroot_idx = 0
+ vroot_tuple = ()
+ vpath = path
+ vroot_idx = -1
else:
- vroot_path = traversal_path(vroot_path_string)
- vroot_idx = len(vroot_path)
- path = vroot_path_string + path
+ vroot_tuple = traversal_path(vroot_path)
+ vpath = vroot_path + path
+ vroot_idx = len(vroot_tuple) -1
ob = vroot = self.root
- if (not path) or path == '/':
- # save a call to traversal_path if we know it's going to return
- # the empty tuple
- path = ()
+ if vpath == '/' or (not vpath):
+ # prevent a call to traversal_path if we know it's going
+ # to return the empty tuple
+ vpath_tuple = ()
else:
- path = traversal_path(path)
-
- # in case you're wondering, we do dead reckoning here instead
- # of pushing and popping temporary lists for speed purposes
-
- i = 1
- j = vroot_idx
-
- for segment in path:
+ # we do dead reckoning here via tuple slicing instead of
+ # pushing and popping temporary lists for speed purposes
+ # and this hurts readability; apologies
+ i = 0
+ vpath_tuple = traversal_path(vpath)
+ for segment in vpath_tuple:
if segment[:2] =='@@':
return dict(context=ob, view_name=segment[2:],
- subpath=path[i:], traversed=path[:j],
+ subpath=vpath_tuple[i+1:],
+ traversed=vpath_tuple[:vroot_idx+i+1],
virtual_root=vroot,
- virtual_root_path=vroot_path,
+ virtual_root_path=vroot_tuple,
root=self.root)
try:
getitem = ob.__getitem__
except AttributeError:
return dict(context=ob, view_name=segment,
- subpath=path[i:], traversed=path[:j],
+ subpath=vpath_tuple[i+1:],
+ traversed=vpath_tuple[:vroot_idx+i+1],
virtual_root=vroot,
- virtual_root_path=vroot_path,
+ virtual_root_path=vroot_tuple,
root=self.root)
try:
next = getitem(segment)
except KeyError:
return dict(context=ob, view_name=segment,
- subpath=path[i:], traversed=path[:j],
+ subpath=vpath_tuple[i+1:],
+ traversed=vpath_tuple[:vroot_idx+i+1],
virtual_root=vroot,
- virtual_root_path=vroot_path,
+ virtual_root_path=vroot_tuple,
root=self.root)
-
- if vroot_idx == i-1:
- vroot = ob
+ if i == vroot_idx:
+ vroot = next
ob = next
i += 1
- j += 1
return dict(context=ob, view_name=u'', subpath=subpath,
- traversed=path, virtual_root=vroot,
- virtual_root_path=vroot_path, root=self.root)
+ traversed=vpath_tuple, virtual_root=vroot,
+ virtual_root_path=vroot_tuple, root=self.root)
class TraversalContextURL(object):
""" The IContextURL adapter used to generate URLs for a context