mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2026-08-10 04:58:20 -05:00
Merge branch '3.x'
This commit is contained in:
@@ -27,3 +27,6 @@ class Qux:
|
||||
class Quux(List[Union[int, float]]):
|
||||
"""A subclass of List[Union[int, float]]"""
|
||||
pass
|
||||
|
||||
|
||||
Alias = Foo
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
docsting of empty_all module.
|
||||
"""
|
||||
__all__ = []
|
||||
|
||||
|
||||
def foo():
|
||||
"""docstring"""
|
||||
|
||||
|
||||
def bar():
|
||||
"""docstring"""
|
||||
|
||||
|
||||
def baz():
|
||||
"""docstring"""
|
||||
@@ -0,0 +1,19 @@
|
||||
#: docstring
|
||||
#:
|
||||
#: :meta hide-value:
|
||||
SENTINEL1 = object()
|
||||
|
||||
#: :meta hide-value:
|
||||
SENTINEL2 = object()
|
||||
|
||||
|
||||
class Foo:
|
||||
"""docstring"""
|
||||
|
||||
#: docstring
|
||||
#:
|
||||
#: :meta hide-value:
|
||||
SENTINEL1 = object()
|
||||
|
||||
#: :meta hide-value:
|
||||
SENTINEL2 = object()
|
||||
@@ -28,4 +28,9 @@ class TestAutodoc(object):
|
||||
return None
|
||||
|
||||
|
||||
class Inherited(missing_module.Class):
|
||||
"""docstring"""
|
||||
pass
|
||||
|
||||
|
||||
sphinx.missing_module4.missing_function(len(missing_name2))
|
||||
|
||||
@@ -9,3 +9,7 @@ def _public_function(name):
|
||||
|
||||
:meta public:
|
||||
"""
|
||||
|
||||
|
||||
PRIVATE_CONSTANT = None #: :meta private:
|
||||
_PUBLIC_CONSTANT = None #: :meta public:
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
exclude_patterns = ['_build']
|
||||
@@ -0,0 +1,6 @@
|
||||
.. image:: http://localhost:7777/
|
||||
:target: http://localhost:7777/
|
||||
|
||||
`weblate.org`_
|
||||
|
||||
.. _weblate.org: http://localhost:7777/
|
||||
@@ -573,3 +573,40 @@ def test_limit_rate_bails_out_after_waiting_max_time(app):
|
||||
checker.rate_limits = {"localhost": RateLimit(90.0, 0.0)}
|
||||
next_check = checker.limit_rate(FakeResponse())
|
||||
assert next_check is None
|
||||
|
||||
|
||||
@pytest.mark.sphinx(
|
||||
'linkcheck', testroot='linkcheck-localserver-two-links', freshenv=True,
|
||||
)
|
||||
def test_priorityqueue_items_are_comparable(app):
|
||||
with http_server(OKHandler):
|
||||
app.builder.build_all()
|
||||
content = (app.outdir / 'output.json').read_text()
|
||||
rows = [json.loads(x) for x in sorted(content.splitlines())]
|
||||
assert rows == [
|
||||
{
|
||||
'filename': 'index.rst',
|
||||
# Should not be None.
|
||||
'lineno': 0,
|
||||
'status': 'working',
|
||||
'code': 0,
|
||||
'uri': 'http://localhost:7777/',
|
||||
'info': '',
|
||||
},
|
||||
{
|
||||
'filename': 'index.rst',
|
||||
'lineno': 0,
|
||||
'status': 'working',
|
||||
'code': 0,
|
||||
'uri': 'http://localhost:7777/',
|
||||
'info': '',
|
||||
},
|
||||
{
|
||||
'filename': 'index.rst',
|
||||
'lineno': 4,
|
||||
'status': 'working',
|
||||
'code': 0,
|
||||
'uri': 'http://localhost:7777/',
|
||||
'info': '',
|
||||
}
|
||||
]
|
||||
|
||||
@@ -23,7 +23,7 @@ def test_create_single_index(app):
|
||||
".. index:: Sphinx\n"
|
||||
".. index:: Ель\n"
|
||||
".. index:: ёлка\n"
|
||||
".. index:: תירבע\n"
|
||||
".. index:: עברית\n"
|
||||
".. index:: 9-symbol\n"
|
||||
".. index:: &-symbol\n"
|
||||
".. index:: £100\n")
|
||||
@@ -41,7 +41,9 @@ def test_create_single_index(app):
|
||||
assert index[4] == ('Е',
|
||||
[('ёлка', [[('', '#index-6')], [], None]),
|
||||
('Ель', [[('', '#index-5')], [], None])])
|
||||
assert index[5] == ('ת', [('תירבע', [[('', '#index-7')], [], None])])
|
||||
# Here the word starts with U+200F RIGHT-TO-LEFT MARK, which should be
|
||||
# ignored when getting the first letter.
|
||||
assert index[5] == ('ע', [('עברית', [[('', '#index-7')], [], None])])
|
||||
|
||||
|
||||
@pytest.mark.sphinx('dummy', freshenv=True)
|
||||
|
||||
@@ -689,6 +689,7 @@ def test_autodoc_special_members(app):
|
||||
actual = do_autodoc(app, 'class', 'target.Class', options)
|
||||
assert list(filter(lambda l: '::' in l, actual)) == [
|
||||
'.. py:class:: Class(arg)',
|
||||
' .. py:attribute:: Class.__annotations__',
|
||||
' .. py:attribute:: Class.__dict__',
|
||||
' .. py:method:: Class.__init__(arg)',
|
||||
' .. py:attribute:: Class.__module__',
|
||||
@@ -2223,3 +2224,49 @@ def test_name_mangling(app):
|
||||
' name of Foo',
|
||||
'',
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 6), reason='python 3.6+ is required.')
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_hide_value(app):
|
||||
options = {'members': True}
|
||||
actual = do_autodoc(app, 'module', 'target.hide_value', options)
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:module:: target.hide_value',
|
||||
'',
|
||||
'',
|
||||
'.. py:class:: Foo()',
|
||||
' :module: target.hide_value',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
'',
|
||||
' .. py:attribute:: Foo.SENTINEL1',
|
||||
' :module: target.hide_value',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
' :meta hide-value:',
|
||||
'',
|
||||
'',
|
||||
' .. py:attribute:: Foo.SENTINEL2',
|
||||
' :module: target.hide_value',
|
||||
'',
|
||||
' :meta hide-value:',
|
||||
'',
|
||||
'',
|
||||
'.. py:data:: SENTINEL1',
|
||||
' :module: target.hide_value',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
' :meta hide-value:',
|
||||
'',
|
||||
'',
|
||||
'.. py:data:: SENTINEL2',
|
||||
' :module: target.hide_value',
|
||||
'',
|
||||
' :meta hide-value:',
|
||||
'',
|
||||
]
|
||||
|
||||
@@ -189,3 +189,29 @@ def test_autoattribute_TypeVar(app):
|
||||
" alias of TypeVar('T1')",
|
||||
'',
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 6), reason='python 3.6+ is required.')
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autoattribute_hide_value(app):
|
||||
actual = do_autodoc(app, 'attribute', 'target.hide_value.Foo.SENTINEL1')
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:attribute:: Foo.SENTINEL1',
|
||||
' :module: target.hide_value',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
' :meta hide-value:',
|
||||
'',
|
||||
]
|
||||
|
||||
actual = do_autodoc(app, 'attribute', 'target.hide_value.Foo.SENTINEL2')
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:attribute:: Foo.SENTINEL2',
|
||||
' :module: target.hide_value',
|
||||
'',
|
||||
' :meta hide-value:',
|
||||
'',
|
||||
]
|
||||
|
||||
@@ -173,3 +173,21 @@ def test_show_inheritance_for_subclass_of_generic_type(app):
|
||||
' A subclass of List[Union[int, float]]',
|
||||
'',
|
||||
]
|
||||
|
||||
|
||||
def test_class_alias(app):
|
||||
def autodoc_process_docstring(*args):
|
||||
"""A handler always raises an error.
|
||||
This confirms this handler is never called for class aliases.
|
||||
"""
|
||||
raise
|
||||
|
||||
app.connect('autodoc-process-docstring', autodoc_process_docstring)
|
||||
actual = do_autodoc(app, 'class', 'target.classes.Alias')
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:attribute:: Alias',
|
||||
' :module: target.classes',
|
||||
'',
|
||||
' alias of :class:`target.classes.Foo`',
|
||||
]
|
||||
|
||||
@@ -129,3 +129,29 @@ def test_autodata_TypeVar(app):
|
||||
" alias of TypeVar('T1')",
|
||||
'',
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 6), reason='python 3.6+ is required.')
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autodata_hide_value(app):
|
||||
actual = do_autodoc(app, 'data', 'target.hide_value.SENTINEL1')
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:data:: SENTINEL1',
|
||||
' :module: target.hide_value',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
' :meta hide-value:',
|
||||
'',
|
||||
]
|
||||
|
||||
actual = do_autodoc(app, 'data', 'target.hide_value.SENTINEL2')
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:data:: SENTINEL2',
|
||||
' :module: target.hide_value',
|
||||
'',
|
||||
' :meta hide-value:',
|
||||
'',
|
||||
]
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
"""
|
||||
test_ext_autodoc_autocmodule
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Test the autodoc extension. This tests mainly the Documenters; the auto
|
||||
directives are tested in a test source file translated by test_build.
|
||||
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from .test_ext_autodoc import do_autodoc
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_empty_all(app):
|
||||
options = {'members': True}
|
||||
actual = do_autodoc(app, 'module', 'target.empty_all', options)
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:module:: target.empty_all',
|
||||
'',
|
||||
'docsting of empty_all module.',
|
||||
'',
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc',
|
||||
confoverrides={'autodoc_mock_imports': ['missing_module',
|
||||
'missing_package1',
|
||||
'missing_package2',
|
||||
'missing_package3',
|
||||
'sphinx.missing_module4']})
|
||||
@pytest.mark.usefixtures("rollback_sysmodules")
|
||||
def test_subclass_of_mocked_object(app):
|
||||
sys.modules.pop('target', None) # unload target module to clear the module cache
|
||||
|
||||
options = {'members': True}
|
||||
actual = do_autodoc(app, 'module', 'target.need_mocks', options)
|
||||
assert '.. py:class:: Inherited(*args: Any, **kwargs: Any)' in actual
|
||||
@@ -429,7 +429,10 @@ def test_autoclass_content_and_docstring_signature_both(app):
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
@pytest.mark.usefixtures("rollback_sysmodules")
|
||||
def test_mocked_module_imports(app, warning):
|
||||
sys.modules.pop('target', None) # unload target module to clear the module cache
|
||||
|
||||
# no autodoc_mock_imports
|
||||
options = {"members": 'TestAutodoc,decoratedFunction,func'}
|
||||
actual = do_autodoc(app, 'module', 'target.need_mocks', options)
|
||||
|
||||
@@ -15,7 +15,7 @@ from typing import TypeVar
|
||||
|
||||
import pytest
|
||||
|
||||
from sphinx.ext.autodoc.mock import _MockModule, _MockObject, mock
|
||||
from sphinx.ext.autodoc.mock import _MockModule, _MockObject, ismock, mock
|
||||
|
||||
|
||||
def test_MockModule():
|
||||
@@ -129,3 +129,19 @@ def test_mock_decorator():
|
||||
assert func.__doc__ == "docstring"
|
||||
assert Foo.meth.__doc__ == "docstring"
|
||||
assert Bar.__doc__ == "docstring"
|
||||
|
||||
|
||||
def test_ismock():
|
||||
with mock(['sphinx.unknown']):
|
||||
mod1 = import_module('sphinx.unknown')
|
||||
mod2 = import_module('sphinx.application')
|
||||
|
||||
class Inherited(mod1.Class):
|
||||
pass
|
||||
|
||||
assert ismock(mod1) is True
|
||||
assert ismock(mod1.Class) is True
|
||||
assert ismock(Inherited) is False
|
||||
|
||||
assert ismock(mod2) is False
|
||||
assert ismock(mod2.Sphinx) is False
|
||||
|
||||
@@ -23,6 +23,13 @@ def test_private_field(app):
|
||||
'.. py:module:: target.private',
|
||||
'',
|
||||
'',
|
||||
'.. py:data:: _PUBLIC_CONSTANT',
|
||||
' :module: target.private',
|
||||
' :value: None',
|
||||
'',
|
||||
' :meta public:',
|
||||
'',
|
||||
'',
|
||||
'.. py:function:: _public_function(name)',
|
||||
' :module: target.private',
|
||||
'',
|
||||
@@ -44,6 +51,20 @@ def test_private_field_and_private_members(app):
|
||||
'.. py:module:: target.private',
|
||||
'',
|
||||
'',
|
||||
'.. py:data:: PRIVATE_CONSTANT',
|
||||
' :module: target.private',
|
||||
' :value: None',
|
||||
'',
|
||||
' :meta private:',
|
||||
'',
|
||||
'',
|
||||
'.. py:data:: _PUBLIC_CONSTANT',
|
||||
' :module: target.private',
|
||||
' :value: None',
|
||||
'',
|
||||
' :meta public:',
|
||||
'',
|
||||
'',
|
||||
'.. py:function:: _public_function(name)',
|
||||
' :module: target.private',
|
||||
'',
|
||||
@@ -66,13 +87,20 @@ def test_private_field_and_private_members(app):
|
||||
def test_private_members(app):
|
||||
app.config.autoclass_content = 'class'
|
||||
options = {"members": None,
|
||||
"private-members": "_public_function"}
|
||||
"private-members": "_PUBLIC_CONSTANT,_public_function"}
|
||||
actual = do_autodoc(app, 'module', 'target.private', options)
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:module:: target.private',
|
||||
'',
|
||||
'',
|
||||
'.. py:data:: _PUBLIC_CONSTANT',
|
||||
' :module: target.private',
|
||||
' :value: None',
|
||||
'',
|
||||
' :meta public:',
|
||||
'',
|
||||
'',
|
||||
'.. py:function:: _public_function(name)',
|
||||
' :module: target.private',
|
||||
'',
|
||||
|
||||
@@ -379,27 +379,47 @@ def test_autosummary_generate_overwrite2(app_params, make_app):
|
||||
|
||||
@pytest.mark.sphinx('dummy', testroot='ext-autosummary-recursive')
|
||||
def test_autosummary_recursive(app, status, warning):
|
||||
app.build()
|
||||
try:
|
||||
app.build()
|
||||
|
||||
# autosummary having :recursive: option
|
||||
assert (app.srcdir / 'generated' / 'package.rst').exists()
|
||||
assert (app.srcdir / 'generated' / 'package.module.rst').exists()
|
||||
assert (app.srcdir / 'generated' / 'package.module_importfail.rst').exists() is False
|
||||
assert (app.srcdir / 'generated' / 'package.package.rst').exists()
|
||||
assert (app.srcdir / 'generated' / 'package.package.module.rst').exists()
|
||||
# autosummary having :recursive: option
|
||||
assert (app.srcdir / 'generated' / 'package.rst').exists()
|
||||
assert (app.srcdir / 'generated' / 'package.module.rst').exists()
|
||||
assert (app.srcdir / 'generated' / 'package.module_importfail.rst').exists() is False
|
||||
assert (app.srcdir / 'generated' / 'package.package.rst').exists()
|
||||
assert (app.srcdir / 'generated' / 'package.package.module.rst').exists()
|
||||
|
||||
# autosummary not having :recursive: option
|
||||
assert (app.srcdir / 'generated' / 'package2.rst').exists()
|
||||
assert (app.srcdir / 'generated' / 'package2.module.rst').exists() is False
|
||||
# autosummary not having :recursive: option
|
||||
assert (app.srcdir / 'generated' / 'package2.rst').exists()
|
||||
assert (app.srcdir / 'generated' / 'package2.module.rst').exists() is False
|
||||
|
||||
# Check content of recursively generated stub-files
|
||||
content = (app.srcdir / 'generated' / 'package.rst').read_text()
|
||||
assert 'package.module' in content
|
||||
assert 'package.package' in content
|
||||
assert 'package.module_importfail' in content
|
||||
# Check content of recursively generated stub-files
|
||||
content = (app.srcdir / 'generated' / 'package.rst').read_text()
|
||||
assert 'package.module' in content
|
||||
assert 'package.package' in content
|
||||
assert 'package.module_importfail' in content
|
||||
|
||||
content = (app.srcdir / 'generated' / 'package.package.rst').read_text()
|
||||
assert 'package.package.module' in content
|
||||
content = (app.srcdir / 'generated' / 'package.package.rst').read_text()
|
||||
assert 'package.package.module' in content
|
||||
finally:
|
||||
sys.modules.pop('package.package', None)
|
||||
sys.modules.pop('package.package.module', None)
|
||||
|
||||
|
||||
@pytest.mark.sphinx('dummy', testroot='ext-autosummary-recursive',
|
||||
srcdir='test_autosummary_recursive_skips_mocked_modules',
|
||||
confoverrides={'autosummary_mock_imports': ['package.package']})
|
||||
def test_autosummary_recursive_skips_mocked_modules(app, status, warning):
|
||||
try:
|
||||
app.build()
|
||||
|
||||
assert (app.srcdir / 'generated' / 'package.rst').exists()
|
||||
assert (app.srcdir / 'generated' / 'package.module.rst').exists()
|
||||
assert (app.srcdir / 'generated' / 'package.package.rst').exists() is False
|
||||
assert (app.srcdir / 'generated' / 'package.package.module.rst').exists() is False
|
||||
finally:
|
||||
sys.modules.pop('package.package', None)
|
||||
sys.modules.pop('package.package.module', None)
|
||||
|
||||
|
||||
@pytest.mark.sphinx('dummy', testroot='ext-autosummary-filename-map')
|
||||
|
||||
@@ -109,6 +109,12 @@ def test_restify_type_hints_alias():
|
||||
assert restify(MyTuple) == ":class:`Tuple`\\ [:class:`str`, :class:`str`]" # type: ignore
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 7), reason='python 3.7+ is required.')
|
||||
def test_restify_type_ForwardRef():
|
||||
from typing import ForwardRef # type: ignore
|
||||
assert restify(ForwardRef("myint")) == ":class:`myint`"
|
||||
|
||||
|
||||
def test_restify_broken_type_hints():
|
||||
assert restify(BrokenType) == ':class:`tests.test_util_typing.BrokenType`'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user