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

发布于 2024-08-29 16:53:45 字数 330 浏览 17 评论 0原文

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

.. 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

長街聽風 2024-09-05 16:53:45

从 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 %}

From Sphinx version 3.1 (June 2020), sphinx.ext.autosummary (finally!) has automatic 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 %}
水染的天色ゝ 2024-09-05 16:53:45

您可以查看我制作的这个脚本。我认为它可以帮助您。

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

更新

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

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.

人生百味 2024-09-05 16:53:45

我不知道Sphinx是否有自动摘要 在提出原始问题时扩展,但现在很可能在不使用 sphinx-apidoc 或类似脚本的情况下设置此类自动生成。下面是适用于我的项目之一的设置。

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

    扩展 = ['sphinx.ext.autodoc', 'sphinx.ext.autosummary']
    自动摘要_生成 = True
    模板路径 = [ '_templates' ]
    排除模式 = ['_build', '_templates']
    
  2. index.rst 文件的 TOC 树中使用 autosummary::。在此示例中,模块 project.module1project.module2 的文档将自动生成并放置在 _autosummary 目录中。

    项目
    =======
    
    .. 目录树::
    
    ..自动摘要::
       :toctree: _自动摘要
    
       项目.module1
       项目.module2
    
  3. 默认情况下,autosummary 只会为模块及其函数生成非常简短的摘要。要更改此设置,您可以将自定义模板文件放入 _templates/autosummary/module.rst (将使用 Jinja2):

    {{ fullname }}
    {{下划线}}
    
    .. automodule:: {{ 全名 }}
        :成员:
    

总之,没有必要将 _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).

可遇━不可求 2024-09-05 16:53:45

Sphinx AutoAPI 正是这样做的。

Sphinx AutoAPI does exactly this.

心碎的声音 2024-09-05 16:53:45

在每个包中,__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.

北座城市 2024-09-05 16:53:45

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

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

吝吻 2024-09-05 16:53:45

我找到的解决方案如下:将所有模块添加到您的 __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"]

A solution I found was the following: add all the modules to your __init__.py file. When Sphinx autodoc processes your module, it looks for the all attribute to determine which names should be included in the generated documentation.

Project Tree

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

Inside project/src/ the __init__.py looks like this:

from project/subpackage import foo

__all__ = ["foo"]

Inside project the __init__.py looks like this:

from project/subpackage import bar

__all__ = ["bar"]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文