Copyright © 2006, 2007 Will Barton
| Revision History | |
|---|---|
| Revision Unreleased | Nebulous Future |
| Initial Public Release | |
Abstract
The PureDocs API documentation system is designed as a modular system to support languages and differing output formats. This document describes this plugin architecture and provides examples to assist in developing new plugins for both languages and output formats for the PureDocs API documentation system.
Table of Contents
Within PureDocs, there are two types of plugins, Language Plugins, and Output Plugins. Each type of plugin has a specific interface that is defined for it, and all plugins of that type are expected to conform to that interface. These interfaces are detailed below.
PureDocs also defines a tree-like structure in the form of Resources that plugins either input or output. A Resource object represents a node that will have properties, documentation, child resources, and importantly, a type that is specific to the language that resource belongs to. Resources are also described in greater detail below.
Language plugins provide PureDocs with a parser for a given language that will parse a source file of that language, and output a tree of Resource objects representing the content of that source file. The language plugin defines properties within resources, as well as resource types.
Output plugins take a resource tree generated by a language plugin, and generates the final output form of the resource tree. This includes parsing documentation that may be attached to a resource. The result of the output plugin's processing is the final output PureDocs provides. It is generally expected to by XML, but PureDocs makes no assumptions about the output format.
PureDocs currently supports plugins written both in the Python language and the C language. While implementation of plugins in either language is different, the concepts involved are identical.
PureDocs provides a single type that is shared by both types of plugins, the Resource. A Resource is a tree of items within a source file that are to be included in the final output, in one form or another. The file itself is the top-level Resource, and all items within the file (functions, classes, etc) are children of that file Resource.
Language Plugins create Resource objects, give them
a type (e.g. function),
set properties on the resource (e.g.
parameters for a function), set the
doc string on the resource, and finally, add
child resources to the resource.
Output Plugins take a tree of Resource
objects that were created by a language plugin, and process that
tree to create the final output format. This includes parsing the
doc string in the plugin's prefered way.
PureDocs plugins register for certain "entry points" based on the type of plugin they are providing and the type of data they opperate on. The declaration of these "entry points" differ between Python and C plugins, however they are concetually identical.
Plugins register with either the
puredocs.lang or
puredocs.out entry points. The entry point
registration maps a string (specific to the plugin type) to
the plugin. What this mapping means is specific to the language
the plugin is written in.
For language plugins, the string is the MIME-type of the file
that the language plugin supports. For example, the reference
Python language plugin maps the python_lang module to the
MIME-type text/x-python. When
PureDocs is given an input file that matches the MIME-type the
language plugin is mapped to, that language plugin is used.
For output plugins, the string is a short description of the
output plugin's output type, that the user specifies with the
-f or --output-format options
to the puredocs command. The Re-Structured
Text XML output plugin uses the
rstxml string.
The Python Plugin API is provided entirely by the puredocs Python package.
__init__(,
type,
doc,
properties,
resources);
Creating a Resource is
straight-forward. The __init__
method takes all the parameters described above.
Parameters
typeThis is decided upon by the language plugin, and
the only requirement is that a language plugin be
consistent with itself. An example would be
function for a resource representing
a function.
docThe documentation string associated with the resource. It could be extracted from a comment around the item in the source file, or another convention used by the language.
propertiesThis is a simple dictionary containing key/value
pairs of property names and values for this
Resource. An example would be a
key of paramters, and a list of the
parameters for a function resource.
resourcesThis is a simple list of resources that are children of this resource. An example would be function or method resources that are children of a class resource.
An example of using the Python API for creating a
Resource is creating a
Resource for a Python language function.
This example is losely based on the Python language plugin.
Example 1. Creating a Resource
def visitFunction(self, node):
func = Resource('function',
doc = node.doc,
properties = {'name':node.name,
'decorators':node.decorators,
'parameters':node.argnames}))
In addition to Resource creation,
Resource objects provide a Python
sequence API for accessing child Resource
objects. Please see the
Python sequence API documentation for more information
on how child Resource objects can be
accessed.
Additionally, properties can be accessed as
Resource object attributes by property
name.
To support loading plugins, PureDocs makes use of the Python package setuptools. setuptools allows for the loading of Python packages ("eggs") that register for certain "entry points". These are declared when the Python package is built and installed, and allows for independence of naming of Python packages, as well as the ability to integrate PureDocs plugins with other Python packages.
For Python plugins, an entry point is a mapping of a string to a python module, class, or function. PureDocs expects both entry points to map to a Python module or class that provides specific members that are detailed below in the Language and Output plugin descriptions.
Entry points are specified in a standard Python
setup.py by importing the
setuptools module, and using the
entry_points dictionary argument to the
setup(). The keys for the dictionary are
the entry points, and the values are a list of the mappings
detailed above.
Example 2. setup.py Entry Point Example
from setuptools import setup
setup(
# ... Standard Arguments and Metadata...
entry_points = {
'puredocs.lang': ['text/x-python = puredocs.plugins.python_lang',],
}
)The setuptools webpage provides more information on setuptools and entry points, as well as more examples.
The language plugin is responsible for parsing a provided file
and returning a tree of Resource objects.
The language plugin is responsible for defining the types of
resource objects, deciding what gets included in the resource
object tree, and attaching documentation strings to the
resources from whatever convention may be used in the language.
Language plugins must provide the following members, whether the plugin is a module or a class.
parserA class that can parse a given file and return a
Resource object tree. The nature of
the parser class is described below.
optionsA class providing any command-line options the parser may wish to take to influence the way a file is parser. The nature of the options class is described below.
The language plugin's parser interface
requirements are very simple. The interface for language parser
classes follows.
The Language Parser
root
The Resource object forming the base of the Resource tree.
__init__(,
filename);
Parse the file with the given filename as this language, generating a tree of Resource objects accessible from this object's root variable.
Beyond that, there are no requirements of the language parser.
PureDocs calls the __init__ method, and
then attempts to pass the root variable to
the output plugin. The root variable could
be populated by the __init__, or it
could be dynamic.
The output plugin is responsible for taking a
Resource tree created by a language
plugin and transforming it into the final output form that will
be given to the user by PureDocs. The output plugin is also
responsible for any processing that may be necessary of a
Resource's doc string.
Like the language plugin, the output plugin must provide the following members, whether the plugin is a module or a class.
writerA class that can process a
Resource object tree and generate the
final output format for the documentation. The nature of
the writer class is described below.
optionsA class providing any command-line options the writer may wish to take to influence the way the output is written. The nature of the options class is described below.
The output writer class is required to implement the following methods:
The Output Writer
__init__(,
resource);
Output a given resource and all of its sub-resources, processing any aspect of the resource that might be necessary, especially its documentation.
string();
Return a string representation of the final format of the output.
write(,
destination);
Write the final format of the output to the given destination.
If the destination is a directory, rather than a filename, generate a filename based on the name of the resource, if available, and place it in that directory.
Command-line arguments can be accepted by any plugin,
independent of PureDocs. These arguments are specified by the
plugin's options object, described above.
This should be a subclass of the
puredocs.Options class, which is imported
from the twisted.python.usage package.
The options that are defined in a plugin's options class are secondary to the standard PureDocs options, and should not conflict. An example of an options class follows.
For more information about Options classes, see the Twisted Project's documentation.
The C Plugin API is provided by the libpuredocs
library, and exposed via the puredocs.h header
file.
Resource *
puredocs_createResource
( | type); |
char * | type; |
Create and return a new Resource object with the given
type. This is similar to the Python
__init__ method described
above.
Parameters
typeThis is decided upon by the language plugin, and
the only requirement is that a language plugin be
consistent with itself. An example would be
function for a resource representing
a function.
int
puredocs_setDocString
( | resource, | |
doc); |
Resource * | resource; |
char * | doc; |
Set the documentation string for the given Resource. The language plugin is responsible for stripping any extra characters (language-specific omment decorations, for example).
Parameters
resourceThe Resource to add the doc string to.
docThe documentation string associated with the resource. It could be extracted from a comment around the item in the source file, or another convention used by the language.
int
puredocs_setProperty
( | resource, | |
| property, | ||
value); |
Resource * | resource; |
char * | property; |
char * | value; |
Set the given property to the given
value on the given Resource.
If the Resource does not already have the
property, it will be added.
Every Resource has properties, which are key/value pairs. An example would be a key of paramters, and a list of the parameters for a function resource.
Parameters
resourceThe Resource to add the doc string to.
propertyThe key for the value
given.
valueThe value for the property
given.
int
puredocs_addChild
( | resource, | |
child); |
Resource * | resource; |
Resource * | child; |
Add the child Resource
to the given Resource. An example of a child
Resource would be a function within a
module.
Parameters
resourceThe Resource to add the doc string to.
childThe Resource to add as the child.
Because XML output is common to PureDocs, XSLT is a natural extension of PureDocs, and indeed, PureDocs ships with a collection of stylesheets for its default output plugin. Generally language plugin authors want to be aware of this, and at some point in the future, a rigid definition of the PureDocs stylesheets, as well as language-specific customizations, will be available. It would be in the best interest of language plugin authors to provide XSLT stylesheets for their language plugin's specific resource types, properties, etc.