2014-01-18 12:56:23 -06:00
|
|
|
"""Tests for :mod:`sphinx.ext.napoleon.__init__` module."""
|
|
|
|
|
2023-07-28 17:24:13 -05:00
|
|
|
import functools
|
2014-04-19 02:58:11 -05:00
|
|
|
from collections import namedtuple
|
2024-09-25 02:57:11 -05:00
|
|
|
from typing import Any
|
2023-02-17 17:05:57 -06:00
|
|
|
from unittest import mock
|
|
|
|
|
|
|
|
import pytest
|
2014-01-18 12:56:23 -06:00
|
|
|
|
2018-02-19 07:39:14 -06:00
|
|
|
from sphinx.application import Sphinx
|
2020-11-11 05:00:27 -06:00
|
|
|
from sphinx.ext.napoleon import Config, _process_docstring, _skip_member, setup
|
2023-07-28 17:24:13 -05:00
|
|
|
|
|
|
|
|
|
|
|
def simple_decorator(f):
|
|
|
|
"""
|
|
|
|
A simple decorator that does nothing, for tests to use.
|
|
|
|
"""
|
2024-08-11 08:58:56 -05:00
|
|
|
|
2023-07-28 17:24:13 -05:00
|
|
|
@functools.wraps(f)
|
|
|
|
def wrapper(*args, **kwargs):
|
|
|
|
return f(*args, **kwargs)
|
2024-08-11 08:58:56 -05:00
|
|
|
|
2023-07-28 17:24:13 -05:00
|
|
|
return wrapper
|
2018-02-19 07:39:14 -06:00
|
|
|
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
def _private_doc():
|
|
|
|
"""module._private_doc.DOCSTRING"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def _private_undoc():
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def __special_doc__():
|
|
|
|
"""module.__special_doc__.DOCSTRING"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def __special_undoc__():
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2018-09-11 08:48:35 -05:00
|
|
|
class SampleClass:
|
2014-01-18 12:56:23 -06:00
|
|
|
def _private_doc(self):
|
|
|
|
"""SampleClass._private_doc.DOCSTRING"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
def _private_undoc(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def __special_doc__(self):
|
|
|
|
"""SampleClass.__special_doc__.DOCSTRING"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
def __special_undoc__(self):
|
|
|
|
pass
|
|
|
|
|
2020-07-03 18:57:15 -05:00
|
|
|
@simple_decorator
|
|
|
|
def __decorated_func__(self):
|
2024-01-14 15:13:46 -06:00
|
|
|
"""Doc"""
|
2020-07-03 18:57:15 -05:00
|
|
|
pass
|
|
|
|
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
class SampleError(Exception):
|
|
|
|
def _private_doc(self):
|
|
|
|
"""SampleError._private_doc.DOCSTRING"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
def _private_undoc(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def __special_doc__(self):
|
|
|
|
"""SampleError.__special_doc__.DOCSTRING"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
def __special_undoc__(self):
|
|
|
|
pass
|
|
|
|
|
2016-11-21 18:12:23 -06:00
|
|
|
|
2014-04-19 02:58:11 -05:00
|
|
|
SampleNamedTuple = namedtuple('SampleNamedTuple', 'user_id block_type def_id')
|
|
|
|
|
2014-01-18 12:56:23 -06:00
|
|
|
|
2023-02-17 17:05:57 -06:00
|
|
|
class TestProcessDocstring:
|
2014-01-18 12:56:23 -06:00
|
|
|
def test_modify_in_place(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
lines = [
|
|
|
|
'Summary line.',
|
|
|
|
'',
|
|
|
|
'Args:',
|
|
|
|
' arg1: arg1 description',
|
|
|
|
]
|
2014-08-10 02:31:28 -05:00
|
|
|
app = mock.Mock()
|
2014-01-18 12:56:23 -06:00
|
|
|
app.config = Config()
|
2024-08-11 08:58:56 -05:00
|
|
|
_process_docstring(
|
|
|
|
app,
|
|
|
|
'class',
|
|
|
|
'SampleClass',
|
|
|
|
SampleClass,
|
|
|
|
mock.Mock(),
|
|
|
|
lines,
|
|
|
|
)
|
|
|
|
|
|
|
|
expected = [
|
|
|
|
'Summary line.',
|
|
|
|
'',
|
|
|
|
':param arg1: arg1 description',
|
|
|
|
'',
|
|
|
|
]
|
|
|
|
assert lines == expected
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
|
2023-02-17 17:05:57 -06:00
|
|
|
class TestSetup:
|
2014-01-18 12:56:23 -06:00
|
|
|
def test_unknown_app_type(self):
|
|
|
|
setup(object())
|
|
|
|
|
|
|
|
def test_add_config_values(self):
|
2014-08-10 02:31:28 -05:00
|
|
|
app = mock.Mock(Sphinx)
|
2014-01-18 12:56:23 -06:00
|
|
|
setup(app)
|
2022-01-14 02:58:02 -06:00
|
|
|
for name in Config._config_values:
|
2014-01-18 12:56:23 -06:00
|
|
|
has_config = False
|
2022-01-10 03:21:53 -06:00
|
|
|
for method_name, args, _kwargs in app.method_calls:
|
2024-08-11 08:58:56 -05:00
|
|
|
if method_name == 'add_config_value' and args[0] == name:
|
2014-01-18 12:56:23 -06:00
|
|
|
has_config = True
|
|
|
|
if not has_config:
|
2023-02-17 17:05:57 -06:00
|
|
|
pytest.fail('Config value was not added to app %s' % name)
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
has_process_docstring = False
|
|
|
|
has_skip_member = False
|
2022-01-10 03:21:53 -06:00
|
|
|
for method_name, args, _kwargs in app.method_calls:
|
2014-01-18 12:56:23 -06:00
|
|
|
if method_name == 'connect':
|
2022-08-01 11:05:25 -05:00
|
|
|
if (
|
2024-08-11 08:58:56 -05:00
|
|
|
args[0] == 'autodoc-process-docstring'
|
|
|
|
and args[1] == _process_docstring
|
2022-08-01 11:05:25 -05:00
|
|
|
):
|
2014-01-18 12:56:23 -06:00
|
|
|
has_process_docstring = True
|
2024-08-11 08:58:56 -05:00
|
|
|
elif args[0] == 'autodoc-skip-member' and args[1] == _skip_member:
|
2014-01-18 12:56:23 -06:00
|
|
|
has_skip_member = True
|
|
|
|
if not has_process_docstring:
|
2023-02-17 17:05:57 -06:00
|
|
|
pytest.fail('autodoc-process-docstring never connected')
|
2014-01-18 12:56:23 -06:00
|
|
|
if not has_skip_member:
|
2023-02-17 17:05:57 -06:00
|
|
|
pytest.fail('autodoc-skip-member never connected')
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
|
2023-02-17 17:05:57 -06:00
|
|
|
class TestSkipMember:
|
2024-09-25 02:57:11 -05:00
|
|
|
def assert_skip(
|
|
|
|
self,
|
|
|
|
what: str,
|
|
|
|
member: str,
|
|
|
|
obj: Any,
|
|
|
|
expect_default_skip: bool,
|
|
|
|
config_name: str,
|
|
|
|
) -> None:
|
2016-11-23 12:45:39 -06:00
|
|
|
skip = True
|
2014-08-10 02:31:28 -05:00
|
|
|
app = mock.Mock()
|
2014-01-18 12:56:23 -06:00
|
|
|
app.config = Config()
|
|
|
|
setattr(app.config, config_name, True)
|
2016-11-23 12:45:39 -06:00
|
|
|
if expect_default_skip:
|
2023-02-17 17:05:57 -06:00
|
|
|
assert None is _skip_member(app, what, member, obj, skip, mock.Mock())
|
2014-01-18 12:56:23 -06:00
|
|
|
else:
|
2023-02-17 17:05:57 -06:00
|
|
|
assert _skip_member(app, what, member, obj, skip, mock.Mock()) is False
|
2014-01-18 12:56:23 -06:00
|
|
|
setattr(app.config, config_name, False)
|
2023-02-17 17:05:57 -06:00
|
|
|
assert None is _skip_member(app, what, member, obj, skip, mock.Mock())
|
2014-01-18 12:56:23 -06:00
|
|
|
|
2014-04-19 02:58:11 -05:00
|
|
|
def test_namedtuple(self):
|
2022-06-16 13:33:55 -05:00
|
|
|
# Since python 3.7, namedtuple._asdict() has not been documented
|
|
|
|
# because there is no way to check the method is a member of the
|
|
|
|
# namedtuple class. This testcase confirms only it does not
|
|
|
|
# raise an error on building document (refs: #1455)
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'class',
|
|
|
|
'_asdict',
|
|
|
|
SampleNamedTuple._asdict,
|
|
|
|
True,
|
|
|
|
'napoleon_include_private_with_doc',
|
|
|
|
)
|
2014-04-19 02:58:11 -05:00
|
|
|
|
2014-01-18 12:56:23 -06:00
|
|
|
def test_class_private_doc(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'class',
|
|
|
|
'_private_doc',
|
|
|
|
SampleClass._private_doc,
|
|
|
|
False,
|
|
|
|
'napoleon_include_private_with_doc',
|
|
|
|
)
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
def test_class_private_undoc(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'class',
|
|
|
|
'_private_undoc',
|
|
|
|
SampleClass._private_undoc,
|
|
|
|
True,
|
|
|
|
'napoleon_include_private_with_doc',
|
|
|
|
)
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
def test_class_special_doc(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'class',
|
|
|
|
'__special_doc__',
|
|
|
|
SampleClass.__special_doc__,
|
|
|
|
False,
|
|
|
|
'napoleon_include_special_with_doc',
|
|
|
|
)
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
def test_class_special_undoc(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'class',
|
|
|
|
'__special_undoc__',
|
|
|
|
SampleClass.__special_undoc__,
|
|
|
|
True,
|
|
|
|
'napoleon_include_special_with_doc',
|
|
|
|
)
|
2014-01-18 12:56:23 -06:00
|
|
|
|
2020-07-03 18:57:15 -05:00
|
|
|
def test_class_decorated_doc(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'class',
|
|
|
|
'__decorated_func__',
|
|
|
|
SampleClass.__decorated_func__,
|
|
|
|
False,
|
|
|
|
'napoleon_include_special_with_doc',
|
|
|
|
)
|
2020-07-03 18:57:15 -05:00
|
|
|
|
2014-01-18 12:56:23 -06:00
|
|
|
def test_exception_private_doc(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'exception',
|
|
|
|
'_private_doc',
|
|
|
|
SampleError._private_doc,
|
|
|
|
False,
|
|
|
|
'napoleon_include_private_with_doc',
|
|
|
|
)
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
def test_exception_private_undoc(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'exception',
|
|
|
|
'_private_undoc',
|
|
|
|
SampleError._private_undoc,
|
|
|
|
True,
|
|
|
|
'napoleon_include_private_with_doc',
|
|
|
|
)
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
def test_exception_special_doc(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'exception',
|
|
|
|
'__special_doc__',
|
|
|
|
SampleError.__special_doc__,
|
|
|
|
False,
|
|
|
|
'napoleon_include_special_with_doc',
|
|
|
|
)
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
def test_exception_special_undoc(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'exception',
|
|
|
|
'__special_undoc__',
|
|
|
|
SampleError.__special_undoc__,
|
|
|
|
True,
|
|
|
|
'napoleon_include_special_with_doc',
|
|
|
|
)
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
def test_module_private_doc(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'module',
|
|
|
|
'_private_doc',
|
|
|
|
_private_doc,
|
|
|
|
False,
|
|
|
|
'napoleon_include_private_with_doc',
|
|
|
|
)
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
def test_module_private_undoc(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'module',
|
|
|
|
'_private_undoc',
|
|
|
|
_private_undoc,
|
|
|
|
True,
|
|
|
|
'napoleon_include_private_with_doc',
|
|
|
|
)
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
def test_module_special_doc(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'module',
|
|
|
|
'__special_doc__',
|
|
|
|
__special_doc__,
|
|
|
|
False,
|
|
|
|
'napoleon_include_special_with_doc',
|
|
|
|
)
|
2014-01-18 12:56:23 -06:00
|
|
|
|
|
|
|
def test_module_special_undoc(self):
|
2024-08-11 08:58:56 -05:00
|
|
|
self.assert_skip(
|
|
|
|
'module',
|
|
|
|
'__special_undoc__',
|
|
|
|
__special_undoc__,
|
|
|
|
True,
|
|
|
|
'napoleon_include_special_with_doc',
|
|
|
|
)
|