使用 Sphinx autodoc 自动递归记录所有模块

问题描述 投票:0回答:7

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

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

这太乏味了,因为我有很多文件。如果我可以指定我想要记录“mods”包,那就容易多了。然后,Sphinx 可以递归地遍历包并为每个子模块创建一个页面。

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

python python-sphinx autodoc
7个回答
168
投票

从 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.rst
    mytoolbox/doc/source/_templates/custom-module-template.rst
  • 复制
    site-packages/sphinx/ext/autosummary/templates/autosummary/class.rst
    mytoolbox/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 %}

163
投票

你可以查看我制作的这个脚本。我想它可以帮助你。

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

更新

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


62
投票

我不知道Sphinx在提出原始问题时是否有

autosummary
扩展,但现在很有可能在不使用
sphinx-apidoc
或类似脚本的情况下设置这种类型的自动生成。下面是适用于我的项目之一的设置。

  1. autosummary
    文件中启用
    autodoc
    扩展(以及
    conf.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.module1
    project.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
下面是行不通的)。


29
投票

Sphinx AutoAPI 正是这样做的。


13
投票

在每个包中,

__init__.py
文件可以包含包的每个部分的
..  automodule:: package.module
组件。

然后你就可以

..  automodule:: package
,它基本上可以满足你的需求。


1
投票

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


0
投票

我找到的解决方案如下:将所有模块添加到您的

__init__.py
文件中。当 Sphinx autodoc 处理您的模块时,它会查找 all 属性来确定生成的文档中应包含哪些名称。

项目树

project
├── src
|   ├── __init__.py
|   ├── bar.py
├── __init__.py
├── foo.py

在project/src/内

__init__.py
看起来像这样:

from project/subpackage import foo

__all__ = ["foo"]

在项目内部

__init__.py
看起来像这样:

from project/subpackage import bar

__all__ = ["bar"]
© www.soinside.com 2019 - 2024. All rights reserved.