pythonpython-sphinxautodocsphinx-apidoc

Include __main__.py in sphinx-apidoc generated files


I am not able to add my __main__.py file correctly and its functions while generating RST file with sphinx-apidoc. Other files and classes are generated correctly.

I works only if I run sphinx-apidoc with -P parameter which includes private modules. But I do not want to add private methods of other modules, I need these from __main__.py only.

__main__.py looks like this:

def main():
    """
    main() description here
    """
    f1()
    f2()

if __name__ == '__main__':
    main()

I would like to have main(), f1() and f2() included in RST files generated by sphinx-apidoc.

There is a similar question Documenting python script entry (__name__ == '__main__') using sphinx but it does not answer my question.


Solution

  • I think this is an undocumented feature, or a it can also be bug in sphinx-apidoc v.3.2.1. If we look at the documentation for -P option, it reads:

    -P, --private
        Include “_private” modules.
    

    Notice this doesn't mention :private-members: from autodoc flag options.

    Two different issues are conflated, "private modules" and "private objects inside a module". The options that impact .rst file generation should be different for each according to the official documentation.

    sphinx-apidoc will generate the .rst files based of 2 main templates, module.rst_t and package.rst_t. (Using Sphinx with a venv on Windows these are found under /venv/Lib/site-packages/sphinx/templates/apidoc).

    The default behaviour (implemented by the templates) is to generate 1 .rst file per package, and within that file place 1 .. automodule:: directive per module. What the -P option does (supposedly) is to add one more directive .. automodule:: your-package.__private-module__ to the .rst file per private module.

    An alternative is using -e option with sphinx-apidoc in which case a separate .rst file is generated for each module and package. So using sphinx-apidoc -e -P will cause an extra .rst file to be generated for private modules.

    But I do not want to add private methods of other modules

    Private classes/methods/variables (objects inside a module) are impacted by the autodoc ':private-members:' option.

    sphinx-apidoc sets the default autodoc options of the generated .. automodule:: directives as defined by the SPHINX_APIDOC_OPTIONS environment variable (namely, :members:, :undoc-members: and show-inheritance). These options can't be passed as a command line argument, you have to set the environment variable before running sphinx-apidoc to change the default values. (sphinx-apidoc does not take them from conf.py, unlike autodoc.)

    Looking at the source code of apidoc.py

    # automodule options
    if 'SPHINX_APIDOC_OPTIONS' in os.environ:
        OPTIONS = os.environ['SPHINX_APIDOC_OPTIONS'].split(',')
    else:
        OPTIONS = [
            'members',
            'undoc-members',
            # 'inherited-members', # disabled because there's a bug in sphinx
            'show-inheritance',
        ]
    

    Because :private-members: is a default autodoc options that should be set using SPHINX_APIDOC_OPTIONS (as documentation states and source code shows). If you include the -P option, its only (documented) effect should be adding .. automodule:: directives for private modules, what does happen is that it also sets the autodoc option :private-members: on each directive.

    The following tree:

    your_package
     ├  one_module.py
     ├  __init__.py
     └  __main__.py
    

    With sphinx-apidoc -P will generate:

    your_package.__main__ module
    ----------------------------
    
    .. automodule:: your_package.__main__  <<-- -P option is documented as having this effect.
       :members:
       :undoc-members:
       :show-inheritance:
       :private-members:    <<-- -P option is not documented to have this effect.
    

    So how to achieve the stated aim in the question?

    If you use -e option with sphinx-apidoc generating one .rst file per module, you could use the [EXCLUDE_PATTERN …] from the signature. By running sphinx-apidoc twice, once for the __main__.py modules (together with -P option), and a second time for the remaining modules.

    If you don't want individual .rst files for you modules, but instead the normal 1 .rst file for each package containing one directive per module. Then there is no practical possibility of achieving that (without resorting to considerable hacking). Your best choice is simply copy-pasting 1 .. automodule:: directive per __main__.py into the .rst files after they are generated.