summaryrefslogtreecommitdiff
path: root/tests/test_ext_autodoc.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_ext_autodoc.py')
-rw-r--r--tests/test_ext_autodoc.py324
1 files changed, 159 insertions, 165 deletions
diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py
index 4ed4a9b05..5cc1f3c22 100644
--- a/tests/test_ext_autodoc.py
+++ b/tests/test_ext_autodoc.py
@@ -1,6 +1,6 @@
"""
- test_autodoc
- ~~~~~~~~~~~~
+ test_ext_autodoc
+ ~~~~~~~~~~~~~~~~
Test the autodoc extension. This tests mainly the Documenters; the auto
directives are tested in a test source file translated by test_build.
@@ -162,7 +162,6 @@ def test_format_signature(app):
pass
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')"
# test for classes
@@ -170,21 +169,64 @@ def test_format_signature(app):
pass
class E:
- pass
- # no signature for classes without __init__
+ def __init__(self):
+ pass
+
+ # an empty init and no init are the same
for C in (D, E):
- assert formatsig('class', 'D', C, None, None) == ''
+ assert formatsig('class', 'D', C, None, None) == '()'
+
+
+ class SomeMeta(type):
+ def __call__(cls, a, b=None):
+ return type.__call__(cls, a, b)
+ # these three are all equivalent
class F:
def __init__(self, a, b=None):
pass
+ class FNew:
+ def __new__(cls, a, b=None):
+ return super().__new__(cls)
+
+ class FMeta(metaclass=SomeMeta):
+ pass
+
+ # and subclasses should always inherit
class G(F):
pass
- for C in (F, G):
+
+ class GNew(FNew):
+ pass
+
+ class GMeta(FMeta):
+ pass
+
+ # subclasses inherit
+ for C in (F, FNew, FMeta, G, GNew, GMeta):
assert formatsig('class', 'C', C, None, None) == '(a, b=None)'
assert formatsig('class', 'C', D, 'a, b', 'X') == '(a, b) -> X'
+
+ class ListSubclass(list):
+ pass
+
+ # only supported if the python implementation decides to document it
+ if getattr(list, '__text_signature__', None) is not None:
+ assert formatsig('class', 'C', ListSubclass, None, None) == '(iterable=(), /)'
+ else:
+ assert formatsig('class', 'C', ListSubclass, None, None) == ''
+
+
+ class ExceptionSubclass(Exception):
+ pass
+
+ # Exception has no __text_signature__ at least in Python 3.8
+ if getattr(Exception, '__text_signature__', None) is None:
+ assert formatsig('class', 'C', ExceptionSubclass, None, None) == ''
+
+
# __init__ have signature at first line of docstring
directive.env.config.autoclass_content = 'both'
@@ -247,6 +289,27 @@ def test_format_signature(app):
'(b, c=42, *d, **e)'
+def test_autodoc_process_signature_typehints(app):
+ captured = []
+
+ def process_signature(*args):
+ captured.append(args)
+
+ app.connect('autodoc-process-signature', process_signature)
+
+ def func(x: int, y: int) -> int:
+ pass
+
+ directive = make_directive_bridge(app.env)
+ inst = app.registry.documenters['function'](directive, 'func')
+ inst.fullname = 'func'
+ inst.object = func
+ inst.objpath = ['func']
+ inst.format_signature()
+ assert captured == [(app, 'function', 'func', func,
+ directive.genopt, '(x: int, y: int)', 'int')]
+
+
def test_get_doc(app):
directive = make_directive_bridge(app.env)
@@ -477,14 +540,14 @@ def test_autodoc_members(app):
# default (no-members)
actual = do_autodoc(app, 'class', 'target.inheritance.Base')
assert list(filter(lambda l: '::' in l, actual)) == [
- '.. py:class:: Base',
+ '.. py:class:: Base()',
]
# default ALL-members
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
assert list(filter(lambda l: '::' in l, actual)) == [
- '.. py:class:: Base',
+ '.. py:class:: Base()',
' .. py:method:: Base.inheritedclassmeth()',
' .. py:method:: Base.inheritedmeth()',
' .. py:method:: Base.inheritedstaticmeth(cls)'
@@ -494,7 +557,7 @@ def test_autodoc_members(app):
options = {"members": "inheritedmeth,inheritedstaticmeth"}
actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
assert list(filter(lambda l: '::' in l, actual)) == [
- '.. py:class:: Base',
+ '.. py:class:: Base()',
' .. py:method:: Base.inheritedmeth()',
' .. py:method:: Base.inheritedstaticmeth(cls)'
]
@@ -506,7 +569,7 @@ def test_autodoc_exclude_members(app):
"exclude-members": "inheritedmeth,inheritedstaticmeth"}
actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
assert list(filter(lambda l: '::' in l, actual)) == [
- '.. py:class:: Base',
+ '.. py:class:: Base()',
' .. py:method:: Base.inheritedclassmeth()'
]
@@ -515,7 +578,7 @@ def test_autodoc_exclude_members(app):
"exclude-members": "inheritedmeth"}
actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
assert list(filter(lambda l: '::' in l, actual)) == [
- '.. py:class:: Base',
+ '.. py:class:: Base()',
]
@@ -659,10 +722,10 @@ 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:: InnerChild()',
'.. py:class:: InstAttCls()',
- '.. py:class:: Outer',
- ' .. py:class:: Outer.Inner',
+ '.. py:class:: Outer()',
+ ' .. py:class:: Outer.Inner()',
'.. py:class:: StrRepr'
]
@@ -683,7 +746,7 @@ def test_autodoc_noindex(app):
actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
assert list(actual) == [
'',
- '.. py:class:: Base',
+ '.. py:class:: Base()',
' :noindex:',
' :module: target.inheritance',
''
@@ -710,13 +773,13 @@ def test_autodoc_inner_class(app):
actual = do_autodoc(app, 'class', 'target.Outer', options)
assert list(actual) == [
'',
- '.. py:class:: Outer',
+ '.. py:class:: Outer()',
' :module: target',
'',
' Foo',
'',
'',
- ' .. py:class:: Outer.Inner',
+ ' .. py:class:: Outer.Inner()',
' :module: target',
'',
' Foo',
@@ -737,7 +800,7 @@ def test_autodoc_inner_class(app):
actual = do_autodoc(app, 'class', 'target.Outer.Inner', options)
assert list(actual) == [
'',
- '.. py:class:: Outer.Inner',
+ '.. py:class:: Outer.Inner()',
' :module: target',
'',
' Foo',
@@ -754,7 +817,7 @@ def test_autodoc_inner_class(app):
actual = do_autodoc(app, 'class', 'target.InnerChild', options)
assert list(actual) == [
'',
- '.. py:class:: InnerChild',
+ '.. py:class:: InnerChild()',
' :module: target', '',
' Bases: :class:`target.Outer.Inner`',
'',
@@ -798,7 +861,7 @@ def test_autodoc_descriptor(app):
actual = do_autodoc(app, 'class', 'target.descriptor.Class', options)
assert list(actual) == [
'',
- '.. py:class:: Class',
+ '.. py:class:: Class()',
' :module: target.descriptor',
'',
'',
@@ -818,21 +881,6 @@ def test_autodoc_descriptor(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
-def test_autodoc_c_module(app):
- actual = do_autodoc(app, 'function', 'time.asctime')
- assert list(actual) == [
- '',
- '.. py:function:: asctime([tuple]) -> string',
- ' :module: time',
- '',
- " 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.',
- '',
- ]
-
-
-@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_member_order(app):
# case member-order='bysource'
options = {"members": None,
@@ -910,6 +958,40 @@ def test_autodoc_member_order(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autodoc_module_member_order(app):
+ # case member-order='bysource'
+ options = {"members": 'foo, Bar, baz, qux, Quux, foobar',
+ 'member-order': 'bysource',
+ "undoc-members": True}
+ actual = do_autodoc(app, 'module', 'target.sort_by_all', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:module:: target.sort_by_all',
+ '.. py:function:: baz()',
+ '.. py:function:: foo()',
+ '.. py:class:: Bar()',
+ '.. py:class:: Quux()',
+ '.. py:function:: foobar()',
+ '.. py:function:: qux()',
+ ]
+
+ # case member-order='bysource' and ignore-module-all
+ options = {"members": 'foo, Bar, baz, qux, Quux, foobar',
+ 'member-order': 'bysource',
+ "undoc-members": True,
+ "ignore-module-all": True}
+ actual = do_autodoc(app, 'module', 'target.sort_by_all', options)
+ assert list(filter(lambda l: '::' in l, actual)) == [
+ '.. py:module:: target.sort_by_all',
+ '.. py:function:: foo()',
+ '.. py:class:: Bar()',
+ '.. py:function:: baz()',
+ '.. py:function:: qux()',
+ '.. py:class:: Quux()',
+ '.. py:function:: foobar()',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_module_scope(app):
app.env.temp_data['autodoc:module'] = 'target'
actual = do_autodoc(app, 'attribute', 'Class.mdocattr')
@@ -947,7 +1029,7 @@ def test_class_attributes(app):
actual = do_autodoc(app, 'class', 'target.AttCls', options)
assert list(actual) == [
'',
- '.. py:class:: AttCls',
+ '.. py:class:: AttCls()',
' :module: target',
'',
'',
@@ -1067,7 +1149,7 @@ def test_slots(app):
' :module: target.slots',
'',
'',
- '.. py:class:: Foo',
+ '.. py:class:: Foo()',
' :module: target.slots',
'',
'',
@@ -1083,7 +1165,7 @@ def test_enum_class(app):
actual = do_autodoc(app, 'class', 'target.enum.EnumCls', options)
assert list(actual) == [
'',
- '.. py:class:: EnumCls',
+ '.. py:class:: EnumCls(value)',
' :module: target.enum',
'',
' this is enum class',
@@ -1167,96 +1249,6 @@ def test_descriptor_class(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
-def test_autofunction_for_classes(app):
- actual = do_autodoc(app, 'function', 'target.classes.Foo')
- assert list(actual) == [
- '',
- '.. py:function:: Foo()',
- ' :module: target.classes',
- '',
- ]
-
- actual = do_autodoc(app, 'function', 'target.classes.Bar')
- assert list(actual) == [
- '',
- '.. py:function:: Bar(x, y)',
- ' :module: target.classes',
- '',
- ]
-
- actual = do_autodoc(app, 'function', 'target.classes.Baz')
- assert list(actual) == [
- '',
- '.. py:function:: Baz(x, y)',
- ' :module: target.classes',
- '',
- ]
-
-
-@pytest.mark.sphinx('html', testroot='ext-autodoc')
-def test_autofunction_for_callable(app):
- actual = do_autodoc(app, 'function', 'target.callable.function')
- assert list(actual) == [
- '',
- '.. py:function:: function(arg1, arg2, **kwargs)',
- ' :module: target.callable',
- '',
- ' A callable object that behaves like a function.',
- '',
- ]
-
-
-@pytest.mark.sphinx('html', testroot='ext-autodoc')
-def test_autofunction_for_method(app):
- actual = do_autodoc(app, 'function', 'target.callable.method')
- assert list(actual) == [
- '',
- '.. py:function:: method(arg1, arg2)',
- ' :module: target.callable',
- '',
- ' docstring of Callable.method().',
- '',
- ]
-
-
-@pytest.mark.sphinx('html', testroot='ext-autodoc')
-def test_autofunction_for_builtin(app):
- actual = do_autodoc(app, 'function', 'os.umask')
- assert list(actual) == [
- '',
- '.. py:function:: umask(mask, /)',
- ' :module: os',
- '',
- ' Set the current numeric umask and return the previous umask.',
- '',
- ]
-
-
-@pytest.mark.sphinx('html', testroot='ext-autodoc')
-def test_autofunction_for_methoddescriptor(app):
- actual = do_autodoc(app, 'function', 'builtins.int.__add__')
- assert list(actual) == [
- '',
- '.. py:function:: int.__add__(self, value, /)',
- ' :module: builtins',
- '',
- ' Return self+value.',
- '',
- ]
-
-
-@pytest.mark.sphinx('html', testroot='ext-autodoc')
-def test_autofunction_for_decorated(app):
- actual = do_autodoc(app, 'function', 'target.decorator.foo')
- assert list(actual) == [
- '',
- '.. py:function:: foo()',
- ' :module: target.decorator',
- '',
- ]
-
-
-@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_automethod_for_builtin(app):
actual = do_autodoc(app, 'method', 'builtins.int.__add__')
assert list(actual) == [
@@ -1290,7 +1282,7 @@ def test_abstractmethods(app):
'.. py:module:: target.abstractmethods',
'',
'',
- '.. py:class:: Base',
+ '.. py:class:: Base()',
' :module: target.abstractmethods',
'',
'',
@@ -1407,7 +1399,7 @@ def test_coroutine(app):
actual = do_autodoc(app, 'class', 'target.coroutine.AsyncClass', options)
assert list(actual) == [
'',
- '.. py:class:: AsyncClass',
+ '.. py:class:: AsyncClass()',
' :module: target.coroutine',
'',
'',
@@ -1449,7 +1441,7 @@ def test_coroutine(app):
def test_partialmethod(app):
expected = [
'',
- '.. py:class:: Cell',
+ '.. py:class:: Cell()',
' :module: target.partialmethod',
'',
' An example for partialmethod.',
@@ -1476,23 +1468,10 @@ def test_partialmethod(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
-def test_wrappedfunction(app):
- actual = do_autodoc(app, 'function', 'target.wrappedfunction.slow_function')
- assert list(actual) == [
- '',
- '.. py:function:: slow_function(message, timeout)',
- ' :module: target.wrappedfunction',
- '',
- ' This function is slow.',
- '',
- ]
-
-
-@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_partialmethod_undoc_members(app):
expected = [
'',
- '.. py:class:: Cell',
+ '.. py:class:: Cell()',
' :module: target.partialmethod',
'',
' An example for partialmethod.',
@@ -1608,6 +1587,37 @@ def test_autodoc_typed_instance_variables(app):
]
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autodoc_GenericAlias(app):
+ options = {"members": None,
+ "undoc-members": None}
+ actual = do_autodoc(app, 'module', 'target.genericalias', options)
+ if sys.version_info < (3, 7):
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.genericalias',
+ '',
+ '',
+ '.. py:attribute:: T',
+ ' :module: target.genericalias',
+ '',
+ ' alias of :class:`typing.List`',
+ ]
+ else:
+ assert list(actual) == [
+ '',
+ '.. py:module:: target.genericalias',
+ '',
+ '',
+ '.. py:data:: T',
+ ' :module: target.genericalias',
+ '',
+ ' A list of int',
+ '',
+ ' alias of List[int]',
+ ]
+
+
@pytest.mark.skipif(sys.version_info < (3, 9), reason='py39+ is required.')
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_Annotated(app):
@@ -1668,22 +1678,6 @@ def test_singledispatch(app):
]
-@pytest.mark.sphinx('html', testroot='ext-autodoc')
-def test_singledispatch_autofunction(app):
- options = {}
- actual = do_autodoc(app, 'function', 'target.singledispatch.func', options)
- assert list(actual) == [
- '',
- '.. 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.sphinx('html', testroot='ext-autodoc')
@@ -1695,7 +1689,7 @@ def test_singledispatchmethod(app):
'.. py:module:: target.singledispatchmethod',
'',
'',
- '.. py:class:: Foo',
+ '.. py:class:: Foo()',
' :module: target.singledispatchmethod',
'',
' docstring',
@@ -1740,7 +1734,7 @@ def test_cython(app):
'.. py:module:: target.cython',
'',
'',
- '.. py:class:: Class',
+ '.. py:class:: Class()',
' :module: target.cython',
'',
' Docstring.',
@@ -1771,7 +1765,7 @@ def test_final(app):
'.. py:module:: target.final',
'',
'',
- '.. py:class:: Class',
+ '.. py:class:: Class()',
' :module: target.final',
' :final:',
'',