#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
-~----------~----~----~----~------~----~------~--~---

Reply via email to