Python has an effective interactive documentation system, utilizing what are known as "docstrings". If the first statement of a python module, a python function or a python class is a string constant, then that string becomes the documentation string, or "docstring", for the given module, function or class. For example,
def func(arg): "Docstring for function func" return "Hello, world!"
Docstrings are fundamentally different from python comments, because of their position relative to the code they describe and because they are used by the python help facility and other documentation tools, such as pydoc:
>>> help(func) Help on function func in module __main__: func(arg) Docstring for function func >>>
It is the policy of PyTrilinos that python docstrings should be maintained to provide useful, current and accurate information to PyTrilinos users that
- correctly reflect the calling arguments of PyTrilinos methods and functions,
- match the coresponding doxygen documentation provided by Trilinos developers when appropriate, and
- supercede the doxygen documentation when the python interface and/or implementation is different from the C++ interface and/or implementation.
The difficulty in adhering to these policies is that the python code (and therefore the python docstrings) that makes up PyTrilinos is automatically generated by swig. Fortunately, there are several tools available that allow these policies to be met.
Every PyTrilinos module should contain a module docstring. This is typically implemented in the package interface file as follows:
%define %my_package_docstring " Multi-line documentation string for My_Package " %enddef %module (docstring = %my_package_docstring) My_Package
SWIG does not require that SWIG macro names begin with "%", but it is allowed and it is the convention for PyTrilinos SWIG macros. Further, PyTrilinos module docstrings follow a set format:
PyTrilinos.My_Package is the python interface to the Trilinos such-and-such package My_Package: http://trilinos.sandia.gov/packages/my_package The purpose of My_Package is to . . . . The python version of the My_Package package supports the following classes: * Class1 - Short description 1 * Class2 - Short description 2 * ... Any other notes about the package as a whole. . . .
Docstrings for functions and methods are partially implemented by the SWIG %feature called autodoc. Before any code is directed to be wrapped within an interface file (by the first %include directive), the following feature should be activated:
%feature("autodoc", "1");
This automatically adds docstrings to each function and class method showing the function name, argument list, and return type. The argument list contains both type and name information (as per the "1" option). If a function or method is overloaded, each valid calling signature is listed.
A system is in place for automatically extracting Doxygen documentation from a Trilinos package source code and inserting it into the package's python module. First, Doxygen is used to extract the documentation and save it in XML format. Second, a python script is run to read this XML data and convert it to a series of valid SWIG statements of the form::
%feature("docstring") <symbol-name> <docstring>
Third, each package interface file implements an %include statement to read these documentation directives. This adds the Doxygen documentation string to the end of the string created by %feature("autodoc", "1").
All of this infrastructure is contained within the PyTrilinos subdirectory:
doc/Doxygen
Within this subdirectory are a series of Doxygen control files, one for each package: Doxyfile_Teuchos, Doxyfile_Epetra, etc. These Doxyfiles have certain features in common: they all generate XML output:
GENERATE_XML = YES
while suppressing all other forms of output. They all direct output to their own subdirectory:
OUTPUT_DIRECTORY = Teuchos XML_OUTPUT = .
If you add documentation for a new package, then add the package name to the PyTrilinos/doc/Doxygen/Makefile variable PACKAGES. When you run make from the shell, this will cause doxygen to be run on the Doxyfile and the script doxy2swig.py (generously provided by Prabhu Ramachandran) to be run on the resulting output. This produces a file with a _dox.i suffix, e.g. Teuchos_dox.i, intended to be included into the package interface file src/Teuchos.i. To facilitate this inclusion, SWIG is invoked with -I$(top_srcdir)/doc/Doxygen.
Sometimes the Doxygen documentation is not appropriate for a given python function or method. This is often the case when %typemap-s are employed or when the python implementation replaces the C++ interface by using %ignore, %extend and/or %inline. This requires that the automatically created docstrings be overridden or appended, and can be accomplished by providing a SWIG documentation directive after the %include "Teuchos_dox.i" (for example) and that redefines the docstring for a specified symbol. These directives should be placed directly in the appropriate interface file. By convention, all directives pertaining to the symbols within a single %include file are grouped together. The documentation directives should be at the top of these groupings.
There are two SWIG documentation directives that can be employed to override or append docstrings. If you wish to append documentation to what is already present, use:
%feature("docstring") <symbol-name> " <docstring> ";
If you wish to replace the existant docstring completely, use the directive:
%feature("autodoc", "<docstring>") <symbol-name>;
The formatting given here tends to be the most readable for the widest range of situations, both for the interface files and for the resulting docstrings.