summaryrefslogtreecommitdiff
path: root/tests/test_autodoc.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_autodoc.py')
-rw-r--r--tests/test_autodoc.py451
1 files changed, 295 insertions, 156 deletions
diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py
index a86211f18..741c4bb60 100644
--- a/tests/test_autodoc.py
+++ b/tests/test_autodoc.py
@@ -22,6 +22,13 @@ from sphinx.testing.util import SphinxTestApp, Struct # NOQA
from sphinx.util import logging
from sphinx.util.docutils import LoggingReporter
+try:
+ # Enable pyximport to test cython module
+ import pyximport
+ pyximport.install()
+except ImportError:
+ pyximport = None
+
app = None
@@ -193,7 +200,7 @@ def test_format_signature():
assert formatsig('function', 'f', f, None, None) == '(a, b, c=1, **d)'
assert formatsig('function', 'f', f, 'a, b, c, d', None) == '(a, b, c, d)'
assert formatsig('function', 'f', f, None, 'None') == '(a, b, c=1, **d) -> None'
- assert formatsig('function', 'g', g, None, None) == r"(a='\\n')"
+ assert formatsig('function', 'g', g, None, None) == r"(a='\n')"
# test for classes
class D:
@@ -247,12 +254,12 @@ def test_format_signature():
assert formatsig('method', 'H.foo', H.foo1, None, None) == '(b, *c)'
assert formatsig('method', 'H.foo', H.foo1, 'a', None) == '(a)'
assert formatsig('method', 'H.foo', H.foo2, None, None) == '(*c)'
- assert formatsig('method', 'H.foo', H.foo3, None, None) == r"(d='\\n')"
+ assert formatsig('method', 'H.foo', H.foo3, None, None) == r"(d='\n')"
# test bound methods interpreted as functions
assert formatsig('function', 'foo', H().foo1, None, None) == '(b, *c)'
assert formatsig('function', 'foo', H().foo2, None, None) == '(*c)'
- assert formatsig('function', 'foo', H().foo3, None, None) == r"(d='\\n')"
+ assert formatsig('function', 'foo', H().foo3, None, None) == r"(d='\n')"
# test exception handling (exception is caught and args is '')
directive.env.config.autodoc_docstring_signature = False
@@ -361,7 +368,7 @@ def test_new_documenter(app):
' :module: target',
'',
' documentation for the integer',
- ' '
+ '',
]
@@ -420,7 +427,7 @@ def test_py_module(app, warning):
' :module: target',
'',
' Function.',
- ' '
+ '',
]
assert ("don't know which module to import for autodocumenting 'Class.meth'"
not in warning.getvalue())
@@ -435,7 +442,7 @@ def test_autodoc_decorator(app):
' :module: target.decorator',
'',
' docstring for deco1',
- ' '
+ '',
]
actual = do_autodoc(app, 'decorator', 'target.decorator.deco2')
@@ -445,7 +452,7 @@ def test_autodoc_decorator(app):
' :module: target.decorator',
'',
' docstring for deco2',
- ' '
+ '',
]
@@ -458,7 +465,7 @@ def test_autodoc_exception(app):
' :module: target',
'',
' My custom exception.',
- ' '
+ '',
]
@@ -582,6 +589,30 @@ def test_autodoc_inherited_members(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autodoc_inherited_members_Base(app):
+ options = {"members": None,
+ "inherited-members": "Base",
+ "special-members": None}
+
+ # check methods for object class are shown
+ actual = do_autodoc(app, 'class', 'target.inheritance.Derived', options)
+ assert ' .. py:method:: Derived.inheritedmeth()' in actual
+ assert ' .. py:method:: Derived.inheritedclassmeth' not in actual
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autodoc_inherited_members_None(app):
+ options = {"members": None,
+ "inherited-members": "None",
+ "special-members": None}
+
+ # check methods for object class are shown
+ actual = do_autodoc(app, 'class', 'target.inheritance.Derived', options)
+ assert ' .. py:method:: Derived.__init__' in actual
+ assert ' .. py:method:: Derived.__str__' in actual
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_imported_members(app):
options = {"members": None,
"imported-members": None,
@@ -661,6 +692,7 @@ def test_autodoc_ignore_module_all(app):
assert list(filter(lambda l: 'class::' in l, actual)) == [
'.. py:class:: Class(arg)',
'.. py:class:: CustomDict',
+ '.. py:class:: InnerChild',
'.. py:class:: InstAttCls()',
'.. py:class:: Outer',
' .. py:class:: Outer.Inner',
@@ -701,7 +733,7 @@ def test_autodoc_subclass_of_builtin_class(app):
' :module: target',
'',
' Docstring.',
- ' '
+ '',
]
@@ -715,23 +747,23 @@ def test_autodoc_inner_class(app):
' :module: target',
'',
' Foo',
- ' ',
- ' ',
+ '',
+ '',
' .. py:class:: Outer.Inner',
' :module: target',
- ' ',
+ '',
' Foo',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: Outer.Inner.meth()',
' :module: target',
- ' ',
+ '',
' Foo',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: Outer.factory',
' :module: target',
- ' ',
+ '',
' alias of :class:`builtins.dict`'
]
@@ -742,13 +774,25 @@ def test_autodoc_inner_class(app):
' :module: target.Outer',
'',
' Foo',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: Inner.meth()',
' :module: target.Outer',
- ' ',
+ '',
' Foo',
- ' ',
+ '',
+ ]
+
+ options['show-inheritance'] = True
+ actual = do_autodoc(app, 'class', 'target.InnerChild', options)
+ assert list(actual) == [
+ '',
+ '.. py:class:: InnerChild',
+ ' :module: target', '',
+ ' Bases: :class:`target.Outer.Inner`',
+ '',
+ ' InnerChild docstring',
+ '',
]
@@ -762,7 +806,7 @@ def test_autodoc_classmethod(app):
' :classmethod:',
'',
' Inherited class method.',
- ' '
+ '',
]
@@ -776,7 +820,7 @@ def test_autodoc_staticmethod(app):
' :staticmethod:',
'',
' Inherited static method.',
- ' '
+ '',
]
@@ -790,19 +834,19 @@ def test_autodoc_descriptor(app):
'.. py:class:: Class',
' :module: target.descriptor',
'',
- ' ',
+ '',
' .. py:attribute:: Class.descr',
' :module: target.descriptor',
- ' ',
+ '',
' Descriptor instance docstring.',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: Class.prop',
' :module: target.descriptor',
' :property:',
- ' ',
+ '',
' Property.',
- ' '
+ ''
]
@@ -817,7 +861,7 @@ def test_autodoc_c_module(app):
" Convert a time tuple to a string, e.g. 'Sat Jun 06 16:26:11 1998'.",
' When the time tuple is not present, current time as returned by localtime()',
' is used.',
- ' '
+ '',
]
@@ -909,7 +953,7 @@ def test_autodoc_module_scope(app):
' :value: <_io.StringIO object>',
'',
' should be documented as well - süß',
- ' '
+ '',
]
@@ -925,7 +969,7 @@ def test_autodoc_class_scope(app):
' :value: <_io.StringIO object>',
'',
' should be documented as well - süß',
- ' '
+ '',
]
@@ -939,16 +983,16 @@ def test_class_attributes(app):
'.. py:class:: AttCls',
' :module: target',
'',
- ' ',
+ '',
' .. py:attribute:: AttCls.a1',
' :module: target',
' :value: hello world',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: AttCls.a2',
' :module: target',
' :value: None',
- ' '
+ ''
]
@@ -962,43 +1006,43 @@ def test_instance_attributes(app):
' :module: target',
'',
' Class with documented class and instance attributes.',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: InstAttCls.ca1',
' :module: target',
" :value: 'a'",
- ' ',
+ '',
' Doc comment for class attribute InstAttCls.ca1.',
' It can have multiple lines.',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: InstAttCls.ca2',
' :module: target',
" :value: 'b'",
- ' ',
+ '',
' Doc comment for InstAttCls.ca2. One line only.',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: InstAttCls.ca3',
' :module: target',
" :value: 'c'",
- ' ',
+ '',
' Docstring for class attribute InstAttCls.ca3.',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: InstAttCls.ia1',
' :module: target',
' :value: None',
- ' ',
+ '',
' Doc comment for instance attribute InstAttCls.ia1',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: InstAttCls.ia2',
' :module: target',
' :value: None',
- ' ',
+ '',
' Docstring for instance attribute InstAttCls.ia2.',
- ' '
+ ''
]
# pick up arbitrary attributes
@@ -1010,22 +1054,22 @@ def test_instance_attributes(app):
' :module: target',
'',
' Class with documented class and instance attributes.',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: InstAttCls.ca1',
' :module: target',
" :value: 'a'",
- ' ',
+ '',
' Doc comment for class attribute InstAttCls.ca1.',
' It can have multiple lines.',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: InstAttCls.ia1',
' :module: target',
' :value: None',
- ' ',
+ '',
' Doc comment for instance attribute InstAttCls.ia1',
- ' '
+ ''
]
@@ -1042,30 +1086,30 @@ def test_slots(app):
'.. py:class:: Bar()',
' :module: target.slots',
'',
- ' ',
+ '',
' .. py:attribute:: Bar.attr1',
' :module: target.slots',
- ' ',
+ '',
' docstring of attr1',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: Bar.attr2',
' :module: target.slots',
- ' ',
+ '',
' docstring of instance attr2',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: Bar.attr3',
' :module: target.slots',
- ' ',
+ '',
'',
'.. py:class:: Foo',
' :module: target.slots',
'',
- ' ',
+ '',
' .. py:attribute:: Foo.attr',
' :module: target.slots',
- ' ',
+ '',
]
@@ -1080,39 +1124,39 @@ def test_enum_class(app):
' :module: target.enum',
'',
' this is enum class',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: EnumCls.say_hello()',
' :module: target.enum',
- ' ',
+ '',
' a method says hello to you.',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: EnumCls.val1',
' :module: target.enum',
' :value: 12',
- ' ',
+ '',
' doc for val1',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: EnumCls.val2',
' :module: target.enum',
' :value: 23',
- ' ',
+ '',
' doc for val2',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: EnumCls.val3',
' :module: target.enum',
' :value: 34',
- ' ',
+ '',
' doc for val3',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: EnumCls.val4',
' :module: target.enum',
' :value: 34',
- ' '
+ ''
]
# checks for an attribute of EnumClass
@@ -1124,7 +1168,7 @@ def test_enum_class(app):
' :value: 12',
'',
' doc for val1',
- ' '
+ ''
]
@@ -1141,19 +1185,19 @@ def test_descriptor_class(app):
' :module: target.descriptor',
'',
' Descriptor class docstring.',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: CustomDataDescriptor.meth()',
' :module: target.descriptor',
- ' ',
+ '',
' Function.',
- ' ',
+ '',
'',
'.. py:class:: CustomDataDescriptor2(doc)',
' :module: target.descriptor',
'',
' Descriptor class with custom metaclass docstring.',
- ' '
+ '',
]
@@ -1166,7 +1210,7 @@ def test_autofunction_for_callable(app):
' :module: target.callable',
'',
' A callable object that behaves like a function.',
- ' '
+ '',
]
@@ -1179,7 +1223,7 @@ def test_autofunction_for_method(app):
' :module: target.callable',
'',
' docstring of Callable.method().',
- ' '
+ '',
]
@@ -1196,39 +1240,39 @@ def test_abstractmethods():
'.. py:class:: Base',
' :module: target.abstractmethods',
'',
- ' ',
+ '',
' .. py:method:: Base.abstractmeth()',
' :module: target.abstractmethods',
' :abstractmethod:',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: Base.classmeth()',
' :module: target.abstractmethods',
' :abstractmethod:',
' :classmethod:',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: Base.coroutinemeth()',
' :module: target.abstractmethods',
' :abstractmethod:',
' :async:',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: Base.meth()',
' :module: target.abstractmethods',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: Base.prop',
' :module: target.abstractmethods',
' :abstractmethod:',
' :property:',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: Base.staticmeth()',
' :module: target.abstractmethods',
' :abstractmethod:',
' :staticmethod:',
- ' '
+ '',
]
@@ -1245,25 +1289,25 @@ def test_partialfunction():
' :module: target.partialfunction',
'',
' docstring of func1',
- ' ',
+ '',
'',
'.. py:function:: func2(b, c)',
' :module: target.partialfunction',
'',
' docstring of func1',
- ' ',
+ '',
'',
'.. py:function:: func3(c)',
' :module: target.partialfunction',
'',
' docstring of func3',
- ' ',
+ '',
'',
'.. py:function:: func4()',
' :module: target.partialfunction',
'',
' docstring of func3',
- ' '
+ '',
]
@@ -1291,7 +1335,7 @@ def test_bound_method():
' :module: target.bound_method',
'',
' Method docstring',
- ' ',
+ '',
]
@@ -1313,29 +1357,29 @@ def test_coroutine():
'.. py:class:: AsyncClass',
' :module: target.coroutine',
'',
- ' ',
+ '',
' .. py:method:: AsyncClass.do_coroutine()',
' :module: target.coroutine',
' :async:',
- ' ',
+ '',
' A documented coroutine function',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: AsyncClass.do_coroutine2()',
' :module: target.coroutine',
' :async:',
' :classmethod:',
- ' ',
+ '',
' A documented coroutine classmethod',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: AsyncClass.do_coroutine3()',
' :module: target.coroutine',
' :async:',
' :staticmethod:',
- ' ',
+ '',
' A documented coroutine staticmethod',
- ' ',
+ '',
]
@@ -1347,21 +1391,21 @@ def test_partialmethod(app):
' :module: target.partialmethod',
'',
' An example for partialmethod.',
- ' ',
+ '',
' refs: https://docs.python.jp/3/library/functools.html#functools.partialmethod',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: Cell.set_alive()',
' :module: target.partialmethod',
- ' ',
+ '',
' Make a cell alive.',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: Cell.set_state(state)',
' :module: target.partialmethod',
- ' ',
+ '',
' Update state of cell to *state*.',
- ' ',
+ '',
]
options = {"members": None}
@@ -1377,25 +1421,25 @@ def test_partialmethod_undoc_members(app):
' :module: target.partialmethod',
'',
' An example for partialmethod.',
- ' ',
+ '',
' refs: https://docs.python.jp/3/library/functools.html#functools.partialmethod',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: Cell.set_alive()',
' :module: target.partialmethod',
- ' ',
+ '',
' Make a cell alive.',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: Cell.set_dead()',
' :module: target.partialmethod',
- ' ',
- ' ',
+ '',
+ '',
' .. py:method:: Cell.set_state(state)',
' :module: target.partialmethod',
- ' ',
+ '',
' Update state of cell to *state*.',
- ' ',
+ '',
]
options = {"members": None,
@@ -1418,48 +1462,48 @@ def test_autodoc_typed_instance_variables(app):
'.. py:class:: Class()',
' :module: target.typed_vars',
'',
- ' ',
+ '',
' .. py:attribute:: Class.attr1',
' :module: target.typed_vars',
' :type: int',
' :value: 0',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: Class.attr2',
' :module: target.typed_vars',
' :type: int',
' :value: None',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: Class.attr3',
' :module: target.typed_vars',
' :type: int',
' :value: 0',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: Class.attr4',
' :module: target.typed_vars',
' :type: int',
' :value: None',
- ' ',
+ '',
' attr4',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: Class.attr5',
' :module: target.typed_vars',
' :type: int',
' :value: None',
- ' ',
+ '',
' attr5',
- ' ',
- ' ',
+ '',
+ '',
' .. py:attribute:: Class.attr6',
' :module: target.typed_vars',
' :type: int',
' :value: None',
- ' ',
+ '',
' attr6',
- ' ',
+ '',
'',
'.. py:data:: attr1',
' :module: target.typed_vars',
@@ -1467,7 +1511,7 @@ def test_autodoc_typed_instance_variables(app):
" :value: ''",
'',
' attr1',
- ' ',
+ '',
'',
'.. py:data:: attr2',
' :module: target.typed_vars',
@@ -1475,7 +1519,7 @@ def test_autodoc_typed_instance_variables(app):
' :value: None',
'',
' attr2',
- ' ',
+ '',
'',
'.. py:data:: attr3',
' :module: target.typed_vars',
@@ -1483,7 +1527,25 @@ def test_autodoc_typed_instance_variables(app):
" :value: ''",
'',
' attr3',
- ' '
+ '',
+ ]
+
+
+@pytest.mark.skipif(sys.version_info < (3, 9), reason='py39+ is required.')
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autodoc_Annotated(app):
+ options = {"members": None}
+ actual = do_autodoc(app, 'module', 'target.annotated', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.annotated',
+ '',
+ '',
+ '.. py:function:: hello(name: str) -> None',
+ ' :module: target.annotated',
+ '',
+ ' docstring',
+ '',
]
@@ -1502,9 +1564,86 @@ def test_autodoc_for_egged_code(app):
' :value: 1',
'',
' constant on sample.py',
- ' ',
+ '',
'',
'.. py:function:: hello(s)',
' :module: sample',
''
]
+
+
+@pytest.mark.usefixtures('setup_test')
+def test_singledispatch():
+ options = {"members": None}
+ actual = do_autodoc(app, 'module', 'target.singledispatch', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.singledispatch',
+ '',
+ '',
+ '.. py:function:: func(arg, kwarg=None)',
+ ' func(arg: int, kwarg=None)',
+ ' func(arg: str, kwarg=None)',
+ ' :module: target.singledispatch',
+ '',
+ ' A function for general use.',
+ '',
+ ]
+
+
+@pytest.mark.skipif(sys.version_info < (3, 8),
+ reason='singledispatchmethod is available since python3.8')
+@pytest.mark.usefixtures('setup_test')
+def test_singledispatchmethod():
+ options = {"members": None}
+ actual = do_autodoc(app, 'module', 'target.singledispatchmethod', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.singledispatchmethod',
+ '',
+ '',
+ '.. py:class:: Foo',
+ ' :module: target.singledispatchmethod',
+ '',
+ ' docstring',
+ '',
+ '',
+ ' .. py:method:: Foo.meth(arg, kwarg=None)',
+ ' Foo.meth(arg: int, kwarg=None)',
+ ' Foo.meth(arg: str, kwarg=None)',
+ ' :module: target.singledispatchmethod',
+ '',
+ ' A method for general use.',
+ '',
+ ]
+
+
+@pytest.mark.usefixtures('setup_test')
+@pytest.mark.skipif(pyximport is None, reason='cython is not installed')
+def test_cython():
+ options = {"members": None,
+ "undoc-members": None}
+ actual = do_autodoc(app, 'module', 'target.cython', options)
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.cython',
+ '',
+ '',
+ '.. py:class:: Class',
+ ' :module: target.cython',
+ '',
+ ' Docstring.',
+ '',
+ '',
+ ' .. py:method:: Class.meth(name: str, age: int = 0) -> None',
+ ' :module: target.cython',
+ '',
+ ' Docstring.',
+ '',
+ '',
+ '.. py:function:: foo(*args, **kwargs)',
+ ' :module: target.cython',
+ '',
+ ' Docstring.',
+ '',
+ ]