summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES1
-rw-r--r--sphinx/ext/autodoc/__init__.py24
-rw-r--r--sphinx/ext/autosummary/generate.py5
-rw-r--r--tests/py35/test_autodoc_py35.py4
-rw-r--r--tests/test_autodoc.py44
5 files changed, 49 insertions, 29 deletions
diff --git a/CHANGES b/CHANGES
index 80d657998..c0f972ffe 100644
--- a/CHANGES
+++ b/CHANGES
@@ -30,6 +30,7 @@ Bugs fixed
* #5348: download reference to remote file is not displayed
* #5282: html theme: ``pygments_style`` of theme was overrided by ``conf.py``
by default
+* #2401: autodoc: ``:members:`` causes ``:special-members:`` not to be shown
Testing
--------
diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py
index 41a6731d2..ead3a25fd 100644
--- a/sphinx/ext/autodoc/__init__.py
+++ b/sphinx/ext/autodoc/__init__.py
@@ -110,6 +110,20 @@ def bool_option(arg):
return True
+def merge_special_members_option(options):
+ # type: (Dict) -> None
+ """Merge :special-members: option to :members: option."""
+ if 'special-members' in options and options['special-members'] is not ALL:
+ if options.get('members') is ALL:
+ pass
+ elif options.get('members'):
+ for member in options['special-members']:
+ if member not in options['members']:
+ options['members'].append(member)
+ else:
+ options['members'] = options['special-members']
+
+
class AutodocReporter(object):
"""
A reporter replacement that assigns the correct source name
@@ -823,6 +837,11 @@ class ModuleDocumenter(Documenter):
'imported-members': bool_option, 'ignore-module-all': bool_option
} # type: Dict[unicode, Callable]
+ def __init__(self, *args):
+ # type: (Any) -> None
+ super(ModuleDocumenter, self).__init__(*args)
+ merge_special_members_option(self.options)
+
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, unicode, bool, Any) -> bool
@@ -1075,6 +1094,11 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
'private-members': bool_option, 'special-members': members_option,
} # type: Dict[unicode, Callable]
+ def __init__(self, *args):
+ # type: (Any) -> None
+ super(ClassDocumenter, self).__init__(*args)
+ merge_special_members_option(self.options)
+
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, unicode, bool, Any) -> bool
diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py
index c45576c3a..dbadfe8d5 100644
--- a/sphinx/ext/autosummary/generate.py
+++ b/sphinx/ext/autosummary/generate.py
@@ -43,11 +43,12 @@ from sphinx.util.rst import escape as rst_escape
if False:
# For type annotation
- from typing import Any, Callable, Dict, Tuple, List # NOQA
+ from typing import Any, Callable, Dict, List, Tuple, Type # NOQA
from jinja2 import BaseLoader # NOQA
from sphinx import addnodes # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
+ from sphinx.ext.autodoc import Documenter # NOQA
class DummyApplication(object):
@@ -69,7 +70,7 @@ def setup_documenters(app):
ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,
FunctionDocumenter, MethodDocumenter, AttributeDocumenter,
InstanceAttributeDocumenter
- ]
+ ] # type: List[Type[Documenter]]
for documenter in documenters:
app.registry.add_documenter(documenter.objtype, documenter)
diff --git a/tests/py35/test_autodoc_py35.py b/tests/py35/test_autodoc_py35.py
index 51a9ef1ff..23b3eb83e 100644
--- a/tests/py35/test_autodoc_py35.py
+++ b/tests/py35/test_autodoc_py35.py
@@ -18,7 +18,7 @@ import six
from docutils.statemachine import ViewList
from six import StringIO
-from sphinx.ext.autodoc import add_documenter, FunctionDocumenter, ALL # NOQA
+from sphinx.ext.autodoc import add_documenter, FunctionDocumenter, ALL, Options # NOQA
from sphinx.testing.util import SphinxTestApp, Struct
from sphinx.util import logging
@@ -49,7 +49,7 @@ def setup_test():
global options, directive
global processed_docstrings, processed_signatures
- options = Struct(
+ options = Options(
inherited_members = False,
undoc_members = False,
private_members = False,
diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py
index c9a342f94..cefceb833 100644
--- a/tests/test_autodoc.py
+++ b/tests/test_autodoc.py
@@ -21,7 +21,7 @@ from six import PY3
from sphinx.ext.autodoc import (
AutoDirective, ModuleLevelDocumenter, cut_lines, between, ALL,
- merge_autodoc_default_flags
+ merge_autodoc_default_flags, Options
)
from sphinx.ext.autodoc.directive import DocumenterBridge, process_documenter_options
from sphinx.testing.util import SphinxTestApp, Struct # NOQA
@@ -79,7 +79,7 @@ def setup_test():
global options, directive
global processed_docstrings, processed_signatures
- options = Struct(
+ options = Options(
inherited_members = False,
undoc_members = False,
private_members = False,
@@ -757,44 +757,40 @@ def test_autodoc_imported_members(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_special_members(app):
- # all special methods
- options = {"members": None,
+ # specific special methods
+ options = {"undoc-members": None,
+ "special-members": "__init__,__special1__"}
+ actual = do_autodoc(app, 'class', 'target.Class', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:class:: Class(arg)',
+ ' .. py:method:: Class.__init__(arg)',
+ ' .. py:method:: Class.__special1__()',
+ ]
+
+ # combination with specific members
+ options = {"members": "attr,docattr",
"undoc-members": None,
- "special-members": None}
+ "special-members": "__init__,__special1__"}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
' .. py:method:: Class.__init__(arg)',
- ' .. py:attribute:: Class.__module__',
' .. py:method:: Class.__special1__()',
- ' .. py:method:: Class.__special2__()',
' .. py:attribute:: Class.attr',
- ' .. py:attribute:: Class.descr',
' .. py:attribute:: Class.docattr',
- ' .. py:method:: Class.excludemeth()',
- ' .. py:attribute:: Class.inst_attr_comment',
- ' .. py:attribute:: Class.inst_attr_inline',
- ' .. py:attribute:: Class.inst_attr_string',
- ' .. py:attribute:: Class.mdocattr',
- ' .. py:method:: Class.meth()',
- ' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
- ' .. py:attribute:: Class.prop',
- ROGER_METHOD,
- ' .. py:attribute:: Class.skipattr',
- ' .. py:method:: Class.skipmeth()',
- ' .. py:attribute:: Class.udocattr',
- ' .. py:method:: Class.undocmeth()'
]
- # specific special methods
+ # all special methods
options = {"members": None,
"undoc-members": None,
- "special-members": "__init__,__special1__"}
+ "special-members": None}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
' .. py:method:: Class.__init__(arg)',
+ ' .. py:attribute:: Class.__module__',
' .. py:method:: Class.__special1__()',
+ ' .. py:method:: Class.__special2__()',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.descr',
' .. py:attribute:: Class.docattr',
@@ -1551,9 +1547,7 @@ def test_autodoc_default_options_with_values(app):
assert ' .. py:attribute:: EnumCls.val4' not in actual
# with :special-members:
- # Note that :members: must be *on* for :special-members: to work.
app.config.autodoc_default_options = {
- 'members': None,
'special-members': '__init__,__iter__',
}
actual = do_autodoc(app, 'class', 'target.CustomIter')