I'm contemplating making a change to the current configuration plugins. I'd
like to get a couple of other eyes to glance over it - I'm unsure whether
this is sound, or just a reaction to an immediate problem that I
encountered working on logging.
The way that configuration plugins work right now in the noun/verb
framework is super simple. A configuration plugin is an object with an
"execute" method. During command dispatch, after the command parser
processes the arguments and a command-appropriate context is created, the
framework iterates over the plugins, and calls the execute method of each
one, with the context object and parsed command line parameters.
There are two problems that I've encountered working with these in practice:
1. Some plugins really want to be run before the command-line arguments
are processed, and some want to be run after. For example, for a
distributed logging system, we'd like to be able to have the logging system
optionally enabled before the command is dispatched, so that the dispatch
process can use logging. But others, for managing things like proxies, need
to be called after arguments are processed, because they rely on arguments.
2. Some plugins need cleanups. For example, in logging again, for best
performance, we'd like to use multiprocessing to do asynchronous
communication with a logserver. But to do that, we need to do a join after
the command completes execution. In the current framework, there's no way
to do that.
What I'm thinking about is going more aspect-oriented in the plugins. There
will be three points during the execution of a command where plugins can
get injected:
1. before any argument processing is performed. The only thing that the
plugin would be allowed to look at would be the raw, unprocessed
command-line parameters. It would return a (potentially) modified copy of
the parameters, which would be passed to other plugins, and finally to the
actual noun/verb for the command being executed.
2. after arguments have been processed, but before the noun/verb is
executed. This is exactly what the current plugin "execute" method does.
3. after the command has completed executing, but before the client
exits.
The code signatures would be:
def beforeDispatch(self, args):
"""code to execute before dispatching to a noun/verb command.
args: a list of the command-line parameters used
to invoke aurora.
Returns: a possibly modified list of command-line arguments. If
this throws an exception, then the execution
of the command will be aborted.
"""
def beforeCommand(self, context):
"""Code to execute after command-line arguments have been
processed, but before executing the command. If the
code throws a CommandException, then the execution of
the command will be aborted.
context: the context object that will be used to invoke
the command.
def cleanupAfterCommand(self, context, returnval):
"""Code to run after the execution of a noun/verb command has
completed, before the command-line application exits.
context: the context object that was used to execute the command.
returnval: the exit code returned by executing the command.
"""
The order of execution of plugins would remain undefined.