pdk.Tools.pdkdoc_overview
index
pdk/Tools/pdkdoc_overview.py

pdk Python code documentation mini-HOWTO

pdk Python code documentation mini-HOWTO

Motivation

  • expose the interface of pdk code objects in a uniform way to improve code readability
  • force coders to be more disciplined in their documentation habits ;-)

Approach

  • specify guidelines for structuring doc strings of objects (i.e., modules, classes, class methods, and functions)
  • use standard tools as much as possible for compliance with the Python library and for ease of maintenance
  • make the generation of documentation from the sources a fully automated process

Implementation

  • use "structured text" to mark up Python doc strings. Advantages are:

    • easy to learn (uses mostly fairly simple directives for markup)
    • a structured text parser and HTML converter are readily available as part of the Python docutils project. This parser uses XML as intermediary representation and allows for customization of individual markup categories with a HTML stylesheet
  • use pydoc to generate HTML pages from the sources. Features of pydoc are:

    • automatic batch processing of whole directory trees
    • run a web server to publish the autogenerated HTML documentation
    • perform keyword search in the synopsis lines of all modules in a directory tree
    • interactive help system similar to the Unix man pages integrated into the Python interpreter

    Note that pydoc works by inspecting "live" objects, i.e., all modules that are documented have to be imported in order to be documented. In rare cases this might pose problems with circular imports which are easily resolved by moving the offending import statements into the local namespace where they are actually used.

    The following features were added to the standard version of pydoc to accommodate the needs for the pdk code base:

    • support for structured text markup in doc strings
    • automatic generation of HTML hyperlinks for references to data attributes and to objects within the same module or in another module
    • command line flags for optional suppression of identifiers marked as protected and/or private by a single or double underscore(s)
    • heed the __all__ attribute of modules specifying the list of exported identifiers
    • support for custom colors in the generated HTML
    • properly handle sub-packages and individual file in sub-packages from the command line
    • command line flag to skip source files with existing HTML documentation

Practical Use

Please study the examples in this module and the links above to learn how to structure and format Python object doc strings for pdk code.

If you want to check how the formatted documentation for a module you wrote looks like, you can do the following from the Python prompt:

from pdkdoc import writedoc
writedoc("packagepath.modulename")

A typical interactive session looks like this:

>>> from pdkdoc import writedoc
>>> writedoc("pdk.DataBaseClasses")
writing documentation for pdk.DataBaseClasses...
Reporter: ERROR/3 (string input) Unexpected indentation at line 3.
Reporter: WARNING/2 (string input) Block quote ends without a blank line; unexpected unindent at line 4.
Reporter: WARNING/2 (string input) Enumerated list ends without a blank line; unexpected unindent at line 12.
...wrote pdk.DataBaseClasses.html
>>>

While this does not give you any hint where the error occurred, you will see a nice HTML-formatted error message in the appropriate place in the generated output.

Random notes:

  • if a module to be documented defines an __all__ attribute, documentation will be restricted to the identifiers listed therein. Note that any references to identifiers not exported by __all__ will not be resolved, even if they are imported into the module name space

  • in order to process a single file from the command line, the file name needs to contain at least one path separator; therefore, you need to do a

    python pdkdoc.py -w ./myfile.py`` to process a file
    

    in the current directory.

 
Classes
            
ProperlyDocumentedClass
ReferenceTestClass
 
class ProperlyDocumentedClass
     
Purpose:this tag explains the purpose of this class (mandatory!)
Detail:

this tag provides further details on the implementation of this class (optional). Note that whenever you have more than one line of description text, they all have to start at the same column in order to be recognized as part of the description.

You can subdivide your description of the implementation details with paragraphs and intersperse unordered lists like this:

  • a first item
  • a second item

Ordered and nested lists are also possible:

  1. a toplevel list item

    1. a nested list item
    2. a second nested list item (there has to be an empty line preceding this item; if it is missing, the nested list is not recognized by the parser!)
  2. a second toplevel list item

    To enclose a literal block (e.g., for coding examples), end the preceding line with two colons like this

    if __name__ == "__main__": loop_forever()
    

    There are a number of inline formatting options: for emphasized text and for strongly emphasized text and for inline literals (for code snippets and Python object references).


 
   Methods defined here:
method1(self, posarg1, posarg2, kwarg1=None)

this is a method doc string. Note that we do not have Purpose and Detail special tags for methods.

A proper description of the input parameters looks like this:

Parameters:
  • posarg1: is the first positional argument; it is used to foo stuff
  • posarg2: is the second positional argument; it is used to bar things
  • kwarg1: is the first keyword argument; it is used for bletching, among other things
Value:use this tag to specify the return value of this method like this: this method returns None.

Note the inverted quotes around the references to the input arguments and the double inverted quotes around the reference to the Python "None" object.

method2(self)

this method shows how to refer to other objects:

Note that only references

  1. to a module, class, callable (i.e., function or method), or (static) data member; and
  2. to identifiers that are either already imported into the current module or can be imported by parsing the (dotted) reference

will be resolved correctly.

method3(self, *varposargs, **varkwargs)
# this method has no docstring, but comment, which will appear # (formatted) in the documentation
 
class ReferenceTestClass
       
   Methods defined here:
method(self)

Data and non-method functions defined here:
MEMBER = 1
 
Functions
            
cursorily_documented_function(arg0)
it is also permissible to specify the signature of a function without an explicit parameter list, particularly if there is not much to say - for instance: this function takes a single argument arg0 and returns it unchanged.
properly_documented_function(arg0)

generally, functions feature the same special sections as methods:

Parameters:
  • arg0 : some numeric value
Value:
  • arg0 times two
 
Data
             __looksLikeABuiltinItem__ = 3
aString = 'this will pop up in the data section'
singleton = instance of ProperlyDocumentedClass