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 |
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!
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.
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,
cred ?
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,
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.
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.
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.
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
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,