Warning: Can't synchronize with the repository (Unsupported version control system "git": Can't find an appropriate component, maybe the corresponding plugin was not enabled? ). Look in the Trac log for more information.

Plugin basics

Fundamentally, a plugin in Higgins is just a python class which is contained in an  Egg. Higgins uses  setuptools to build a plugin into an Egg and load it into the application at runtime. This document hopefully explains enough about developing a Higgins plugin that a thorough understanding of setuptools is not necessary, but when in doubt the above links should prove helpful.

Necessary boilerplate

Plugins must be structured within a specific directory hierarchy, or else Higgins will not be able to 'find' the plugin, due to the way python loads packages. Suppose we have a new plugin called MyPlugin. The source directory must be laid out thus:

    MyPlugin/
    |
    +-- setup.py
    | 
    +-- higgins/
        |
        +-- __init__.py
        |
        +-- plugins/
            |
            +-- __init__.py
            |
            +-- myplugin
                |
                +-- <actual code goes in this directory>

The name of the toplevel source directory (MyPlugin in this case) doesn't matter, but the name of the package directory in MyPlugin/higgins/plugins/ must be unique across all Higgins plugins. This is because Higgins utilizes a feature of setuptools called namespace packages. Furthermore the files MyPlugin/higgins/__init__.py and MyPlugin/higgins/plugins/__init__.py have a a very specific format which must be followed. The only thing that these two files can contain (and they must contain) is the following line:

__import__('pkg_resources').declare_namespace(__name__)

The curious developer can read more about namespace packages  here.

The file MyPlugin/setup.py is also part of the required boilerplate, and is described later. For now it suffices to know that it must be present.

At this point we have the appropriate directory structure to create a new plugin, but we don't have any actual plugin code yet. We need to decide what kind of plugin to make; the most basic choice is a Service plugin, which is good for an example. First, in the myplugin directory we create a new file __init__.py which will contain our plugin definition. Then we add the actual definition:

import higgins

class MyService(higgins.service.Service):
    pass

This code is a legal plugin. However, it doesn't do anything (except waste a little bit of memory). We need to write some methods for the class, and the first one to write is our initialization method (also known as the constructor).

Plugin initialization

When Higgins starts up, one of the first things it does is scan the system for plugins. For each plugin found, Higgins creates a single instance of the plugin by calling the plugin constructor method __init__. Higgins does not pass any parameters to the constructor function. A plugin constructor is expected to throw an exception if initialization fails for some reason; otherwise Higgins expects that initialization succeeded and the plugin is thus viable. Plugins are not required to define an __init__ method, in which case the __init__ method of the base class is called, but if an __init__ method is defined it must call the parent constructor method. Here's a barebones example of an __init__ method:

import higgins

class MyPlugin(higgins.service.Service):
    def __init__(self):
        try:
            import myfoomodule
        except:
            raise Exception("required module 'myfoomodule' wasn't found")
        higgins.service.Service.__init__(self)

Defining the plugin methods

Declaring your plugin