Module ReadMeForPlugins
[show private | hide private]
[frames | no frames]

Module ReadMeForPlugins

README for Plugins and Plugin writing

Inside the contrib/ directory, you'll see the plugins/ directory. To install a given plugin, move the plugin file you want from the contrib/ directory to the Pyblosxom/plugins/ directory of your installation.

Some plugins take effect immediately, like the conditionalhttp.py and the statusnotfound.py. Some plugins require some setup before they work. Read the plugin file in a text editor to see what installation steps are required.

Below is documentation for plugin developers detailing the standard callbacks that they can use to implement plugins.

Implementing a callback in a plugin

If you want to implement a callback, you add a function corresponding to the callback name to your plugin module. For example, if you wanted to modify the Request object just before rendering, you'd implement cb_prepare something like this:
   def cb_prepare(args):
       pass

Each callback passes in arguments through a single dictionary. Each callback passes in different arguments and expects different return values. Consult the documentation for the callback you're seeking before implementing it in your code to understand what it does and how to use it.

The BlosxomRenderer plugin callbacks

The BlosxomRenderer plugins are based on the blosxom 2.0 callbacks. The names of the arguments are different, but the callbacks are called at the same points that the blosxom 2.0 callbacks are called and serve the same function.

The available blosxom renderer callbacks are: Some of the other blosxom 2.0 callbacks are handled slightly differently in PyBlosxom.

See the callback documentation below for more details.

verify_installation

As of PyBlosxom 0.9, the pyblosxom.cgi is able to test your PyBlosxom installation. It verifies certain items in your config file and also loads all the plugins and lets them verify their configuration as well.

At the prompt, you would run:
  ./pyblosxom.cgi

It tells you your Python version, OS name, and then proceeds to verify your config properties (did you specify a valid datadir? does it exist?...) and then initializes all your plugins and executes verify_installation(request) on every plugin you have installed that has the function.

As a plugin developer, you should add a verify_installation function to your plugin module. Something like this (taken from pycategories):
  def verify_installation(request):
      config = request.getConfiguration()

      if not config.has_key("category_flavour"):
          print "missing optional config property 'category_flavour' which allows "
          print "you to specify the flavour for the category link.  refer to "
          print "pycategory plugin documentation for more details."
      return 1

Basically this gives you (the plugin developer) the opportunity to walk the user through configuring your highly complex, quantum-charged, turbo plugin in small baby steps without having to hunt for where their logs might be.

So check the things you need to check, print out error messages (informative ones), and then return a 1 if the plugin is configured correctly or a 0 if it's not configured correctly.

This is not a substitute for reading the installation instructions. But it should be a really easy way to catch a lot of potential problems without involving the web server's error logs and debugging information being sent to a web-browser and things of that nature.
Function Summary
dict cb_date_head(args)
The date_head callback is called before a date_head flavour template is rendered.
None cb_end(args)
The start callback allows plugins to execute teardown/cleanup code, save any data that hasn't been saved, clean up temporary files, and otherwise return the system to a normal state.
dict cb_entryparser(entryparsingdict)
The entryparser callback allows plugins to register the entryparsers they have.
list cb_filelist(args)
The filelist callback allows plugins to generate the list of entries to be rendered.
dict cb_filestat(args)
The filestat callback allows plugins to override the mtime of the entry.
dict cb_foot(args)
The foot callback is called before the variables in the entry are substituted into the foot template.
dict cb_head(args)
The head callback is called before a head flavour template is rendered.
None cb_logrequest(args)
The logrequest callback is used to notify plugins of the current PyBlosxom request for the purposes of logging.
None cb_pathinfo(args)
The pathinfo callback allows plugins to parse the HTTP PATH_INFO item.
  cb_postformat(args)
The postformat callback allows plugins to make further modifications to entry text.
string cb_preformat(args)
The preformat callback acts in conjunction with the entryparser that handled the entry to do a two-pass formatting of the entry.
None cb_prepare(args)
The prepare callback is called in the default blosxom handler after we've figured out what we're rendering and before we actually go to the renderer.
object instace cb_renderer(args)
The renderer callback allows plugins to specify a renderer to use by returning a renderer instance to use.
None cb_start(args)
The start callback allows plugins to execute startup/initialization code.
dict cb_story(args)
The story callback gets called before the entry is rendered.
dict cb_story_end(args)
The story_end callback is is called after the variables in the entry are substituted into the template.

Function Details

cb_date_head(args)

The date_head callback is called before a date_head flavour template is rendered.

cb_date_head is called before the variables in the entry are substituted into the template. This is the place to modify the date_head template based on the entry content. You have access to all the content variables via entry.

Blosxom 2.0 calls this callback 'date'.

Functions that implement this callback will get an args dict containing:
  • 'request' - the Request object
  • 'renderer' - the BlosxomRenderer that called the callback
  • 'entry' - a EntryBase to be rendered
  • 'template' - a string containing the flavour template to be processed
Functions that implement this callback must return the input args dict whether or not they adjust anything in it.
Parameters:
args - a dict containing 'request', 'renderer', 'entry' and 'template'
           (type=dict)
Returns:
the args dict
           (type=dict)

cb_end(args)

The start callback allows plugins to execute teardown/cleanup code, save any data that hasn't been saved, clean up temporary files, and otherwise return the system to a normal state.

Examples of usage:
  • save data to a file
  • clean up any temporary files
Functions that implement this callback will get an args dict containing:
  • 'request' - a Request object

Functions that implement this callback don't need to return anything.

Note: The cb_end callback is called for every PyBlosxom request regardless of whether it's handled by the default blosxom handler. This is slightly different than blosxom.
Parameters:
args - a dict containing 'request'
           (type=dict)
Returns:
None
           (type=None)

cb_entryparser(entryparsingdict)

The entryparser callback allows plugins to register the entryparsers they have. Entry parsers are linked with a filename extension. For example, the default blosxom text entry parser will be used for any file ending in ".txt".

Functions that implement this callback will get the entryparser dict consisting of file extension -> entry parsing function pairs.

Functions that implement this callback should return the entryparser dict after modifying it.

A bit about entry parsing functions

Entry parsing functions take in a filename and the Request object. They then open the file and parse it out. The can call cb_preformat and cb_postformat as they see fit. They should return a dict containing at least 'title' and 'story' keys. The 'title' should be a single string. The 'story' should be a list of strings (with \n at the end).

Here's an example code that reads *.plain files:
   import os
   def cb_entryparser(entryparsingdict):
       """
       Register self as plain file handler
       """
       entryparsingdict['plain'] = parse
       return entryparsingdict

   def parse(filename, request):
       """
       We just read everything off the file here, using the filename as
       title
       """
       entryData = {}
       entryData['title'] = os.path.basename(filename)
       entryData['story'] = open(filename).read()
       return entryData
Parameters:
entryparsingdict - a dict that comtains file extension -> entry parsing function pairs
           (type=dict)
Returns:
the entry parsing dict
           (type=dict)

cb_filelist(args)

The filelist callback allows plugins to generate the list of entries to be rendered. Entries should be EntryBase derivatives--either by instantiating EntryBase, FileEntry, or creating your own EntryBase subclass.

Functions that implement this callback will get an args dict containing:
  • 'request' - the PyBlosxom Request
Functions that implement this callback should return None if they don't plan on generating the entry list or a list of entries. if they do. When a function returns None, the callback will continue to the next function to see if it will return a list of entries. When a function returns a list of entries, the callback will stop.
Parameters:
args - a dict containing 'request'
           (type=dict)
Returns:
None or list of EntryBase objects
           (type=list)

cb_filestat(args)

The filestat callback allows plugins to override the mtime of the entry. One of the contributed plugins uses this to set the mtime to the time specified in the entry's filename.

Functions that implement this callback will get an args dict containing:
  • 'filename' - the filename of the entry
  • 'mtime' - the result of an os.stat on the filename of the entry
Functions that implement this callback must return the input args dict whether or not they adjust anything in it.
Parameters:
args - a dict containing 'filename' and 'mtime'
           (type=dict)
Returns:
the args dict
           (type=dict)

cb_foot(args)

The foot callback is called before the variables in the entry are substituted into the foot template. This is the place to modify the foot template based on the entry content. You have access to all the content variables via entry.

Blosxom 2.0 calls this callback 'foot'.

Functions that implement this callback will get an args dict containing:
  • 'request' - the Request object
  • 'renderer' - the BlosxomRenderer that called the callback
  • 'entry' - a EntryBase to be rendered
  • 'template' - a string containing the flavour template to be processed
Functions that implement this callback must return the input args dict whether or not they adjust anything in it.
Parameters:
args - a dict containing 'request', 'renderer', 'entry' and 'template'
           (type=dict)
Returns:
the args dict
           (type=dict)

cb_head(args)

The head callback is called before a head flavour template is rendered.

cb_head is called before the variables in the entry are substituted into the template. This is the place to modify the head template based on the entry content. You can also set variables on the entry that will be used by the cb_story or cb_foot templates. You have access to all the content variables via entry.

Blosxom 2.0 calls this callback 'head'.

Functions that implement this callback will get an args dict containing:
  • 'request' - the Request object
  • 'renderer' - the BlosxomRenderer that called the callback
  • 'entry' - a EntryBase to be rendered
  • 'template' - a string containing the flavour template to be processed

Functions that implement this callback must return the input args dict whether or not they adjust anything in it.

Example in which we add the number of entries being rendered to the $blog_title variable:
  def cb_head(args):
      request = args["request"]
      config = request.getConfiguration()
      data = request.getData()

      num_entries = len(data.get("entry_list", []))
      config["blog_title"] = config.get("blog_title", "") + ": %d entries" % num_entries

      return args
Parameters:
args - a dict containing 'request', 'renderer', 'entry' and 'template'
           (type=dict)
Returns:
the args dict
           (type=dict)

cb_logrequest(args)

The logrequest callback is used to notify plugins of the current PyBlosxom request for the purposes of logging.

Functions that implement this callback will get an args dict containing:
  • 'filename' - a filename (typically a base filename)
  • 'return_code' - A HTTP error code (e.g 200, 404, 304)
  • 'request' - a Request object

Functions that implement this callback can return whatever they want--it doesn't affect the callback chain.

cb_logrequest is called after rendering and will contain all the modifications to the Request object made by the plugins.

An example input args dict is like this:
   {'filename': filename, 'return_code': '200', 'request': Request()}
Parameters:
args - a dict containing 'filename', 'return_code', and 'request'
           (type=dict)
Returns:
None
           (type=None)

cb_pathinfo(args)

The pathinfo callback allows plugins to parse the HTTP PATH_INFO item. This item is stored in the http dict of the Request object. Functions would parse this as they desire, then set the following variables in the data dict of the Request object:
 'bl_type'       (dir|file)
 'pi_bl'         typically the same as PATH_INFO
 'pi_yr'         yyyy
 'pi_mo'         (mm|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)
 'pi_da'         dd
 'root_datadir'  full path to the entry folder or entry file on filesystem
 'flavour'       The flavour gathered from the URL
Functions that implement this callback will get an args dict containing:
  • 'request' - a Request object
Functions that implement this callback should make the modifications to the data dict in place--no need to return anything.
Parameters:
args - a dict containing 'request'
           (type=dict)
Returns:
None
           (type=None)

cb_postformat(args)

The postformat callback allows plugins to make further modifications to entry text. It typically gets called after a preformatter by the entryparser. It can also be used to add additional properties to entries. The changes from postformat functions are saved in the cache (if the user has caching enabled). As such, this shouldn't be used for dynamic data like comment counts.

Examples of usage:
  • Adding a word count property to the entry
  • Using a macro replacement plugin (Radio Userland glossary)
  • Acronym expansion
  • A 'more' text processor
Functions that implement this callback will get an args dict containing:
  • 'entry_data' - a dict that minimally contains a 'title' and a 'story'
  • 'request' - a Request object
Functions that implement this callback don't need to return anything--modifications to the 'entry_data' dict are done in place.
Parameters:
args - a dict containing 'request' and 'entry_data'
           (type=dict)

cb_preformat(args)

The preformat callback acts in conjunction with the entryparser that handled the entry to do a two-pass formatting of the entry.

Functions that implement cb_preformat are text transformation tools. Once one of them returns a transformed entry, then we stop processing.

Functions that implement this callback will get an args dict containing:
  • 'parser' - a string that indicates whether a preformatter should run
  • 'story' - a list containing lines of text (with '\n' included)
  • 'request' - a Request object

Functions that implement this callback should return None if they didn't modify the story or a single story string.

A typical preformat plugin look like:
   def cb_preformat(args):
       if args['parser'] == 'linebreaks':
           return parse(''.join(args['story']))

   def parse(text):
       # A preformatter to convert linebreak to its HTML counterpart
       text = re.sub('\n\n+','</p><p>',text)
       text = re.sub('\n','<br />',text)
       return '<p>%s</p>' % text
Parameters:
args - a dict containing 'request' (Request object), 'story' (list of strings), and 'parser' (single string)
           (type=dict)
Returns:
string containing the formatted text
           (type=string)

cb_prepare(args)

The prepare callback is called in the default blosxom handler after we've figured out what we're rendering and before we actually go to the renderer.

Plugins should implement cb_prepare to modify the data dict which is in the Request. Inside the data dict is 'entry_list' (amongst other things) which holds the list of entries to be renderered (in the order they will be rendered).

Functions that implement this callback will get an args dict containing:
  • 'request' - The Request object at the particular moment

Functions that implement this callback can return whatever they want--it doesn't affect the callback chain.

Example of a cb_prepare function in a plugin:
   def cb_prepare(args):
       """
       This plugin shows the number of entries we are going to render and
       place the result in $countNoOfEntries.
       """
       request = args['request']
       data = request.getData()
       config = request.getConfiguration()

       # Can anyone say Ternary? :)
       IF = lambda a,b,c:(a() and [b()] or [c()])[0]

       num_entry = config['num_entries']
       entries = len(data['entry_list'])

       data['countNoOfEntries'] = IF(num_entry > entries, num_entry, entries)
Parameters:
args - dict containing 'request'
           (type=dict)
Returns:
None
           (type=None)

cb_renderer(args)

The renderer callback allows plugins to specify a renderer to use by returning a renderer instance to use. If no renderer is specified, we use the default blosxom renderer.

Functions that implement this callback will get an args dict containing:
  • 'request' - the PyBlosxom Request
Functions that implement this callback should return None if they don't want to specify a renderer or the renderer object instanct if they do. When a function returns a renderer instance, processing stops.
Parameters:
args - a dict containing 'request'
           (type=dict)
Returns:
None or a Pyblosxom.renderers.base.RendererBase instance
           (type=object instace)

cb_start(args)

The start callback allows plugins to execute startup/initialization code. Use this callback for any setup code that your plugin needs, like:
  • reading saved data from a file
  • checking to make sure configuration variables are set
  • allocating resources

Note: The cb_start callback is slightly different than in blosxom in that cb_start is called for every PyBlosxom request regardless of whether it's handled by the default blosxom handler. In general, it's better to delay allocating resources until you absolutely know you are going to use them.

Functions that implement this callback will get an args dict containing:
  • 'request' - a Request object
Functions that implement this callback don't need to return anything.
Parameters:
args - a dict containing 'request'
           (type=dict)
Returns:
None
           (type=None)

cb_story(args)

The story callback gets called before the entry is rendered.

The template used is typically the story template, but we allow entries to override this if they have a "template" property. If they have the "template" property, then we'll use that template instead.

cb_story is called before the variables in the entry are substituted into the template. This is the place to modify the story template based on the entry content. You have access to all the content variables via entry.

Blosxom 2.0 calls this callback 'story'.

Functions that implement this callback will get an args dict containing:
  • 'renderer' - the BlosxomRenderer that called the callback
  • 'request' - the PyBlosxom a Request being handled
  • 'template' - a string containing the flavour template to be processed
  • 'entry' - a EntryBase object to be rendered
Functions that implement this callback must return the input args dict whether or not they adjust anything in it.
Parameters:
args - a dict containing 'request', 'renderer', 'entry' and 'template'
           (type=dict)
Returns:
the args dict
           (type=dict)

cb_story_end(args)

The story_end callback is is called after the variables in the entry are substituted into the template. You have access to all the content variables via entry.

Functions that implement this callback will get an args dict containing:
  • 'request' - the Request object
  • 'renderer' - the BlosxomRenderer that called the callback
  • 'entry' - a EntryBase to be rendered
  • 'template' - a string containing the flavour template to be processed
Functions that implement this callback must return the input args dict whether or not they adjust anything in it.
Parameters:
args - a dict containing 'request', 'renderer', 'entry' and 'template'
           (type=dict)
Returns:
the args dict
           (type=dict)

Generated by Epydoc 2.1 on Mon Jun 6 10:38:35 2005 http://epydoc.sf.net