wxPython Documentation Project
The purpose of this wiki page is to explain how to add reference documentation to the various wxPython modules, and how to submit those documentation snippets back to the wxPython project. The goal is to eventually be able to replace the wxWidgets C++ docs in the wxPython distributions, and to make the Python specific docs sufficient for the needs of the wxpython programmer.
A current snapshot of the wxPython reference docs can be found here.
Epydoc
Epydoc is the tool chosen to put the wxPython docs into a usable format. It is able to extract docstrings from Python modules and add simple formatting, linking to related docs, an index, and etc. Epydoc supports various forms of document markup, including epytext as well as ReStructuredText.
wxPython has standardized on using the ReStructuredText format, because it is a cleaner markup syntax that doesn't get in the way as much when reading the document as plain text, and also because there is much familiarity with it within the Python community. However, if a module author prefers to use epytext or another of epydoc's supported formats, then the format can be specified for that module by defining a module-level string variable __docformat__, containing the name of the module's markup language.
A slightly customized version of epydoc 2.1 is being used for the wxPython documentation. You can get a copy of the source tarball, as well as some installers, at the wxPython tools page.
What to document
Keep in mind that the things specified here are just guidelines. I expect that there will be varying circumstances with different modules, and some things may make more sense in various cases. So feel free to adapt these guidelines to fit those needs.
Modules
Every module should have a module level docstring that describes the contents and purpose of the module. The content of the module docstring will appear in two places in the docs. The first place is on a page that gives a listing and summary of the classes and functions in the module. (Example) The second place is on the page for the package that the module belongs to. (Example) In this case the first sentence of the module's docstring is used as summary text, so care should be taken that the first sentence makes sense and gives enough information about the module to let the reader know if that is what he or she is looking for, but without being too verbose.
Depending on the content of the module, it may make some sense to do things like bits of sample code that demonstrates how to use the classes and functions in the module.
Sometimes there are things in a module that should not be documented. For example, there may be a helper function intended to be used by the other things in the module, but not by code external to the module. There are 2 ways to cause something in a module to be skipped by epydoc, both of these methods follow the example of how Python importing works:
If the module has a global variable named __all__ that is a list of names then only those named items will be documented by epydoc.
- Similarly, any item within the module whose name starts with an underscore will not be included in the epydoc generated documentation.
Classes
Epydoc generates class documentation in a similar pattern to how it does for modules. There is a page devoted to the class, and which contains the full docstring for the class, along with a summary of the contents (the methods) of the class. Also, the first sentence of the class' docstring is used for the contents summary listing in the module's page so, again, care should be taken that the first sentence is descriptive of the purpose of the class.
Class docs can be anywhere from a couple paragraphs, to several pages in length, depending on the class and the needs for explaining things to the reader. For UI classes this is a good place to document the styles accepted by the constructor, or the events generated by the widget. In this example a table is used to display these.
Functions and methods
Every function or method intended for use outside of the module or class should have a docstring. Once again, the first sentence of the docstring for functions and methods will be used in a summary listing. Beyond that the level of detail needed is dependent on the function being documented. In many cases just the first sentence will be enough. In other cases much more detail would be useful. (Example) The function's parameters can be documented (see below for the markup used to do this) but if the purpose of the parameters are real obvious I don't mind leaving them undocumented. For example, a function that sets the position of something doesn't need to have the x and y parameters described in excruciating detail.
Any class methods that are not meant to be used outside of the class do not need to have their docstrings (if any) appear in the reference docs. The easiest way to do this it to name the methods with a leading underscore character. This will signal epydoc to not generate documentation for it, and is also an accepted convention for programmers to know that the method is not part of the public API of the class.
Markup Examples
Please see the ReStructuredText Specification for more details, but following are some examples of the basic markup as used in the wxPython documentation.
Paragraphs
Like many plain-text based markup languages, (including that used by this wiki) paragraphs consist of one or more lines indented at the same level, and separated by blank lines.
Basic Markup
Various forms of punctuation are used for inline markup of the text.
Emphasis:
Surround text by *asterisk*
Strong emphasis:
Surround text by **double asterisk**
Inline literal:
Use text surrounded by ``double backticks``
Interdocument link:
To make a link to other classes, functions, etc. you can surround the name with `single backticks` and epydoc will make the link for you if it can find an object with that name.
Bullet Lists:
Use a series of indented paragraphs starting with an asterisk. Here is a list of items: * item one * item two * item three
Numbered lists:
Here is a list of items: 1 item one 2 item two 3 item three
Literal blocks:
Literal blocks are good for giving examples of code or similar situations when you want to have a block of monospaced text. You do it by indenting a block of text, and ending the preceding paragraph with a double colon. Like this:: The text in this block will be rendered in a monospaced font.
Tables:
There are two syntaxes for tables: Grid tables; complete, but complex and verbose: +------------------------+------------+----------+ | Header row, column 1 | Header 2 | Header 3 | +========================+============+==========+ | body row 1, column 1 | column 2 | column 3 | +------------------------+------------+----------+ | body row 2 | Cells may span | +------------------------+-----------------------+ Simple tables; easy and compact, but limited: ==================== ========== ========== Header row, column 1 Header 2 Header 3 ==================== ========== ========== body row 1, column 1 column 2 column 3 body row 2 Cells may span columns ==================== ======================
Fields
Various "field" tags are used to control other forms of epydoc output. For example, for specifying parameters and return types, making "see also" links, notes or warning messages, etc. When using the structured text format fields are specified by putting a colon in front of and after the field.
:param p: text
The text describes the parameter p.
:type p: text
Specify the type of parameter p.
:return: text
Describe the return value of a function
:rtype: text
Specify the type of the return value
:see: text
Puts text after a "See also" header
:todo: text
Puts text after a "Todo" tag
For more supported fields and their explanations, see the epydoc page.
Samples
def Bind(self, event, handler, source=None, id=wx.ID_ANY, id2=wx.ID_ANY): """ Bind an event to an event handler. :param event: One of the EVT_* objects that specifies the type of event to bind, :param handler: A callable object to be invoked when the event is delivered to self. Pass None to disconnect an event handler. :param source: Sometimes the event originates from a different window than self, but you still want to catch it in self. (For example, a button event delivered to a frame.) By passing the source of the event, the event handling system is able to differentiate between the same event type from different controls. :param id: Used to spcify the event source by ID instead of instance. :param id2: Used when it is desirable to bind a handler to a range of IDs, such as with EVT_MENU_RANGE. """
class MultiSplitterWindow(wx.PyPanel): """ This class is very similar to `wx.SplitterWindow` except that it allows for more than two windows and more than one sash. Many of the same styles, constants, and methods behave the same as in wx.SplitterWindow. The key differences are seen in the methods that deal with the child windows managed by the splitter, and also those that deal with the sash positions. In most cases you will need to pass an index value to tell the class which window or sash you are refering to. The concept of the sash position is also different than in wx.SplitterWindow. Since the wx.Splitterwindow has only one sash you can think of it's position as either relative to the whole splitter window, or as relative to the first window pane managed by the splitter. Once there is more than one sash then the distinciton between the two concepts needs to be clairified. I've chosen to use the second definition, and sash positions are the distance (either horizontally or vertically) from the origin of the window just before the sash in the splitter stack. NOTE: These things are not yet supported: * Using negative sash positions to indicate a position offset from the end. * User controlled unsplitting (with double clicks on the sash or dragging a sash until the pane size is zero.) * Sash gravity """
class PySimpleApp(wx.App): """ A simple application class. You can just create one of these and then then make your top level windows later, and not have to worry about OnInit. For example:: app = wx.PySimpleApp() frame = wx.Frame(None, title='Hello World') frame.Show() app.MainLoop() :see: `wx.App` """
Giving docstrings to SWIG generated code