| Author: | Matthias Baas (baas@ira.uka.de) |
|---|---|
| Date: | 2003-01-21 |
| Version: | 1.5.5 |
You may have heard of Doxygen, a program that generates source code documentation by directly reading the source files and extracting the documentation from there. Unfortunately, doxygen can't read Python code directly (it was originally written to extract documentation from C/C++ code). However, it is possible to apply a filter to an input file and doxygen will then process the filtered result. And this is what you can get right here, a filter that transforms Python code into C++ stubs so that doxygen can process the documentation.
You can download the filter here (v1.5.5, 21KB).
2003-01-21: Version 1.5.5: Support for raw or unicode doc strings, support for static and class methods and a few bug fixes (thanks to Richard Laager for the patches).
2003-12-21: Version 1.5.4: Methods beginning with two underscores that end with something other than two underscores are considered private and are handled accordingly (thanks to Richard Laager for the patch).
2003-12-05: Version 1.5.3: The first parameter of class methods (self) is removed from the documentation.
2003-11-03: Version 1.5.2: The module docstring will be used as namespace documentation (thanks to Joe Bronkema for the patch)
Here's an example Python file and what doxygen produces out of it:
## \file example.py
## \brief An example Python program.
# Demo class
class Demo:
"""\brief A demo class, it's really just for demonstration.
The detailed description of the class would appear right here.
However, as this class is utterly useless when talking about its
functionality it actually has no detailed description which is
sort of a pity, since a couple of lines of documentation would
make it look like a real documentation. But as this is just an
example of how the doxygen output might look like a one-liner has
to be enough. Insert your documentation here as appropriate. You
get the idea now, don't you? If not, I can't help it but I
certainly won't type in a lot of nonsense just to make it look \em
real. No, definitely not.
"""
def __init__(self):
"""The constructor."""
def foo(self, bar):
"""The infamous foo method.
There's no detailed description necessary for the \em foo()
function as everybody know what it does.
\param bar The \a bar argument is compulsory, never leave it out.
\return The \a bar input after processing by the \em foo() function.
"""
pass
## protected:
def spam(self, amount):
"""Return an amount of spam.
\param amount (\c int) The amount of spam.
\return An amount of spam.
"""
return amount*"spam"
# Another demo class
class AnotherDemo(Demo):
"""\brief This class is derived from the demo class."""
def __init__(self):
pass
The filter creates the following "pseudo" C++ code out of the Python code:
namespace example {
/**
\file example.py
\brief An example Python program.
*/
/**
\brief A demo class, it's really just for demonstration.
The detailed description of the class would appear right here.
However, as this class is utterly useless when talking about its
functionality it actually has no detailed description which is
sort of a pity, since a couple of lines of documentation would
make it look like a real documentation. But as this is just an
example of how the doxygen output might look like a one-liner has
to be enough. Insert your documentation here as appropriate. You
get the idea now, don't you? If not, I can't help it but I
certainly won't type in a lot of nonsense just to make it look \em
real. No, definitely not.
*/
class Demo
{
public:
/**
The constructor.*/
__init__();
/**
The infamous foo method.
There's no detailed description necessary for the \em foo()
function as everybody know what it does.
\param bar The \a bar argument is compulsory, never leave it out.
\return The \a bar input after processing by the \em foo() function.
*/
foo(bar);
protected:
/**
Return an amount of spam.
\param amount (\c int) The amount of spam.
\return An amount of spam.
*/
spam(amount);
}; // end of class
/**
\brief This class is derived from the demo class.*/
class AnotherDemo : public Demo
{
public:
__init__();
}; // end of class
} // end of namespace
/** \namespace example
\brief Module "example" */
After being processed by doxygen it might look like this (this is just an example of the html output with the default settings. Doxygen has a lot of options to customize the output pages and it can also output other formats).
The filter can be used in two ways. The first way is to use it as a true filter that doxygen will launch every time it reads the contents of a file. In this case you have to add the following lines to your Doxyfile:
INPUT_FILTER = "python pythfilter.py -f" FILTER_SOURCE_FILES = YES
The -f option has to be used to execute pythfilter.py as a doxygen filter. If you leave it out you're using the second way where the filter is used as a stand-alone command line tool that converts a Python source tree into a corresponding C++ stubs tree. In this case you have to provide the input and output directories:
pythfilter.py code doxytmp
This call converts all code in the code directory. For each file a corresponding file is created in the directory doxytmp. If you keep the output directory during two calls of the filter only those files will be filtered again that have changed in code. Files or directories that got deleted will be deleted in doxytmp too.
If you aren't familiar with doxygen you should first check out the doxygen manual and familiarize yourself with the idea of the program (http://www.doxygen.org).
Now what does the filter actually do? It translates classes and funtions into empty C++ stubs and transforms all comments starting with ## and all doc strings into doxygen comment blocks. Inside those comments you can use any doxygen markup as you would do in your C/C++ code as well.
Furthermore, it puts the entire contents of a file into a namespace with the name of the file (without the .py suffix).
There's a problem when you create the documentation for a package that has several subdirectories. In this case, the references to other classes aren't right so that the generated class hierarchy isn't always accurate.