#2205: Provide a simple way to evaluate repoze.what predicates
------------------------------------------------+---------------------------
Reporter: chrisz | Owner: Gustavo
Type: enhancement | Status: assigned
Priority: high | Milestone: 2.0b6
Component: TurboGears | Version: 2.0b1
Severity: major | Resolution:
Keywords: repoze.what predicates permissions |
------------------------------------------------+---------------------------
Old description:
> There is no simple way to evaluate repoze.what predicates such as
> `has_permission()` inside the controller or inside a template. Such a
> feature would be useful for changing the behavior or displaying
> additional information in the template depending on the permissions, a
> very common requirement.
>
> We already have related tickets #2712 and #2173, but #2712 does only
> cover one special case (and is not yet implemented) and #2173 is not
> simple enough.
>
> There is a [http://groups.google.cl/group/turbogears-
> trunk/browse_thread/thread/52572857f68c1bd7 thread on turbogears-trunk]
> summing up the discussion and proposing different solutions for this
> problem. Unfortunately, there was not enough feedback yet to make a good
> decision which of the ideas should get implemented. Maybe there is also a
> better solution or a modifications of these ideas will do.
>
> I think this is an important feature that should get into TG 2.0, so I've
> given this ticket a high priority. I's actually easy to implement, but we
> need to make an API decision here. Any comments on this ticket or on the
> thread mentioned above are highly appreciated.
>
> The two ideas from that thread that need further discussion were numbers
> 3) and 4) which I will repeat here:
>
> '''3) Using the standard boolean evaluation mechanism'''
>
> Michael came up with the idea to overwrite the `__nonzero__` method of
> predicates (side note, `__nonzero__` is for boolean evaluation and thus
> was renamed to `__bool__` in Python 3.0).
>
> This method could for example raise an error when used in the form
> `py:if="has_permission('manage')"` without the evaluate call (as proposed
> in #2173). But we could also go a step further and let `__nonzero__`
> automatically evaluate the predicate. The predicates would have a dual
> use then, both for require decorators (not immediately evaluated) and for
> `py:if` statements
> (immediately evaluated).
>
> The following simple monkey-patch would allow this double usage of all
> repoze.what predicates in TG2:
>
> {{{
> from tg import request
> from repoze.what.predicates import Predicate
> Predicate.__nonzero__ = lambda self: self.is_met(request.environ)
> }}}
>
> Instead, we could also create a TG specific subclass of repoze.what
> predicates that allows this double usage, and also create copies of the
> existing predicates on the fly.
>
> Both the monkey-patching (or subclassing and copying) and the double
> usage may appear a bit hackish and magical though. But I think it's
> pretty elegant and straightforward and the following idea works a bit
> magical, too.
>
> '''4) Providing a special "access" object'''
>
> A different solution is to add an `access` object to TG2 and make it a
> standard template variable that auto-evaluates predicates passed as
> attributes. Here is a possible implementation:
>
> {{{
> from tg import request
> from repoze.what import predicates
>
> class Access(object):
> """Environ-aware predicates evaluating immediately."""
>
> def __getattr__(self, name):
> predicate = getattr(predicates, name)
> if callable(predicate):
> def predicate_is_met(*args, **kwargs):
> return predicate(*args, *kwargs).is_met(
> request.environ)
> return predicate_is_met
> else:
> return predicate
>
> access = Access() # make this a standard tg template variable
> }}}
>
> This would allow easy evaluation of all existing predicates in templates
> in the form `tg.acess.has_permission('edit')`. We could also provide a
> mechanism for including additional custom predicates in the access
> object.
New description:
There is no simple way to evaluate repoze.what predicates such as
`has_permission()` inside the controller or inside a template. Such a
feature would be useful for changing the behavior or displaying additional
information in the template depending on the permissions, a very common
requirement.
We already have related tickets #2172 and #2173, but #2172 does only cover
one special case (and is not yet implemented) and #2173 is not simple
enough.
There is a [http://groups.google.cl/group/turbogears-
trunk/browse_thread/thread/52572857f68c1bd7 thread on turbogears-trunk]
summing up the discussion and proposing different solutions for this
problem. Unfortunately, there was not enough feedback yet to make a good
decision which of the ideas should get implemented. Maybe there is also a
better solution or a modifications of these ideas will do.
I think this is an important feature that should get into TG 2.0, so I've
given this ticket a high priority. I's actually easy to implement, but we
need to make an API decision here. Any comments on this ticket or on the
thread mentioned above are highly appreciated.
The two ideas from that thread that need further discussion were numbers
3) and 4) which I will repeat here:
'''3) Using the standard boolean evaluation mechanism'''
Michael came up with the idea to overwrite the `__nonzero__` method of
predicates (side note, `__nonzero__` is for boolean evaluation and thus
was renamed to `__bool__` in Python 3.0).
This method could for example raise an error when used in the form
`py:if="has_permission('manage')"` without the evaluate call (as proposed
in #2173). But we could also go a step further and let `__nonzero__`
automatically evaluate the predicate. The predicates would have a dual use
then, both for require decorators (not immediately evaluated) and for
`py:if` statements
(immediately evaluated).
The following simple monkey-patch would allow this double usage of all
repoze.what predicates in TG2:
{{{
from tg import request
from repoze.what.predicates import Predicate
Predicate.__nonzero__ = lambda self: self.is_met(request.environ)
}}}
Instead, we could also create a TG specific subclass of repoze.what
predicates that allows this double usage, and also create copies of the
existing predicates on the fly.
Both the monkey-patching (or subclassing and copying) and the double usage
may appear a bit hackish and magical though. But I think it's pretty
elegant and straightforward and the following idea works a bit magical,
too.
'''4) Providing a special "access" object'''
A different solution is to add an `access` object to TG2 and make it a
standard template variable that auto-evaluates predicates passed as
attributes. Here is a possible implementation:
{{{
from tg import request
from repoze.what import predicates
class Access(object):
"""Environ-aware predicates evaluating immediately."""
def __getattr__(self, name):
predicate = getattr(predicates, name)
if callable(predicate):
def predicate_is_met(*args, **kwargs):
return predicate(*args, *kwargs).is_met(
request.environ)
return predicate_is_met
else:
return predicate
access = Access() # make this a standard tg template variable
}}}
This would allow easy evaluation of all existing predicates in templates
in the form `tg.acess.has_permission('edit')`. We could also provide a
mechanism for including additional custom predicates in the access object.
--
Ticket URL: <http://trac.turbogears.org/ticket/2205#comment:7>
TurboGears <http://www.turbogears.org/>
TurboGears front-to-back web development
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "TurboGears Tickets" group.
This group is read-only. No posting by normal members allowed.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/turbogears-tickets?hl=en?hl=en
-~----------~----~----~----~------~----~------~--~---