mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #5215 from LewisHaley/lewis/allow-setting-audodoc-default-options-in-conf
Allow setting audodoc default options in conf
This commit is contained in:
commit
00072ec0e7
@ -341,7 +341,8 @@ There are also new config values that you can set:
|
|||||||
This value is a list of autodoc directive flags that should be automatically
|
This value is a list of autodoc directive flags that should be automatically
|
||||||
applied to all autodoc directives. The supported flags are ``'members'``,
|
applied to all autodoc directives. The supported flags are ``'members'``,
|
||||||
``'undoc-members'``, ``'private-members'``, ``'special-members'``,
|
``'undoc-members'``, ``'private-members'``, ``'special-members'``,
|
||||||
``'inherited-members'``, ``'show-inheritance'`` and ``'ignore-module-all'``.
|
``'inherited-members'``, ``'show-inheritance'``, ``'ignore-module-all'``
|
||||||
|
and ``'exclude-members'``.
|
||||||
|
|
||||||
If you set one of these flags in this config value, you can use a negated
|
If you set one of these flags in this config value, you can use a negated
|
||||||
form, :samp:`'no-{flag}'`, in an autodoc directive, to disable it once.
|
form, :samp:`'no-{flag}'`, in an autodoc directive, to disable it once.
|
||||||
@ -353,8 +354,26 @@ There are also new config values that you can set:
|
|||||||
|
|
||||||
the directive will be interpreted as if only ``:members:`` was given.
|
the directive will be interpreted as if only ``:members:`` was given.
|
||||||
|
|
||||||
|
You can also set `autodoc_default_flags` to a dictionary, mapping option
|
||||||
|
names to the values which can used in .rst files. For example::
|
||||||
|
|
||||||
|
autodoc_default_flags = {
|
||||||
|
'members': 'var1, var2',
|
||||||
|
'member-order': 'bysource',
|
||||||
|
'special-members': '__init__',
|
||||||
|
'undoc-members': None,
|
||||||
|
'exclude-members': '__weakref__'
|
||||||
|
}
|
||||||
|
|
||||||
|
Setting ``None`` is equivalent to giving the option name in the list format
|
||||||
|
(i.e. it means "yes/true/on").
|
||||||
|
|
||||||
.. versionadded:: 1.0
|
.. versionadded:: 1.0
|
||||||
|
|
||||||
|
.. versionchanged:: 1.8
|
||||||
|
|
||||||
|
Specifying in dictionary format added.
|
||||||
|
|
||||||
.. confval:: autodoc_docstring_signature
|
.. confval:: autodoc_docstring_signature
|
||||||
|
|
||||||
Functions imported from C modules cannot be introspected, and therefore the
|
Functions imported from C modules cannot be introspected, and therefore the
|
||||||
|
@ -15,6 +15,7 @@ import inspect
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from docutils.statemachine import ViewList
|
from docutils.statemachine import ViewList
|
||||||
from six import iteritems, itervalues, text_type, class_types, string_types
|
from six import iteritems, itervalues, text_type, class_types, string_types
|
||||||
@ -41,6 +42,7 @@ if False:
|
|||||||
from docutils import nodes # NOQA
|
from docutils import nodes # NOQA
|
||||||
from docutils.utils import Reporter # NOQA
|
from docutils.utils import Reporter # NOQA
|
||||||
from sphinx.application import Sphinx # NOQA
|
from sphinx.application import Sphinx # NOQA
|
||||||
|
from sphinx.config import Config # NOQA
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
from sphinx.environment import BuildEnvironment # NOQA
|
||||||
from sphinx.ext.autodoc.directive import DocumenterBridge # NOQA
|
from sphinx.ext.autodoc.directive import DocumenterBridge # NOQA
|
||||||
|
|
||||||
@ -679,8 +681,13 @@ class Documenter(object):
|
|||||||
|
|
||||||
# remove members given by exclude-members
|
# remove members given by exclude-members
|
||||||
if self.options.exclude_members:
|
if self.options.exclude_members:
|
||||||
members = [(membername, member) for (membername, member) in members
|
members = [
|
||||||
if membername not in self.options.exclude_members]
|
(membername, member) for (membername, member) in members
|
||||||
|
if (
|
||||||
|
self.options.exclude_members is ALL or
|
||||||
|
membername not in self.options.exclude_members
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
# document non-skipped members
|
# document non-skipped members
|
||||||
memberdocumenters = [] # type: List[Tuple[Documenter, bool]]
|
memberdocumenters = [] # type: List[Tuple[Documenter, bool]]
|
||||||
@ -1528,6 +1535,34 @@ def autodoc_attrgetter(app, obj, name, *defargs):
|
|||||||
return safe_getattr(obj, name, *defargs)
|
return safe_getattr(obj, name, *defargs)
|
||||||
|
|
||||||
|
|
||||||
|
def convert_autodoc_default_flags(app, config):
|
||||||
|
# type: (Sphinx, Config) -> None
|
||||||
|
"""This converts the old list-of-flags (strings) to a dict of Nones."""
|
||||||
|
if isinstance(config.autodoc_default_flags, dict):
|
||||||
|
# Already new-style
|
||||||
|
return
|
||||||
|
|
||||||
|
elif not isinstance(config.autodoc_default_flags, list):
|
||||||
|
# Not old-style list
|
||||||
|
logger.error(
|
||||||
|
__("autodoc_default_flags is invalid type %r"),
|
||||||
|
config.autodoc_default_flags.__class__.__name__
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
autodoc_default_flags = {} # type: Dict[unicode, Any]
|
||||||
|
for option in config.autodoc_default_flags:
|
||||||
|
if isinstance(option, string_types):
|
||||||
|
autodoc_default_flags[option] = None
|
||||||
|
else:
|
||||||
|
logger.warning(
|
||||||
|
__("Ignoring invalid option in autodoc_default_flags: %r"),
|
||||||
|
option
|
||||||
|
)
|
||||||
|
|
||||||
|
config.autodoc_default_flags = autodoc_default_flags # type: ignore
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
# type: (Sphinx) -> Dict[unicode, Any]
|
# type: (Sphinx) -> Dict[unicode, Any]
|
||||||
app.add_autodocumenter(ModuleDocumenter)
|
app.add_autodocumenter(ModuleDocumenter)
|
||||||
@ -1541,7 +1576,7 @@ def setup(app):
|
|||||||
|
|
||||||
app.add_config_value('autoclass_content', 'class', True)
|
app.add_config_value('autoclass_content', 'class', True)
|
||||||
app.add_config_value('autodoc_member_order', 'alphabetic', True)
|
app.add_config_value('autodoc_member_order', 'alphabetic', True)
|
||||||
app.add_config_value('autodoc_default_flags', [], True)
|
app.add_config_value('autodoc_default_flags', {}, True, Any)
|
||||||
app.add_config_value('autodoc_docstring_signature', True, True)
|
app.add_config_value('autodoc_docstring_signature', True, True)
|
||||||
app.add_config_value('autodoc_mock_imports', [], True)
|
app.add_config_value('autodoc_mock_imports', [], True)
|
||||||
app.add_config_value('autodoc_warningiserror', True, True)
|
app.add_config_value('autodoc_warningiserror', True, True)
|
||||||
@ -1550,4 +1585,6 @@ def setup(app):
|
|||||||
app.add_event('autodoc-process-signature')
|
app.add_event('autodoc-process-signature')
|
||||||
app.add_event('autodoc-skip-member')
|
app.add_event('autodoc-skip-member')
|
||||||
|
|
||||||
|
app.connect('config-inited', convert_autodoc_default_flags)
|
||||||
|
|
||||||
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
||||||
|
@ -31,7 +31,7 @@ logger = logging.getLogger(__name__)
|
|||||||
# common option names for autodoc directives
|
# common option names for autodoc directives
|
||||||
AUTODOC_DEFAULT_OPTIONS = ['members', 'undoc-members', 'inherited-members',
|
AUTODOC_DEFAULT_OPTIONS = ['members', 'undoc-members', 'inherited-members',
|
||||||
'show-inheritance', 'private-members', 'special-members',
|
'show-inheritance', 'private-members', 'special-members',
|
||||||
'ignore-module-all']
|
'ignore-module-all', 'exclude-members']
|
||||||
|
|
||||||
|
|
||||||
class DummyOptionSpec(object):
|
class DummyOptionSpec(object):
|
||||||
@ -68,7 +68,7 @@ def process_documenter_options(documenter, config, options):
|
|||||||
else:
|
else:
|
||||||
negated = options.pop('no-' + name, True) is None
|
negated = options.pop('no-' + name, True) is None
|
||||||
if name in config.autodoc_default_flags and not negated:
|
if name in config.autodoc_default_flags and not negated:
|
||||||
options[name] = None
|
options[name] = config.autodoc_default_flags[name]
|
||||||
|
|
||||||
return Options(assemble_option_dict(options.items(), documenter.option_spec))
|
return Options(assemble_option_dict(options.items(), documenter.option_spec))
|
||||||
|
|
||||||
|
@ -234,3 +234,18 @@ class EnumCls(enum.Enum):
|
|||||||
val3 = 34
|
val3 = 34
|
||||||
"""doc for val3"""
|
"""doc for val3"""
|
||||||
val4 = 34
|
val4 = 34
|
||||||
|
|
||||||
|
|
||||||
|
class CustomIter(object):
|
||||||
|
def __init__(self):
|
||||||
|
"""Create a new `CustomIter`."""
|
||||||
|
self.values = range(10)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
"""Iterate squares of each value."""
|
||||||
|
for i in self.values:
|
||||||
|
yield i ** 2
|
||||||
|
|
||||||
|
def snafucate(self):
|
||||||
|
"""Makes this snafucated."""
|
||||||
|
print("snafucated")
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import platform
|
||||||
import sys
|
import sys
|
||||||
from warnings import catch_warnings
|
from warnings import catch_warnings
|
||||||
|
|
||||||
@ -19,7 +20,8 @@ from docutils.statemachine import ViewList
|
|||||||
from six import PY3
|
from six import PY3
|
||||||
|
|
||||||
from sphinx.ext.autodoc import (
|
from sphinx.ext.autodoc import (
|
||||||
AutoDirective, ModuleLevelDocumenter, cut_lines, between, ALL
|
AutoDirective, ModuleLevelDocumenter, cut_lines, between, ALL,
|
||||||
|
convert_autodoc_default_flags
|
||||||
)
|
)
|
||||||
from sphinx.ext.autodoc.directive import DocumenterBridge, process_documenter_options
|
from sphinx.ext.autodoc.directive import DocumenterBridge, process_documenter_options
|
||||||
from sphinx.testing.util import SphinxTestApp, Struct # NOQA
|
from sphinx.testing.util import SphinxTestApp, Struct # NOQA
|
||||||
@ -33,8 +35,12 @@ if PY3:
|
|||||||
else:
|
else:
|
||||||
ROGER_METHOD = ' .. py:classmethod:: Class.roger(a, e=5, f=6)'
|
ROGER_METHOD = ' .. py:classmethod:: Class.roger(a, e=5, f=6)'
|
||||||
|
|
||||||
|
IS_PYPY = platform.python_implementation() == 'PyPy'
|
||||||
|
|
||||||
def do_autodoc(app, objtype, name, options={}):
|
|
||||||
|
def do_autodoc(app, objtype, name, options=None):
|
||||||
|
if options is None:
|
||||||
|
options = {}
|
||||||
doccls = app.registry.documenters[objtype]
|
doccls = app.registry.documenters[objtype]
|
||||||
docoptions = process_documenter_options(doccls, app.config, options)
|
docoptions = process_documenter_options(doccls, app.config, options)
|
||||||
bridge = DocumenterBridge(app.env, LoggingReporter(''), docoptions, 1)
|
bridge = DocumenterBridge(app.env, LoggingReporter(''), docoptions, 1)
|
||||||
@ -1412,21 +1418,146 @@ def test_partialmethod(app):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_autodoc_default_flags(app):
|
def test_autodoc_default_flags__as_list__converted(app):
|
||||||
|
orig = [
|
||||||
|
'members',
|
||||||
|
'undoc-members',
|
||||||
|
('skipped', 1, 2),
|
||||||
|
{'also': 'skipped'},
|
||||||
|
]
|
||||||
|
expected = {
|
||||||
|
'members': None,
|
||||||
|
'undoc-members': None,
|
||||||
|
}
|
||||||
|
app.config.autodoc_default_flags = orig
|
||||||
|
convert_autodoc_default_flags(app, app.config)
|
||||||
|
assert app.config.autodoc_default_flags == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_autodoc_default_flags__as_dict__no_conversion(app):
|
||||||
|
orig = {
|
||||||
|
'members': 'this,that,other',
|
||||||
|
'undoc-members': None,
|
||||||
|
}
|
||||||
|
app.config.autodoc_default_flags = orig
|
||||||
|
convert_autodoc_default_flags(app, app.config)
|
||||||
|
assert app.config.autodoc_default_flags == orig
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_autodoc_default_flags__with_flags(app):
|
||||||
# no settings
|
# no settings
|
||||||
actual = do_autodoc(app, 'class', 'target.EnumCls')
|
actual = do_autodoc(app, 'class', 'target.EnumCls')
|
||||||
assert ' .. py:attribute:: EnumCls.val1' not in actual
|
assert ' .. py:attribute:: EnumCls.val1' not in actual
|
||||||
assert ' .. py:attribute:: EnumCls.val4' not in actual
|
assert ' .. py:attribute:: EnumCls.val4' not in actual
|
||||||
|
actual = do_autodoc(app, 'class', 'target.CustomIter')
|
||||||
|
assert ' .. py:method:: target.CustomIter' not in actual
|
||||||
|
|
||||||
# with :members:
|
# with :members:
|
||||||
app.config.autodoc_default_flags = ['members']
|
app.config.autodoc_default_flags = {'members': None}
|
||||||
actual = do_autodoc(app, 'class', 'target.EnumCls')
|
actual = do_autodoc(app, 'class', 'target.EnumCls')
|
||||||
assert ' .. py:attribute:: EnumCls.val1' in actual
|
assert ' .. py:attribute:: EnumCls.val1' in actual
|
||||||
assert ' .. py:attribute:: EnumCls.val4' not in actual
|
assert ' .. py:attribute:: EnumCls.val4' not in actual
|
||||||
|
|
||||||
# with :members: and :undoc-members:
|
# with :members: and :undoc-members:
|
||||||
app.config.autodoc_default_flags = ['members',
|
app.config.autodoc_default_flags = {
|
||||||
'undoc-members']
|
'members': None,
|
||||||
|
'undoc-members': None,
|
||||||
|
}
|
||||||
actual = do_autodoc(app, 'class', 'target.EnumCls')
|
actual = do_autodoc(app, 'class', 'target.EnumCls')
|
||||||
assert ' .. py:attribute:: EnumCls.val1' in actual
|
assert ' .. py:attribute:: EnumCls.val1' in actual
|
||||||
assert ' .. py:attribute:: EnumCls.val4' in actual
|
assert ' .. py:attribute:: EnumCls.val4' in actual
|
||||||
|
|
||||||
|
# with :special-members:
|
||||||
|
# Note that :members: must be *on* for :special-members: to work.
|
||||||
|
app.config.autodoc_default_flags = {
|
||||||
|
'members': None,
|
||||||
|
'special-members': None
|
||||||
|
}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.CustomIter')
|
||||||
|
assert ' .. py:method:: CustomIter.__init__()' in actual
|
||||||
|
assert ' Create a new `CustomIter`.' in actual
|
||||||
|
assert ' .. py:method:: CustomIter.__iter__()' in actual
|
||||||
|
assert ' Iterate squares of each value.' in actual
|
||||||
|
if not IS_PYPY:
|
||||||
|
assert ' .. py:attribute:: CustomIter.__weakref__' in actual
|
||||||
|
assert ' list of weak references to the object (if defined)' in actual
|
||||||
|
|
||||||
|
# :exclude-members: None - has no effect. Unlike :members:,
|
||||||
|
# :special-members:, etc. where None == "include all", here None means
|
||||||
|
# "no/false/off".
|
||||||
|
app.config.autodoc_default_flags = {
|
||||||
|
'members': None,
|
||||||
|
'exclude-members': None,
|
||||||
|
}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.EnumCls')
|
||||||
|
assert ' .. py:attribute:: EnumCls.val1' in actual
|
||||||
|
assert ' .. py:attribute:: EnumCls.val4' not in actual
|
||||||
|
app.config.autodoc_default_flags = {
|
||||||
|
'members': None,
|
||||||
|
'special-members': None,
|
||||||
|
'exclude-members': None,
|
||||||
|
}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.CustomIter')
|
||||||
|
assert ' .. py:method:: CustomIter.__init__()' in actual
|
||||||
|
assert ' Create a new `CustomIter`.' in actual
|
||||||
|
assert ' .. py:method:: CustomIter.__iter__()' in actual
|
||||||
|
assert ' Iterate squares of each value.' in actual
|
||||||
|
if not IS_PYPY:
|
||||||
|
assert ' .. py:attribute:: CustomIter.__weakref__' in actual
|
||||||
|
assert ' list of weak references to the object (if defined)' in actual
|
||||||
|
assert ' .. py:method:: CustomIter.snafucate()' in actual
|
||||||
|
assert ' Makes this snafucated.' in actual
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_autodoc_default_flags__with_values(app):
|
||||||
|
# with :members:
|
||||||
|
app.config.autodoc_default_flags = {'members': 'val1,val2'}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.EnumCls')
|
||||||
|
assert ' .. py:attribute:: EnumCls.val1' in actual
|
||||||
|
assert ' .. py:attribute:: EnumCls.val2' in actual
|
||||||
|
assert ' .. py:attribute:: EnumCls.val3' not in actual
|
||||||
|
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_flags = {
|
||||||
|
'members': None,
|
||||||
|
'special-members': '__init__,__iter__',
|
||||||
|
}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.CustomIter')
|
||||||
|
assert ' .. py:method:: CustomIter.__init__()' in actual
|
||||||
|
assert ' Create a new `CustomIter`.' in actual
|
||||||
|
assert ' .. py:method:: CustomIter.__iter__()' in actual
|
||||||
|
assert ' Iterate squares of each value.' in actual
|
||||||
|
if not IS_PYPY:
|
||||||
|
assert ' .. py:attribute:: CustomIter.__weakref__' not in actual
|
||||||
|
assert ' list of weak references to the object (if defined)' not in actual
|
||||||
|
|
||||||
|
# with :exclude-members:
|
||||||
|
app.config.autodoc_default_flags = {
|
||||||
|
'members': None,
|
||||||
|
'exclude-members': 'val1'
|
||||||
|
}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.EnumCls')
|
||||||
|
assert ' .. py:attribute:: EnumCls.val1' not in actual
|
||||||
|
assert ' .. py:attribute:: EnumCls.val2' in actual
|
||||||
|
assert ' .. py:attribute:: EnumCls.val3' in actual
|
||||||
|
assert ' .. py:attribute:: EnumCls.val4' not in actual
|
||||||
|
app.config.autodoc_default_flags = {
|
||||||
|
'members': None,
|
||||||
|
'special-members': None,
|
||||||
|
'exclude-members': '__weakref__,snafucate',
|
||||||
|
}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.CustomIter')
|
||||||
|
assert ' .. py:method:: CustomIter.__init__()' in actual
|
||||||
|
assert ' Create a new `CustomIter`.' in actual
|
||||||
|
assert ' .. py:method:: CustomIter.__iter__()' in actual
|
||||||
|
assert ' Iterate squares of each value.' in actual
|
||||||
|
if not IS_PYPY:
|
||||||
|
assert ' .. py:attribute:: CustomIter.__weakref__' not in actual
|
||||||
|
assert ' list of weak references to the object (if defined)' not in actual
|
||||||
|
assert ' .. py:method:: CustomIter.snafucate()' not in actual
|
||||||
|
assert ' Makes this snafucated.' not in actual
|
||||||
|
Loading…
Reference in New Issue
Block a user