watch this The wheels are turning, slowly turning. home
Adding Axiomatic plugins 2005-11-15

axiomatic has featured prominently in many of my recent blog posts, but what is it?

As one might guess, in simplest terms, axiomatic is a tool for manipulating Axiom databases. Going into a little more detail, axiomatic is a command line tool which gathers axiom.iaxiom.IAxiomaticCommand plugins using the Twisted plugin system and presents them as subcommands to the user, while providing the implementations of these subcommands with access to objects that pretty much any Axiom manipulation code is going to want (currently, that amounts to an opened Store instance). Twisted’s option parser is used as the basic unit of functionality here.

I’ve already talked about several IAxiomaticCommand implementations: web, mantissa, and start. The first two of these add new Items to an Axiom database or change the values associated with existing Items. The last “starts” an Axiom database (more on what that means in a future post!).

So what you really want to know is how do I write an axiomatic plugin? Let me tell you, it could scarcely be easier:

from zope.interface import classProvides
from twisted import plugin
from twisted.python import usage
from axiom import iaxiom
from axiom.scripts import axiomatic

class PrintAllItems(usage.Options, axiomatic.AxiomaticSubCommandMixin):
        # This one tells the plugin system this object is a plugin
        # This one tells axiom it is an axiomatic plugin

    # This is how it will be invoked on the command line
    name = "print-some-items"

    # This will show up next to the name in --help output
    description = "Display an arbitrary number of Items"

    optParameters = [
        # We'll take the number of Items to display as a command 
        # line parameter.  This is "--num-items x" or "-n x" or
        # any of the other standard spellings.  The default is 5.
        ('num-items', 'n', '5', 'The number of Items to display'),

    def postOptions(self):
        s = self.parent.getStore()
        count = int(self.decodeCommandLine(self['num-items']))
        for i in xrange(count):
                print s.getItemByID(i)
            except KeyError:
                # The Item didn't exist

(Okay, seriously - I know this is a bit long: we’ll be working on lifting a lot of the boilerplate out to simplify things; expect about half of the above code to become redundant soon). I just drop this into a file in axiom/plugins/ (there are other places I could put it, if I wanted; read the Twisted plugin documentation to learn more) and I’ve got a new subcommand:

exarkun@boson:~$ axiomatic --help
Usage: axiomatic [options]
  -d, --dbdir=   Path containing axiom database to configure/create
      --help     Display this help and exit.
    mail                      Accept SMTP connections
    userbase                  Users. Yay.
    mantissa                  Blank Mantissa service 
    web-application           Web interface for normal user
    web                       Web. Yay.
    web-admin                 Administrative controls for the web
    radical                   omfg play the game now
    click-chronicle-site      Chronicler of clicking
    encore                    Install BookEncore site store requirements.
    sip-proxy                 SIP proxy and registrar
    vendor                    Interface for purchasing new services.
    vendor-site               Required site-store installation gunk
    print-some-items          Display an arbitrary number of Items
    start                     Launch the given Axiomatic database

Neat, huh?*

In case you’re dying to see the output of this new command:

exarkun@boson:~/Scratch/Run/demo$ axiomatic -d my.axiom/ print-some-items
<axiom.item._PowerupConnector object at 0xb6fc770c>
<axiom.item._PowerupConnector object at 0xb6fc770c>
<axiom.userbase.LoginSystem object at 0xb6f42104>