mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #6434 from tk0miya/refactor_test_autodoc
Refactor test_autodoc
This commit is contained in:
commit
4d1e40785f
@ -22,31 +22,6 @@ class CustomEx(Exception):
|
|||||||
"""Exception method."""
|
"""Exception method."""
|
||||||
|
|
||||||
|
|
||||||
class CustomDataDescriptor(object):
|
|
||||||
"""Descriptor class docstring."""
|
|
||||||
|
|
||||||
def __init__(self, doc):
|
|
||||||
self.__doc__ = doc
|
|
||||||
|
|
||||||
def __get__(self, obj, type=None):
|
|
||||||
if obj is None:
|
|
||||||
return self
|
|
||||||
return 42
|
|
||||||
|
|
||||||
def meth(self):
|
|
||||||
"""Function."""
|
|
||||||
return "The Answer"
|
|
||||||
|
|
||||||
|
|
||||||
class CustomDataDescriptorMeta(type):
|
|
||||||
"""Descriptor metaclass docstring."""
|
|
||||||
|
|
||||||
|
|
||||||
class CustomDataDescriptor2(CustomDataDescriptor):
|
|
||||||
"""Descriptor class with custom metaclass docstring."""
|
|
||||||
__metaclass__ = CustomDataDescriptorMeta
|
|
||||||
|
|
||||||
|
|
||||||
def _funky_classmethod(name, b, c, d, docstring=None):
|
def _funky_classmethod(name, b, c, d, docstring=None):
|
||||||
"""Generates a classmethod for a class from a template by filling out
|
"""Generates a classmethod for a class from a template by filling out
|
||||||
some arguments."""
|
some arguments."""
|
||||||
@ -81,8 +56,6 @@ class Derived(Base):
|
|||||||
class Class(Base):
|
class Class(Base):
|
||||||
"""Class to document."""
|
"""Class to document."""
|
||||||
|
|
||||||
descr = CustomDataDescriptor("Descriptor instance docstring.")
|
|
||||||
|
|
||||||
def meth(self):
|
def meth(self):
|
||||||
"""Function."""
|
"""Function."""
|
||||||
|
|
||||||
@ -101,10 +74,6 @@ class Class(Base):
|
|||||||
#: should be documented -- süß
|
#: should be documented -- süß
|
||||||
attr = 'bar'
|
attr = 'bar'
|
||||||
|
|
||||||
@property
|
|
||||||
def prop(self):
|
|
||||||
"""Property."""
|
|
||||||
|
|
||||||
docattr = 'baz'
|
docattr = 'baz'
|
||||||
"""should likewise be documented -- süß"""
|
"""should likewise be documented -- süß"""
|
||||||
|
|
||||||
|
31
tests/roots/test-ext-autodoc/target/descriptor.py
Normal file
31
tests/roots/test-ext-autodoc/target/descriptor.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
class CustomDataDescriptor(object):
|
||||||
|
"""Descriptor class docstring."""
|
||||||
|
|
||||||
|
def __init__(self, doc):
|
||||||
|
self.__doc__ = doc
|
||||||
|
|
||||||
|
def __get__(self, obj, type=None):
|
||||||
|
if obj is None:
|
||||||
|
return self
|
||||||
|
return 42
|
||||||
|
|
||||||
|
def meth(self):
|
||||||
|
"""Function."""
|
||||||
|
return "The Answer"
|
||||||
|
|
||||||
|
|
||||||
|
class CustomDataDescriptorMeta(type):
|
||||||
|
"""Descriptor metaclass docstring."""
|
||||||
|
|
||||||
|
|
||||||
|
class CustomDataDescriptor2(CustomDataDescriptor):
|
||||||
|
"""Descriptor class with custom metaclass docstring."""
|
||||||
|
__metaclass__ = CustomDataDescriptorMeta
|
||||||
|
|
||||||
|
|
||||||
|
class Class:
|
||||||
|
descr = CustomDataDescriptor("Descriptor instance docstring.")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def prop(self):
|
||||||
|
"""Property."""
|
8
tests/roots/test-ext-autodoc/target/process_docstring.py
Normal file
8
tests/roots/test-ext-autodoc/target/process_docstring.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
def func():
|
||||||
|
"""
|
||||||
|
first line
|
||||||
|
---
|
||||||
|
second line
|
||||||
|
---
|
||||||
|
third line
|
||||||
|
"""
|
@ -9,7 +9,6 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import platform
|
|
||||||
import sys
|
import sys
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
from warnings import catch_warnings
|
from warnings import catch_warnings
|
||||||
@ -17,10 +16,7 @@ from warnings import catch_warnings
|
|||||||
import pytest
|
import pytest
|
||||||
from docutils.statemachine import ViewList
|
from docutils.statemachine import ViewList
|
||||||
|
|
||||||
from sphinx.ext.autodoc import (
|
from sphinx.ext.autodoc import ModuleLevelDocumenter, ALL, Options
|
||||||
ModuleLevelDocumenter, cut_lines, between, ALL,
|
|
||||||
merge_autodoc_default_flags, Options
|
|
||||||
)
|
|
||||||
from sphinx.ext.autodoc.directive import DocumenterBridge, process_documenter_options
|
from sphinx.ext.autodoc.directive import DocumenterBridge, process_documenter_options
|
||||||
from sphinx.testing.util import SphinxTestApp, Struct # NOQA
|
from sphinx.testing.util import SphinxTestApp, Struct # NOQA
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
@ -28,8 +24,6 @@ from sphinx.util.docutils import LoggingReporter
|
|||||||
|
|
||||||
app = None
|
app = None
|
||||||
|
|
||||||
IS_PYPY = platform.python_implementation() == 'PyPy'
|
|
||||||
|
|
||||||
|
|
||||||
def do_autodoc(app, objtype, name, options=None):
|
def do_autodoc(app, objtype, name, options=None):
|
||||||
if options is None:
|
if options is None:
|
||||||
@ -58,7 +52,6 @@ def setup_module(rootdir, sphinx_test_tempdir):
|
|||||||
app = SphinxTestApp(srcdir=srcdir)
|
app = SphinxTestApp(srcdir=srcdir)
|
||||||
app.builder.env.app = app
|
app.builder.env.app = app
|
||||||
app.builder.env.temp_data['docname'] = 'dummy'
|
app.builder.env.temp_data['docname'] = 'dummy'
|
||||||
app.connect('autodoc-process-docstring', process_docstring)
|
|
||||||
app.connect('autodoc-process-signature', process_signature)
|
app.connect('autodoc-process-signature', process_signature)
|
||||||
app.connect('autodoc-skip-member', skip_member)
|
app.connect('autodoc-skip-member', skip_member)
|
||||||
yield
|
yield
|
||||||
@ -73,7 +66,7 @@ directive = options = None
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def setup_test():
|
def setup_test():
|
||||||
global options, directive
|
global options, directive
|
||||||
global processed_docstrings, processed_signatures
|
global processed_signatures
|
||||||
|
|
||||||
options = Options(
|
options = Options(
|
||||||
inherited_members = False,
|
inherited_members = False,
|
||||||
@ -102,7 +95,6 @@ def setup_test():
|
|||||||
)
|
)
|
||||||
directive.state.document.settings.tab_width = 8
|
directive.state.document.settings.tab_width = 8
|
||||||
|
|
||||||
processed_docstrings = []
|
|
||||||
processed_signatures = []
|
processed_signatures = []
|
||||||
|
|
||||||
app._status.truncate(0)
|
app._status.truncate(0)
|
||||||
@ -113,16 +105,9 @@ def setup_test():
|
|||||||
app.registry.autodoc_attrgettrs.clear()
|
app.registry.autodoc_attrgettrs.clear()
|
||||||
|
|
||||||
|
|
||||||
processed_docstrings = []
|
|
||||||
processed_signatures = []
|
processed_signatures = []
|
||||||
|
|
||||||
|
|
||||||
def process_docstring(app, what, name, obj, options, lines):
|
|
||||||
processed_docstrings.append((what, name))
|
|
||||||
if name == 'bar':
|
|
||||||
lines.extend(['42', ''])
|
|
||||||
|
|
||||||
|
|
||||||
def process_signature(app, what, name, obj, options, args, retann):
|
def process_signature(app, what, name, obj, options, args, retann):
|
||||||
processed_signatures.append((what, name))
|
processed_signatures.append((what, name))
|
||||||
if name == 'bar':
|
if name == 'bar':
|
||||||
@ -479,61 +464,6 @@ def test_get_doc():
|
|||||||
assert getdocl('method', Derived.inheritedmeth) == ['Inherited function.']
|
assert getdocl('method', Derived.inheritedmeth) == ['Inherited function.']
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures('setup_test')
|
|
||||||
def test_docstring_processing():
|
|
||||||
def process(objtype, name, obj):
|
|
||||||
inst = app.registry.documenters[objtype](directive, name)
|
|
||||||
inst.object = obj
|
|
||||||
inst.fullname = name
|
|
||||||
return list(inst.process_doc(inst.get_doc()))
|
|
||||||
|
|
||||||
class E:
|
|
||||||
def __init__(self):
|
|
||||||
"""Init docstring"""
|
|
||||||
|
|
||||||
# docstring processing by event handler
|
|
||||||
assert process('class', 'bar', E) == ['Init docstring', '', '42', '']
|
|
||||||
|
|
||||||
lid = app.connect('autodoc-process-docstring',
|
|
||||||
cut_lines(1, 1, ['function']))
|
|
||||||
|
|
||||||
def f():
|
|
||||||
"""
|
|
||||||
first line
|
|
||||||
second line
|
|
||||||
third line
|
|
||||||
"""
|
|
||||||
assert process('function', 'f', f) == ['second line', '']
|
|
||||||
app.disconnect(lid)
|
|
||||||
|
|
||||||
lid = app.connect('autodoc-process-docstring', between('---', ['function']))
|
|
||||||
|
|
||||||
def g():
|
|
||||||
"""
|
|
||||||
first line
|
|
||||||
---
|
|
||||||
second line
|
|
||||||
---
|
|
||||||
third line
|
|
||||||
"""
|
|
||||||
assert process('function', 'g', g) == ['second line', '']
|
|
||||||
app.disconnect(lid)
|
|
||||||
|
|
||||||
lid = app.connect('autodoc-process-docstring',
|
|
||||||
between('---', ['function'], exclude=True))
|
|
||||||
|
|
||||||
def h():
|
|
||||||
"""
|
|
||||||
first line
|
|
||||||
---
|
|
||||||
second line
|
|
||||||
---
|
|
||||||
third line
|
|
||||||
"""
|
|
||||||
assert process('function', 'h', h) == ['first line', 'third line', '']
|
|
||||||
app.disconnect(lid)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_new_documenter(app):
|
def test_new_documenter(app):
|
||||||
class MyDocumenter(ModuleLevelDocumenter):
|
class MyDocumenter(ModuleLevelDocumenter):
|
||||||
@ -752,7 +682,6 @@ def test_autodoc_undoc_members(app):
|
|||||||
assert list(filter(lambda l: '::' in l, actual)) == [
|
assert list(filter(lambda l: '::' in l, actual)) == [
|
||||||
'.. py:class:: Class(arg)',
|
'.. py:class:: Class(arg)',
|
||||||
' .. py:attribute:: Class.attr',
|
' .. py:attribute:: Class.attr',
|
||||||
' .. py:attribute:: Class.descr',
|
|
||||||
' .. py:attribute:: Class.docattr',
|
' .. py:attribute:: Class.docattr',
|
||||||
' .. py:method:: Class.excludemeth()',
|
' .. py:method:: Class.excludemeth()',
|
||||||
' .. py:attribute:: Class.inst_attr_comment',
|
' .. py:attribute:: Class.inst_attr_comment',
|
||||||
@ -761,7 +690,6 @@ def test_autodoc_undoc_members(app):
|
|||||||
' .. py:attribute:: Class.mdocattr',
|
' .. py:attribute:: Class.mdocattr',
|
||||||
' .. py:method:: Class.meth()',
|
' .. py:method:: Class.meth()',
|
||||||
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
||||||
' .. py:method:: Class.prop',
|
|
||||||
' .. py:method:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
|
' .. py:method:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
|
||||||
' .. py:attribute:: Class.skipattr',
|
' .. py:attribute:: Class.skipattr',
|
||||||
' .. py:method:: Class.skipmeth()',
|
' .. py:method:: Class.skipmeth()',
|
||||||
@ -782,7 +710,6 @@ def test_autodoc_inherited_members(app):
|
|||||||
' .. py:method:: Class.inheritedstaticmeth(cls)',
|
' .. py:method:: Class.inheritedstaticmeth(cls)',
|
||||||
' .. py:method:: Class.meth()',
|
' .. py:method:: Class.meth()',
|
||||||
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
||||||
' .. py:method:: Class.prop',
|
|
||||||
' .. py:method:: Class.skipmeth()'
|
' .. py:method:: Class.skipmeth()'
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -833,7 +760,6 @@ def test_autodoc_special_members(app):
|
|||||||
' .. py:method:: Class.__special1__()',
|
' .. py:method:: Class.__special1__()',
|
||||||
' .. py:method:: Class.__special2__()',
|
' .. py:method:: Class.__special2__()',
|
||||||
' .. py:attribute:: Class.attr',
|
' .. py:attribute:: Class.attr',
|
||||||
' .. py:attribute:: Class.descr',
|
|
||||||
' .. py:attribute:: Class.docattr',
|
' .. py:attribute:: Class.docattr',
|
||||||
' .. py:method:: Class.excludemeth()',
|
' .. py:method:: Class.excludemeth()',
|
||||||
' .. py:attribute:: Class.inst_attr_comment',
|
' .. py:attribute:: Class.inst_attr_comment',
|
||||||
@ -842,7 +768,6 @@ def test_autodoc_special_members(app):
|
|||||||
' .. py:attribute:: Class.mdocattr',
|
' .. py:attribute:: Class.mdocattr',
|
||||||
' .. py:method:: Class.meth()',
|
' .. py:method:: Class.meth()',
|
||||||
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
||||||
' .. py:method:: Class.prop',
|
|
||||||
' .. py:method:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
|
' .. py:method:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
|
||||||
' .. py:attribute:: Class.skipattr',
|
' .. py:attribute:: Class.skipattr',
|
||||||
' .. py:method:: Class.skipmeth()',
|
' .. py:method:: Class.skipmeth()',
|
||||||
@ -866,9 +791,6 @@ def test_autodoc_ignore_module_all(app):
|
|||||||
actual = do_autodoc(app, 'module', 'target', options)
|
actual = do_autodoc(app, 'module', 'target', options)
|
||||||
assert list(filter(lambda l: 'class::' in l, actual)) == [
|
assert list(filter(lambda l: 'class::' in l, actual)) == [
|
||||||
'.. py:class:: Class(arg)',
|
'.. py:class:: Class(arg)',
|
||||||
'.. py:class:: CustomDataDescriptor(doc)',
|
|
||||||
'.. py:class:: CustomDataDescriptor2(doc)',
|
|
||||||
'.. py:class:: CustomDataDescriptorMeta',
|
|
||||||
'.. py:class:: CustomDict',
|
'.. py:class:: CustomDict',
|
||||||
'.. py:class:: InstAttCls()',
|
'.. py:class:: InstAttCls()',
|
||||||
'.. py:class:: Outer',
|
'.. py:class:: Outer',
|
||||||
@ -991,13 +913,26 @@ def test_autodoc_staticmethod(app):
|
|||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_autodoc_descriptor(app):
|
def test_autodoc_descriptor(app):
|
||||||
actual = do_autodoc(app, 'attribute', 'target.Class.descr')
|
options = {"members": None,
|
||||||
|
"undoc-members": True}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.descriptor.Class', options)
|
||||||
assert list(actual) == [
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:class:: Class',
|
||||||
|
' :module: target.descriptor',
|
||||||
|
'',
|
||||||
' ',
|
' ',
|
||||||
' .. py:attribute:: Class.descr',
|
' .. py:attribute:: Class.descr',
|
||||||
' :module: target',
|
' :module: target.descriptor',
|
||||||
' ',
|
' ',
|
||||||
' Descriptor instance docstring.',
|
' Descriptor instance docstring.',
|
||||||
|
' ',
|
||||||
|
' ',
|
||||||
|
' .. py:method:: Class.prop',
|
||||||
|
' :module: target.descriptor',
|
||||||
|
' :property:',
|
||||||
|
' ',
|
||||||
|
' Property.',
|
||||||
' '
|
' '
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1027,14 +962,12 @@ def test_autodoc_member_order(app):
|
|||||||
actual = do_autodoc(app, 'class', 'target.Class', options)
|
actual = do_autodoc(app, 'class', 'target.Class', options)
|
||||||
assert list(filter(lambda l: '::' in l, actual)) == [
|
assert list(filter(lambda l: '::' in l, actual)) == [
|
||||||
'.. py:class:: Class(arg)',
|
'.. py:class:: Class(arg)',
|
||||||
' .. py:attribute:: Class.descr',
|
|
||||||
' .. py:method:: Class.meth()',
|
' .. py:method:: Class.meth()',
|
||||||
' .. py:method:: Class.undocmeth()',
|
' .. py:method:: Class.undocmeth()',
|
||||||
' .. py:method:: Class.skipmeth()',
|
' .. py:method:: Class.skipmeth()',
|
||||||
' .. py:method:: Class.excludemeth()',
|
' .. py:method:: Class.excludemeth()',
|
||||||
' .. py:attribute:: Class.skipattr',
|
' .. py:attribute:: Class.skipattr',
|
||||||
' .. py:attribute:: Class.attr',
|
' .. py:attribute:: Class.attr',
|
||||||
' .. py:method:: Class.prop',
|
|
||||||
' .. py:attribute:: Class.docattr',
|
' .. py:attribute:: Class.docattr',
|
||||||
' .. py:attribute:: Class.udocattr',
|
' .. py:attribute:: Class.udocattr',
|
||||||
' .. py:attribute:: Class.mdocattr',
|
' .. py:attribute:: Class.mdocattr',
|
||||||
@ -1062,13 +995,11 @@ def test_autodoc_member_order(app):
|
|||||||
' .. py:method:: Class.undocmeth()',
|
' .. py:method:: Class.undocmeth()',
|
||||||
' .. py:attribute:: Class._private_inst_attr',
|
' .. py:attribute:: Class._private_inst_attr',
|
||||||
' .. py:attribute:: Class.attr',
|
' .. py:attribute:: Class.attr',
|
||||||
' .. py:attribute:: Class.descr',
|
|
||||||
' .. py:attribute:: Class.docattr',
|
' .. py:attribute:: Class.docattr',
|
||||||
' .. py:attribute:: Class.inst_attr_comment',
|
' .. py:attribute:: Class.inst_attr_comment',
|
||||||
' .. py:attribute:: Class.inst_attr_inline',
|
' .. py:attribute:: Class.inst_attr_inline',
|
||||||
' .. py:attribute:: Class.inst_attr_string',
|
' .. py:attribute:: Class.inst_attr_string',
|
||||||
' .. py:attribute:: Class.mdocattr',
|
' .. py:attribute:: Class.mdocattr',
|
||||||
' .. py:method:: Class.prop',
|
|
||||||
' .. py:attribute:: Class.skipattr',
|
' .. py:attribute:: Class.skipattr',
|
||||||
' .. py:attribute:: Class.udocattr'
|
' .. py:attribute:: Class.udocattr'
|
||||||
]
|
]
|
||||||
@ -1082,7 +1013,6 @@ def test_autodoc_member_order(app):
|
|||||||
'.. py:class:: Class(arg)',
|
'.. py:class:: Class(arg)',
|
||||||
' .. py:attribute:: Class._private_inst_attr',
|
' .. py:attribute:: Class._private_inst_attr',
|
||||||
' .. py:attribute:: Class.attr',
|
' .. py:attribute:: Class.attr',
|
||||||
' .. py:attribute:: Class.descr',
|
|
||||||
' .. py:attribute:: Class.docattr',
|
' .. py:attribute:: Class.docattr',
|
||||||
' .. py:method:: Class.excludemeth()',
|
' .. py:method:: Class.excludemeth()',
|
||||||
' .. py:attribute:: Class.inst_attr_comment',
|
' .. py:attribute:: Class.inst_attr_comment',
|
||||||
@ -1091,7 +1021,6 @@ def test_autodoc_member_order(app):
|
|||||||
' .. py:attribute:: Class.mdocattr',
|
' .. py:attribute:: Class.mdocattr',
|
||||||
' .. py:method:: Class.meth()',
|
' .. py:method:: Class.meth()',
|
||||||
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
||||||
' .. py:method:: Class.prop',
|
|
||||||
' .. py:method:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
|
' .. py:method:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
|
||||||
' .. py:attribute:: Class.skipattr',
|
' .. py:attribute:: Class.skipattr',
|
||||||
' .. py:method:: Class.skipmeth()',
|
' .. py:method:: Class.skipmeth()',
|
||||||
@ -1131,95 +1060,6 @@ def test_autodoc_class_scope(app):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
|
||||||
def test_autodoc_docstring_signature(app):
|
|
||||||
options = {"members": None}
|
|
||||||
actual = do_autodoc(app, 'class', 'target.DocstringSig', options)
|
|
||||||
assert list(actual) == [
|
|
||||||
'',
|
|
||||||
'.. py:class:: DocstringSig',
|
|
||||||
' :module: target',
|
|
||||||
'',
|
|
||||||
' ',
|
|
||||||
' .. 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:method:: DocstringSig.prop1',
|
|
||||||
' :module: target',
|
|
||||||
' :property:',
|
|
||||||
' ',
|
|
||||||
' First line of docstring',
|
|
||||||
' ',
|
|
||||||
' ',
|
|
||||||
' .. py:method:: DocstringSig.prop2',
|
|
||||||
' :module: target',
|
|
||||||
' :property:',
|
|
||||||
' ',
|
|
||||||
' 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',
|
|
||||||
' :module: target',
|
|
||||||
'',
|
|
||||||
' ',
|
|
||||||
' .. 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:method:: DocstringSig.prop1',
|
|
||||||
' :module: target',
|
|
||||||
' :property:',
|
|
||||||
' ',
|
|
||||||
' DocstringSig.prop1(self)',
|
|
||||||
' First line of docstring',
|
|
||||||
' ',
|
|
||||||
' ',
|
|
||||||
' .. py:method:: DocstringSig.prop2',
|
|
||||||
' :module: target',
|
|
||||||
' :property:',
|
|
||||||
' ',
|
|
||||||
' First line of docstring',
|
|
||||||
' Second line of docstring',
|
|
||||||
' '
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_class_attributes(app):
|
def test_class_attributes(app):
|
||||||
options = {"members": None,
|
options = {"members": None,
|
||||||
@ -1422,26 +1262,26 @@ def test_enum_class(app):
|
|||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_descriptor_class(app):
|
def test_descriptor_class(app):
|
||||||
options = {"members": 'CustomDataDescriptor,CustomDataDescriptor2'}
|
options = {"members": 'CustomDataDescriptor,CustomDataDescriptor2'}
|
||||||
actual = do_autodoc(app, 'module', 'target', options)
|
actual = do_autodoc(app, 'module', 'target.descriptor', options)
|
||||||
assert list(actual) == [
|
assert list(actual) == [
|
||||||
'',
|
'',
|
||||||
'.. py:module:: target',
|
'.. py:module:: target.descriptor',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
'.. py:class:: CustomDataDescriptor(doc)',
|
'.. py:class:: CustomDataDescriptor(doc)',
|
||||||
' :module: target',
|
' :module: target.descriptor',
|
||||||
'',
|
'',
|
||||||
' Descriptor class docstring.',
|
' Descriptor class docstring.',
|
||||||
' ',
|
' ',
|
||||||
' ',
|
' ',
|
||||||
' .. py:method:: CustomDataDescriptor.meth()',
|
' .. py:method:: CustomDataDescriptor.meth()',
|
||||||
' :module: target',
|
' :module: target.descriptor',
|
||||||
' ',
|
' ',
|
||||||
' Function.',
|
' Function.',
|
||||||
' ',
|
' ',
|
||||||
'',
|
'',
|
||||||
'.. py:class:: CustomDataDescriptor2(doc)',
|
'.. py:class:: CustomDataDescriptor2(doc)',
|
||||||
' :module: target',
|
' :module: target.descriptor',
|
||||||
'',
|
'',
|
||||||
' Descriptor class with custom metaclass docstring.',
|
' Descriptor class with custom metaclass docstring.',
|
||||||
' '
|
' '
|
||||||
@ -1474,57 +1314,6 @@ def test_autofunction_for_method(app):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
|
||||||
def test_mocked_module_imports(app, warning):
|
|
||||||
# no autodoc_mock_imports
|
|
||||||
options = {"members": 'TestAutodoc,decoratedFunction,func'}
|
|
||||||
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:class:: TestAutodoc',
|
|
||||||
' :module: target.need_mocks',
|
|
||||||
'',
|
|
||||||
' TestAutodoc 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.usefixtures('setup_test')
|
@pytest.mark.usefixtures('setup_test')
|
||||||
def test_abstractmethods():
|
def test_abstractmethods():
|
||||||
options = {"members": None,
|
options = {"members": None,
|
||||||
@ -1713,236 +1502,6 @@ def test_module_variables():
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
|
||||||
def test_autodoc_typehints_signature(app):
|
|
||||||
app.config.autodoc_typehints = "signature"
|
|
||||||
|
|
||||||
options = {"members": None,
|
|
||||||
"undoc-members": True}
|
|
||||||
actual = do_autodoc(app, 'module', 'target.typehints', options)
|
|
||||||
assert list(actual) == [
|
|
||||||
'',
|
|
||||||
'.. py:module:: target.typehints',
|
|
||||||
'',
|
|
||||||
'',
|
|
||||||
'.. py:class:: Math(s: str, o: object = None)',
|
|
||||||
' :module: target.typehints',
|
|
||||||
'',
|
|
||||||
' ',
|
|
||||||
' .. py:method:: Math.incr(a: int, b: int = 1) -> int',
|
|
||||||
' :module: target.typehints',
|
|
||||||
' ',
|
|
||||||
'',
|
|
||||||
'.. py:function:: incr(a: int, b: int = 1) -> int',
|
|
||||||
' :module: target.typehints',
|
|
||||||
''
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
|
||||||
def test_autodoc_typehints_none(app):
|
|
||||||
app.config.autodoc_typehints = "none"
|
|
||||||
|
|
||||||
options = {"members": None,
|
|
||||||
"undoc-members": True}
|
|
||||||
actual = do_autodoc(app, 'module', 'target.typehints', options)
|
|
||||||
assert list(actual) == [
|
|
||||||
'',
|
|
||||||
'.. py:module:: target.typehints',
|
|
||||||
'',
|
|
||||||
'',
|
|
||||||
'.. py:class:: Math(s, o = None)',
|
|
||||||
' :module: target.typehints',
|
|
||||||
'',
|
|
||||||
' ',
|
|
||||||
' .. py:method:: Math.incr(a, b = 1) -> int',
|
|
||||||
' :module: target.typehints',
|
|
||||||
' ',
|
|
||||||
'',
|
|
||||||
'.. py:function:: incr(a, b = 1) -> int',
|
|
||||||
' :module: target.typehints',
|
|
||||||
''
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
|
||||||
@pytest.mark.filterwarnings('ignore:autodoc_default_flags is now deprecated.')
|
|
||||||
def test_merge_autodoc_default_flags1(app):
|
|
||||||
app.config.autodoc_default_flags = ['members', 'undoc-members']
|
|
||||||
merge_autodoc_default_flags(app, app.config)
|
|
||||||
assert app.config.autodoc_default_options == {'members': None,
|
|
||||||
'undoc-members': None}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
|
||||||
@pytest.mark.filterwarnings('ignore:autodoc_default_flags is now deprecated.')
|
|
||||||
def test_merge_autodoc_default_flags2(app):
|
|
||||||
app.config.autodoc_default_flags = ['members', 'undoc-members']
|
|
||||||
app.config.autodoc_default_options = {'members': 'this,that,order',
|
|
||||||
'inherited-members': 'this'}
|
|
||||||
merge_autodoc_default_flags(app, app.config)
|
|
||||||
assert app.config.autodoc_default_options == {'members': None,
|
|
||||||
'undoc-members': None,
|
|
||||||
'inherited-members': 'this'}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
|
||||||
def test_autodoc_default_options(app):
|
|
||||||
# no settings
|
|
||||||
actual = do_autodoc(app, 'class', 'target.enum.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:: save_traceback(app: Sphinx) -> str' not in actual
|
|
||||||
|
|
||||||
# with :members:
|
|
||||||
app.config.autodoc_default_options = {'members': None}
|
|
||||||
actual = do_autodoc(app, 'class', 'target.enum.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': True}
|
|
||||||
actual = do_autodoc(app, 'class', 'target.enum.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.enum.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 to the object (if defined)' 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.enum.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 to the object (if defined)' in actual
|
|
||||||
assert ' .. py:method:: CustomIter.snafucate()' in actual
|
|
||||||
assert ' Makes this snafucated.' in actual
|
|
||||||
|
|
||||||
# with :imported-members:
|
|
||||||
app.config.autodoc_default_options = {
|
|
||||||
'members': None,
|
|
||||||
'imported-members': None,
|
|
||||||
'ignore-module-all': None,
|
|
||||||
}
|
|
||||||
actual = do_autodoc(app, 'module', 'target')
|
|
||||||
print('\n'.join(actual))
|
|
||||||
assert '.. py:function:: save_traceback(app: Sphinx) -> str' in actual
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
|
||||||
def test_autodoc_default_options_with_values(app):
|
|
||||||
# with :members:
|
|
||||||
app.config.autodoc_default_options = {'members': 'val1,val2'}
|
|
||||||
actual = do_autodoc(app, 'class', 'target.enum.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:attribute:: Class.descr',
|
|
||||||
' .. py:method:: Class.meth()',
|
|
||||||
' .. py:method:: Class.skipmeth()',
|
|
||||||
' .. py:method:: Class.excludemeth()',
|
|
||||||
' .. py:attribute:: Class.attr',
|
|
||||||
' .. py:method:: Class.prop',
|
|
||||||
' .. 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 to the object (if defined)' not in actual
|
|
||||||
|
|
||||||
# with :exclude-members:
|
|
||||||
app.config.autodoc_default_options = {
|
|
||||||
'members': None,
|
|
||||||
'exclude-members': 'val1'
|
|
||||||
}
|
|
||||||
actual = do_autodoc(app, 'class', 'target.enum.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 to the object (if defined)' not in actual
|
|
||||||
assert ' .. py:method:: CustomIter.snafucate()' not in actual
|
|
||||||
assert ' Makes this snafucated.' not in actual
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='pycode-egg')
|
@pytest.mark.sphinx('html', testroot='pycode-egg')
|
||||||
def test_autodoc_for_egged_code(app):
|
def test_autodoc_for_egged_code(app):
|
||||||
options = {"members": None,
|
options = {"members": None,
|
||||||
|
386
tests/test_ext_autodoc_configs.py
Normal file
386
tests/test_ext_autodoc_configs.py
Normal file
@ -0,0 +1,386 @@
|
|||||||
|
"""
|
||||||
|
test_ext_autodoc_configs
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Test the autodoc extension. This tests mainly for config variables
|
||||||
|
|
||||||
|
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||||
|
:license: BSD, see LICENSE for details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import platform
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from sphinx.ext.autodoc import merge_autodoc_default_flags
|
||||||
|
from test_autodoc import do_autodoc
|
||||||
|
|
||||||
|
IS_PYPY = platform.python_implementation() == 'PyPy'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_autodoc_docstring_signature(app):
|
||||||
|
options = {"members": None}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.DocstringSig', options)
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:class:: DocstringSig',
|
||||||
|
' :module: target',
|
||||||
|
'',
|
||||||
|
' ',
|
||||||
|
' .. 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:method:: DocstringSig.prop1',
|
||||||
|
' :module: target',
|
||||||
|
' :property:',
|
||||||
|
' ',
|
||||||
|
' First line of docstring',
|
||||||
|
' ',
|
||||||
|
' ',
|
||||||
|
' .. py:method:: DocstringSig.prop2',
|
||||||
|
' :module: target',
|
||||||
|
' :property:',
|
||||||
|
' ',
|
||||||
|
' 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',
|
||||||
|
' :module: target',
|
||||||
|
'',
|
||||||
|
' ',
|
||||||
|
' .. 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:method:: DocstringSig.prop1',
|
||||||
|
' :module: target',
|
||||||
|
' :property:',
|
||||||
|
' ',
|
||||||
|
' DocstringSig.prop1(self)',
|
||||||
|
' First line of docstring',
|
||||||
|
' ',
|
||||||
|
' ',
|
||||||
|
' .. py:method:: DocstringSig.prop2',
|
||||||
|
' :module: target',
|
||||||
|
' :property:',
|
||||||
|
' ',
|
||||||
|
' First line of docstring',
|
||||||
|
' Second line of docstring',
|
||||||
|
' '
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_mocked_module_imports(app, warning):
|
||||||
|
# no autodoc_mock_imports
|
||||||
|
options = {"members": 'TestAutodoc,decoratedFunction,func'}
|
||||||
|
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:class:: TestAutodoc',
|
||||||
|
' :module: target.need_mocks',
|
||||||
|
'',
|
||||||
|
' TestAutodoc 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')
|
||||||
|
def test_autodoc_typehints_signature(app):
|
||||||
|
app.config.autodoc_typehints = "signature"
|
||||||
|
|
||||||
|
options = {"members": None,
|
||||||
|
"undoc-members": True}
|
||||||
|
actual = do_autodoc(app, 'module', 'target.typehints', options)
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:module:: target.typehints',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'.. py:class:: Math(s: str, o: object = None)',
|
||||||
|
' :module: target.typehints',
|
||||||
|
'',
|
||||||
|
' ',
|
||||||
|
' .. py:method:: Math.incr(a: int, b: int = 1) -> int',
|
||||||
|
' :module: target.typehints',
|
||||||
|
' ',
|
||||||
|
'',
|
||||||
|
'.. py:function:: incr(a: int, b: int = 1) -> int',
|
||||||
|
' :module: target.typehints',
|
||||||
|
''
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_autodoc_typehints_none(app):
|
||||||
|
app.config.autodoc_typehints = "none"
|
||||||
|
|
||||||
|
options = {"members": None,
|
||||||
|
"undoc-members": True}
|
||||||
|
actual = do_autodoc(app, 'module', 'target.typehints', options)
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:module:: target.typehints',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'.. py:class:: Math(s, o = None)',
|
||||||
|
' :module: target.typehints',
|
||||||
|
'',
|
||||||
|
' ',
|
||||||
|
' .. py:method:: Math.incr(a, b = 1) -> int',
|
||||||
|
' :module: target.typehints',
|
||||||
|
' ',
|
||||||
|
'',
|
||||||
|
'.. py:function:: incr(a, b = 1) -> int',
|
||||||
|
' :module: target.typehints',
|
||||||
|
''
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
@pytest.mark.filterwarnings('ignore:autodoc_default_flags is now deprecated.')
|
||||||
|
def test_merge_autodoc_default_flags1(app):
|
||||||
|
app.config.autodoc_default_flags = ['members', 'undoc-members']
|
||||||
|
merge_autodoc_default_flags(app, app.config)
|
||||||
|
assert app.config.autodoc_default_options == {'members': None,
|
||||||
|
'undoc-members': None}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
@pytest.mark.filterwarnings('ignore:autodoc_default_flags is now deprecated.')
|
||||||
|
def test_merge_autodoc_default_flags2(app):
|
||||||
|
app.config.autodoc_default_flags = ['members', 'undoc-members']
|
||||||
|
app.config.autodoc_default_options = {'members': 'this,that,order',
|
||||||
|
'inherited-members': 'this'}
|
||||||
|
merge_autodoc_default_flags(app, app.config)
|
||||||
|
assert app.config.autodoc_default_options == {'members': None,
|
||||||
|
'undoc-members': None,
|
||||||
|
'inherited-members': 'this'}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_autodoc_default_options(app):
|
||||||
|
# no settings
|
||||||
|
actual = do_autodoc(app, 'class', 'target.enum.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:: save_traceback(app: Sphinx) -> str' not in actual
|
||||||
|
|
||||||
|
# with :members:
|
||||||
|
app.config.autodoc_default_options = {'members': None}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.enum.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': True}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.enum.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.enum.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 to the object (if defined)' 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.enum.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 to the object (if defined)' in actual
|
||||||
|
assert ' .. py:method:: CustomIter.snafucate()' in actual
|
||||||
|
assert ' Makes this snafucated.' in actual
|
||||||
|
|
||||||
|
# with :imported-members:
|
||||||
|
app.config.autodoc_default_options = {
|
||||||
|
'members': None,
|
||||||
|
'imported-members': None,
|
||||||
|
'ignore-module-all': None,
|
||||||
|
}
|
||||||
|
actual = do_autodoc(app, 'module', 'target')
|
||||||
|
print('\n'.join(actual))
|
||||||
|
assert '.. py:function:: save_traceback(app: Sphinx) -> str' in actual
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_autodoc_default_options_with_values(app):
|
||||||
|
# with :members:
|
||||||
|
app.config.autodoc_default_options = {'members': 'val1,val2'}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.enum.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 to the object (if defined)' not in actual
|
||||||
|
|
||||||
|
# with :exclude-members:
|
||||||
|
app.config.autodoc_default_options = {
|
||||||
|
'members': None,
|
||||||
|
'exclude-members': 'val1'
|
||||||
|
}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.enum.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 to the object (if defined)' not in actual
|
||||||
|
assert ' .. py:method:: CustomIter.snafucate()' not in actual
|
||||||
|
assert ' Makes this snafucated.' not in actual
|
81
tests/test_ext_autodoc_events.py
Normal file
81
tests/test_ext_autodoc_events.py
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
"""
|
||||||
|
test_ext_autodoc_events
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Test the autodoc extension. This tests mainly for autodoc events
|
||||||
|
|
||||||
|
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||||
|
:license: BSD, see LICENSE for details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from sphinx.ext.autodoc import between, cut_lines
|
||||||
|
from test_autodoc import do_autodoc
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_process_docstring(app):
|
||||||
|
def on_process_docstring(app, what, name, obj, options, lines):
|
||||||
|
lines.clear()
|
||||||
|
lines.append('my docstring')
|
||||||
|
|
||||||
|
app.connect('autodoc-process-docstring', on_process_docstring)
|
||||||
|
|
||||||
|
actual = do_autodoc(app, 'function', 'target.process_docstring.func')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:function:: func()',
|
||||||
|
' :module: target.process_docstring',
|
||||||
|
'',
|
||||||
|
' my docstring'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_cut_lines(app):
|
||||||
|
app.connect('autodoc-process-docstring',
|
||||||
|
cut_lines(2, 2, ['function']))
|
||||||
|
|
||||||
|
actual = do_autodoc(app, 'function', 'target.process_docstring.func')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:function:: func()',
|
||||||
|
' :module: target.process_docstring',
|
||||||
|
'',
|
||||||
|
' second line',
|
||||||
|
' '
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_between(app):
|
||||||
|
app.connect('autodoc-process-docstring',
|
||||||
|
between('---', ['function']))
|
||||||
|
|
||||||
|
actual = do_autodoc(app, 'function', 'target.process_docstring.func')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:function:: func()',
|
||||||
|
' :module: target.process_docstring',
|
||||||
|
'',
|
||||||
|
' second line',
|
||||||
|
' '
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_between_exclude(app):
|
||||||
|
app.connect('autodoc-process-docstring',
|
||||||
|
between('---', ['function'], exclude=True))
|
||||||
|
|
||||||
|
actual = do_autodoc(app, 'function', 'target.process_docstring.func')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:function:: func()',
|
||||||
|
' :module: target.process_docstring',
|
||||||
|
'',
|
||||||
|
' first line',
|
||||||
|
' third line',
|
||||||
|
' '
|
||||||
|
]
|
Loading…
Reference in New Issue
Block a user