Opened 12 years ago
Last modified 11 years ago
#638 accepted enhancement
meta-decorator hooks / emacs-lisp style advice — at Version 2
Reported by: | Christopher Allan Webber | Owned by: | |
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | programming | Keywords: | pluginapi |
Cc: | Parent Tickets: |
Description (last modified by )
This is an incredibly evil and flexible idea that, like decorators itself, is probably elegant, hard to understand, powerful, and yes, a little bit evil.
So this is an idea inspired from emacs lisp, which allows you to pass in functions to wrap a function that already exists (this is called "advising functions"). Actually, hooks in emacs look a heck of a lot like decorators, so actually...
Say you have this function:
@meta_decorator_hook('some_function_hook') def some_function(foo): bla bla
Now, you want to wrap this function! But how do you wrap it? It's already defined, you can't just wrap arbitrary things around it! ... or can you?
In this meta_decorator_hook, the meta_decorator_hook returns a lazy-loaded method set to actually construct a chain of wrapped methods. So if we did something like:
pluginapi.wrap_function('some_function_hook', our_function)
.. it would return, basically a WrappedFunction() that, the first time it is executed, walks through all the decorator like methods that have been pushed onto that hook and wraps them in each other. That meta-decorated method is cached, and eventually, executed.
Sounds evil, right? :)
This could be super powerful though. You could do crazy things like double-check the results of a view before returning it, or totally override the view and decide not to call it at all for your plugin, call it both before and after, or set up special-case exception handling for hooks that are called within the function itself.
I'm sure I didn't make that sound any less evil, but I think it'd be really great.
Change History (2)
comment:1 by , 12 years ago
Type: | defect → enhancement |
---|
comment:2 by , 12 years ago
Description: | modified (diff) |
---|
These are some extra notes explaining additional rationale for this that I wrote in my email about plugins to the mailing list:
How do we "halt" a function if a plugin needs to tell us to?
Exceptions probably... but how to make this clean?
Okay, let me explain a bit more. Say someone implements a special hook that sets up something special (I'm having a hard time thinking of what) but notices that something is terribly wrong. It needs to immediately halt the execution of the function. A reasonable thing to do is raise an exception. But we don't just want it to show up as a programming error and hit the logs. How to handle it? One of two ways:
We could already be expecting certain types of exceptions to possibly be raised like the following:
Okay, but what if the view designers weren't able to anticipate the kind of issue you have... how to handle this?
The answer is the meta-decorators solution above I think. In your own meta-decorator around the view that calls the hook above, you could set yourself up to catch the exception.
Tricky, but should work! :)