summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-01-22 08:08:02 +0000
committerChris McDonough <chrism@agendaless.com>2009-01-22 08:08:02 +0000
commitf662908175abb6ac9c638dbdeeea2635956ac80c (patch)
tree77911b9c9a3aa14dc4ed6cb3b496a35499c77c54
parent2bb9b76c01019f3c82776429c07d34bd1c439f2b (diff)
downloadpyramid-f662908175abb6ac9c638dbdeeea2635956ac80c.tar.gz
pyramid-f662908175abb6ac9c638dbdeeea2635956ac80c.tar.bz2
pyramid-f662908175abb6ac9c638dbdeeea2635956ac80c.zip
- The Allowed and Denied classes in ``repoze.bfg.security`` now are
lazier about constructing the representation of a reason message for speed; ``repoze.bfg.view_execution_permitted`` takes advantage of this. - The ``is_response`` check was sped up by about half at the expense of making its code slightly uglier.
-rw-r--r--CHANGES.txt8
-rw-r--r--repoze/bfg/security.py38
-rw-r--r--repoze/bfg/view.py52
3 files changed, 61 insertions, 37 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index d2c31903f..4739b9601 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -23,6 +23,14 @@ Implementation Changes
If no subscribers are registered via ``registerHandler`` or
``registerSubscriptionAdapter``, ``notify`` is a noop for speed.
+- The Allowed and Denied classes in ``repoze.bfg.security`` now are
+ lazier about constructing the representation of a reason message for
+ speed; ``repoze.bfg.view_execution_permitted`` takes advantage of
+ this.
+
+- The ``is_response`` check was sped up by about half at the expense
+ of making its code slightly uglier.
+
0.6.3 (2009-01-19)
==================
diff --git a/repoze/bfg/security.py b/repoze/bfg/security.py
index 1f7c80028..ccc223919 100644
--- a/repoze/bfg/security.py
+++ b/repoze/bfg/security.py
@@ -231,8 +231,13 @@ class Denied(PermitsResult):
or other ``repoze.bfg`` code denies an action unlrelated to an ACL
check. It evaluates equal to all boolean false types. It has an
attribute named ``msg`` describing the circumstances for the deny."""
- def __init__(self, msg):
- self.msg = msg
+ def __init__(self, s, *args):
+ self.s = s
+ self.args = args
+
+ @property
+ def msg(self):
+ return self.s % self.args
def __nonzero__(self):
return False
@@ -246,8 +251,13 @@ class Allowed(PermitsResult):
check. It evaluates equal to all boolean true types. It has an
attribute named ``msg`` describing the circumstances for the
allow."""
- def __init__(self, msg):
- self.msg = msg
+ def __init__(self, s, *args):
+ self.s = s
+ self.args = args
+
+ @property
+ def msg(self):
+ return self.s % self.args
def __nonzero__(self):
return True
@@ -262,15 +272,17 @@ class ACLPermitsResult:
self.acl = acl
self.principals = principals
self.context = context
- msg = ('%s permission %r via ACE %r in ACL %r on context %r for '
- 'principals %r')
- msg = msg % (self.__class__.__name__,
- self.permission,
- self.ace,
- self.acl,
- self.context,
- self.principals)
- self.msg = msg
+
+ @property
+ def msg(self):
+ s = ('%s permission %r via ACE %r in ACL %r on context %r for '
+ 'principals %r')
+ return s % (self.__class__.__name__,
+ self.permission,
+ self.ace,
+ self.acl,
+ self.context,
+ self.principals)
class ACLDenied(ACLPermitsResult, Denied):
""" An instance of ``ACLDenied`` represents that a security check
diff --git a/repoze/bfg/view.py b/repoze/bfg/view.py
index 0aacc0061..8ed23748c 100644
--- a/repoze/bfg/view.py
+++ b/repoze/bfg/view.py
@@ -14,7 +14,7 @@ from zope.interface import Interface
from repoze.bfg.interfaces import IRequest
-_marker = ()
+_marker = object()
def view_execution_permitted(context, request, name=''):
""" If the view specified by ``context`` and ``name`` is protected
@@ -23,17 +23,16 @@ def view_execution_permitted(context, request, name=''):
the ``request``. If no security policy is in effect, or if the
view is not protected by a permission, return a True value. """
security_policy = queryUtility(ISecurityPolicy)
- if security_policy:
+ if security_policy is not None:
permission = queryMultiAdapter((context, request), IViewPermission,
name=name)
if permission is None:
return Allowed(
'Allowed: view name %r in context %r (no permission '
- 'registered for name %r).' % (name, context, name)
- )
+ 'registered for name %r).', name, context, name)
return permission(security_policy)
return Allowed('Allowed: view name %r in context %r (no security policy '
- 'in use).' % (name, context))
+ 'in use).', name, context)
def render_view_to_response(context, request, name='', secure=True):
""" Render the view named ``name`` against the specified
@@ -117,14 +116,19 @@ def is_response(ob):
duck-typing check, as response objects are not obligated to
actually implement a Zope interface."""
# response objects aren't obligated to implement a Zope interface,
- # so we do it the hard way
- if ( hasattr(ob, 'app_iter') and hasattr(ob, 'headerlist') and
- hasattr(ob, 'status') ):
- if ( hasattr(ob.app_iter, '__iter__') and
- hasattr(ob.headerlist, '__iter__') and
- isinstance(ob.status, basestring) ) :
- return True
- return False
+ # so we do it the hard way; this is written awkwardly for
+ # performance reasons
+ try:
+ ob.app_iter, ob.headerlist, ob.status
+ except AttributeError:
+ return False
+ try:
+ ob.app_iter.__iter__, ob.headerlist.__iter__
+ except AttributeError:
+ return False
+ if not isinstance(ob.status, basestring):
+ return False
+ return True
class static(object):
""" An instance of this class is a callable which can act as a BFG
@@ -228,19 +232,19 @@ class bfg_view(object):
# time the application starts in case any of the decorators
# has been changed. Disallowing these functions from being
# pickled enforces that.
- def decorator(context, request):
+ def _bfg_view(context, request):
return wrapped(context, request)
- decorator.__is_bfg_view__ = True
- decorator.__permission__ = self.permission
- decorator.__for__ = self.for_
- decorator.__view_name__ = self.name
- decorator.__request_type__ = self.request_type
+ _bfg_view.__is_bfg_view__ = True
+ _bfg_view.__permission__ = self.permission
+ _bfg_view.__for__ = self.for_
+ _bfg_view.__view_name__ = self.name
+ _bfg_view.__request_type__ = self.request_type
# we assign to __grok_module__ here rather than __module__ to
# make it unpickleable but allow for the grokker to be able to
# find it
- decorator.__grok_module__ = wrapped.__module__
- decorator.__name__ = wrapped.__name__
- decorator.__doc__ = wrapped.__doc__
- decorator.__dict__.update(wrapped.__dict__)
- return decorator
+ _bfg_view.__grok_module__ = wrapped.__module__
+ _bfg_view.__name__ = wrapped.__name__
+ _bfg_view.__doc__ = wrapped.__doc__
+ _bfg_view.__dict__.update(wrapped.__dict__)
+ return _bfg_view