summaryrefslogtreecommitdiff
path: root/repoze
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-04-30 03:57:57 +0000
committerChris McDonough <chrism@agendaless.com>2009-04-30 03:57:57 +0000
commit013c4bc7b3337bc50794300d7cb8502d191f4490 (patch)
tree06c8f873748444225e0f3667f432a20cf338af9c /repoze
parent361e49d1bd5bb498710d70c1122ff6feef589f95 (diff)
downloadpyramid-013c4bc7b3337bc50794300d7cb8502d191f4490.tar.gz
pyramid-013c4bc7b3337bc50794300d7cb8502d191f4490.tar.bz2
pyramid-013c4bc7b3337bc50794300d7cb8502d191f4490.zip
Make ModelGraphTraverser assume that all traversed objects provide ILocation. Make WrappingModelGraphTraverser assume that *no* traversed objects provide ILocation. This makes it unnecessary to explain why the root object in a WrappingModelGraphTraverser setup needs to supply the ILocation interface. Now it doesn't.
Diffstat (limited to 'repoze')
-rw-r--r--repoze/bfg/tests/test_traversal.py43
-rw-r--r--repoze/bfg/traversal.py59
2 files changed, 56 insertions, 46 deletions
diff --git a/repoze/bfg/tests/test_traversal.py b/repoze/bfg/tests/test_traversal.py
index 3354dcce1..942f84684 100644
--- a/repoze/bfg/tests/test_traversal.py
+++ b/repoze/bfg/tests/test_traversal.py
@@ -195,17 +195,12 @@ class WrappingModelGraphTraverserTests(ModelGraphTraverserTests):
from repoze.bfg.traversal import WrappingModelGraphTraverser
return WrappingModelGraphTraverser
- def test_call_with_ILocation_root_proxies(self):
+ def test_call_proxies(self):
baz = DummyContext()
bar = DummyContext(baz)
foo = DummyContext(bar)
root = DummyContext(foo)
- from zope.interface import directlyProvides
- from repoze.bfg.interfaces import ILocation
from zope.proxy import isProxy
- directlyProvides(root, ILocation)
- root.__name__ = None
- root.__parent__ = None
policy = self._makeOne(root)
environ = self._getEnviron(PATH_INFO='/foo/bar/baz')
ctx, name, subpath, traversed, vroot, vroot_path = policy(environ)
@@ -221,47 +216,13 @@ class WrappingModelGraphTraverserTests(ModelGraphTraverserTests):
self.failUnless(isProxy(ctx.__parent__.__parent__))
self.assertEqual(ctx.__parent__.__parent__.__name__, 'foo')
self.assertEqual(ctx.__parent__.__parent__.__parent__, root)
- self.failIf(isProxy(ctx.__parent__.__parent__.__parent__))
+ self.failUnless(isProxy(ctx.__parent__.__parent__.__parent__))
self.assertEqual(ctx.__parent__.__parent__.__parent__.__name__, None)
self.assertEqual(ctx.__parent__.__parent__.__parent__.__parent__, None)
self.assertEqual(traversed, [u'foo', u'bar', u'baz'])
self.assertEqual(vroot, root)
self.assertEqual(vroot_path, [])
- def test_call_with_ILocation_root_proxies_til_next_ILocation(self):
- # This is a test of an insane setup; it tests the case where
- # intermediate objects (foo and bar) do not implement
- # ILocation, and so are returned as proxies to the traverser,
- # but when we reach the "baz" object, it *does* implement
- # ILocation, and its parent should be the *real* "bar" object
- # rather than the proxied bar.
- from zope.interface import directlyProvides
- from repoze.bfg.interfaces import ILocation
- baz = DummyContext()
- directlyProvides(baz, ILocation)
- baz.__name__ = 'baz'
- bar = DummyContext(baz)
- baz.__parent__ = bar
- foo = DummyContext(bar)
- root = DummyContext(foo)
- from zope.proxy import isProxy
- directlyProvides(root, ILocation)
- root.__name__ = None
- root.__parent__ = None
- policy = self._makeOne(root)
- environ = self._getEnviron(PATH_INFO='/foo/bar/baz')
- ctx, name, subpath, traversed, vroot, vroot_path = policy(environ)
- self.assertEqual(name, '')
- self.assertEqual(subpath, [])
- self.assertEqual(ctx, baz)
- self.failIf(isProxy(ctx))
- self.assertEqual(ctx.__name__, 'baz')
- self.assertEqual(ctx.__parent__, bar)
- self.failIf(isProxy(ctx.__parent__))
- self.assertEqual(traversed, [u'foo', u'bar', u'baz'])
- self.assertEqual(vroot, root)
- self.assertEqual(vroot_path, [])
-
class FindInterfaceTests(unittest.TestCase):
def _callFUT(self, context, iface):
from repoze.bfg.traversal import find_interface
diff --git a/repoze/bfg/traversal.py b/repoze/bfg/traversal.py
index 6c2e6aa9a..ddfd7183d 100644
--- a/repoze/bfg/traversal.py
+++ b/repoze/bfg/traversal.py
@@ -380,9 +380,11 @@ def quote_path_segment(segment):
_marker = object()
class ModelGraphTraverser(object):
+ """ A model graph traverser that should be used (for speed) when
+ every object in the graph supplies a ``__name__`` and
+ ``__parent__`` attribute (ie. every object 'provides ILocation') ."""
classProvides(ITraverserFactory)
implements(ITraverser)
- SUPPLY_LOCATION_PROXIES = False
def __init__(self, root):
self.root = root
@@ -407,7 +409,6 @@ class ModelGraphTraverser(object):
ob = vroot = self.root
name = ''
- locatable = self.SUPPLY_LOCATION_PROXIES and ILocation.providedBy(ob)
i = 1
@@ -422,8 +423,6 @@ class ModelGraphTraverser(object):
next = getitem(segment)
except KeyError:
return ob, segment, path[i:], traversed, vroot, vroot_path
- if locatable and (not ILocation.providedBy(next)):
- next = LocationProxy(next, ob, segment)
if vroot_idx == i-1:
vroot = ob
traversed.append(segment)
@@ -433,7 +432,57 @@ class ModelGraphTraverser(object):
return ob, '', [], traversed, vroot, vroot_path
class WrappingModelGraphTraverser(ModelGraphTraverser):
- SUPPLY_LOCATION_PROXIES = True
+ """ A model graph traverser that should be used (for convenience)
+ when no object in the graph supplies either a ``__name__`` or a
+ ``__parent__`` attribute (ie. no object 'provides ILocation') ."""
+ classProvides(ITraverserFactory)
+ implements(ITraverser)
+ def __init__(self, root):
+ self.root = root
+
+ def __call__(self, environ, _marker=_marker):
+ try:
+ path = environ['PATH_INFO']
+ except KeyError:
+ path = '/'
+ try:
+ vroot_path_string = environ[VH_ROOT_KEY]
+ except KeyError:
+ vroot_path = []
+ vroot_idx = 0
+ else:
+ vroot_path = list(traversal_path(vroot_path_string))
+ vroot_idx = len(vroot_path)
+ path = vroot_path_string + path
+
+ path = list(traversal_path(path))
+
+ traversed = []
+
+ ob = vroot = LocationProxy(self.root)
+ name = ''
+
+ i = 1
+
+ for segment in path:
+ if segment[:2] =='@@':
+ return ob, segment[2:], path[i:], traversed, vroot, vroot_path
+ try:
+ getitem = ob.__getitem__
+ except AttributeError:
+ return ob, segment, path[i:], traversed, vroot, vroot_path
+ try:
+ next = getitem(segment)
+ except KeyError:
+ return ob, segment, path[i:], traversed, vroot, vroot_path
+ next = LocationProxy(next, ob, segment)
+ if vroot_idx == i-1:
+ vroot = ob
+ traversed.append(segment)
+ ob = next
+ i += 1
+
+ return ob, '', [], traversed, vroot, vroot_path
class TraversalContextURL(object):
""" The IContextURL adapter used to generate URLs for a context