diff options
| author | Chris McDonough <chrism@agendaless.com> | 2009-04-30 03:57:57 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2009-04-30 03:57:57 +0000 |
| commit | 013c4bc7b3337bc50794300d7cb8502d191f4490 (patch) | |
| tree | 06c8f873748444225e0f3667f432a20cf338af9c /repoze | |
| parent | 361e49d1bd5bb498710d70c1122ff6feef589f95 (diff) | |
| download | pyramid-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.py | 43 | ||||
| -rw-r--r-- | repoze/bfg/traversal.py | 59 |
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 |
