summaryrefslogtreecommitdiffstats
path: root/tests/test_extensions/test_ext_autodoc_configs.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_extensions/test_ext_autodoc_configs.py')
-rw-r--r--tests/test_extensions/test_ext_autodoc_configs.py1743
1 files changed, 1743 insertions, 0 deletions
diff --git a/tests/test_extensions/test_ext_autodoc_configs.py b/tests/test_extensions/test_ext_autodoc_configs.py
new file mode 100644
index 0000000..6c2af5a
--- /dev/null
+++ b/tests/test_extensions/test_ext_autodoc_configs.py
@@ -0,0 +1,1743 @@
+"""Test the autodoc extension. This tests mainly for config variables"""
+
+import platform
+import sys
+from contextlib import contextmanager
+
+import pytest
+
+from sphinx.testing import restructuredtext
+
+from tests.test_extensions.autodoc_util import do_autodoc
+
+IS_PYPY = platform.python_implementation() == 'PyPy'
+
+
+@contextmanager
+def overwrite_file(path, content):
+ current_content = path.read_bytes() if path.exists() else None
+ try:
+ path.write_text(content, encoding='utf-8')
+ yield
+ finally:
+ if current_content is not None:
+ path.write_bytes(current_content)
+ else:
+ path.unlink()
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autoclass_content_class(app):
+ app.config.autoclass_content = 'class'
+ options = {"members": None}
+ actual = do_autodoc(app, 'module', 'target.autoclass_content', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.autoclass_content',
+ '',
+ '',
+ '.. py:class:: A()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having no __init__, no __new__',
+ '',
+ '',
+ '.. py:class:: B()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having __init__(no docstring), no __new__',
+ '',
+ '',
+ '.. py:class:: C()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having __init__, no __new__',
+ '',
+ '',
+ '.. py:class:: D()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having no __init__, __new__(no docstring)',
+ '',
+ '',
+ '.. py:class:: E()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having no __init__, __new__',
+ '',
+ '',
+ '.. py:class:: F()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having both __init__ and __new__',
+ '',
+ '',
+ '.. py:class:: G()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class inherits __init__ without docstring.',
+ '',
+ '',
+ '.. py:class:: H()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class inherits __new__ without docstring.',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autoclass_content_init(app):
+ app.config.autoclass_content = 'init'
+ options = {"members": None}
+ actual = do_autodoc(app, 'module', 'target.autoclass_content', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.autoclass_content',
+ '',
+ '',
+ '.. py:class:: A()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having no __init__, no __new__',
+ '',
+ '',
+ '.. py:class:: B()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having __init__(no docstring), no __new__',
+ '',
+ '',
+ '.. py:class:: C()',
+ ' :module: target.autoclass_content',
+ '',
+ ' __init__ docstring',
+ '',
+ '',
+ '.. py:class:: D()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having no __init__, __new__(no docstring)',
+ '',
+ '',
+ '.. py:class:: E()',
+ ' :module: target.autoclass_content',
+ '',
+ ' __new__ docstring',
+ '',
+ '',
+ '.. py:class:: F()',
+ ' :module: target.autoclass_content',
+ '',
+ ' __init__ docstring',
+ '',
+ '',
+ '.. py:class:: G()',
+ ' :module: target.autoclass_content',
+ '',
+ ' __init__ docstring',
+ '',
+ '',
+ '.. py:class:: H()',
+ ' :module: target.autoclass_content',
+ '',
+ ' __new__ docstring',
+ '',
+ ]
+
+
+@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'
+ options = {"members": None}
+ actual = do_autodoc(app, 'module', 'target.autoclass_content', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.autoclass_content',
+ '',
+ '',
+ '.. py:class:: A()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having no __init__, no __new__',
+ '',
+ '',
+ '.. py:class:: B()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having __init__(no docstring), no __new__',
+ '',
+ '',
+ '.. py:class:: C()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having __init__, no __new__',
+ '',
+ ' __init__ docstring',
+ '',
+ '',
+ '.. py:class:: D()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having no __init__, __new__(no docstring)',
+ '',
+ '',
+ '.. py:class:: E()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having no __init__, __new__',
+ '',
+ ' __new__ docstring',
+ '',
+ '',
+ '.. py:class:: F()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class having both __init__ and __new__',
+ '',
+ ' __init__ docstring',
+ '',
+ '',
+ '.. py:class:: G()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class inherits __init__ without docstring.',
+ '',
+ ' __init__ docstring',
+ '',
+ '',
+ '.. py:class:: H()',
+ ' :module: target.autoclass_content',
+ '',
+ ' A class inherits __new__ without docstring.',
+ '',
+ ' __new__ docstring',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autodoc_inherit_docstrings(app):
+ assert app.config.autodoc_inherit_docstrings is True # default
+ actual = do_autodoc(app, 'method', 'target.inheritance.Derived.inheritedmeth')
+ assert list(actual) == [
+ '',
+ '.. py:method:: Derived.inheritedmeth()',
+ ' :module: target.inheritance',
+ '',
+ ' Inherited function.',
+ '',
+ ]
+
+ # disable autodoc_inherit_docstrings
+ app.config.autodoc_inherit_docstrings = False
+ actual = do_autodoc(app, 'method', 'target.inheritance.Derived.inheritedmeth')
+ assert list(actual) == [
+ '',
+ '.. py:method:: Derived.inheritedmeth()',
+ ' :module: target.inheritance',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autodoc_inherit_docstrings_for_inherited_members(app):
+ options = {"members": None,
+ "inherited-members": None}
+
+ assert app.config.autodoc_inherit_docstrings is True # default
+ actual = do_autodoc(app, 'class', 'target.inheritance.Derived', options)
+ assert list(actual) == [
+ '',
+ '.. py:class:: Derived()',
+ ' :module: target.inheritance',
+ '',
+ '',
+ ' .. py:attribute:: Derived.inheritedattr',
+ ' :module: target.inheritance',
+ ' :value: None',
+ '',
+ ' docstring',
+ '',
+ '',
+ ' .. py:method:: Derived.inheritedclassmeth()',
+ ' :module: target.inheritance',
+ ' :classmethod:',
+ '',
+ ' Inherited class method.',
+ '',
+ '',
+ ' .. py:method:: Derived.inheritedmeth()',
+ ' :module: target.inheritance',
+ '',
+ ' Inherited function.',
+ '',
+ '',
+ ' .. py:method:: Derived.inheritedstaticmeth(cls)',
+ ' :module: target.inheritance',
+ ' :staticmethod:',
+ '',
+ ' Inherited static method.',
+ '',
+ ]
+
+ # disable autodoc_inherit_docstrings
+ app.config.autodoc_inherit_docstrings = False
+ actual = do_autodoc(app, 'class', 'target.inheritance.Derived', options)
+ assert list(actual) == [
+ '',
+ '.. py:class:: Derived()',
+ ' :module: target.inheritance',
+ '',
+ '',
+ ' .. py:method:: Derived.inheritedclassmeth()',
+ ' :module: target.inheritance',
+ ' :classmethod:',
+ '',
+ ' Inherited class method.',
+ '',
+ '',
+ ' .. py:method:: Derived.inheritedstaticmeth(cls)',
+ ' :module: target.inheritance',
+ ' :staticmethod:',
+ '',
+ ' Inherited static method.',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autodoc_docstring_signature(app):
+ options = {"members": None, "special-members": "__init__, __new__"}
+ actual = do_autodoc(app, 'class', 'target.DocstringSig', options)
+ assert list(actual) == [
+ '',
+ # FIXME: Ideally this would instead be: `DocstringSig(d, e=1)` but
+ # currently `ClassDocumenter` does not apply the docstring signature
+ # logic when extracting a signature from a __new__ or __init__ method.
+ '.. py:class:: DocstringSig(*new_args, **new_kwargs)',
+ ' :module: target',
+ '',
+ '',
+ ' .. py:method:: DocstringSig.__init__(self, a, b=1) -> None',
+ ' :module: target',
+ '',
+ ' First line of docstring',
+ '',
+ ' rest of docstring',
+ '',
+ '',
+ ' .. py:method:: DocstringSig.__new__(cls, d, e=1) -> DocstringSig',
+ ' :module: target',
+ ' :staticmethod:',
+ '',
+ ' First line of docstring',
+ '',
+ ' rest of docstring',
+ '',
+ '',
+ ' .. py:method:: DocstringSig.meth(FOO, BAR=1) -> BAZ',
+ ' :module: target',
+ '',
+ ' First line of docstring',
+ '',
+ ' rest of docstring',
+ '',
+ '',
+ ' .. py:method:: DocstringSig.meth2()',
+ ' :module: target',
+ '',
+ ' First line, no signature',
+ ' Second line followed by indentation::',
+ '',
+ ' indented line',
+ '',
+ '',
+ ' .. py:property:: DocstringSig.prop1',
+ ' :module: target',
+ '',
+ ' First line of docstring',
+ '',
+ '',
+ ' .. py:property:: DocstringSig.prop2',
+ ' :module: target',
+ '',
+ ' First line of docstring',
+ ' Second line of docstring',
+ '',
+ ]
+
+ # disable autodoc_docstring_signature
+ app.config.autodoc_docstring_signature = False
+ actual = do_autodoc(app, 'class', 'target.DocstringSig', options)
+ assert list(actual) == [
+ '',
+ '.. py:class:: DocstringSig(*new_args, **new_kwargs)',
+ ' :module: target',
+ '',
+ '',
+ ' .. py:method:: DocstringSig.__init__(*init_args, **init_kwargs)',
+ ' :module: target',
+ '',
+ ' __init__(self, a, b=1) -> None',
+ ' First line of docstring',
+ '',
+ ' rest of docstring',
+ '',
+ '',
+ '',
+ ' .. py:method:: DocstringSig.__new__(cls, *new_args, **new_kwargs)',
+ ' :module: target',
+ ' :staticmethod:',
+ '',
+ ' __new__(cls, d, e=1) -> DocstringSig',
+ ' First line of docstring',
+ '',
+ ' rest of docstring',
+ '',
+ '',
+ '',
+ ' .. py:method:: DocstringSig.meth()',
+ ' :module: target',
+ '',
+ ' meth(FOO, BAR=1) -> BAZ',
+ ' First line of docstring',
+ '',
+ ' rest of docstring',
+ '',
+ '',
+ '',
+ ' .. py:method:: DocstringSig.meth2()',
+ ' :module: target',
+ '',
+ ' First line, no signature',
+ ' Second line followed by indentation::',
+ '',
+ ' indented line',
+ '',
+ '',
+ ' .. py:property:: DocstringSig.prop1',
+ ' :module: target',
+ '',
+ ' DocstringSig.prop1(self)',
+ ' First line of docstring',
+ '',
+ '',
+ ' .. py:property:: DocstringSig.prop2',
+ ' :module: target',
+ '',
+ ' First line of docstring',
+ ' Second line of docstring',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autoclass_content_and_docstring_signature_class(app):
+ app.config.autoclass_content = 'class'
+ options = {"members": None,
+ "undoc-members": None}
+ actual = do_autodoc(app, 'module', 'target.docstring_signature', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: A(foo, bar)',
+ ' :module: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: B(foo, bar)',
+ ' :module: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: C(foo, bar)',
+ ' :module: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: D()',
+ ' :module: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: E()',
+ ' :module: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: F()',
+ ' :module: target.docstring_signature',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autoclass_content_and_docstring_signature_init(app):
+ app.config.autoclass_content = 'init'
+ options = {"members": None,
+ "undoc-members": None}
+ actual = do_autodoc(app, 'module', 'target.docstring_signature', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: A(foo, bar)',
+ ' :module: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: B(foo, bar, baz)',
+ ' :module: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: C(foo, bar, baz)',
+ ' :module: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: D(foo, bar, baz)',
+ ' :module: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: E(foo: int, bar: int, baz: int)',
+ ' E(foo: str, bar: str, baz: str)',
+ ' E(foo: float, bar: float, baz: float)',
+ ' :module: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: F(foo: int, bar: int, baz: int)',
+ ' F(foo: str, bar: str, baz: str)',
+ ' F(foo: float, bar: float, baz: float)',
+ ' :module: target.docstring_signature',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autoclass_content_and_docstring_signature_both(app):
+ app.config.autoclass_content = 'both'
+ options = {"members": None,
+ "undoc-members": None}
+ actual = do_autodoc(app, 'module', 'target.docstring_signature', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: A(foo, bar)',
+ ' :module: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: B(foo, bar)',
+ ' :module: target.docstring_signature',
+ '',
+ ' B(foo, bar, baz)',
+ '',
+ '',
+ '.. py:class:: C(foo, bar)',
+ ' :module: target.docstring_signature',
+ '',
+ ' C(foo, bar, baz)',
+ '',
+ '',
+ '.. py:class:: D(foo, bar, baz)',
+ ' :module: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: E(foo: int, bar: int, baz: int)',
+ ' E(foo: str, bar: str, baz: str)',
+ ' E(foo: float, bar: float, baz: float)',
+ ' :module: target.docstring_signature',
+ '',
+ '',
+ '.. py:class:: F(foo: int, bar: int, baz: int)',
+ ' F(foo: str, bar: str, baz: str)',
+ ' F(foo: float, bar: float, baz: float)',
+ ' :module: target.docstring_signature',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
+@pytest.mark.usefixtures("rollback_sysmodules")
+def test_mocked_module_imports(app, warning):
+ sys.modules.pop('target', None) # unload target module to clear the module cache
+
+ # no autodoc_mock_imports
+ options = {"members": 'TestAutodoc,decoratedFunction,func,Alias'}
+ actual = do_autodoc(app, 'module', 'target.need_mocks', options)
+ assert list(actual) == []
+ assert "autodoc: failed to import module 'need_mocks'" in warning.getvalue()
+
+ # with autodoc_mock_imports
+ app.config.autodoc_mock_imports = [
+ 'missing_module',
+ 'missing_package1',
+ 'missing_package2',
+ 'missing_package3',
+ 'sphinx.missing_module4',
+ ]
+
+ warning.truncate(0)
+ actual = do_autodoc(app, 'module', 'target.need_mocks', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.need_mocks',
+ '',
+ '',
+ '.. py:data:: Alias',
+ ' :module: target.need_mocks',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:class:: TestAutodoc()',
+ ' :module: target.need_mocks',
+ '',
+ ' TestAutodoc docstring.',
+ '',
+ '',
+ ' .. py:attribute:: TestAutodoc.Alias',
+ ' :module: target.need_mocks',
+ '',
+ ' docstring',
+ '',
+ '',
+ ' .. py:method:: TestAutodoc.decoratedMethod()',
+ ' :module: target.need_mocks',
+ '',
+ ' TestAutodoc::decoratedMethod docstring',
+ '',
+ '',
+ '.. py:function:: decoratedFunction()',
+ ' :module: target.need_mocks',
+ '',
+ ' decoratedFunction docstring',
+ '',
+ '',
+ '.. py:function:: func(arg: missing_module.Class)',
+ ' :module: target.need_mocks',
+ '',
+ ' a function takes mocked object as an argument',
+ '',
+ ]
+ assert warning.getvalue() == ''
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints': "signature"})
+def test_autodoc_typehints_signature(app):
+ if sys.version_info[:2] <= (3, 10):
+ type_o = "~typing.Any | None"
+ else:
+ type_o = "~typing.Any"
+
+ options = {"members": None,
+ "undoc-members": None}
+ actual = do_autodoc(app, 'module', 'target.typehints', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.typehints',
+ '',
+ '',
+ '.. py:data:: CONST1',
+ ' :module: target.typehints',
+ ' :type: int',
+ '',
+ '',
+ '.. py:data:: CONST2',
+ ' :module: target.typehints',
+ ' :type: int',
+ ' :value: 1',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:data:: CONST3',
+ ' :module: target.typehints',
+ ' :type: ~pathlib.PurePosixPath',
+ " :value: PurePosixPath('/a/b/c')",
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:class:: Math(s: str, o: %s = None)' % type_o,
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:attribute:: Math.CONST1',
+ ' :module: target.typehints',
+ ' :type: int',
+ '',
+ '',
+ ' .. py:attribute:: Math.CONST2',
+ ' :module: target.typehints',
+ ' :type: int',
+ ' :value: 1',
+ '',
+ '',
+ ' .. py:attribute:: Math.CONST3',
+ ' :module: target.typehints',
+ ' :type: ~pathlib.PurePosixPath',
+ " :value: PurePosixPath('/a/b/c')",
+ '',
+ '',
+ ' .. py:method:: Math.decr(a: int, b: int = 1) -> int',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:method:: Math.horse(a: str, b: int) -> None',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:method:: Math.incr(a: int, b: int = 1) -> int',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:method:: Math.nothing() -> None',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:property:: Math.path',
+ ' :module: target.typehints',
+ ' :type: ~pathlib.PurePosixPath',
+ '',
+ '',
+ ' .. py:property:: Math.prop',
+ ' :module: target.typehints',
+ ' :type: int',
+ '',
+ '',
+ '.. py:class:: NewAnnotation(i: int)',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:class:: NewComment(i: int)',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:class:: SignatureFromMetaclass(a: int)',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:class:: T',
+ ' :module: target.typehints',
+ '',
+ ' docstring',
+ '',
+ " alias of TypeVar('T', bound=\\ :py:class:`~pathlib.PurePosixPath`)",
+ '',
+ '',
+ '.. py:function:: complex_func(arg1: str, arg2: List[int], arg3: Tuple[int, '
+ 'Union[str, Unknown]] = None, *args: str, **kwargs: str) -> None',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:function:: decr(a: int, b: int = 1) -> int',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:function:: incr(a: int, b: int = 1) -> int',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:function:: missing_attr(c, a: str, b: Optional[str] = None) -> str',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:function:: tuple_args(x: tuple[int, int | str]) -> tuple[int, int]',
+ ' :module: target.typehints',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints': "none"})
+def test_autodoc_typehints_none(app):
+ options = {"members": None,
+ "undoc-members": None}
+ actual = do_autodoc(app, 'module', 'target.typehints', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.typehints',
+ '',
+ '',
+ '.. py:data:: CONST1',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:data:: CONST2',
+ ' :module: target.typehints',
+ ' :value: 1',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:data:: CONST3',
+ ' :module: target.typehints',
+ " :value: PurePosixPath('/a/b/c')",
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:class:: Math(s, o=None)',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:attribute:: Math.CONST1',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:attribute:: Math.CONST2',
+ ' :module: target.typehints',
+ ' :value: 1',
+ '',
+ '',
+ ' .. py:attribute:: Math.CONST3',
+ ' :module: target.typehints',
+ " :value: PurePosixPath('/a/b/c')",
+ '',
+ '',
+ ' .. py:method:: Math.decr(a, b=1)',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:method:: Math.horse(a, b)',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:method:: Math.incr(a, b=1)',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:method:: Math.nothing()',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:property:: Math.path',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:property:: Math.prop',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:class:: NewAnnotation(i)',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:class:: NewComment(i)',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:class:: SignatureFromMetaclass(a)',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:class:: T',
+ ' :module: target.typehints',
+ '',
+ ' docstring',
+ '',
+ " alias of TypeVar('T', bound=\\ :py:class:`~pathlib.PurePosixPath`)",
+ '',
+ '',
+ '.. py:function:: complex_func(arg1, arg2, arg3=None, *args, **kwargs)',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:function:: decr(a, b=1)',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:function:: incr(a, b=1)',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:function:: missing_attr(c, a, b=None)',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:function:: tuple_args(x)',
+ ' :module: target.typehints',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints': 'none'})
+def test_autodoc_typehints_none_for_overload(app):
+ options = {"members": None}
+ actual = do_autodoc(app, 'module', 'target.overload', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.overload',
+ '',
+ '',
+ '.. py:class:: Bar(x, y)',
+ ' :module: target.overload',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:class:: Baz(x, y)',
+ ' :module: target.overload',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:class:: Foo(x, y)',
+ ' :module: target.overload',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:class:: Math()',
+ ' :module: target.overload',
+ '',
+ ' docstring',
+ '',
+ '',
+ ' .. py:method:: Math.sum(x, y=None)',
+ ' :module: target.overload',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:function:: sum(x, y=None)',
+ ' :module: target.overload',
+ '',
+ ' docstring',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('text', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints': "description"},
+ freshenv=True)
+def test_autodoc_typehints_description(app):
+ app.build()
+ context = (app.outdir / 'index.txt').read_text(encoding='utf8')
+ assert ('target.typehints.incr(a, b=1)\n'
+ '\n'
+ ' Parameters:\n'
+ ' * **a** (*int*)\n'
+ '\n'
+ ' * **b** (*int*)\n'
+ '\n'
+ ' Return type:\n'
+ ' int\n'
+ in context)
+ assert ('target.typehints.tuple_args(x)\n'
+ '\n'
+ ' Parameters:\n'
+ ' **x** (*tuple**[**int**, **int** | **str**]*)\n'
+ '\n'
+ ' Return type:\n'
+ ' tuple[int, int]\n'
+ in context)
+
+ # Overloads still get displayed in the signature
+ assert ('target.overload.sum(x: int, y: int = 0) -> int\n'
+ 'target.overload.sum(x: float, y: float = 0.0) -> float\n'
+ 'target.overload.sum(x: str, y: str = None) -> str\n'
+ '\n'
+ ' docstring\n'
+ in context)
+
+
+@pytest.mark.sphinx('text', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints': "description",
+ 'autodoc_typehints_description_target': 'documented'})
+def test_autodoc_typehints_description_no_undoc(app):
+ # No :type: or :rtype: will be injected for `incr`, which does not have
+ # a description for its parameters or its return. `tuple_args` does
+ # describe them, so :type: and :rtype: will be added.
+ with overwrite_file(app.srcdir / 'index.rst',
+ '.. autofunction:: target.typehints.incr\n'
+ '\n'
+ '.. autofunction:: target.typehints.decr\n'
+ '\n'
+ ' :returns: decremented number\n'
+ '\n'
+ '.. autofunction:: target.typehints.tuple_args\n'
+ '\n'
+ ' :param x: arg\n'
+ ' :return: another tuple\n'):
+ app.build()
+ # Restore the original content of the file
+ context = (app.outdir / 'index.txt').read_text(encoding='utf8')
+ assert ('target.typehints.incr(a, b=1)\n'
+ '\n'
+ 'target.typehints.decr(a, b=1)\n'
+ '\n'
+ ' Returns:\n'
+ ' decremented number\n'
+ '\n'
+ ' Return type:\n'
+ ' int\n'
+ '\n'
+ 'target.typehints.tuple_args(x)\n'
+ '\n'
+ ' Parameters:\n'
+ ' **x** (*tuple**[**int**, **int** | **str**]*) -- arg\n'
+ '\n'
+ ' Returns:\n'
+ ' another tuple\n'
+ '\n'
+ ' Return type:\n'
+ ' tuple[int, int]\n'
+ in context)
+
+
+@pytest.mark.sphinx('text', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints': "description",
+ 'autodoc_typehints_description_target': 'documented_params'})
+def test_autodoc_typehints_description_no_undoc_doc_rtype(app):
+ # No :type: will be injected for `incr`, which does not have a description
+ # for its parameters or its return, just :rtype: will be injected due to
+ # autodoc_typehints_description_target. `tuple_args` does describe both, so
+ # :type: and :rtype: will be added. `nothing` has no parameters but a return
+ # type of None, which will be added.
+ with overwrite_file(app.srcdir / 'index.rst',
+ '.. autofunction:: target.typehints.incr\n'
+ '\n'
+ '.. autofunction:: target.typehints.decr\n'
+ '\n'
+ ' :returns: decremented number\n'
+ '\n'
+ '.. autofunction:: target.typehints.tuple_args\n'
+ '\n'
+ ' :param x: arg\n'
+ ' :return: another tuple\n'
+ '\n'
+ '.. autofunction:: target.typehints.Math.nothing\n'
+ '\n'
+ '.. autofunction:: target.typehints.Math.horse\n'
+ '\n'
+ ' :return: nothing\n'):
+ app.build()
+ context = (app.outdir / 'index.txt').read_text(encoding='utf8')
+ assert context == (
+ 'target.typehints.incr(a, b=1)\n'
+ '\n'
+ ' Return type:\n'
+ ' int\n'
+ '\n'
+ 'target.typehints.decr(a, b=1)\n'
+ '\n'
+ ' Returns:\n'
+ ' decremented number\n'
+ '\n'
+ ' Return type:\n'
+ ' int\n'
+ '\n'
+ 'target.typehints.tuple_args(x)\n'
+ '\n'
+ ' Parameters:\n'
+ ' **x** (*tuple**[**int**, **int** | **str**]*) -- arg\n'
+ '\n'
+ ' Returns:\n'
+ ' another tuple\n'
+ '\n'
+ ' Return type:\n'
+ ' tuple[int, int]\n'
+ '\n'
+ 'target.typehints.Math.nothing(self)\n'
+ '\n'
+ 'target.typehints.Math.horse(self, a, b)\n'
+ '\n'
+ ' Returns:\n'
+ ' nothing\n'
+ '\n'
+ ' Return type:\n'
+ ' None\n'
+ )
+
+
+@pytest.mark.sphinx('text', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints': "description"})
+def test_autodoc_typehints_description_with_documented_init(app):
+ with overwrite_file(app.srcdir / 'index.rst',
+ '.. autoclass:: target.typehints._ClassWithDocumentedInit\n'
+ ' :special-members: __init__\n'):
+ app.build()
+ context = (app.outdir / 'index.txt').read_text(encoding='utf8')
+ assert context == (
+ 'class target.typehints._ClassWithDocumentedInit(x, *args, **kwargs)\n'
+ '\n'
+ ' Class docstring.\n'
+ '\n'
+ ' Parameters:\n'
+ ' * **x** (*int*)\n'
+ '\n'
+ ' * **args** (*int*)\n'
+ '\n'
+ ' * **kwargs** (*int*)\n'
+ '\n'
+ ' __init__(x, *args, **kwargs)\n'
+ '\n'
+ ' Init docstring.\n'
+ '\n'
+ ' Parameters:\n'
+ ' * **x** (*int*) -- Some integer\n'
+ '\n'
+ ' * **args** (*int*) -- Some integer\n'
+ '\n'
+ ' * **kwargs** (*int*) -- Some integer\n'
+ '\n'
+ ' Return type:\n'
+ ' None\n'
+ )
+
+
+@pytest.mark.sphinx('text', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints': "description",
+ 'autodoc_typehints_description_target': 'documented'})
+def test_autodoc_typehints_description_with_documented_init_no_undoc(app):
+ with overwrite_file(app.srcdir / 'index.rst',
+ '.. autoclass:: target.typehints._ClassWithDocumentedInit\n'
+ ' :special-members: __init__\n'):
+ app.build()
+ context = (app.outdir / 'index.txt').read_text(encoding='utf8')
+ assert context == (
+ 'class target.typehints._ClassWithDocumentedInit(x, *args, **kwargs)\n'
+ '\n'
+ ' Class docstring.\n'
+ '\n'
+ ' __init__(x, *args, **kwargs)\n'
+ '\n'
+ ' Init docstring.\n'
+ '\n'
+ ' Parameters:\n'
+ ' * **x** (*int*) -- Some integer\n'
+ '\n'
+ ' * **args** (*int*) -- Some integer\n'
+ '\n'
+ ' * **kwargs** (*int*) -- Some integer\n'
+ )
+
+
+@pytest.mark.sphinx('text', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints': "description",
+ 'autodoc_typehints_description_target': 'documented_params'})
+def test_autodoc_typehints_description_with_documented_init_no_undoc_doc_rtype(app):
+ # see test_autodoc_typehints_description_with_documented_init_no_undoc
+ # returnvalue_and_documented_params should not change class or method
+ # docstring.
+ with overwrite_file(app.srcdir / 'index.rst',
+ '.. autoclass:: target.typehints._ClassWithDocumentedInit\n'
+ ' :special-members: __init__\n'):
+ app.build()
+ context = (app.outdir / 'index.txt').read_text(encoding='utf8')
+ assert context == (
+ 'class target.typehints._ClassWithDocumentedInit(x, *args, **kwargs)\n'
+ '\n'
+ ' Class docstring.\n'
+ '\n'
+ ' __init__(x, *args, **kwargs)\n'
+ '\n'
+ ' Init docstring.\n'
+ '\n'
+ ' Parameters:\n'
+ ' * **x** (*int*) -- Some integer\n'
+ '\n'
+ ' * **args** (*int*) -- Some integer\n'
+ '\n'
+ ' * **kwargs** (*int*) -- Some integer\n'
+ )
+
+
+@pytest.mark.sphinx('text', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints': "description"})
+def test_autodoc_typehints_description_for_invalid_node(app):
+ text = ".. py:function:: hello; world"
+ restructuredtext.parse(app, text) # raises no error
+
+
+@pytest.mark.sphinx('text', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints': "both"})
+def test_autodoc_typehints_both(app):
+ with overwrite_file(app.srcdir / 'index.rst',
+ '.. autofunction:: target.typehints.incr\n'
+ '\n'
+ '.. autofunction:: target.typehints.tuple_args\n'
+ '\n'
+ '.. autofunction:: target.overload.sum\n'):
+ app.build()
+ context = (app.outdir / 'index.txt').read_text(encoding='utf8')
+ assert ('target.typehints.incr(a: int, b: int = 1) -> int\n'
+ '\n'
+ ' Parameters:\n'
+ ' * **a** (*int*)\n'
+ '\n'
+ ' * **b** (*int*)\n'
+ '\n'
+ ' Return type:\n'
+ ' int\n'
+ in context)
+ assert ('target.typehints.tuple_args(x: tuple[int, int | str]) -> tuple[int, int]\n'
+ '\n'
+ ' Parameters:\n'
+ ' **x** (*tuple**[**int**, **int** | **str**]*)\n'
+ '\n'
+ ' Return type:\n'
+ ' tuple[int, int]\n'
+ in context)
+
+ # Overloads still get displayed in the signature
+ assert ('target.overload.sum(x: int, y: int = 0) -> int\n'
+ 'target.overload.sum(x: float, y: float = 0.0) -> float\n'
+ 'target.overload.sum(x: str, y: str = None) -> str\n'
+ '\n'
+ ' docstring\n'
+ in context)
+
+
+@pytest.mark.sphinx('text', testroot='ext-autodoc')
+def test_autodoc_type_aliases(app):
+ # default
+ options = {"members": None}
+ actual = do_autodoc(app, 'module', 'target.autodoc_type_aliases', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.autodoc_type_aliases',
+ '',
+ '',
+ '.. py:class:: Foo()',
+ ' :module: target.autodoc_type_aliases',
+ '',
+ ' docstring',
+ '',
+ '',
+ ' .. py:attribute:: Foo.attr1',
+ ' :module: target.autodoc_type_aliases',
+ ' :type: int',
+ '',
+ ' docstring',
+ '',
+ '',
+ ' .. py:attribute:: Foo.attr2',
+ ' :module: target.autodoc_type_aliases',
+ ' :type: int',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:function:: mult(x: int, y: int) -> int',
+ ' mult(x: float, y: float) -> float',
+ ' :module: target.autodoc_type_aliases',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:function:: read(r: ~_io.BytesIO) -> ~_io.StringIO',
+ ' :module: target.autodoc_type_aliases',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:function:: sum(x: int, y: int) -> int',
+ ' :module: target.autodoc_type_aliases',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:data:: variable',
+ ' :module: target.autodoc_type_aliases',
+ ' :type: int',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:data:: variable2',
+ ' :module: target.autodoc_type_aliases',
+ ' :type: int',
+ ' :value: None',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:data:: variable3',
+ ' :module: target.autodoc_type_aliases',
+ ' :type: int | None',
+ '',
+ ' docstring',
+ '',
+ ]
+
+ # define aliases
+ app.config.autodoc_type_aliases = {'myint': 'myint',
+ 'io.StringIO': 'my.module.StringIO'}
+ actual = do_autodoc(app, 'module', 'target.autodoc_type_aliases', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.autodoc_type_aliases',
+ '',
+ '',
+ '.. py:class:: Foo()',
+ ' :module: target.autodoc_type_aliases',
+ '',
+ ' docstring',
+ '',
+ '',
+ ' .. py:attribute:: Foo.attr1',
+ ' :module: target.autodoc_type_aliases',
+ ' :type: myint',
+ '',
+ ' docstring',
+ '',
+ '',
+ ' .. py:attribute:: Foo.attr2',
+ ' :module: target.autodoc_type_aliases',
+ ' :type: myint',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:function:: mult(x: myint, y: myint) -> myint',
+ ' mult(x: float, y: float) -> float',
+ ' :module: target.autodoc_type_aliases',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:function:: read(r: ~_io.BytesIO) -> my.module.StringIO',
+ ' :module: target.autodoc_type_aliases',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:function:: sum(x: myint, y: myint) -> myint',
+ ' :module: target.autodoc_type_aliases',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:data:: variable',
+ ' :module: target.autodoc_type_aliases',
+ ' :type: myint',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:data:: variable2',
+ ' :module: target.autodoc_type_aliases',
+ ' :type: myint',
+ ' :value: None',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:data:: variable3',
+ ' :module: target.autodoc_type_aliases',
+ ' :type: myint | None',
+ '',
+ ' docstring',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('text', testroot='ext-autodoc',
+ srcdir='autodoc_typehints_description_and_type_aliases',
+ confoverrides={'autodoc_typehints': "description",
+ 'autodoc_type_aliases': {'myint': 'myint'}})
+def test_autodoc_typehints_description_and_type_aliases(app):
+ with overwrite_file(app.srcdir / 'autodoc_type_aliases.rst',
+ '.. autofunction:: target.autodoc_type_aliases.sum'):
+ app.build()
+ context = (app.outdir / 'autodoc_type_aliases.txt').read_text(encoding='utf8')
+ assert context == (
+ 'target.autodoc_type_aliases.sum(x, y)\n'
+ '\n'
+ ' docstring\n'
+ '\n'
+ ' Parameters:\n'
+ ' * **x** (*myint*)\n'
+ '\n'
+ ' * **y** (*myint*)\n'
+ '\n'
+ ' Return type:\n'
+ ' myint\n'
+ )
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints_format': "fully-qualified"})
+def test_autodoc_typehints_format_fully_qualified(app):
+ if sys.version_info[:2] <= (3, 10):
+ type_o = "typing.Any | None"
+ else:
+ type_o = "typing.Any"
+
+ options = {"members": None,
+ "undoc-members": None}
+ actual = do_autodoc(app, 'module', 'target.typehints', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.typehints',
+ '',
+ '',
+ '.. py:data:: CONST1',
+ ' :module: target.typehints',
+ ' :type: int',
+ '',
+ '',
+ '.. py:data:: CONST2',
+ ' :module: target.typehints',
+ ' :type: int',
+ ' :value: 1',
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:data:: CONST3',
+ ' :module: target.typehints',
+ ' :type: pathlib.PurePosixPath',
+ " :value: PurePosixPath('/a/b/c')",
+ '',
+ ' docstring',
+ '',
+ '',
+ '.. py:class:: Math(s: str, o: %s = None)' % type_o,
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:attribute:: Math.CONST1',
+ ' :module: target.typehints',
+ ' :type: int',
+ '',
+ '',
+ ' .. py:attribute:: Math.CONST2',
+ ' :module: target.typehints',
+ ' :type: int',
+ ' :value: 1',
+ '',
+ '',
+ ' .. py:attribute:: Math.CONST3',
+ ' :module: target.typehints',
+ ' :type: pathlib.PurePosixPath',
+ " :value: PurePosixPath('/a/b/c')",
+ '',
+ '',
+ ' .. py:method:: Math.decr(a: int, b: int = 1) -> int',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:method:: Math.horse(a: str, b: int) -> None',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:method:: Math.incr(a: int, b: int = 1) -> int',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:method:: Math.nothing() -> None',
+ ' :module: target.typehints',
+ '',
+ '',
+ ' .. py:property:: Math.path',
+ ' :module: target.typehints',
+ ' :type: pathlib.PurePosixPath',
+ '',
+ '',
+ ' .. py:property:: Math.prop',
+ ' :module: target.typehints',
+ ' :type: int',
+ '',
+ '',
+ '.. py:class:: NewAnnotation(i: int)',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:class:: NewComment(i: int)',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:class:: SignatureFromMetaclass(a: int)',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:class:: T',
+ ' :module: target.typehints',
+ '',
+ ' docstring',
+ '',
+ " alias of TypeVar('T', bound=\\ :py:class:`pathlib.PurePosixPath`)",
+ '',
+ '',
+ '.. py:function:: complex_func(arg1: str, arg2: List[int], arg3: Tuple[int, '
+ 'Union[str, Unknown]] = None, *args: str, **kwargs: str) -> None',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:function:: decr(a: int, b: int = 1) -> int',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:function:: incr(a: int, b: int = 1) -> int',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:function:: missing_attr(c, a: str, b: Optional[str] = None) -> str',
+ ' :module: target.typehints',
+ '',
+ '',
+ '.. py:function:: tuple_args(x: tuple[int, int | str]) -> tuple[int, int]',
+ ' :module: target.typehints',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints_format': "fully-qualified"})
+def test_autodoc_typehints_format_fully_qualified_for_class_alias(app):
+ actual = do_autodoc(app, 'class', 'target.classes.Alias')
+ assert list(actual) == [
+ '',
+ '.. py:attribute:: Alias',
+ ' :module: target.classes',
+ '',
+ ' alias of :py:class:`target.classes.Foo`',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints_format': "fully-qualified"})
+def test_autodoc_typehints_format_fully_qualified_for_generic_alias(app):
+ actual = do_autodoc(app, 'data', 'target.genericalias.L')
+ assert list(actual) == [
+ '',
+ '.. py:data:: L',
+ ' :module: target.genericalias',
+ '',
+ ' A list of Class',
+ '',
+ ' alias of :py:class:`~typing.List`\\ [:py:class:`target.genericalias.Class`]',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc',
+ confoverrides={'autodoc_typehints_format': "fully-qualified"})
+def test_autodoc_typehints_format_fully_qualified_for_newtype_alias(app):
+ actual = do_autodoc(app, 'class', 'target.typevar.T6')
+ assert list(actual) == [
+ '',
+ '.. py:class:: T6',
+ ' :module: target.typevar',
+ '',
+ ' T6',
+ '',
+ ' alias of :py:class:`datetime.date`',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autodoc_default_options(app):
+ if (
+ (3, 11, 7) <= sys.version_info < (3, 12)
+ or sys.version_info >= (3, 12, 1)
+ ):
+ list_of_weak_references = " list of weak references to the object"
+ else:
+ list_of_weak_references = " list of weak references to the object (if defined)"
+
+ # no settings
+ actual = do_autodoc(app, 'class', 'target.enums.EnumCls')
+ assert ' .. py:attribute:: EnumCls.val1' 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
+ actual = do_autodoc(app, 'module', 'target')
+ assert '.. py:function:: function_to_be_imported(app)' not in actual
+
+ # with :members:
+ 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
+
+ # with :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
+
+ # with :members: and :undoc-members:
+ app.config.autodoc_default_options = {
+ 'members': None,
+ 'undoc-members': None,
+ }
+ actual = do_autodoc(app, 'class', 'target.enums.EnumCls')
+ assert ' .. py:attribute:: EnumCls.val1' 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_options = {
+ '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 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_options = {
+ 'members': None,
+ 'exclude-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
+ app.config.autodoc_default_options = {
+ '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 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_options_with_values(app):
+ if (
+ (3, 11, 7) <= sys.version_info < (3, 12)
+ or sys.version_info >= (3, 12, 1)
+ ):
+ list_of_weak_references = " list of weak references to the object"
+ else:
+ list_of_weak_references = " list of weak references to the object (if defined)"
+
+ # with :members:
+ app.config.autodoc_default_options = {'members': 'val1,val2'}
+ actual = do_autodoc(app, 'class', 'target.enums.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 :member-order:
+ app.config.autodoc_default_options = {
+ 'members': None,
+ 'member-order': 'bysource',
+ }
+ actual = do_autodoc(app, 'class', 'target.Class')
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:class:: Class(arg)',
+ ' .. py:method:: Class.meth()',
+ ' .. py:method:: Class.skipmeth()',
+ ' .. py:method:: Class.excludemeth()',
+ ' .. py:attribute:: Class.attr',
+ ' .. py:attribute:: Class.docattr',
+ ' .. py:attribute:: Class.udocattr',
+ ' .. py:attribute:: Class.mdocattr',
+ ' .. py:method:: Class.moore(a, e, f) -> happiness',
+ ' .. py:attribute:: Class.inst_attr_inline',
+ ' .. py:attribute:: Class.inst_attr_comment',
+ ' .. py:attribute:: Class.inst_attr_string',
+ ]
+
+ # with :special-members:
+ app.config.autodoc_default_options = {
+ '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 not in actual
+
+ # with :exclude-members:
+ app.config.autodoc_default_options = {
+ 'members': None,
+ 'exclude-members': 'val1',
+ }
+ actual = do_autodoc(app, 'class', 'target.enums.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_options = {
+ '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 not in actual
+ assert ' .. py:method:: CustomIter.snafucate()' not in actual
+ assert ' Makes this snafucated.' not in actual