Proposal: Predicate overloader

7 views
Skip to first unread message

Gustavo Narea

unread,
Jun 22, 2009, 1:09:24 PM6/22/09
to turbogea...@googlegroups.com
Hi everyone.

I've always agreed that it's absolutely handy to have predicate checkers act
as booleans, but at the same time, I've been opposed to all the alternatives
proposed to work around this because I consider them to have serious side-
effects, even the one I implemented by popular demand (the so-called
"predicate booleanizers").

However, a new potential solution has popped into my head and I'd be happy
with it, so let me propose it to see if it'd make you happy too.

We can use Python's overloading functionality like this:
"""
<p py_if='overloader.in_group("foo")'>This is a sensitive message!</p>
"""

Where "overloader" is a class instance with the __getattr__ method defined, so
we can return the class "in_group" (the class itself, not an instance). This
method will be implemented like this:
"""
def __getattr__(self, name):
original_class = self.get_predicate_checker(name)
class BooleanPredicate(original_class):
def __nonzero__(self,):
return self.is_met()
return BooleanPredicate
"""

I'd be happy with this because it wouldn't affect repoze.what globally, and
thus it wouldn't affect other software powered by repoze.what in the same
environment.

And another great thing would be that we could replace tg.predicates in the
template with this object and everything will be backwards compatible.

What do you think?

Cheers.
--
Gustavo Narea <xri://=Gustavo>.
| Tech blog: =Gustavo/(+blog)/tech ~ About me: =Gustavo/about |

Gustavo Narea

unread,
Jun 22, 2009, 1:18:25 PM6/22/09
to turbogea...@googlegroups.com
Gustavo said:
> """
> def __getattr__(self, name):
> original_class = self.get_predicate_checker(name)
> class BooleanPredicate(original_class):
> def __nonzero__(self,):
> return self.is_met()
> return BooleanPredicate
> """

Sorry, forgot to explain how get_predicate_checker() would look like:
"""
def get_predicate_checker(self, name):
for mod in self.predicate_modules:
if hasattr(mod, name):
return getattr(mod, name)
raise NameError(...)
"""

As a consequence:
1.- User-defined predicate checkers could be used in the same namespace.
2.- This could also be used in the controllers, not only in the templates.

Cheers!

Florent Aide

unread,
Jun 22, 2009, 1:50:50 PM6/22/09
to turbogea...@googlegroups.com
On Mon, Jun 22, 2009 at 7:18 PM, Gustavo Narea<m...@gustavonarea.net> wrote:
>
> Gustavo said:
>> """
>> def __getattr__(self, name):
>>     original_class = self.get_predicate_checker(name)
>>     class BooleanPredicate(original_class):
>>         def __nonzero__(self,):
>>             return self.is_met()
>>     return BooleanPredicate
>> """
>
> Sorry, forgot to explain how get_predicate_checker() would look like:
> """
> def get_predicate_checker(self, name):
>    for mod in self.predicate_modules:
>        if hasattr(mod, name):
>            return getattr(mod, name)
>    raise NameError(...)
> """
>
> As a consequence:
>  1.- User-defined predicate checkers could be used in the same namespace.
>  2.- This could also be used in the controllers, not only in the templates.

We would need some nice name for the "overloader" and I think it could
settle all those discussions flaring on the mailing list at the
moment.

Florent.

Gustavo Narea

unread,
Jun 22, 2009, 1:55:06 PM6/22/09
to turbogea...@googlegroups.com
Bonjour, Florent.

Florent said:
> We would need some nice name for the "overloader"

Sure, although I don't have anything better in mind right now. Suggestions are
welcome. :)


> I think it could
> settle all those discussions flaring on the mailing list at the
> moment.

I hope so.

Cheers,

Florent Aide

unread,
Jun 22, 2009, 2:00:26 PM6/22/09
to turbogea...@googlegroups.com
On Mon, Jun 22, 2009 at 7:55 PM, Gustavo Narea<m...@gustavonarea.net> wrote:
>
> Bonjour, Florent.
>
> Florent said:
>> We would need some nice name for the "overloader"
>
> Sure, although I don't have anything better in mind right now. Suggestions are
> welcome. :)

cred ?

Florent Aide

unread,
Jun 22, 2009, 2:01:05 PM6/22/09
to turbogea...@googlegroups.com

no this is too authentication geared... "gate" or "authgate" then?

Gustavo Narea

unread,
Jun 22, 2009, 2:14:42 PM6/22/09
to turbogea...@googlegroups.com
Florent said:
> no this is too authentication geared... "gate" or "authgate" then?

Whoops, sorry, now I that read this again, I actually meant "predicate
autoloader" (instead of "predicate overloader"). Doesn't "autoloader" sound
good to you either?

By the way, we'd need two names here: one for this functionality in
repoze.what (e.g., "predicate autoloader") and the other for the class
instance in TG (e.g., tg.predicates). Are you suggesting "gate" and "authgate"
for the former or for the later?

Thanks,

Florent Aide

unread,
Jun 22, 2009, 2:19:31 PM6/22/09
to turbogea...@googlegroups.com
On Mon, Jun 22, 2009 at 8:14 PM, Gustavo Narea<m...@gustavonarea.net> wrote:
>
> Florent said:
>> no this is too authentication geared... "gate" or "authgate" then?
>
> Whoops, sorry, now I that read this again, I actually meant "predicate
> autoloader" (instead of "predicate overloader"). Doesn't "autoloader" sound
> good to you either?
>
> By the way, we'd need two names here: one for this functionality in
> repoze.what (e.g., "predicate autoloader") and the other for the class
> instance in TG (e.g., tg.predicates). Are you suggesting "gate" and "authgate"
> for the former or for the later?

I don't really know. Those where names that bubbled in my head... at
least in TG the term tg.authgate would imply that you need to go
through it to do something useful.
In repoze.what I think a simple PredicateAutoLoader class would do it no?

Florent.

Gustavo Narea

unread,
Jun 22, 2009, 2:30:33 PM6/22/09
to turbogea...@googlegroups.com
Florent said:
> I don't really know. Those where names that bubbled in my head... at
> least in TG the term tg.authgate would imply that you need to go
> through it to do something useful.

Hmm, ok, I got the idea. Yes, it sounds good. Unless someone comes up with a
better name, I think we can go for it.


> In repoze.what I think a simple PredicateAutoLoader class would do it no?

Yes, that's what I had in mind.

Florent Aide

unread,
Jun 22, 2009, 3:28:36 PM6/22/09
to turbogea...@googlegroups.com
On Mon, Jun 22, 2009 at 8:30 PM, Gustavo Narea<m...@gustavonarea.net> wrote:
>
> Florent said:
>> I don't really know. Those where names that bubbled in my head... at
>> least in TG the term tg.authgate would imply that you need to go
>> through it to do something useful.
>
> Hmm, ok, I got the idea. Yes, it sounds good. Unless someone comes up with a
> better name, I think we can go for it.

Let's wait a few hours to see if everyone out there is in synch of if
we receive a better naming idea from some lurking reader that would
have an interesting idea!

>
>> In repoze.what I think a simple PredicateAutoLoader class would do it no?
>
> Yes, that's what I had in mind.

I now that already because I just used MindReader v2.1 to scan you
brains microwave emissions :)

Cheers,
Florent.

Christoph Zwerschke

unread,
Jun 23, 2009, 3:21:14 AM6/23/09
to turbogea...@googlegroups.com
Gustavo Narea schrieb:

> Where "overloader" is a class instance with the __getattr__ method defined, so
> we can return the class "in_group" (the class itself, not an instance). This
> method will be implemented like this:
> """
> def __getattr__(self, name):
> original_class = self.get_predicate_checker(name)
> class BooleanPredicate(original_class):
> def __nonzero__(self,):
> return self.is_met()
> return BooleanPredicate
> """

I thught the problem was that is_met() needs the environment? So I guess
you wanted to say that "overloader" stores the environment in an
attribute when instantiated and then calls self.is_met(self._environ).

By the way, isn't this pretty much the same idea as option 4) that had
been proposed already here? http://trac.turbogears.org/ticket/2205

One thing I don't like in this solution is all the overhead that makes
things hard to understand and is bad for performance (your proposed
get_predicate_checker even has a for loop in it).

-- Christoph

Gustavo Narea

unread,
Jun 23, 2009, 9:06:17 AM6/23/09
to turbogea...@googlegroups.com
Hi, Christoph.

Christoph said:
> Gustavo Narea schrieb:
> > Where "overloader" is a class instance with the __getattr__ method
> > defined, so we can return the class "in_group" (the class itself, not an
> > instance). This method will be implemented like this:
> > """
> > def __getattr__(self, name):
> > original_class = self.get_predicate_checker(name)
> > class BooleanPredicate(original_class):
> > def __nonzero__(self,):
> > return self.is_met()
> > return BooleanPredicate
> > """
>
> I thught the problem was that is_met() needs the environment? So I guess
> you wanted to say that "overloader" stores the environment in an
> attribute when instantiated and then calls self.is_met(self._environ).

Oh, yes, I'm sorry. I meant to write:
"""
def __getattr__(self, name):
original_class = self.get_predicate_checker(name)
class BooleanPredicate(original_class):
def __nonzero__(self,):

return self.is_met(request.environ) # <--- HERE
return BooleanPredicate
"""


> By the way, isn't this pretty much the same idea as option 4) that had
> been proposed already here? http://trac.turbogears.org/ticket/2205

They're similar because both use __getattr__, but this will return a valid
predicate, not a callable (which in turn returns True/False). So you'd be able
to use the result like a normal predicate (i.e., as explained in the main
docs, not in a way too specific to TG).


> One thing I don't like in this solution is all the overhead that makes
> things hard to understand and is bad for performance (your proposed
> get_predicate_checker even has a for loop in it).

I fully agree, but I believe it's the best compromise among the solutions
proposed.

Cheers,

Reply all
Reply to author
Forward
0 new messages