summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2014-10-14 21:21:59 +0000
committerGerrit Code Review <review@openstack.org>2014-10-14 21:21:59 +0000
commit65ce81dee6bb5fbbf8dbe05fa133b2b0643c47f7 (patch)
treeb00b2a1982b9dffc7ea1fbeacc064b7bd2ccb997
parent8b30a0ec72860aa78b3b9c2246aa1c6e7a1b9cfe (diff)
parent960d83971c712e98c45c830df84fdc61cb8cd15b (diff)
downloadpecan-65ce81dee6bb5fbbf8dbe05fa133b2b0643c47f7.tar.gz
Merge "Fix a routing bug for generic subcontrollers."
-rw-r--r--pecan/routing.py13
-rw-r--r--pecan/tests/test_generic.py26
2 files changed, 38 insertions, 1 deletions
diff --git a/pecan/routing.py b/pecan/routing.py
index 7acff76..58a74c6 100644
--- a/pecan/routing.py
+++ b/pecan/routing.py
@@ -3,7 +3,7 @@ import warnings
from webob import exc
from .secure import handle_security, cross_boundary
-from .util import iscontroller, getargspec
+from .util import iscontroller, getargspec, _cfg
__all__ = ['lookup_controller', 'find_object']
@@ -148,6 +148,17 @@ def find_object(obj, remainder, notfound_handlers, request):
if not remainder:
raise PecanNotFound
+
+ prev_remainder = remainder
prev_obj = obj
remainder = rest
obj = getattr(obj, next_obj, None)
+
+ # Last-ditch effort: if there's not a matching subcontroller, no
+ # `_default`, no `_lookup`, and no `_route`, look to see if there's
+ # an `index` that has a generic method defined for the current request
+ # method.
+ if not obj and not notfound_handlers and hasattr(prev_obj, 'index'):
+ if request.method in _cfg(prev_obj.index).get('generic_handlers',
+ {}):
+ return prev_obj.index, prev_remainder
diff --git a/pecan/tests/test_generic.py b/pecan/tests/test_generic.py
index 453f123..19127fc 100644
--- a/pecan/tests/test_generic.py
+++ b/pecan/tests/test_generic.py
@@ -60,3 +60,29 @@ class TestGeneric(PecanTestCase):
r = app.delete('/', expect_errors=True)
assert r.status_int == 405
assert r.headers['Allow'] == 'GET, PATCH, POST'
+
+ def test_nested_generic(self):
+
+ class SubSubController(object):
+ @expose(generic=True)
+ def index(self):
+ return 'GET'
+
+ @index.when(method='DELETE', template='json')
+ def do_delete(self, name, *args):
+ return dict(result=name, args=', '.join(args))
+
+ class SubController(object):
+ sub = SubSubController()
+
+ class RootController(object):
+ sub = SubController()
+
+ app = TestApp(Pecan(RootController()))
+ r = app.get('/sub/sub/')
+ assert r.status_int == 200
+ assert r.body == b_('GET')
+
+ r = app.delete('/sub/sub/joe/is/cool')
+ assert r.status_int == 200
+ assert r.body == b_(dumps(dict(result='joe', args='is, cool')))