Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sphinx-doc/sphinx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/usage/extensions/autodoc.rst11
-rw-r--r--sphinx/ext/autodoc/directive.py17
-rw-r--r--tests/test_ext_autodoc.py193
-rw-r--r--tests/test_ext_autodoc_autoclass.py8
-rw-r--r--tests/test_ext_autodoc_automodule.py4
-rw-r--r--tests/test_ext_autodoc_configs.py6
6 files changed, 210 insertions, 29 deletions
diff --git a/doc/usage/extensions/autodoc.rst b/doc/usage/extensions/autodoc.rst
index 5222592ab..a07042781 100644
--- a/doc/usage/extensions/autodoc.rst
+++ b/doc/usage/extensions/autodoc.rst
@@ -127,6 +127,17 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
.. automodule:: foo
:no-undoc-members:
+ .. tip::
+
+ You can use autodoc directive options to temporarily override or
+ extend default options which takes list as an input. For example::
+
+ .. autoclass:: Noodle
+ :members: eat
+ :private-members: +_spicy, _garlickly
+
+ .. versionchanged:: 3.5
+ The default options can be overridden or extended temporarily.
* Members without docstrings will be left out, unless you give the
``undoc-members`` flag option::
diff --git a/sphinx/ext/autodoc/directive.py b/sphinx/ext/autodoc/directive.py
index b4c5fd28d..c932c6f9f 100644
--- a/sphinx/ext/autodoc/directive.py
+++ b/sphinx/ext/autodoc/directive.py
@@ -37,6 +37,9 @@ AUTODOC_DEFAULT_OPTIONS = ['members', 'undoc-members', 'inherited-members',
'ignore-module-all', 'exclude-members', 'member-order',
'imported-members']
+AUTODOC_EXTENDABLE_OPTIONS = ['members', 'private-members', 'special-members',
+ 'exclude-members']
+
class DummyOptionSpec(dict):
"""An option_spec allows any options."""
@@ -90,7 +93,19 @@ def process_documenter_options(documenter: "Type[Documenter]", config: Config, o
else:
negated = options.pop('no-' + name, True) is None
if name in config.autodoc_default_options and not negated:
- options[name] = config.autodoc_default_options[name]
+ if name in options and isinstance(config.autodoc_default_options[name], str):
+ # take value from options if present or extend it
+ # with autodoc_default_options if necessary
+ if name in AUTODOC_EXTENDABLE_OPTIONS:
+ if options[name] is not None and options[name].startswith('+'):
+ options[name] = ','.join([config.autodoc_default_options[name],
+ options[name][1:]])
+ else:
+ options[name] = config.autodoc_default_options[name]
+
+ elif options.get(name) is not None:
+ # remove '+' from option argument if there's nothing to merge it with
+ options[name] = options[name].lstrip('+')
return Options(assemble_option_dict(options.items(), documenter.option_spec))
diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py
index 93b80f7ad..42aa3e808 100644
--- a/tests/test_ext_autodoc.py
+++ b/tests/test_ext_autodoc.py
@@ -569,6 +569,36 @@ def test_autodoc_members(app):
' .. py:method:: Base.inheritedstaticmeth(cls)'
]
+ # ALL-members override autodoc_default_options
+ options = {"members": None}
+ app.config.autodoc_default_options["members"] = "inheritedstaticmeth"
+ actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:class:: Base()',
+ ' .. py:method:: Base.inheritedclassmeth()',
+ ' .. py:method:: Base.inheritedmeth()',
+ ' .. py:method:: Base.inheritedstaticmeth(cls)'
+ ]
+
+ # members override autodoc_default_options
+ options = {"members": "inheritedmeth"}
+ app.config.autodoc_default_options["members"] = "inheritedstaticmeth"
+ actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:class:: Base()',
+ ' .. py:method:: Base.inheritedmeth()',
+ ]
+
+ # members extends autodoc_default_options
+ options = {"members": "+inheritedmeth"}
+ app.config.autodoc_default_options["members"] = "inheritedstaticmeth"
+ actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:class:: Base()',
+ ' .. py:method:: Base.inheritedmeth()',
+ ' .. py:method:: Base.inheritedstaticmeth(cls)'
+ ]
+
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_exclude_members(app):
@@ -588,6 +618,57 @@ def test_autodoc_exclude_members(app):
'.. py:class:: Base()',
]
+ # + has no effect when autodoc_default_options are not present
+ options = {"members": None,
+ "exclude-members": "+inheritedmeth,inheritedstaticmeth"}
+ actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:class:: Base()',
+ ' .. py:method:: Base.inheritedclassmeth()'
+ ]
+
+ # exclude-members overrides autodoc_default_options
+ options = {"members": None,
+ "exclude-members": "inheritedmeth"}
+ app.config.autodoc_default_options["exclude-members"] = "inheritedstaticmeth"
+ actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:class:: Base()',
+ ' .. py:method:: Base.inheritedclassmeth()',
+ ' .. py:method:: Base.inheritedstaticmeth(cls)'
+ ]
+
+ # exclude-members extends autodoc_default_options
+ options = {"members": None,
+ "exclude-members": "+inheritedmeth"}
+ app.config.autodoc_default_options["exclude-members"] = "inheritedstaticmeth"
+ actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:class:: Base()',
+ ' .. py:method:: Base.inheritedclassmeth()',
+ ]
+
+ # no exclude-members causes use autodoc_default_options
+ options = {"members": None}
+ app.config.autodoc_default_options["exclude-members"] = "inheritedstaticmeth,inheritedmeth"
+ actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:class:: Base()',
+ ' .. py:method:: Base.inheritedclassmeth()',
+ ]
+
+ # empty exclude-members cancels autodoc_default_options
+ options = {"members": None,
+ "exclude-members": None}
+ app.config.autodoc_default_options["exclude-members"] = "inheritedstaticmeth,inheritedmeth"
+ actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:class:: Base()',
+ ' .. py:method:: Base.inheritedclassmeth()',
+ ' .. py:method:: Base.inheritedmeth()',
+ ' .. py:method:: Base.inheritedstaticmeth(cls)'
+ ]
+
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_undoc_members(app):
@@ -612,6 +693,48 @@ def test_autodoc_undoc_members(app):
' .. py:method:: Class.undocmeth()'
]
+ # use autodoc_default_options
+ options = {"members": None}
+ app.config.autodoc_default_options["undoc-members"] = None
+ actual = do_autodoc(app, 'class', 'target.Class', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:class:: Class(arg)',
+ ' .. py:attribute:: Class.attr',
+ ' .. 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:method:: Class.moore(a, e, f) -> happiness',
+ ' .. py:method:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
+ ' .. py:attribute:: Class.skipattr',
+ ' .. py:method:: Class.skipmeth()',
+ ' .. py:attribute:: Class.udocattr',
+ ' .. py:method:: Class.undocmeth()'
+ ]
+
+ # options negation work check
+ options = {"members": None,
+ "no-undoc-members": None}
+ app.config.autodoc_default_options["undoc-members"] = None
+ actual = do_autodoc(app, 'class', 'target.Class', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:class:: Class(arg)',
+ ' .. py:attribute:: Class.attr',
+ ' .. 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:method:: Class.moore(a, e, f) -> happiness',
+ ' .. py:method:: Class.skipmeth()',
+ ' .. py:attribute:: Class.udocattr',
+ ]
+
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_inherited_members(app):
@@ -713,6 +836,38 @@ def test_autodoc_special_members(app):
' .. py:method:: Class.undocmeth()'
]
+ # specific special methods from autodoc_default_options
+ options = {"undoc-members": None}
+ app.config.autodoc_default_options["special-members"] = "__special2__"
+ actual = do_autodoc(app, 'class', 'target.Class', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:class:: Class(arg)',
+ ' .. py:method:: Class.__special2__()',
+ ]
+
+ # specific special methods option with autodoc_default_options
+ options = {"undoc-members": None,
+ "special-members": "__init__,__special1__"}
+ app.config.autodoc_default_options["special-members"] = "__special2__"
+ 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__()',
+ ]
+
+ # specific special methods merge with autodoc_default_options
+ options = {"undoc-members": None,
+ "special-members": "+__init__,__special1__"}
+ app.config.autodoc_default_options["special-members"] = "__special2__"
+ 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__()',
+ ' .. py:method:: Class.__special2__()',
+ ]
+
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_ignore_module_all(app):
@@ -740,7 +895,7 @@ def test_autodoc_ignore_module_all(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_noindex(app):
- options = {"noindex": True}
+ options = {"noindex": None}
actual = do_autodoc(app, 'module', 'target', options)
assert list(actual) == [
'',
@@ -821,7 +976,7 @@ def test_autodoc_inner_class(app):
'',
]
- options['show-inheritance'] = True
+ options['show-inheritance'] = None
actual = do_autodoc(app, 'class', 'target.InnerChild', options)
assert list(actual) == [
'',
@@ -865,7 +1020,7 @@ def test_autodoc_staticmethod(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_descriptor(app):
options = {"members": None,
- "undoc-members": True}
+ "undoc-members": None}
actual = do_autodoc(app, 'class', 'target.descriptor.Class', options)
assert list(actual) == [
'',
@@ -893,7 +1048,7 @@ def test_autodoc_descriptor(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_cached_property(app):
options = {"members": None,
- "undoc-members": True}
+ "undoc-members": None}
actual = do_autodoc(app, 'class', 'target.cached_property.Foo', options)
assert list(actual) == [
'',
@@ -913,8 +1068,8 @@ def test_autodoc_member_order(app):
# case member-order='bysource'
options = {"members": None,
'member-order': 'bysource',
- "undoc-members": True,
- 'private-members': True}
+ "undoc-members": None,
+ 'private-members': None}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
@@ -938,8 +1093,8 @@ def test_autodoc_member_order(app):
# case member-order='groupwise'
options = {"members": None,
'member-order': 'groupwise',
- "undoc-members": True,
- 'private-members': True}
+ "undoc-members": None,
+ 'private-members': None}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
@@ -962,8 +1117,8 @@ def test_autodoc_member_order(app):
# case member-order=None
options = {"members": None,
- "undoc-members": True,
- 'private-members': True}
+ "undoc-members": None,
+ 'private-members': None}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
@@ -990,7 +1145,7 @@ def test_autodoc_module_member_order(app):
# case member-order='bysource'
options = {"members": 'foo, Bar, baz, qux, Quux, foobar',
'member-order': 'bysource',
- "undoc-members": True}
+ "undoc-members": None}
actual = do_autodoc(app, 'module', 'target.sort_by_all', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:module:: target.sort_by_all',
@@ -1005,8 +1160,8 @@ def test_autodoc_module_member_order(app):
# case member-order='bysource' and ignore-module-all
options = {"members": 'foo, Bar, baz, qux, Quux, foobar',
'member-order': 'bysource',
- "undoc-members": True,
- "ignore-module-all": True}
+ "undoc-members": None,
+ "ignore-module-all": None}
actual = do_autodoc(app, 'module', 'target.sort_by_all', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:module:: target.sort_by_all',
@@ -1053,7 +1208,7 @@ def test_autodoc_class_scope(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_class_attributes(app):
options = {"members": None,
- "undoc-members": True}
+ "undoc-members": None}
actual = do_autodoc(app, 'class', 'target.AttCls', options)
assert list(actual) == [
'',
@@ -1163,7 +1318,7 @@ def test_autoattribute_instance_attributes(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_slots(app):
options = {"members": None,
- "undoc-members": True}
+ "undoc-members": None}
actual = do_autodoc(app, 'module', 'target.slots', options)
assert list(actual) == [
'',
@@ -1561,7 +1716,7 @@ def test_partialmethod_undoc_members(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_typed_instance_variables(app):
options = {"members": None,
- "undoc-members": True}
+ "undoc-members": None}
actual = do_autodoc(app, 'module', 'target.typed_vars', options)
assert list(actual) == [
'',
@@ -1660,8 +1815,8 @@ def test_autodoc_typed_instance_variables(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_typed_inherited_instance_variables(app):
options = {"members": None,
- "undoc-members": True,
- "inherited-members": True}
+ "undoc-members": None,
+ "inherited-members": None}
actual = do_autodoc(app, 'class', 'target.typed_vars.Derived', options)
assert list(actual) == [
'',
@@ -2284,7 +2439,7 @@ def test_type_union_operator(app):
@pytest.mark.skipif(sys.version_info < (3, 6), reason='python 3.6+ is required.')
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_hide_value(app):
- options = {'members': True}
+ options = {'members': None}
actual = do_autodoc(app, 'module', 'target.hide_value', options)
assert list(actual) == [
'',
diff --git a/tests/test_ext_autodoc_autoclass.py b/tests/test_ext_autodoc_autoclass.py
index 74ddb02f9..e729f220d 100644
--- a/tests/test_ext_autodoc_autoclass.py
+++ b/tests/test_ext_autodoc_autoclass.py
@@ -53,7 +53,7 @@ def test_classes(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_instance_variable(app):
- options = {'members': True}
+ options = {'members': None}
actual = do_autodoc(app, 'class', 'target.instance_variable.Bar', options)
assert list(actual) == [
'',
@@ -77,8 +77,8 @@ def test_instance_variable(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_inherited_instance_variable(app):
- options = {'members': True,
- 'inherited-members': True}
+ options = {'members': None,
+ 'inherited-members': None}
actual = do_autodoc(app, 'class', 'target.instance_variable.Bar', options)
assert list(actual) == [
'',
@@ -228,7 +228,7 @@ def test_slots_attribute(app):
@pytest.mark.skipif(sys.version_info < (3, 7), reason='python 3.7+ is required.')
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_show_inheritance_for_subclass_of_generic_type(app):
- options = {'show-inheritance': True}
+ options = {'show-inheritance': None}
actual = do_autodoc(app, 'class', 'target.classes.Quux', options)
assert list(actual) == [
'',
diff --git a/tests/test_ext_autodoc_automodule.py b/tests/test_ext_autodoc_automodule.py
index df57724b3..3332704bb 100644
--- a/tests/test_ext_autodoc_automodule.py
+++ b/tests/test_ext_autodoc_automodule.py
@@ -18,7 +18,7 @@ from .test_ext_autodoc import do_autodoc
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_empty_all(app):
- options = {'members': True}
+ options = {'members': None}
actual = do_autodoc(app, 'module', 'target.empty_all', options)
assert list(actual) == [
'',
@@ -39,6 +39,6 @@ def test_empty_all(app):
def test_subclass_of_mocked_object(app):
sys.modules.pop('target', None) # unload target module to clear the module cache
- options = {'members': True}
+ options = {'members': None}
actual = do_autodoc(app, 'module', 'target.need_mocks', options)
assert '.. py:class:: Inherited(*args: Any, **kwargs: Any)' in actual
diff --git a/tests/test_ext_autodoc_configs.py b/tests/test_ext_autodoc_configs.py
index bae684397..06bf39c24 100644
--- a/tests/test_ext_autodoc_configs.py
+++ b/tests/test_ext_autodoc_configs.py
@@ -486,7 +486,7 @@ def test_mocked_module_imports(app, warning):
confoverrides={'autodoc_typehints': "signature"})
def test_autodoc_typehints_signature(app):
options = {"members": None,
- "undoc-members": True}
+ "undoc-members": None}
actual = do_autodoc(app, 'module', 'target.typehints', options)
assert list(actual) == [
'',
@@ -552,7 +552,7 @@ def test_autodoc_typehints_signature(app):
confoverrides={'autodoc_typehints': "none"})
def test_autodoc_typehints_none(app):
options = {"members": None,
- "undoc-members": True}
+ "undoc-members": None}
actual = do_autodoc(app, 'module', 'target.typehints', options)
assert list(actual) == [
'',
@@ -851,7 +851,7 @@ def test_autodoc_default_options(app):
assert ' .. py:attribute:: EnumCls.val4' not in actual
# with :members: = True
- app.config.autodoc_default_options = {'members': True}
+ app.config.autodoc_default_options = {'members': None}
actual = do_autodoc(app, 'class', 'target.enums.EnumCls')
assert ' .. py:attribute:: EnumCls.val1' in actual
assert ' .. py:attribute:: EnumCls.val4' not in actual