summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMalthe Borch <mborch@gmail.com>2009-10-26 12:27:34 +0000
committerMalthe Borch <mborch@gmail.com>2009-10-26 12:27:34 +0000
commit0d13f6596c2cf38a611183e01a7f73173d5d6faa (patch)
tree91482267042f6403dab57816615e1e35c24b99ce
parent077c3c521b1a3cc3b17449f3360f2a0532d50dc7 (diff)
downloadpyramid-0d13f6596c2cf38a611183e01a7f73173d5d6faa.tar.gz
pyramid-0d13f6596c2cf38a611183e01a7f73173d5d6faa.tar.bz2
pyramid-0d13f6596c2cf38a611183e01a7f73173d5d6faa.zip
The root factory may now return an object which implements ``ITraverser`` directly. In this case, no adaptation is done before traversal. This feature is added such that a routes factory can implement its own traversal logic without establishing an artificial context only to get a hook into the traversal machinery.
-rw-r--r--CHANGES.txt4
-rw-r--r--docs/narr/hooks.rst3
-rw-r--r--repoze/bfg/tests/test_router.py40
-rw-r--r--repoze/bfg/traversal.py9
4 files changed, 50 insertions, 6 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index b4c04304e..b112a996a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,6 +4,10 @@ Next release
Features
--------
+- The root factory may now return an object which implements
+ ``ITraverser`` directly. In this case, no adaptation is done before
+ traversal.
+
- Add ``path_info`` view configuration predicate.
- ``paster bfgshell`` now supports IPython if it's available for
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index d2020af0d..6babeace0 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -278,6 +278,9 @@ when the application :term:`root factory` returned an instance of the
``myapp.models.MyRoot`` object. Otherwise it would use the default
:mod:`repoze.bfg` traverser to do traversal.
+Note that the root object may itself implement ``ITraverser`` in which
+case adaptation is skipped.
+
Example implementations of alternate traversers can be found "in the
wild" within `repoze.bfg.traversalwrapper
<http://pypi.python.org/pypi/repoze.bfg.traversalwrapper>`_ and
diff --git a/repoze/bfg/tests/test_router.py b/repoze/bfg/tests/test_router.py
index 13a5bd11a..6c0497653 100644
--- a/repoze/bfg/tests/test_router.py
+++ b/repoze/bfg/tests/test_router.py
@@ -28,10 +28,9 @@ class TestRouter(unittest.TestCase):
settings.update(kw)
self.registry.registerUtility(settings, ISettings)
- def _registerTraverserFactory(self, context, view_name='', subpath=None,
+ def _makeTraverserFactory(self, context, view_name='', subpath=None,
traversed=None, virtual_root=None,
virtual_root_path=None, **kw):
- from repoze.bfg.interfaces import ITraverser
if virtual_root is None:
virtual_root = context
@@ -42,8 +41,13 @@ class TestRouter(unittest.TestCase):
if virtual_root_path is None:
virtual_root_path = []
+ from zope.interface import implements
+ from repoze.bfg.interfaces import ITraverser
+
class DummyTraverserFactory:
- def __init__(self, root):
+ implements(ITraverser)
+
+ def __init__(self, root=None):
self.root = root
def __call__(self, path):
@@ -57,6 +61,11 @@ class TestRouter(unittest.TestCase):
kw.update(values)
return kw
+ return DummyTraverserFactory
+
+ def _registerTraverserFactory(self, *args, **kwargs):
+ DummyTraverserFactory = self._makeTraverserFactory(*args, **kwargs)
+ from repoze.bfg.interfaces import ITraverser
self.registry.registerAdapter(DummyTraverserFactory, (None,),
ITraverser, name='')
@@ -147,6 +156,31 @@ class TestRouter(unittest.TestCase):
self.failIf('debug_notfound' in result[0])
self.assertEqual(len(logger.messages), 0)
+ def test_call_traverser_model(self):
+ environ = self._makeEnviron()
+ from zope.interface import Interface
+ class IContext(Interface):
+ pass
+ context = DummyContext()
+ from zope.interface import directlyProvides
+ directlyProvides(context, IContext)
+ RootFactory = self._makeTraverserFactory(context, view_name='def')
+ root = RootFactory()
+ self._registerRootFactory(root)
+ from repoze.bfg.interfaces import IRequest
+ response = DummyResponse()
+ response.app_iter = ['Hello world']
+ view = DummyView(response)
+ self._registerView(view, 'def', IContext, IRequest)
+ logger = self._registerLogger()
+ router = self._makeOne()
+ start_response = DummyStartResponse()
+ result = router(environ, start_response)
+ self.assertEqual(result, ['Hello world'])
+ headers = start_response.headers
+ status = start_response.status
+ self.assertEqual(status, '200 OK')
+
def test_has_webob_adhoc_attrs(self):
environ = self._makeEnviron()
environ['webob.adhoc_attrs'] = {}
diff --git a/repoze/bfg/traversal.py b/repoze/bfg/traversal.py
index 11e5ca806..580225566 100644
--- a/repoze/bfg/traversal.py
+++ b/repoze/bfg/traversal.py
@@ -273,9 +273,12 @@ def traverse(model, path):
return _traverse(model, {'PATH_INFO':path})
def _traverse(model, environ):
- traverser = queryAdapter(model, ITraverser)
- if traverser is None:
- traverser = ModelGraphTraverser(model)
+ if ITraverser.providedBy(model):
+ traverser = model
+ else:
+ traverser = queryAdapter(model, ITraverser)
+ if traverser is None:
+ traverser = ModelGraphTraverser(model)
result = traverser(environ)
return result