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 >