From ed710e8ad78a29747d39d59d8ff6b138a7a59ddb Mon Sep 17 00:00:00 2001 From: Wyatt L Baldwin Date: Sun, 5 Jun 2011 14:05:30 -0700 Subject: [PATCH] Allow `view_permission` keyword arg to be passed to `add_handler()`. If `view_permission` (or its alias, `permission`) is passed to `add_handler()`, it will be used as the default permission for all views registered via the handler. Handler views can override this default permission via the `action` decorator. Added two tests to exercise this new functionality on both types of `add_handler()` calls--i.e., with '{action}' in route path and with `action` as a keyword arg. References: https://github.com/Pylons/pyramid_handlers/issues/1 --- pyramid_handlers/__init__.py | 28 +++++++++++++++------- pyramid_handlers/tests.py | 45 ++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/pyramid_handlers/__init__.py b/pyramid_handlers/__init__.py index d2b55f4..75f61a6 100644 --- a/pyramid_handlers/__init__.py +++ b/pyramid_handlers/__init__.py @@ -44,6 +44,10 @@ def add_handler(self, route_name, pattern, handler, action=None, **kw): This method returns the result of add_route.""" handler = self.maybe_dotted(handler) + default_view_args = { + 'permission': kw.pop('view_permission', kw.pop('permission', None)) + } + if pattern is not None: route = self.add_route(route_name, pattern, **kw) else: @@ -79,19 +83,22 @@ def add_handler(self, route_name, pattern, handler, action=None, **kw): 'path %r' % (action, pattern)) if path_has_action: - scan_handler(self, handler, route_name, action_decorator) + scan_handler(self, handler, route_name, action_decorator, + **default_view_args) else: locate_view_by_name( config=self, handler=handler, route_name=route_name, action_decorator=action_decorator, - name=action + name=action, + **default_view_args ) return route -def scan_handler(config, handler, route_name, action_decorator): +def scan_handler(config, handler, route_name, action_decorator, + **default_view_args): """Scan a handler for automatically exposed views to register""" autoexpose = getattr(handler, '__autoexpose__', r'[A-Za-z]+') if autoexpose: @@ -107,7 +114,8 @@ def scan_handler(config, handler, route_name, action_decorator): for expose_config in configs: # we don't want to mutate any dict in __exposed__, # so we copy each - view_args = expose_config.copy() + view_args = default_view_args.copy() + view_args.update(expose_config.copy()) action = view_args.pop('name', method_name) preds = list(view_args.pop('custom_predicates', [])) preds.append(ActionPredicate(action)) @@ -117,7 +125,8 @@ def scan_handler(config, handler, route_name, action_decorator): decorator=action_decorator, **view_args) -def locate_view_by_name(config, handler, route_name, action_decorator, name): +def locate_view_by_name(config, handler, route_name, action_decorator, name, + **default_view_args): """Locate and add all the views in a handler with the matching name, or the method itself if it exists.""" method_name = name @@ -137,7 +146,8 @@ def locate_view_by_name(config, handler, route_name, action_decorator, name): continue # we don't want to mutate any dict in __exposed__, # so we copy each - view_args = expose_config.copy() + view_args = default_view_args.copy() + view_args.update(expose_config.copy()) del view_args['name'] config.add_view(view=handler, attr=attr, route_name=route_name, @@ -152,11 +162,13 @@ def locate_view_by_name(config, handler, route_name, action_decorator, name): if 'name' in expose_config and expose_config['name'] != name: continue view_regged = True + view_args = default_view_args.copy() + view_args.update(expose_config.copy()) config.add_view(view=handler, attr=name, route_name=route_name, - decorator=action_decorator, **expose_config) + decorator=action_decorator, **view_args) if not view_regged: config.add_view(view=handler, attr=name, route_name=route_name, - decorator=action_decorator) + decorator=action_decorator, **default_view_args) class ActionPredicate(object): diff --git a/pyramid_handlers/tests.py b/pyramid_handlers/tests.py index 2b64845..17b17fe 100644 --- a/pyramid_handlers/tests.py +++ b/pyramid_handlers/tests.py @@ -313,6 +313,51 @@ def two(self): pass view = views[0] self.assertEqual(view['view'], DummyHandler) + def test_add_handler_with_view_permission_and_action_in_path(self): + from pyramid_handlers import action + config = self._makeOne() + views = [] + def dummy_add_view(**kw): + views.append(kw) # pragma: no cover + config.add_view = dummy_add_view + class MyView(DummyHandler): + @action(permission='different_perm') + def action_with_non_default_permission(self): # pragma: no cover + return 'My permission is different!' + config.add_handler('name', '/{action}', MyView, view_permission='perm') + self._assertRoute(config, 'name', '/{action}', 0) + self.assertEqual(len(views), 3) + for view in views: + self.assert_('permission' in view) + if view['attr'] == 'action_with_non_default_permission': + self.assertEqual(view['permission'], 'different_perm') + else: + self.assertEqual(view['permission'], 'perm') + + def test_add_handler_with_view_permission_and_action_as_kwarg(self): + from pyramid_handlers import action + config = self._makeOne() + views = [] + def dummy_add_view(**kw): + views.append(kw) # pragma: no cover + config.add_view = dummy_add_view + class MyView(DummyHandler): + def index(self): # pragma: no cover + return 'Index' + @action(name='index', permission='different_perm') + def index2(self): # pragma: no cover + return 'Index with different permission.' + config.add_handler('name', '/', MyView, action='index', + view_permission='perm') + self._assertRoute(config, 'name', '/', 0) + self.assertEqual(len(views), 2) + for view in views: + self.assert_('permission' in view) + if view['attr'] == 'index': + self.assertEqual(view['permission'], 'perm') + elif view['attr'] == 'index2': + self.assertEqual(view['permission'], 'different_perm') + def _assertRoute(self, config, name, path, num_predicates=0): from pyramid.interfaces import IRoutesMapper mapper = config.registry.getUtility(IRoutesMapper)