========================================================
Generating GPlates Python API documentation using Sphinx
========================================================

This documentation gives an overview of generating the GPlates Python API documentation using Sphinx to generate HTML
from the Python docstrings (classes, class methods, functions, etc) in the 'pygplates' Python module.


Installing Sphinx
=================

Instructions for installing Sphinx can be found at:
http://sphinx-doc.org/latest/install.html

Note: For Debian/Ubuntu you can run 'sudo apt-get install sphinx'.
      For Macports (on macOS systems) you can run 'sudo port install sphinx'.
      For Windows you can run 'python -m pip install sphinx'.

Then install the Read the Doc Sphinx Theme (currently used as the HTML theme for GPlates Python API docs).
For example:
    python -m pip install sphinx_rtd_theme


Building the HTML documentation
===============================

To build the HTML documentation, build the 'doc-python-api' target.

For example, on Linux:
  make doc-python-api

On Windows, build the 'doc-python-api' project in Visual Studio.

'doc-python-api' is a CMake-generated target that uses the installed 'sphinx-build' executable to create HTML from the built 'pygplates' module.


Viewing the HTML documentation
==============================

The built documentation should be in the following HTML file, relative to the cmake *build* directory corresponding to your GPlates source directory
(if you are doing in-place cmake builds then the root GPlates source directory is the same as the build directory):

  doc-python-api/html/index.html


Issues
======

This section covers various issues encountered while using Sphinx to document pygplates.

First some background:
Using the 'autosummary' directive (eg, in 'pygplates_reference.rst' file) combined with its ':toctree:' option
will cause Sphinx to generate a stub '.rst' file for each class/function listed under an 'autosummary' directive
(provided the 'autosummary_generate' is set to 'True' in the 'conf.py.in' file).
By default autosummary will list the methods in a class' '.rst' file but it won't generate documentation
for the methods. Previously we used 'automodule' (instead of 'autosummary' to generate the documentation)
and it required the ':members:' option to the class members. But when 'autosummary' generates stub
files (using the ':toctree:' option) it generates an 'autoclass' directive in each stub file but doesn't
add the ':members:' option. So we need to set ':members:' as on by default using the 'autodoc_default_options'
flag (in 'conf.py.in'). We also need to turn ':inherited-members:' on by default since each stub class
autosummary listing seems to include inherited members and if we don't generate documentation for them
then those listing entries will have no hyperlinks (like the non-inherited members). Update: We now turn
off inherited members (the missing hyperlinks essentially document that the method is inherited and user
should look up the base class documentation instead).


Use Sphinx >= 1.8
-----------------

As of Sphinx 1.8, the 'autodoc_default_flags' flag in 'conf.py' has been deprecated.
The new flag is 'autodoc_default_options'. Unfortunately there is no warning using the old flag
and it is simply ignored (leading to class members not getting documented). We now use the new flag,
which means you should use Sphinx >= 1.8.


Use autosummary (with :toctree:) instead of automodule
------------------------------------------------------

As noted above we previously used 'automodule' (instead of 'autosummary').
This listed all functions/class/methods on a single HTML page (our reference page).
Using 'autosummary' (with its ':toctree:' option) generates a stub '.rst' file for each function/class.
This means each function and class has its own HTML page which makes for easier browser loading, etc.
Another advantage is 'autosummary' generates a short list of the methods of a class (in addition
to the usual detailed method documentation). This is something 'automodule' does not do as far as I'm aware.


Specify default autodoc flags
-----------------------------

We're currently using autosummary with ':toctree:' to generate a stub ".rst" file for each class/function.
But to get decent looking documentation we still need to change the 'autodoc_default_options' flag to include
'members', otherwise they will be missing from the default documentation generated by autosummary (and ":toctree:").

So the 'autodoc_default_options' should look something like:
autodoc_default_options = { 'members' : True, 'inherited-members' : False, 'show-inheritance' : True }


Adding, removing or renaming functions or class methods
-------------------------------------------------------

Whenever you add/remove/rename any functions/class-methods be sure to delete the 'doc-python-api/generated/'
directory in the GPlates (pygplates) build directory (same as source directory if using in-place builds).

This is because Sphinx does not appear to update the 'autosummary' generated (via ':toctree:')
stub '.rst' files.


Provide docstrings (with function signature( for all regular methods and "__init__()" of documented classes
-----------------------------------------------------------------------------------------------------------

Now that we're using autosummary (instead of automodule) we will get warnings such as the following...

  WARNING: error while formatting arguments for pygplates.Earth.__init__: <Boost.Python.function object at 0x04E7AA28> is not a Python function

...if we don't provide a docstring (in the above example for "pygplates.Earth.__init__()")
containing a function signature. In the above example this can be fixed by specifying the first line of the docstring as:

__init__()

...note there are no arguments in this example since we're using the default constructor.
It has to be a function signature which means it needs the "()" containing any arguments.

'automodule' didn't have this problem - it just ignored (didn't document) functions/methods
with no docstrings.


Set autodoc_docstring_signature to True
---------------------------------------

Setting 'autodoc_docstring_signature' to 'True' just gets autodoc to extract the function signature from the
first line of the docstring in C modules (because it can't introspect C functions - only pure Python functions).
The default value is True anyway so we don't really need to set this.


Using templates with autosummary is problematic
-----------------------------------------------

UPDATE: This was for Sphinx version 1.x. For later versions it may no longer be an issue.

'autosummary' has its own template for classes and modules when it generates stub '.rst' files
(for each function/class). If you want to change it slightly (such as adding the :nosignatures:
option under the 'autosummary' method listing it puts in each stub '.rst' file) then you need
to make a template. This can be done by specifying a 'templates_path' variable in 'conf.py.in' -
it seems to default to "['_templates']" - and then putting your own 'autosummary/class.rst' file
relative to that path (or if you want to use a different filename then use the ':template:' option
under 'autosummary').

So that seems relatively straightforward.
Templates change the appearance of each class/function from the default provided by autosummary.

But there are two problems:
 1) There's a gotcha with Sphinx versions prior to 1.3, and
 2) I just can't seem to get it to work.

1) It seems prior to Sphinx version 1.3 (eg, 1.2.3) '_templates' needs to be added to the 'exclude_patterns'
   variable in 'conf.py.in' to workaround a Sphinx bug that was apparently fixed in 1.3
   The bug is mentioned here: https://groups.google.com/forum/#!topic/sphinx-dev/KGdNpizMqDE
   So I've verified that adding '_templates' to 'exclude_patterns' avoids the error message with 1.2.3
   and that it's not needed with 1.3.

2) However neither 1.2.3 nor 1.3 seem to actually use our templates.
   It seems the default autosummary templates are always used regardless.

However it seems we can get decent looking documentation without using templates by specifying the
'autodoc_default_options' flag (in 'conf.py.in') to include 'members' such that
autosummary generates them (by effectively adding ':members:' to the 'autoclass' it places in
each stub '.rst' file - although you won't actually see ':members:' in there - but generates
documentation as if it was there).

So we're not currently using autosummary *templates*.
