mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #9171 from tk0miya/4257_autodoc_class_signature
Close #4257: autodoc: Add autodoc_class_signature
This commit is contained in:
commit
99f4672575
2
CHANGES
2
CHANGES
@ -28,6 +28,8 @@ Features added
|
||||
* #9195: autodoc: The arguments of ``typing.Literal`` are wrongly rendered
|
||||
* #9185: autodoc: :confval:`autodoc_typehints` allows ``'both'`` setting to
|
||||
allow typehints to be included both in the signature and description
|
||||
* #4257: autodoc: Add :confval:`autodoc_class_signature` to separate the class
|
||||
entry and the definition of ``__init__()`` method
|
||||
* #3257: autosummary: Support instance attributes for classes
|
||||
* #9129: html search: Show search summaries when html_copy_source = False
|
||||
* #9120: html theme: Eliminate prompt characters of code-block from copyable
|
||||
|
@ -463,6 +463,20 @@ There are also config values that you can set:
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
.. confval:: autodoc_class_signature
|
||||
|
||||
This value selects how the signautre will be displayed for the class defined
|
||||
by :rst:dir:`autoclass` directive. The possible values are:
|
||||
|
||||
``"mixed"``
|
||||
Display the signature with the class name.
|
||||
``"separated"``
|
||||
Display the signature as a method.
|
||||
|
||||
The default is ``"mixed"``.
|
||||
|
||||
.. versionadded:: 4.1
|
||||
|
||||
.. confval:: autodoc_member_order
|
||||
|
||||
This value selects if automatically documented members are sorted
|
||||
|
@ -70,6 +70,9 @@ class _All:
|
||||
def __contains__(self, item: Any) -> bool:
|
||||
return True
|
||||
|
||||
def append(self, item: Any) -> None:
|
||||
pass # nothing
|
||||
|
||||
|
||||
class _Empty:
|
||||
"""A special value for :exclude-members: that never matches to any member."""
|
||||
@ -1440,6 +1443,15 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
|
||||
def __init__(self, *args: Any) -> None:
|
||||
super().__init__(*args)
|
||||
|
||||
if self.config.autodoc_class_signature == 'separated':
|
||||
# show __init__() method
|
||||
if self.options.special_members is None:
|
||||
self.options['special-members'] = {'__new__', '__init__'}
|
||||
else:
|
||||
self.options.special_members.append('__new__')
|
||||
self.options.special_members.append('__init__')
|
||||
|
||||
merge_members_option(self.options)
|
||||
|
||||
@classmethod
|
||||
@ -1556,6 +1568,9 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
def format_signature(self, **kwargs: Any) -> str:
|
||||
if self.doc_as_attr:
|
||||
return ''
|
||||
if self.config.autodoc_class_signature == 'separated':
|
||||
# do not show signatures
|
||||
return ''
|
||||
|
||||
sig = super().format_signature()
|
||||
sigs = []
|
||||
@ -2193,6 +2208,38 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_doc(self, ignore: int = None) -> Optional[List[List[str]]]:
|
||||
if self.objpath[-1] == '__init__':
|
||||
docstring = getdoc(self.object, self.get_attr,
|
||||
self.config.autodoc_inherit_docstrings,
|
||||
self.parent, self.object_name)
|
||||
if (docstring is not None and
|
||||
(docstring == object.__init__.__doc__ or # for pypy
|
||||
docstring.strip() == object.__init__.__doc__)): # for !pypy
|
||||
docstring = None
|
||||
if docstring:
|
||||
tab_width = self.directive.state.document.settings.tab_width
|
||||
return [prepare_docstring(docstring, tabsize=tab_width)]
|
||||
else:
|
||||
return []
|
||||
elif self.objpath[-1] == '__new__':
|
||||
__new__ = self.get_attr(self.object, '__new__', None)
|
||||
if __new__:
|
||||
docstring = getdoc(__new__, self.get_attr,
|
||||
self.config.autodoc_inherit_docstrings,
|
||||
self.parent, self.object_name)
|
||||
if (docstring is not None and
|
||||
(docstring == object.__new__.__doc__ or # for pypy
|
||||
docstring.strip() == object.__new__.__doc__)): # for !pypy
|
||||
docstring = None
|
||||
if docstring:
|
||||
tab_width = self.directive.state.document.settings.tab_width
|
||||
return [prepare_docstring(docstring, tabsize=tab_width)]
|
||||
else:
|
||||
return []
|
||||
else:
|
||||
return super().get_doc()
|
||||
|
||||
|
||||
class NonDataDescriptorMixin(DataDocumenterMixinBase):
|
||||
"""
|
||||
@ -2662,6 +2709,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.add_config_value('autoclass_content', 'class', True, ENUM('both', 'class', 'init'))
|
||||
app.add_config_value('autodoc_member_order', 'alphabetical', True,
|
||||
ENUM('alphabetic', 'alphabetical', 'bysource', 'groupwise'))
|
||||
app.add_config_value('autodoc_class_signature', 'mixed', True, ENUM('mixed', 'separated'))
|
||||
app.add_config_value('autodoc_default_options', {}, True)
|
||||
app.add_config_value('autodoc_docstring_signature', True, True)
|
||||
app.add_config_value('autodoc_mock_imports', [], True)
|
||||
|
@ -174,6 +174,7 @@ class FakeDirective(DocumenterBridge):
|
||||
document = Struct(settings=settings)
|
||||
env = BuildEnvironment()
|
||||
env.config = Config()
|
||||
env.config.add('autodoc_class_signature', 'mixed', True, None)
|
||||
state = Struct(document=document)
|
||||
super().__init__(env, None, Options(), 0, state)
|
||||
|
||||
|
@ -140,6 +140,57 @@ def test_autoclass_content_init(app):
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autodoc_class_signature_mixed(app):
|
||||
app.config.autodoc_class_signature = 'mixed'
|
||||
options = {"members": None,
|
||||
"undoc-members": None}
|
||||
actual = do_autodoc(app, 'class', 'target.classes.Bar', options)
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:class:: Bar(x, y)',
|
||||
' :module: target.classes',
|
||||
'',
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autodoc_class_signature_separated_init(app):
|
||||
app.config.autodoc_class_signature = 'separated'
|
||||
options = {"members": None,
|
||||
"undoc-members": None}
|
||||
actual = do_autodoc(app, 'class', 'target.classes.Bar', options)
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:class:: Bar',
|
||||
' :module: target.classes',
|
||||
'',
|
||||
'',
|
||||
' .. py:method:: Bar.__init__(x, y)',
|
||||
' :module: target.classes',
|
||||
'',
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autodoc_class_signature_separated_new(app):
|
||||
app.config.autodoc_class_signature = 'separated'
|
||||
options = {"members": None,
|
||||
"undoc-members": None}
|
||||
actual = do_autodoc(app, 'class', 'target.classes.Baz', options)
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:class:: Baz',
|
||||
' :module: target.classes',
|
||||
'',
|
||||
'',
|
||||
' .. py:method:: Baz.__new__(cls, x, y)',
|
||||
' :module: target.classes',
|
||||
' :staticmethod:',
|
||||
'',
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autoclass_content_both(app):
|
||||
app.config.autoclass_content = 'both'
|
||||
|
Loading…
Reference in New Issue
Block a user