
At 08:26 AM 6/25/04 -0400, David Abrahams wrote:
"Phillip J. Eby" <pje@telecommunity.com> writes:
You'd need to do something like keep a copy of the locals and on each "new line" event from the trace hook, you'd need to both call the old trace hook (so that debugging could still take place) and check to see if the locals had a new function object. As soon as the function object appeared, you could do your dirty work (after first restoring the *old* value bound to that name, so the decorators would have access to the previous binding of the name).
I'm perfectly happy for this decorate function to work on the very next name binding; I don't think it's reasonable to expect to be able to do anything else between it and the function definition.
Keep in mind that this means code like this: decorate(foo) decorate(bar(baz=[x*2 for x in y])) def spam(): pass Will likely fail horribly, applying the 'foo' decorator to the first element of 'y' before trying to multiply by 2, or worse, possibly applying them to the "anonymous" list object that's created to hold the results of the list comprehension. Or, it might sometimes *seem* to work due to hashing order and the vagaries of when 'line' events fire, and then fail in a new release of Python. This is why I consider it somewhat of a wart in the current implementation, as I note below...
Anyway, it works with CPython 2.2. Caveat: do *not* use listcomps or any other assignment statements between your 'decorate()' invocation and the function definition, or the decorators will be applied to the bound-to variable!
Personally, I think the 'decorate()' function is probably actually not that useful, compared to making specialized decoration functions like, say:
classmethod_follows() def foo(klass, x, y, z): # ...
Ick!
Is it the name you dislike? Or the idea of simply invoking decorating functions directly?
Only with better names. :) Also, using this approach means you can do something like:
[classmethod_follows()]
Ick in brackets ;-> !