Fix an infinite recursion error in PecanHook application.
Subclassing both `rest.RestController` and `hooks.HookController` results in an infinite recursion error in hook application (which prevents your application from starting). Fixes bug 1357540 Change-Id: I6e26c6d8771b4b35943bfb85bf41e73d0982e74c
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import types
|
||||
import sys
|
||||
from inspect import getmembers
|
||||
|
||||
@@ -27,7 +28,15 @@ def walk_controller(root_class, controller, hooks):
|
||||
for hook in hooks:
|
||||
value._pecan.setdefault('hooks', set()).add(hook)
|
||||
elif hasattr(value, '__class__'):
|
||||
if name.startswith('__') and name.endswith('__'):
|
||||
# Skip non-exposed methods that are defined in parent classes;
|
||||
# they're internal implementation details of that class, and
|
||||
# not actual routable controllers, so we shouldn't bother
|
||||
# assigning hooks to them.
|
||||
if (
|
||||
isinstance(value, types.MethodType) and
|
||||
any(filter(lambda c: value.__func__ in c.__dict__.values(),
|
||||
value.im_class.mro()[1:]))
|
||||
):
|
||||
continue
|
||||
walk_controller(root_class, value, hooks)
|
||||
|
||||
|
@@ -1656,3 +1656,43 @@ class TestRequestViewerHook(PecanTestCase):
|
||||
viewer = RequestViewerHook(conf)
|
||||
|
||||
assert viewer.items == ['url']
|
||||
|
||||
|
||||
class TestRestControllerWithHooks(PecanTestCase):
|
||||
|
||||
def test_restcontroller_with_hooks(self):
|
||||
|
||||
class SomeHook(PecanHook):
|
||||
|
||||
def before(self, state):
|
||||
state.response.headers['X-Testing'] = 'XYZ'
|
||||
|
||||
class BaseController(rest.RestController):
|
||||
|
||||
@expose()
|
||||
def delete(self, _id):
|
||||
return 'Deleting %s' % _id
|
||||
|
||||
class RootController(BaseController, HookController):
|
||||
|
||||
__hooks__ = [SomeHook()]
|
||||
|
||||
@expose()
|
||||
def get_all(self):
|
||||
return 'Hello, World!'
|
||||
|
||||
app = TestApp(
|
||||
make_app(
|
||||
RootController()
|
||||
)
|
||||
)
|
||||
|
||||
response = app.get('/')
|
||||
assert response.status_int == 200
|
||||
assert response.body == b_('Hello, World!')
|
||||
assert response.headers['X-Testing'] == 'XYZ'
|
||||
|
||||
response = app.delete('/100/')
|
||||
assert response.status_int == 200
|
||||
assert response.body == b_('Deleting 100')
|
||||
assert response.headers['X-Testing'] == 'XYZ'
|
||||
|
Reference in New Issue
Block a user