diff options
| author | Chris McDonough <chrism@agendaless.com> | 2009-01-22 08:08:02 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2009-01-22 08:08:02 +0000 |
| commit | f662908175abb6ac9c638dbdeeea2635956ac80c (patch) | |
| tree | 77911b9c9a3aa14dc4ed6cb3b496a35499c77c54 | |
| parent | 2bb9b76c01019f3c82776429c07d34bd1c439f2b (diff) | |
| download | pyramid-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.txt | 8 | ||||
| -rw-r--r-- | repoze/bfg/security.py | 38 | ||||
| -rw-r--r-- | repoze/bfg/view.py | 52 |
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 |
