摘要自动生成的文档缺少所有双下划线方法,除了`__init__`。

3

我正在使用Sphinx自动摘要功能,为我的模块中的每个成员自动生成单独的rst文件。文档已按预期创建,但是生成的rst文件缺少所有dunder方法,除了__init__之外。

在我的conf.py中,我有以下代码:

extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.autosummary',
]

autosummary_generate = True
autosummary_imported_members = True

考虑下面的虚拟类,该类包含下划线方法和常规公共方法:
class MyClassA:

    def __init__(self):
        r'__init__ docstring'
        pass

    def __call__(self):
        r'__call__ docstring'
        pass

    def __len__(self):
        r'__len__ docstring'
        pass

    def public_method_1(self):
        r'public_method_1 docstring'
        pass

    def public_method_2(self):
        r'public_method_2 docstring'
        pass


在我的主要rst文件中,我按照以下方式设置了自动摘要:
.. autosummary::
    :toctree: my_module_members

    my_module.MyClassA
    my_module.MyClassB

如预料的那样,autosummary会创建一个名为/my_module_members的子目录,在其中为模块的每个成员创建单独的rst文件。但是,在这些自动生成的rst文件的方法部分中,只有__init__被列出。例如:

my_module.MyClassA
==================

.. currentmodule:: my_module

.. autoclass:: MyClassA




   .. rubric:: Methods

   .. autosummary::

      ~MyClassA.__init__
      ~MyClassA.public_method_1
      ~MyClassA.public_method_2

因此,在生成的HTML文档中,方法表中只列出了这三种方法,而没有列出“__call__”和“__len__”:

enter image description here

所以我的问题是:如何在使用autosummary时包含所有特殊方法?

2个回答

6
问题出在autosummary默认模板上,这是文档中相关页面,但直接查看默认模板更有帮助:
# In the sphinx v3.0.4 source code:
# sphinx/ext/autosummary/templates/autosummary/class.rst
{{ fullname | escape | underline}}

.. currentmodule:: {{ module }}

.. autoclass:: {{ objname }}

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

你可以看到这个模板与为你的项目生成的桩文件相对应(虽然我不确定为什么你的缺少..automethod:: __init__行; 可能我们使用不同版本的sphinx)。重要部分是{% for item in methods %}循环。上面链接的文档简要提到methods只包括“public”方法,这意味着不以下划线开头的方法。__init__()也被视为公共方法,根据sphinx / ext / autosummary / generate.py第242行,尽管这似乎没有记录在任何地方。因此,希望这解释了你所看到的行为。
考虑到这一点,我可以想到三种方法来包含所有特殊方法的文档:
  1. Provide a custom template that uses members instead of methods. This should document everything, but will eliminate the distinction between methods, attributes, inherited members, inner classes, etc.

  2. This isn't documented and I haven't tried it, it looks like you might be able to replace methods with all_methods to include all methods in the autosummary (see line 242 again). There won't be any distinction between public and private methods, though.

  3. Try using autoclasstoc. Full disclosure: this is a package I wrote to do a better job of summarizing class methods in sphinx docs. It's much more configurable than autosummary, and it includes every method by default. It also collapses inherited methods, which can be really nice for big classes, although that may or may not be relevant to you.

    This page describes how to use autoclasstoc in conjunction with autosummary, but the gist of it is that you need a custom template that looks something like this:

    {{ fullname | escape | underline}}
    
    .. currentmodule:: {{ module }}
    
    .. autoclass:: {{ objname }}
       :members:
       :special-members:
    
        .. autoclasstoc::
    

非常感谢您提供详细的答案!首先,我正在使用自定义模板,这就是为什么缺少 .. automethod:: __init__ 的原因,我主要在类文档字符串中编写大部分文档,因此我更喜欢省略它。关于您的建议,在我的模板中使用 {% for item in all_methods %} 就可以解决问题,但现在它列出了所有的 dunder 方法,包括继承的方法(甚至是从 object 继承的方法),所以列表很长。实际上,我更希望在 autosummary 表格中只列出一些最重要的 dunder 方法,例如 __call____len__ - gilbertohasnofb
我也会看一下你的autoclasstoc,谢谢你的建议! - gilbertohasnofb

3

我最终通过使用自定义类模板解决了这个问题,该模板查找all_methods,然后过滤掉所有私有方法以及不在要包含的dunder方法列表中的方法。

{{ fullname | escape | underline}}

.. currentmodule:: {{ module }}

.. autoclass:: {{ objname }}

   {% block methods %}

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

   .. autosummary::
   {% for item in all_methods %}
      {%- if not item.startswith('_') or item in ['__init__',
                                                  '__repr__',
                                                  '__len__',
                                                  '__call__',
                                                  '__next__',
                                                  '__iter__',
                                                  '__getitem__',
                                                  '__setitem__',
                                                  '__delitem__',
                                                  ] %}
      ~{{ name }}.{{ item }}
      {%- endif -%}
   {%- endfor %}
   {% endif %}
   {% endblock %}

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接