Sphinx 没有记录复杂的枚举 类

Sphinx not documenting complex Enum classes

在我的代码中,我有一些 class 是复杂的枚举类型。例如:

class ComplexEnum(SomeOtherClass, Enum):
    """ Some documentation """

    MEMBER1 = SomeOtherClass(1)
    MEMBER2 = SomeOtherClass(2)

    def __init__(self, arg):
        """ more doc """
        pass

    def somemethod(self):
        """ more doc """
        pass

    @classmethod
    def someclassmethod(cls, otherparam):
        """ more doc """
        pass

当我现在使用 autodoc 使用 Sphinx 创建我的文档时,这个 class 被跳过了。我尝试将这样的自定义文档添加到我的 conf.py 文件中:

from sphinx.ext.autodoc import ClassDocumenter

class MyClassDocumenter(ClassDocumenter):
    objtype = 'ComplexEnum'
    directivetype = 'class'

    @classmethod
    def can_document_member(cls, member, membername, isattr, parent):
        return isinstance(member, ComplexEnum)

def setup(app):
    app.add_autodocumenter(MyClassDocumenter)

但这也不行。

我怎样才能使 sphinx 记录那些 classes?

这是 Sphinx autodoc 中的一个错误,在使用 Enum 时出现。

可以通过编写 .rst 文件的谨慎变通方法来解决。

话虽如此,我认为这是针对:

对应.rst:

my_module module
================

.. automodule:: my_module
   :exclude-members: ComplexEnum


   .. autoclass:: ComplexEnum
      :members: some_method
      :show-inheritance:
      :exclude-members: MEMBER1, MEMBER2, __init__, some_classmethod

      .. automethod:: some_classmethod  

      .. autoattribute:: MEMBER1
         :annotation: = SomeOtherClass(1)

      .. autoattribute:: MEMBER2
         :annotation: = SomeOtherClass(2)

      .. automethod:: __init__

   .. autoclass:: SomeOtherClass
      :special-members: __init__

我稍微修改了代码以更好地解释解决方法的一些细节:

from enum import Enum


class SomeOtherClass:
    """ SomeOtherClass documentation """

    def __init__(self, other_arg):
        """Example of docstring on the __init__ method.

        Args:
            other_arg (int): Description of `other_arg`.
        """
        self.other_arg = other_arg


class ComplexEnum(SomeOtherClass, Enum):
    """ComplexEnum documentation."""

    #: :py:mod:`~my_package.my_module.SomeOtherClass`: MEMBER1 docstring comment.
    MEMBER1 = SomeOtherClass(1)
    #: :py:mod:`~my_package.my_module.SomeOtherClass`: MEMBER2 docstring comment.
    MEMBER2 = SomeOtherClass(2)

    def __init__(self, complex_arg):
        """Example of docstring on the __init__ method.

        Args:
            complex_arg (int): Description of `complex_arg`.
        """
        self.complex_arg = complex_arg
        super().__init__(complex_arg)

    def some_method(self):
        """The doc of some_method."""
        pass

    @classmethod
    def some_classmethod(cls, some_arg):
        """The doc of some_classmethod.

        Args:
            some_arg (int): Description of `some_arg`.
        """
        pass

你的conf.py可以留标准,我只加了extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']启用google风格的评论。



到目前为止,在 link @mzjn 贡献的 link 和您的 post 中,确定了触发错误 的具体 条件组合,即:

  1. 使用@class方法+ IntEnum.
  2. 使用@class方法+多重继承,父类之一为Enum

需要注意的是:使用带有@class方法的简单枚举不会触发错误。 (在这种情况下,.. autoclass:: 的行为与预期一致,几乎可以处理所有事情。)



该错误会影响多个 autodoc 指令及其选项,导致它们出现意外行为。

编写 .rst 的必要解决方法如下:

  1. 不要在 Enum 中使用 :undoc-members:,否则会发生 caos。如果你这样做,@class 方法始终被包含而不获取描述符或文档字符串,并且用 :exclude-members: 排除它不会有任何效果。

  2. 接下来__init__是最有问题的方面。有效的方法是用 :exclude-members: 排除它,并明确使用 .. automethod:: __init__

  3. 连同上面的:你不能把@class方法放在__init__旁边,在.rst中使用:automethod:,否则整个@class方法得到"absorved"作为__init__文档字符串的一部分。

  4. 对我来说,最有效的是 including/excluding Enum 的所有部分明确地使用 :members::exclude-members:。这保证了 autodoc directives/options.

  5. 行为的最佳一致性


两个 最后的笔记 与使用 Sphinx 记录 Enum 的 有关(与错误没有直接关系)。

  1. 在记录 Enum 成员时,为了获得最佳一致性,请使用 #: 语法而不是三引号 ''' 或内联 #。原因是,因为后者经常"mixed-up"甚至被Sphinx丢掉。

    • 即使将 ..member-order: by source 作为指令选项或在配置中使用,通常也是如此。
  2. 最后,如果您希望 Enum 成员的值显示在文档中,就像它们出现在 class 声明语法中一样。根据我的经验,最好的方法是使用 :annotation:,如 .rst 所示。否则,枚举成员将在文档中显示如下:

使用 Python 3.8 和 Sphinx v2.2.2。