Writing Extensions and Hooks
============================

The Basic Model
---------------

Almost every command uses the PMH.Runner.Runner indirection mechanism.
Runner is a singleton class (which means you can call the constructor
as many times as you like, and you'll always get the same instance).
It has a simple action facility -- a code can register a function
to perform a given action, such as sending e-mail. Additionally, every
action has pre-hooks and post-hooks. The post-hooks receive as an 
additional argument the return value of the action function.

Order!
------

Registering an action removes any previously registered actions. Pre-hooks
are called in the order of registration, and post-hooks are called in
reverse order of registration. Currently, there is no way to remove
a registered pre- or post- hook.

Note that the ``show'' and ``edit'' action, because they are so UI-specific
have no out-of-the box defaults, so you'll have to register something
there, or PMS will not work correctly. To register something that fits
with common UNIX ui, import PMH.Console.

Arguments
---------

Actions can have any number of yes/no arguments. For arguments with more
substance, please use the PMS.Configuration mechanism. The way to register
which yes/no arguments are acceptable, so that frontends can be intelegient
about it, please use the following convention:

class action:

	args = <list of strings>

	def __call__(self, runner, [required arguments], [keyword arguments):
		....

The keyword arguments should all default to 0, and should be the same as those
in the args list. 

Configuration
-------------

For configuration related to an action, use

PMS.Configuration.Configuration().config[action_name]

which is a dictionary mapping directive->value. No common sets of
directives have been agreed upon so far.

Servers
-------

PMS uses a set of named servers, which are small python files which define
a function called server. This function receives a single argument (the
name of the server, which is the same as the name of the file without
the .py extension), and should return something that corresponds to the
PMS.Server.Server interface. Usually it does so by instantiating some
PMS.Server.Server base class, such as MHServer.
