问题
In my code I have some classes that are complex Enum types. For example:
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
When I now create my documentation with Sphinx using autodoc this class is just skipped. I tried adding a custom documenter like this to my conf.py file:
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)
But this does not work either.
How can I make sphinx document those kind of classes?
回答1:
This is a bug in Sphinx autodoc
occurring with some uses of Enum.
It can be solved by careful workarounds writing the .rst
files.
Having said that, I assume this is aimed for:
The corresponding .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__
I slightly altered the code to better explain some details of the workarounds:
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
Your conf.py
can be left standard, I only added extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']
to enable google style comments.
The specific combination of conditions triggering the bug are identified, so far, in the link @mzjn contributed, and by your post, namely:
- Using @classmethod + IntEnum.
- Using @classmethod + multiple inheritance, one of the parents being Enum.
It should be noted: using a simple Enum with @classmethod does not trigger the bug. (In that case .. autoclass::
behaves as expected and takes care of almost everything.)
The bug affects several autodoc
directives and their options, causing them to have unexpected behavior.
The necessary workarounds in writing the .rst are as follows:
DO NOT use
:undoc-members:
in the Enum, or else caos breaks out. If you do, the @classmethod with always be included without picking up the descriptor or the docstring, and excluding it with:exclude-members:
will have no effect.Next
__init__
is the most problematic aspect. What worked was excluding it with:exclude-members:
, together with explicitly using.. automethod:: __init__
.Together with the above: you CAN NOT put the @classmethod next to
__init__
using:automethod:
in the.rst
, or else the entire @classmethod gets "absorved" as part of the__init__
docstring.What worked best, for me, is including/excluding all parts of the Enum explicitly with
:members:
and:exclude-members:
. That guarantees the best consistency to the behavior of theautodoc
directives/options.
Two last notes are pertinent to documenting Enum's using Sphinx (not directly related to the bug).
When documenting Enum members, for best consistency use
#:
syntax instead of triple-quotes'''
or inline#
. The reason is, because the later are frequently "mixed-up" or even lost by Sphinx.- The above is usually so even if using
..member-order: by source
as a directive option or in the configurations.
- The above is usually so even if using
Finally, in case you want the values of the Enum members to show in the documentation, as they appear in the class declaration syntax. The best way, in my experience, is using an
:annotation:
as shown in the.rst
. Or else, the Enum members will show in documentation like this:
Using Python 3.8 with Sphinx v2.2.2.
来源:https://stackoverflow.com/questions/59611074/sphinx-not-documenting-complex-enum-classes