The problem isn't with the decorator per se, but with the condition being 
evaluated. If you have:

@auth.requires_permission('read')
def secrets():
    etc.

that is equivalent to:

@auth.requires(condition=auth.has_permission('read'))
def secrets():
    etc.

In this case, the decorator takes an argument (the condition to be 
evaluated), and the argument itself is a function call that does a db 
query. So, setting up the decorated function ends up running the db query 
in auth.has_permission. In trunk, there is a new feature that allows a way 
around this -- the condition argument to auth.requires can be a callable, 
so you can do:

@auth.requires(lambda: auth.has_permission('read'))
def secrets():

In that case, when the decorator is created, it simply passes the lambda as 
the condition, rather than calling auth.has_permission. The lambda doesn't 
actually get called until the secrets() function is called.

Perhaps we should change auth.requires_membership and 
auth.requires_permission to use lambda in this way.

Anthony


On Friday, November 18, 2011 4:07:28 PM UTC-5, howesc wrote:
>
> the distinction being made here is that decorators appear to be executed 
> for methods that are not called during this request.  whether or not a 
> query is run is not really the point, the point is that it seems that code 
> is being executed that the user never intended.
>
> that said, i don't know enough about decorators to know how they work 
> under the covers.  i would tend to agree with Ids that this behavior is not 
> what i expect, and with the auth decorators that run queries can 
> significantly slow down an application.
>
> can anyone comment on whether Ids and my expectation of how decorators 
> work are correct? 
>
> thanks,
>
> cfh
>

Reply via email to