Sphinx autodoc不够自动化

问题:Sphinx autodoc不够自动化

我正在尝试使用Sphinx在Python中记录5,000多个项目。它有大约7个基本模块。据我所知,为了使用自动文档,我需要为项目中的每个文件编写如下代码:

.. automodule:: mods.set.tests
    :members:
    :show-inheritance:

这太繁琐了,因为我有很多文件。如果我只想指定要记录的“ mods”包,那会容易得多。然后,Sphinx可以递归地浏览包并为每个子模块创建一个页面。

有这样的功能吗?如果没有,我可以编写一个脚本来制作所有.rst文件,但这将花费很多时间。

I’m trying to use Sphinx to document a 5,000+ line project in Python. It has about 7 base modules. As far as I know, In order to use autodoc I need to write code like this for each file in my project:

.. automodule:: mods.set.tests
    :members:
    :show-inheritance:

This is way too tedious because I have many files. It would be much easier if I could just specify that I wanted the ‘mods’ package to be documented. Sphinx could then recursively go through the package and make a page for each submodule.

Is there a feature like this? If not I could write a script to make all the .rst files, but that would take up a lot of time.


回答 0

您可以检查我编写的脚本。我认为它可以帮助您。

该脚本解析目录树以查找python模块和软件包,并适当地创建ReST文件以使用Sphinx创建代码文档。它还创建一个模块索引。

更新

现在,此脚本作为apidoc是Sphinx 1.1的一部分

You can check this script that I’ve made. I think it can help you.

This script parses a directory tree looking for python modules and packages and creates ReST files appropriately to create code documentation with Sphinx. It also creates a modules index.

UPDATE

This script is now part of Sphinx 1.1 as apidoc.


回答 1

我不知道autosummary在最初提出问题时Sphinx是否具有扩展名,但是现在很可能无需使用sphinx-apidoc类似脚本就可以设置这种自动生成。下面是适用于我的一个项目的设置。

  1. 在文件中启用autosummary扩展名(以及autodocconf.py,并将其autosummary_generate选项设置为True。如果您不使用自定义*.rst模板,这可能就足够了。否则,请添加您的模板目录以排除列表,或者autosummary尝试将它们视为输入文件(这似乎是一个错误)。

    extensions = ['sphinx.ext.autodoc', 'sphinx.ext.autosummary']
    autosummary_generate = True
    templates_path = [ '_templates' ]
    exclude_patterns = ['_build', '_templates']
  2. autosummary::index.rst文件的目录树中使用。在用于模块此示例中的文档project.module1project.module2将自动生成并放入_autosummary目录。

    PROJECT
    =======
    
    .. toctree::
    
    .. autosummary::
       :toctree: _autosummary
    
       project.module1
       project.module2
  3. 默认情况下,autosummary只会为模块及其功能生成非常简短的摘要。要进行更改,可以将自定义模板文件放入_templates/autosummary/module.rst(将使用Jinja2进行解析):

    {{ fullname }}
    {{ underline }}
    
    .. automodule:: {{ fullname }}
        :members:

总之,无需将_autosummary目录保持在版本控制之下。另外,您可以_build随意命名它,并将其放在源代码树中的任何位置(不过,将其放在下面将不起作用)。

I do not know whether Sphinx had had autosummary extension at the time original question was asked, but for now it is quite possible to set up automatic generation of that kind without using sphinx-apidoc or similar script. Below there are settings which work for one of my projects.

  1. Enable autosummary extension (as well as autodoc) in conf.py file and set its autosummary_generate option to True. This may be enough if you’re not using custom *.rst templates. Otherwise add your templates directory to exclude list, or autosummary will try to treat them as input files (which seems to be a bug).

    extensions = ['sphinx.ext.autodoc', 'sphinx.ext.autosummary']
    autosummary_generate = True
    templates_path = [ '_templates' ]
    exclude_patterns = ['_build', '_templates']
    
  2. Use autosummary:: in TOC tree in your index.rst file. In this example documentation for modules project.module1 and project.module2 will be generated automatically and placed into _autosummary directory.

    PROJECT
    =======
    
    .. toctree::
    
    .. autosummary::
       :toctree: _autosummary
    
       project.module1
       project.module2
    
  3. By default autosummary will generate only very short summaries for modules and their functions. To change that you can put a custom template file into _templates/autosummary/module.rst (which will be parsed with Jinja2):

    {{ fullname }}
    {{ underline }}
    
    .. automodule:: {{ fullname }}
        :members:
    

In conclusion, there is no need to keep _autosummary directory under version control. Also, you may name it anything you want and place it anywhere in the source tree (putting it below _build will not work, though).


回答 2

在每个包中,__init__.py文件可以具有.. automodule:: package.module包中每个部分的组件。

然后,您可以.. automodule:: package并且它基本上可以完成您想要的。

In each package, the __init__.py file can have .. automodule:: package.module components for each part of the package.

Then you can .. automodule:: package and it mostly does what you want.


回答 3

从Sphinx 3.1版(2020年6月)开始,sphinx.ext.autosummary(最终!)具有递归功能。

因此,不再需要对模块名称进行硬编码,也无需依赖Sphinx AutoAPISphinx AutoPackageSummary之类的第三方库来进行自动程序包检测。

示例Python 3.7包以进行文档记录(请参阅Github 上的代码ReadTheDocs 上的结果):

mytoolbox
|-- mypackage
|   |-- __init__.py
|   |-- foo.py
|   |-- mysubpackage
|       |-- __init__.py
|       |-- bar.py
|-- doc
|   |-- source
|       |--index.rst
|       |--conf.py
|       |-- _templates
|           |-- custom-module-template.rst
|           |-- custom-class-template.rst

conf.py

import os
import sys
sys.path.insert(0, os.path.abspath('../..'))  # Source code dir relative to this file

extensions = [
    'sphinx.ext.autodoc',  # Core library for html generation from docstrings
    'sphinx.ext.autosummary',  # Create neat summary tables
]
autosummary_generate = True  # Turn on sphinx.ext.autosummary

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

index.rst(请注意新:recursive:选项):

Welcome to My Toolbox
=====================

Some words.

.. autosummary::
   :toctree: _autosummary
   :template: custom-module-template.rst
   :recursive:

   mypackage

这足以自动汇总包中的每个模块,无论它们嵌套得多么深。然后,针对每个模块,汇总该模块中的每个属性,函数,类和异常。

奇怪的是,默认sphinx.ext.autosummary模板不会继续为每个属性,函数,类和异常生成单独的文档页面,并从摘要表链接到它们。可以扩展模板来执行此操作,如下所示,但是我不明白为什么这不是默认行为-当然这是大多数人想要的。我已将其作为功能要求提出

我必须在本地复制默认模板,然后添加到其中:

  • 复制site-packages/sphinx/ext/autosummary/templates/autosummary/module.rstmytoolbox/doc/source/_templates/custom-module-template.rst
  • 复制site-packages/sphinx/ext/autosummary/templates/autosummary/class.rstmytoolbox/doc/source/_templates/custom-class-template.rst

使用该选项,钩子custom-module-template.rst位于index.rst上方:template:。(删除该行以查看使用默认站点程序包模板会发生什么。)

custom-module-template.rst (右侧另加了几行):

{{ fullname | escape | underline}}

.. automodule:: {{ fullname }}
  
   {% block attributes %}
   {% if attributes %}
   .. rubric:: Module Attributes

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in attributes %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block functions %}
   {% if functions %}
   .. rubric:: {{ _('Functions') }}

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in functions %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block classes %}
   {% if classes %}
   .. rubric:: {{ _('Classes') }}

   .. autosummary::
      :toctree:                                          <-- add this line
      :template: custom-class-template.rst               <-- add this line
   {% for item in classes %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block exceptions %}
   {% if exceptions %}
   .. rubric:: {{ _('Exceptions') }}

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in exceptions %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

{% block modules %}
{% if modules %}
.. rubric:: Modules

.. autosummary::
   :toctree:
   :template: custom-module-template.rst                 <-- add this line
   :recursive:
{% for item in modules %}
   {{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

custom-class-template.rst (右侧另加了几行):

{{ fullname | escape | underline}}

.. currentmodule:: {{ module }}

.. autoclass:: {{ objname }}
   :members:                                    <-- add at least this line
   :show-inheritance:                           <-- plus I want to show inheritance...
   :inherited-members:                          <-- ...and inherited members too

   {% block methods %}
   .. automethod:: __init__

   {% if methods %}
   .. rubric:: {{ _('Methods') }}

   .. autosummary::
   {% for item in methods %}
      ~{{ name }}.{{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block attributes %}
   {% if attributes %}
   .. rubric:: {{ _('Attributes') }}

   .. autosummary::
   {% for item in attributes %}
      ~{{ name }}.{{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

From Sphinx version 3.1 (June 2020), sphinx.ext.autosummary (finally!) has recursion.

So no need to hard code module names or rely on 3rd party libraries like Sphinx AutoAPI or Sphinx AutoPackageSummary for their automatic package detection any more.

Example Python 3.7 package to document (see code on Github and result on ReadTheDocs):

mytoolbox
|-- mypackage
|   |-- __init__.py
|   |-- foo.py
|   |-- mysubpackage
|       |-- __init__.py
|       |-- bar.py
|-- doc
|   |-- source
|       |--index.rst
|       |--conf.py
|       |-- _templates
|           |-- custom-module-template.rst
|           |-- custom-class-template.rst

conf.py:

import os
import sys
sys.path.insert(0, os.path.abspath('../..'))  # Source code dir relative to this file

extensions = [
    'sphinx.ext.autodoc',  # Core library for html generation from docstrings
    'sphinx.ext.autosummary',  # Create neat summary tables
]
autosummary_generate = True  # Turn on sphinx.ext.autosummary

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

index.rst (note new :recursive: option):

Welcome to My Toolbox
=====================

Some words.

.. autosummary::
   :toctree: _autosummary
   :template: custom-module-template.rst
   :recursive:

   mypackage

This is sufficient to automatically summarise every module in the package, however deeply nested. For each module, it then summarises every attribute, function, class and exception in that module.

Oddly, though, the default sphinx.ext.autosummary templates don’t go on to generate separate documentation pages for each attribute, function, class and exception, and link to them from the summary tables. It’s possible to extend the templates to do this, as shown below, but I can’t understand why this isn’t the default behaviour – surely that’s what most people would want..? I’ve raised it as a feature request.

I had to copy the default templates locally, and then add to them:

  • Copy site-packages/sphinx/ext/autosummary/templates/autosummary/module.rst to mytoolbox/doc/source/_templates/custom-module-template.rst
  • Copy site-packages/sphinx/ext/autosummary/templates/autosummary/class.rst to mytoolbox/doc/source/_templates/custom-class-template.rst

The hook into custom-module-template.rst is in index.rst above, using the :template: option. (Delete that line to see what happens using the default site-packages templates.)

custom-module-template.rst (additional lines noted on the right):

{{ fullname | escape | underline}}

.. automodule:: {{ fullname }}
  
   {% block attributes %}
   {% if attributes %}
   .. rubric:: Module Attributes

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in attributes %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block functions %}
   {% if functions %}
   .. rubric:: {{ _('Functions') }}

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in functions %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block classes %}
   {% if classes %}
   .. rubric:: {{ _('Classes') }}

   .. autosummary::
      :toctree:                                          <-- add this line
      :template: custom-class-template.rst               <-- add this line
   {% for item in classes %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block exceptions %}
   {% if exceptions %}
   .. rubric:: {{ _('Exceptions') }}

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in exceptions %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

{% block modules %}
{% if modules %}
.. rubric:: Modules

.. autosummary::
   :toctree:
   :template: custom-module-template.rst                 <-- add this line
   :recursive:
{% for item in modules %}
   {{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

custom-class-template.rst (additional lines noted on the right):

{{ fullname | escape | underline}}

.. currentmodule:: {{ module }}

.. autoclass:: {{ objname }}
   :members:                                    <-- add at least this line
   :show-inheritance:                           <-- plus I want to show inheritance...
   :inherited-members:                          <-- ...and inherited members too

   {% block methods %}
   .. automethod:: __init__

   {% if methods %}
   .. rubric:: {{ _('Methods') }}

   .. autosummary::
   {% for item in methods %}
      ~{{ name }}.{{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block attributes %}
   {% if attributes %}
   .. rubric:: {{ _('Attributes') }}

   .. autosummary::
   {% for item in attributes %}
      ~{{ name }}.{{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

回答 4

Sphinx AutoAPI正是这样做的。


回答 5

也许您正在寻找的是Epydoc和此Sphinx扩展

Maybe what you’re looking for is Epydoc and this Sphinx extension.