Skip to content

Commit

Permalink
Allow view_permission keyword arg to be passed to add_handler().
Browse files Browse the repository at this point in the history
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: #1
  • Loading branch information
wylee committed Jun 5, 2011
1 parent 7ae145e commit ed710e8
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 8 deletions.
28 changes: 20 additions & 8 deletions pyramid_handlers/__init__.py
Expand Up @@ -44,6 +44,10 @@ def add_handler(self, route_name, pattern, handler, action=None, **kw):
This method returns the result of add_route.""" This method returns the result of add_route."""
handler = self.maybe_dotted(handler) handler = self.maybe_dotted(handler)


default_view_args = {
'permission': kw.pop('view_permission', kw.pop('permission', None))
}

if pattern is not None: if pattern is not None:
route = self.add_route(route_name, pattern, **kw) route = self.add_route(route_name, pattern, **kw)
else: else:
Expand Down Expand Up @@ -79,19 +83,22 @@ def add_handler(self, route_name, pattern, handler, action=None, **kw):
'path %r' % (action, pattern)) 'path %r' % (action, pattern))


if path_has_action: if path_has_action:
scan_handler(self, handler, route_name, action_decorator) scan_handler(self, handler, route_name, action_decorator,
**default_view_args)
else: else:
locate_view_by_name( locate_view_by_name(
config=self, config=self,
handler=handler, handler=handler,
route_name=route_name, route_name=route_name,
action_decorator=action_decorator, action_decorator=action_decorator,
name=action name=action,
**default_view_args
) )
return route 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""" """Scan a handler for automatically exposed views to register"""
autoexpose = getattr(handler, '__autoexpose__', r'[A-Za-z]+') autoexpose = getattr(handler, '__autoexpose__', r'[A-Za-z]+')
if autoexpose: if autoexpose:
Expand All @@ -107,7 +114,8 @@ def scan_handler(config, handler, route_name, action_decorator):
for expose_config in configs: for expose_config in configs:
# we don't want to mutate any dict in __exposed__, # we don't want to mutate any dict in __exposed__,
# so we copy each # 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) action = view_args.pop('name', method_name)
preds = list(view_args.pop('custom_predicates', [])) preds = list(view_args.pop('custom_predicates', []))
preds.append(ActionPredicate(action)) preds.append(ActionPredicate(action))
Expand All @@ -117,7 +125,8 @@ def scan_handler(config, handler, route_name, action_decorator):
decorator=action_decorator, **view_args) 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 """Locate and add all the views in a handler with the matching name, or
the method itself if it exists.""" the method itself if it exists."""
method_name = name method_name = name
Expand All @@ -137,7 +146,8 @@ def locate_view_by_name(config, handler, route_name, action_decorator, name):
continue continue
# we don't want to mutate any dict in __exposed__, # we don't want to mutate any dict in __exposed__,
# so we copy each # 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'] del view_args['name']
config.add_view(view=handler, attr=attr, config.add_view(view=handler, attr=attr,
route_name=route_name, route_name=route_name,
Expand All @@ -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: if 'name' in expose_config and expose_config['name'] != name:
continue continue
view_regged = True 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, 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: if not view_regged:
config.add_view(view=handler, attr=name, route_name=route_name, config.add_view(view=handler, attr=name, route_name=route_name,
decorator=action_decorator) decorator=action_decorator, **default_view_args)




class ActionPredicate(object): class ActionPredicate(object):
Expand Down
45 changes: 45 additions & 0 deletions pyramid_handlers/tests.py
Expand Up @@ -313,6 +313,51 @@ def two(self): pass
view = views[0] view = views[0]
self.assertEqual(view['view'], DummyHandler) 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): def _assertRoute(self, config, name, path, num_predicates=0):
from pyramid.interfaces import IRoutesMapper from pyramid.interfaces import IRoutesMapper
mapper = config.registry.getUtility(IRoutesMapper) mapper = config.registry.getUtility(IRoutesMapper)
Expand Down

0 comments on commit ed710e8

Please sign in to comment.