summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pecan/hooks.py11
-rw-r--r--pecan/tests/test_hooks.py40
2 files changed, 50 insertions, 1 deletions
diff --git a/pecan/hooks.py b/pecan/hooks.py
index 57392d7..f1f7073 100644
--- a/pecan/hooks.py
+++ b/pecan/hooks.py
@@ -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)
diff --git a/pecan/tests/test_hooks.py b/pecan/tests/test_hooks.py
index 0bfd216..d3fe05b 100644
--- a/pecan/tests/test_hooks.py
+++ b/pecan/tests/test_hooks.py
@@ -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'