sphinx/tests/test_extensions/test_ext_autodoc_configs.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1851 lines
54 KiB
Python
Raw Normal View History

"""Test the autodoc extension. This tests mainly for config variables"""
import platform
import sys
2024-10-25 16:41:08 -05:00
from collections.abc import Iterator
from contextlib import contextmanager
2024-10-25 16:41:08 -05:00
from pathlib import Path
import pytest
from sphinx.testing import restructuredtext
from tests.test_extensions.autodoc_util import do_autodoc
2024-10-17 19:22:37 -05:00
skip_py314_segfault = pytest.mark.skipif(
sys.version_info[:2] >= (3, 14),
reason='Segmentation fault: https://github.com/python/cpython/issues/125017',
)
IS_PYPY = platform.python_implementation() == 'PyPy'
@contextmanager
2024-10-25 16:41:08 -05:00
def overwrite_file(path: Path, content: str) -> Iterator[None]:
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'
2024-08-11 08:58:56 -05:00
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'
2024-08-11 08:58:56 -05:00
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'
2024-08-11 08:58:56 -05:00
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'
2024-08-11 08:58:56 -05:00
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',
'',
]
2024-10-17 19:22:37 -05:00
@skip_py314_segfault
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_class_signature_separated_new(app):
app.config.autodoc_class_signature = 'separated'
2024-08-11 08:58:56 -05:00
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'
2024-08-11 08:58:56 -05:00
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',
2023-02-17 16:11:14 -06:00
'',
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_inherit_docstrings_for_inherited_members(app):
2024-08-11 08:58:56 -05:00
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.',
'',
]
2024-10-17 19:22:37 -05:00
@skip_py314_segfault
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_docstring_signature(app):
2024-08-11 08:58:56 -05:00
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'
2024-08-11 08:58:56 -05:00
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'
2024-08-11 08:58:56 -05:00
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'
2024-08-11 08:58:56 -05:00
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')
2024-08-11 08:58:56 -05:00
@pytest.mark.usefixtures('rollback_sysmodules')
def test_mocked_module_imports(app):
sys.modules.pop('target', None) # unload target module to clear the module cache
# no autodoc_mock_imports
2024-08-11 08:58:56 -05:00
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 app.warning.getvalue()
# with autodoc_mock_imports
app.config.autodoc_mock_imports = [
'missing_module',
'missing_package1',
'missing_package2',
'missing_package3',
'sphinx.missing_module4',
]
app.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 app.warning.getvalue() == ''
2024-08-11 08:58:56 -05:00
@pytest.mark.sphinx(
'html',
testroot='ext-autodoc',
confoverrides={'autodoc_typehints': 'signature'},
)
def test_autodoc_typehints_signature(app):
2024-05-14 23:28:40 -05:00
if sys.version_info[:2] >= (3, 13):
2024-08-11 08:58:56 -05:00
type_ppp = 'pathlib._local.PurePosixPath'
2024-05-14 23:28:40 -05:00
else:
2024-08-11 08:58:56 -05:00
type_ppp = 'pathlib.PurePosixPath'
2024-08-11 08:58:56 -05:00
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',
2024-05-14 23:28:40 -05:00
f' :type: ~{type_ppp}',
" :value: PurePosixPath('/a/b/c')",
'',
' docstring',
'',
'',
2024-10-17 14:59:41 -05:00
'.. py:class:: Math(s: str, o: ~typing.Any = None)',
' :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',
2024-05-14 23:28:40 -05:00
f' :type: ~{type_ppp}',
" :value: PurePosixPath('/a/b/c')",
'',
'',
' .. py:method:: Math.decr(a: int, b: int = 1) -> int',
' :module: target.typehints',
'',
'',
2020-02-13 09:27:58 -06:00
' .. 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',
'',
'',
2020-02-13 09:27:58 -06:00
' .. py:method:: Math.nothing() -> None',
' :module: target.typehints',
'',
'',
' .. py:property:: Math.path',
' :module: target.typehints',
2024-05-14 23:28:40 -05:00
f' :type: ~{type_ppp}',
'',
'',
' .. 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',
'',
2024-05-14 23:28:40 -05:00
f" alias of TypeVar('T', bound=\\ :py:class:`~{type_ppp}`)",
'',
'',
'.. 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',
2020-02-13 09:27:58 -06:00
'',
'',
'.. py:function:: missing_attr(c, a: str, b: Optional[str] = None) -> str',
2020-02-13 09:27:58 -06:00
' :module: target.typehints',
'',
'',
2023-01-01 18:01:14 -06:00
'.. py:function:: tuple_args(x: tuple[int, int | str]) -> tuple[int, int]',
' :module: target.typehints',
'',
]
2024-08-11 08:58:56 -05:00
@pytest.mark.sphinx(
'html',
testroot='ext-autodoc',
confoverrides={'autodoc_typehints': 'none'},
)
def test_autodoc_typehints_none(app):
2024-05-14 23:28:40 -05:00
if sys.version_info[:2] >= (3, 13):
2024-08-11 08:58:56 -05:00
type_ppp = 'pathlib._local.PurePosixPath'
2024-05-14 23:28:40 -05:00
else:
2024-08-11 08:58:56 -05:00
type_ppp = 'pathlib.PurePosixPath'
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',
'',
'',
2020-02-13 09:27:58 -06:00
' .. py:method:: Math.horse(a, b)',
' :module: target.typehints',
'',
'',
' .. py:method:: Math.incr(a, b=1)',
' :module: target.typehints',
'',
'',
2020-02-13 09:27:58 -06:00
' .. 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',
'',
2024-05-14 23:28:40 -05:00
f" alias of TypeVar('T', bound=\\ :py:class:`~{type_ppp}`)",
'',
'',
'.. 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',
2020-02-13 09:27:58 -06:00
'',
'',
'.. py:function:: missing_attr(c, a, b=None)',
' :module: target.typehints',
'',
'',
'.. py:function:: tuple_args(x)',
' :module: target.typehints',
'',
]
2024-08-11 08:58:56 -05:00
@pytest.mark.sphinx(
'html',
testroot='ext-autodoc',
confoverrides={'autodoc_typehints': 'none'},
)
def test_autodoc_typehints_none_for_overload(app):
2024-08-11 08:58:56 -05:00
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',
'',
]
2024-08-11 08:58:56 -05:00
@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')
2024-08-11 08:58:56 -05:00
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
2021-09-07 19:15:25 -05:00
# Overloads still get displayed in the signature
2024-08-11 08:58:56 -05:00
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
2024-08-11 08:58:56 -05:00
@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.
2024-08-11 08:58:56 -05:00
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')
2024-08-11 08:58:56 -05:00
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',
},
)
2021-11-29 12:55:26 -06:00
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.
2024-08-11 08:58:56 -05:00
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'
2023-01-01 18:01:14 -06:00
' **x** (*tuple**[**int**, **int** | **str**]*) -- arg\n'
'\n'
' Returns:\n'
' another tuple\n'
'\n'
' Return type:\n'
2023-01-01 18:01:14 -06:00
' 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'
)
2021-11-29 12:55:26 -06:00
2024-08-11 08:58:56 -05:00
@pytest.mark.sphinx(
'text',
testroot='ext-autodoc',
confoverrides={'autodoc_typehints': 'description'},
)
def test_autodoc_typehints_description_with_documented_init(app):
2024-08-11 08:58:56 -05:00
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'
)
2024-08-11 08:58:56 -05:00
@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):
2024-08-11 08:58:56 -05:00
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'
)
2021-11-29 12:55:26 -06:00
2024-08-11 08:58:56 -05:00
@pytest.mark.sphinx(
'text',
testroot='ext-autodoc',
confoverrides={
'autodoc_typehints': 'description',
'autodoc_typehints_description_target': 'documented_params',
},
)
2021-11-29 12:55:26 -06:00
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.
2024-08-11 08:58:56 -05:00
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'
)
2024-08-11 08:58:56 -05:00
@pytest.mark.sphinx(
'text',
testroot='ext-autodoc',
confoverrides={'autodoc_typehints': 'description'},
)
def test_autodoc_typehints_description_for_invalid_node(app):
2024-08-11 08:58:56 -05:00
text = '.. py:function:: hello; world'
restructuredtext.parse(app, text) # raises no error
2024-08-11 08:58:56 -05:00
@pytest.mark.sphinx(
'text',
testroot='ext-autodoc',
confoverrides={'autodoc_typehints': 'both'},
)
def test_autodoc_typehints_both(app):
2024-08-11 08:58:56 -05:00
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')
2024-08-11 08:58:56 -05:00
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
2021-09-07 19:15:25 -05:00
# Overloads still get displayed in the signature
2024-08-11 08:58:56 -05:00
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
2024-08-11 08:58:56 -05:00
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
2024-08-11 08:58:56 -05:00
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',
'',
]
2024-08-11 08:58:56 -05:00
@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):
2024-08-11 08:58:56 -05:00
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'
)
2024-08-11 08:58:56 -05:00
@pytest.mark.sphinx(
'html',
testroot='ext-autodoc',
confoverrides={'autodoc_typehints_format': 'fully-qualified'},
)
def test_autodoc_typehints_format_fully_qualified(app):
2024-05-14 23:28:40 -05:00
if sys.version_info[:2] >= (3, 13):
2024-08-11 08:58:56 -05:00
type_ppp = 'pathlib._local.PurePosixPath'
2024-05-14 23:28:40 -05:00
else:
2024-08-11 08:58:56 -05:00
type_ppp = 'pathlib.PurePosixPath'
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',
2024-05-14 23:28:40 -05:00
f' :type: {type_ppp}',
" :value: PurePosixPath('/a/b/c')",
'',
' docstring',
'',
'',
2024-10-17 14:59:41 -05:00
'.. py:class:: Math(s: str, o: typing.Any = None)',
' :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',
2024-05-14 23:28:40 -05:00
f' :type: {type_ppp}',
" :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',
2024-05-14 23:28:40 -05:00
f' :type: {type_ppp}',
'',
'',
' .. 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',
'',
2024-05-14 23:28:40 -05:00
f" alias of TypeVar('T', bound=\\ :py:class:`{type_ppp}`)",
'',
'',
'.. 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',
'',
'',
2023-01-01 18:01:14 -06:00
'.. py:function:: tuple_args(x: tuple[int, int | str]) -> tuple[int, int]',
' :module: target.typehints',
'',
]
2024-08-11 08:58:56 -05:00
@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`',
]
2024-08-11 08:58:56 -05:00
@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')
2022-06-16 13:33:55 -05:00
assert list(actual) == [
'',
'.. py:data:: L',
' :module: target.genericalias',
'',
' A list of Class',
'',
' alias of :py:class:`~typing.List`\\ [:py:class:`target.genericalias.Class`]',
'',
]
2024-08-11 08:58:56 -05:00
@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):
2024-08-11 08:58:56 -05:00
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:
2024-08-11 08:58:56 -05:00
list_of_weak_references = " list of weak references to the object (if defined)" # fmt: skip
# 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')
2019-06-08 11:27:34 -05:00
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
2021-02-01 03:58:09 -06:00
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,
2023-02-17 16:11:14 -06:00
'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):
2024-08-11 08:58:56 -05:00
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:
2024-08-11 08:58:56 -05:00
list_of_weak_references = " list of weak references to the object (if defined)" # fmt: skip
# 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,
2023-02-17 16:11:14 -06:00
'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