mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Further improve typing in tests/
(#12816)
Co-authored-by: Adam Turner <9087854+aa-turner@users.noreply.github.com>
This commit is contained in:
parent
b6f818f600
commit
7546545876
@ -146,7 +146,6 @@ files = [
|
|||||||
exclude = [
|
exclude = [
|
||||||
"tests/roots",
|
"tests/roots",
|
||||||
# tests/
|
# tests/
|
||||||
"^tests/test_events\\.py$",
|
|
||||||
"^tests/test_quickstart\\.py$",
|
"^tests/test_quickstart\\.py$",
|
||||||
"^tests/test_search\\.py$",
|
"^tests/test_search\\.py$",
|
||||||
# tests/test_builders
|
# tests/test_builders
|
||||||
@ -175,14 +174,12 @@ exclude = [
|
|||||||
# tests/test_extensions
|
# tests/test_extensions
|
||||||
"^tests/test_extensions/test_ext_apidoc\\.py$",
|
"^tests/test_extensions/test_ext_apidoc\\.py$",
|
||||||
"^tests/test_extensions/test_ext_autodoc\\.py$",
|
"^tests/test_extensions/test_ext_autodoc\\.py$",
|
||||||
"^tests/test_extensions/test_ext_autodoc_autofunction\\.py$",
|
|
||||||
"^tests/test_extensions/test_ext_autodoc_events\\.py$",
|
"^tests/test_extensions/test_ext_autodoc_events\\.py$",
|
||||||
"^tests/test_extensions/test_ext_autodoc_mock\\.py$",
|
"^tests/test_extensions/test_ext_autodoc_mock\\.py$",
|
||||||
"^tests/test_extensions/test_ext_autosummary\\.py$",
|
"^tests/test_extensions/test_ext_autosummary\\.py$",
|
||||||
"^tests/test_extensions/test_ext_doctest\\.py$",
|
"^tests/test_extensions/test_ext_doctest\\.py$",
|
||||||
"^tests/test_extensions/test_ext_inheritance_diagram\\.py$",
|
"^tests/test_extensions/test_ext_inheritance_diagram\\.py$",
|
||||||
"^tests/test_extensions/test_ext_intersphinx\\.py$",
|
"^tests/test_extensions/test_ext_intersphinx\\.py$",
|
||||||
"^tests/test_extensions/test_ext_napoleon\\.py$",
|
|
||||||
"^tests/test_extensions/test_ext_napoleon_docstring\\.py$",
|
"^tests/test_extensions/test_ext_napoleon_docstring\\.py$",
|
||||||
# tests/test_intl
|
# tests/test_intl
|
||||||
"^tests/test_intl/test_intl\\.py$",
|
"^tests/test_intl/test_intl\\.py$",
|
||||||
|
@ -8,7 +8,8 @@ from sphinx.events import EventManager
|
|||||||
|
|
||||||
def test_event_priority():
|
def test_event_priority():
|
||||||
result = []
|
result = []
|
||||||
events = EventManager(object()) # pass an dummy object as an app
|
app = object() # pass a dummy object as an app
|
||||||
|
events = EventManager(app) # type: ignore[arg-type]
|
||||||
events.connect('builder-inited', lambda app: result.append(1), priority=500)
|
events.connect('builder-inited', lambda app: result.append(1), priority=500)
|
||||||
events.connect('builder-inited', lambda app: result.append(2), priority=500)
|
events.connect('builder-inited', lambda app: result.append(2), priority=500)
|
||||||
# earlier
|
# earlier
|
||||||
@ -30,7 +31,8 @@ def test_event_allowed_exceptions():
|
|||||||
def raise_error(app):
|
def raise_error(app):
|
||||||
raise RuntimeError
|
raise RuntimeError
|
||||||
|
|
||||||
events = EventManager(FakeApp()) # pass an dummy object as an app
|
app = FakeApp() # pass a dummy object as an app
|
||||||
|
events = EventManager(app) # type: ignore[arg-type]
|
||||||
events.connect('builder-inited', raise_error, priority=500)
|
events.connect('builder-inited', raise_error, priority=500)
|
||||||
|
|
||||||
# all errors are converted to ExtensionError
|
# all errors are converted to ExtensionError
|
||||||
@ -46,7 +48,8 @@ def test_event_pdb():
|
|||||||
def raise_error(app):
|
def raise_error(app):
|
||||||
raise RuntimeError
|
raise RuntimeError
|
||||||
|
|
||||||
events = EventManager(FakeApp(pdb=True)) # pass an dummy object as an app
|
app = FakeApp(pdb=True) # pass a dummy object as an app
|
||||||
|
events = EventManager(app) # type: ignore[arg-type]
|
||||||
events.connect('builder-inited', raise_error, priority=500)
|
events.connect('builder-inited', raise_error, priority=500)
|
||||||
|
|
||||||
# errors aren't converted
|
# errors aren't converted
|
||||||
|
@ -4,6 +4,8 @@ This tests mainly the Documenters; the auto directives are tested in a test
|
|||||||
source file translated by test_build.
|
source file translated by test_build.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from tests.test_extensions.autodoc_util import do_autodoc
|
from tests.test_extensions.autodoc_util import do_autodoc
|
||||||
@ -109,7 +111,7 @@ def test_decorated(app):
|
|||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_singledispatch(app):
|
def test_singledispatch(app):
|
||||||
options = {}
|
options: dict[str, Any] = {}
|
||||||
actual = do_autodoc(app, 'function', 'target.singledispatch.func', options)
|
actual = do_autodoc(app, 'function', 'target.singledispatch.func', options)
|
||||||
assert list(actual) == [
|
assert list(actual) == [
|
||||||
'',
|
'',
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import functools
|
import functools
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from typing import Any
|
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@ -111,7 +110,7 @@ class TestProcessDocstring:
|
|||||||
|
|
||||||
class TestSetup:
|
class TestSetup:
|
||||||
def test_unknown_app_type(self):
|
def test_unknown_app_type(self):
|
||||||
setup(object())
|
setup(object()) # type: ignore[arg-type]
|
||||||
|
|
||||||
def test_add_config_values(self):
|
def test_add_config_values(self):
|
||||||
app = mock.Mock(Sphinx)
|
app = mock.Mock(Sphinx)
|
||||||
@ -146,7 +145,7 @@ class TestSkipMember:
|
|||||||
self,
|
self,
|
||||||
what: str,
|
what: str,
|
||||||
member: str,
|
member: str,
|
||||||
obj: Any,
|
obj: object,
|
||||||
expect_default_skip: bool,
|
expect_default_skip: bool,
|
||||||
config_name: str,
|
config_name: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
"""Test the sphinx.quickstart module."""
|
"""Test the sphinx.quickstart module."""
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
from collections.abc import Callable
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from os import path
|
from os import path
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@ -17,10 +20,12 @@ def setup_module():
|
|||||||
nocolor()
|
nocolor()
|
||||||
|
|
||||||
|
|
||||||
def mock_input(answers, needanswer=False):
|
def mock_input(
|
||||||
|
answers: dict[str, str], needanswer: bool = False
|
||||||
|
) -> Callable[[str], str]:
|
||||||
called = set()
|
called = set()
|
||||||
|
|
||||||
def input_(prompt):
|
def input_(prompt: str) -> str:
|
||||||
if prompt in called:
|
if prompt in called:
|
||||||
raise AssertionError(
|
raise AssertionError(
|
||||||
'answer for %r missing and no default present' % prompt
|
'answer for %r missing and no default present' % prompt
|
||||||
@ -36,7 +41,7 @@ def mock_input(answers, needanswer=False):
|
|||||||
return input_
|
return input_
|
||||||
|
|
||||||
|
|
||||||
real_input = input
|
real_input: Callable[[str], str] = input
|
||||||
|
|
||||||
|
|
||||||
def teardown_module():
|
def teardown_module():
|
||||||
@ -95,13 +100,13 @@ def test_quickstart_defaults(tmp_path):
|
|||||||
'Project version': '0.1',
|
'Project version': '0.1',
|
||||||
}
|
}
|
||||||
qs.term_input = mock_input(answers)
|
qs.term_input = mock_input(answers)
|
||||||
d = {}
|
d: dict[str, Any] = {}
|
||||||
qs.ask_user(d)
|
qs.ask_user(d)
|
||||||
qs.generate(d)
|
qs.generate(d)
|
||||||
|
|
||||||
conffile = tmp_path / 'conf.py'
|
conffile = tmp_path / 'conf.py'
|
||||||
assert conffile.is_file()
|
assert conffile.is_file()
|
||||||
ns = {}
|
ns: dict[str, Any] = {}
|
||||||
exec(conffile.read_text(encoding='utf8'), ns) # NoQA: S102
|
exec(conffile.read_text(encoding='utf8'), ns) # NoQA: S102
|
||||||
assert ns['extensions'] == []
|
assert ns['extensions'] == []
|
||||||
assert ns['templates_path'] == ['_templates']
|
assert ns['templates_path'] == ['_templates']
|
||||||
@ -145,13 +150,13 @@ def test_quickstart_all_answers(tmp_path):
|
|||||||
'Do you want to use the epub builder': 'yes',
|
'Do you want to use the epub builder': 'yes',
|
||||||
}
|
}
|
||||||
qs.term_input = mock_input(answers, needanswer=True)
|
qs.term_input = mock_input(answers, needanswer=True)
|
||||||
d = {}
|
d: dict[str, Any] = {}
|
||||||
qs.ask_user(d)
|
qs.ask_user(d)
|
||||||
qs.generate(d)
|
qs.generate(d)
|
||||||
|
|
||||||
conffile = tmp_path / 'source' / 'conf.py'
|
conffile = tmp_path / 'source' / 'conf.py'
|
||||||
assert conffile.is_file()
|
assert conffile.is_file()
|
||||||
ns = {}
|
ns: dict[str, Any] = {}
|
||||||
exec(conffile.read_text(encoding='utf8'), ns) # NoQA: S102
|
exec(conffile.read_text(encoding='utf8'), ns) # NoQA: S102
|
||||||
assert ns['extensions'] == [
|
assert ns['extensions'] == [
|
||||||
'sphinx.ext.autodoc',
|
'sphinx.ext.autodoc',
|
||||||
@ -184,11 +189,11 @@ def test_generated_files_eol(tmp_path):
|
|||||||
'Project version': '0.1',
|
'Project version': '0.1',
|
||||||
}
|
}
|
||||||
qs.term_input = mock_input(answers)
|
qs.term_input = mock_input(answers)
|
||||||
d = {}
|
d: dict[str, Any] = {}
|
||||||
qs.ask_user(d)
|
qs.ask_user(d)
|
||||||
qs.generate(d)
|
qs.generate(d)
|
||||||
|
|
||||||
def assert_eol(filename, eol):
|
def assert_eol(filename: Path, eol: str) -> None:
|
||||||
content = filename.read_bytes().decode()
|
content = filename.read_bytes().decode()
|
||||||
assert all(l[-len(eol) :] == eol for l in content.splitlines(keepends=True))
|
assert all(l[-len(eol) :] == eol for l in content.splitlines(keepends=True))
|
||||||
|
|
||||||
@ -204,7 +209,7 @@ def test_quickstart_and_build(tmp_path):
|
|||||||
'Project version': '0.1',
|
'Project version': '0.1',
|
||||||
}
|
}
|
||||||
qs.term_input = mock_input(answers)
|
qs.term_input = mock_input(answers)
|
||||||
d = {}
|
d: dict[str, Any] = {}
|
||||||
qs.ask_user(d)
|
qs.ask_user(d)
|
||||||
qs.generate(d)
|
qs.generate(d)
|
||||||
|
|
||||||
@ -223,13 +228,13 @@ def test_default_filename(tmp_path):
|
|||||||
'Project version': '0.1',
|
'Project version': '0.1',
|
||||||
}
|
}
|
||||||
qs.term_input = mock_input(answers)
|
qs.term_input = mock_input(answers)
|
||||||
d = {}
|
d: dict[str, Any] = {}
|
||||||
qs.ask_user(d)
|
qs.ask_user(d)
|
||||||
qs.generate(d)
|
qs.generate(d)
|
||||||
|
|
||||||
conffile = tmp_path / 'conf.py'
|
conffile = tmp_path / 'conf.py'
|
||||||
assert conffile.is_file()
|
assert conffile.is_file()
|
||||||
ns = {}
|
ns: dict[str, Any] = {}
|
||||||
exec(conffile.read_text(encoding='utf8'), ns) # NoQA: S102
|
exec(conffile.read_text(encoding='utf8'), ns) # NoQA: S102
|
||||||
|
|
||||||
|
|
||||||
@ -247,7 +252,7 @@ def test_extensions(tmp_path):
|
|||||||
|
|
||||||
conffile = tmp_path / 'conf.py'
|
conffile = tmp_path / 'conf.py'
|
||||||
assert conffile.is_file()
|
assert conffile.is_file()
|
||||||
ns = {}
|
ns: dict[str, Any] = {}
|
||||||
exec(conffile.read_text(encoding='utf8'), ns) # NoQA: S102
|
exec(conffile.read_text(encoding='utf8'), ns) # NoQA: S102
|
||||||
assert ns['extensions'] == ['foo', 'bar', 'baz']
|
assert ns['extensions'] == ['foo', 'bar', 'baz']
|
||||||
|
|
||||||
@ -263,6 +268,6 @@ def test_exits_when_existing_confpy(monkeypatch):
|
|||||||
qs.term_input = mock_input({
|
qs.term_input = mock_input({
|
||||||
'Please enter a new root path (or just Enter to exit)': '',
|
'Please enter a new root path (or just Enter to exit)': '',
|
||||||
})
|
})
|
||||||
d = {}
|
d: dict[str, Any] = {}
|
||||||
with pytest.raises(SystemExit):
|
with pytest.raises(SystemExit):
|
||||||
qs.ask_user(d)
|
qs.ask_user(d)
|
||||||
|
@ -17,6 +17,10 @@ from tests.utils import TESTS_ROOT
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from collections.abc import Iterator
|
from collections.abc import Iterator
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from sphinx.domains import ObjType
|
||||||
|
|
||||||
JAVASCRIPT_TEST_ROOTS = [
|
JAVASCRIPT_TEST_ROOTS = [
|
||||||
directory
|
directory
|
||||||
@ -52,9 +56,9 @@ class DummyDomain:
|
|||||||
def __init__(self, name: str, data: dict) -> None:
|
def __init__(self, name: str, data: dict) -> None:
|
||||||
self.name = name
|
self.name = name
|
||||||
self.data = data
|
self.data = data
|
||||||
self.object_types = {}
|
self.object_types: dict[str, ObjType] = {}
|
||||||
|
|
||||||
def get_objects(self):
|
def get_objects(self) -> list[tuple[str, str, str, str, str, int]]:
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
|
|
||||||
@ -72,7 +76,7 @@ def setup_module():
|
|||||||
parser = rst.Parser()
|
parser = rst.Parser()
|
||||||
|
|
||||||
|
|
||||||
def load_searchindex(path):
|
def load_searchindex(path: Path) -> Any:
|
||||||
searchindex = path.read_text(encoding='utf8')
|
searchindex = path.read_text(encoding='utf8')
|
||||||
assert searchindex.startswith('Search.setIndex(')
|
assert searchindex.startswith('Search.setIndex(')
|
||||||
assert searchindex.endswith(')')
|
assert searchindex.endswith(')')
|
||||||
@ -80,7 +84,7 @@ def load_searchindex(path):
|
|||||||
return json.loads(searchindex[16:-1])
|
return json.loads(searchindex[16:-1])
|
||||||
|
|
||||||
|
|
||||||
def is_registered_term(index, keyword):
|
def is_registered_term(index: Any, keyword: str) -> bool:
|
||||||
return index['terms'].get(keyword, []) != []
|
return index['terms'].get(keyword, []) != []
|
||||||
|
|
||||||
|
|
||||||
@ -191,12 +195,12 @@ def test_IndexBuilder():
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
env = DummyEnvironment('1.0', DummyDomainsContainer(dummy1=domain1, dummy2=domain2))
|
env = DummyEnvironment('1.0', DummyDomainsContainer(dummy1=domain1, dummy2=domain2))
|
||||||
doc = utils.new_document(b'test data', settings)
|
doc = utils.new_document('test data', settings)
|
||||||
doc['file'] = 'dummy'
|
doc['file'] = 'dummy'
|
||||||
parser.parse(FILE_CONTENTS, doc)
|
parser.parse(FILE_CONTENTS, doc)
|
||||||
|
|
||||||
# feed
|
# feed
|
||||||
index = IndexBuilder(env, 'en', {}, None)
|
index = IndexBuilder(env, 'en', {}, '')
|
||||||
index.feed('docname1_1', 'filename1_1', 'title1_1', doc)
|
index.feed('docname1_1', 'filename1_1', 'title1_1', doc)
|
||||||
index.feed('docname1_2', 'filename1_2', 'title1_2', doc)
|
index.feed('docname1_2', 'filename1_2', 'title1_2', doc)
|
||||||
index.feed('docname2_2', 'filename2_2', 'title2_2', doc)
|
index.feed('docname2_2', 'filename2_2', 'title2_2', doc)
|
||||||
@ -285,7 +289,7 @@ def test_IndexBuilder():
|
|||||||
index.dump(stream, 'pickle')
|
index.dump(stream, 'pickle')
|
||||||
stream.seek(0)
|
stream.seek(0)
|
||||||
|
|
||||||
index2 = IndexBuilder(env, 'en', {}, None)
|
index2 = IndexBuilder(env, 'en', {}, '')
|
||||||
index2.load(stream, 'pickle')
|
index2.load(stream, 'pickle')
|
||||||
|
|
||||||
assert index2._titles == index._titles
|
assert index2._titles == index._titles
|
||||||
@ -366,11 +370,11 @@ def test_IndexBuilder_lookup():
|
|||||||
env = DummyEnvironment('1.0', {})
|
env = DummyEnvironment('1.0', {})
|
||||||
|
|
||||||
# zh
|
# zh
|
||||||
index = IndexBuilder(env, 'zh', {}, None)
|
index = IndexBuilder(env, 'zh', {}, '')
|
||||||
assert index.lang.lang == 'zh'
|
assert index.lang.lang == 'zh'
|
||||||
|
|
||||||
# zh_CN
|
# zh_CN
|
||||||
index = IndexBuilder(env, 'zh_CN', {}, None)
|
index = IndexBuilder(env, 'zh_CN', {}, '')
|
||||||
assert index.lang.lang == 'zh'
|
assert index.lang.lang == 'zh'
|
||||||
|
|
||||||
|
|
||||||
@ -426,7 +430,7 @@ def test_search_index_is_deterministic(app):
|
|||||||
assert_is_sorted(index, '')
|
assert_is_sorted(index, '')
|
||||||
|
|
||||||
|
|
||||||
def is_title_tuple_type(item: list[int | str]):
|
def is_title_tuple_type(item: list[int | str]) -> bool:
|
||||||
"""
|
"""
|
||||||
In the search index, titles inside .alltitles are stored as a tuple of
|
In the search index, titles inside .alltitles are stored as a tuple of
|
||||||
(document_idx, title_anchor). Tuples are represented as lists in JSON,
|
(document_idx, title_anchor). Tuples are represented as lists in JSON,
|
||||||
@ -436,7 +440,9 @@ def is_title_tuple_type(item: list[int | str]):
|
|||||||
return len(item) == 2 and isinstance(item[0], int) and isinstance(item[1], str)
|
return len(item) == 2 and isinstance(item[0], int) and isinstance(item[1], str)
|
||||||
|
|
||||||
|
|
||||||
def assert_is_sorted(item, path: str):
|
def assert_is_sorted(
|
||||||
|
item: dict[str, str] | list[int | str] | int | str, path: str
|
||||||
|
) -> None:
|
||||||
lists_not_to_sort = {
|
lists_not_to_sort = {
|
||||||
# Each element of .titles is related to the element of .docnames in the same position.
|
# Each element of .titles is related to the element of .docnames in the same position.
|
||||||
# The ordering is deterministic because .docnames is sorted.
|
# The ordering is deterministic because .docnames is sorted.
|
||||||
|
@ -6,12 +6,12 @@ from unittest import mock
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from sphinx.jinja2glue import BuiltinTemplateLoader
|
from sphinx.jinja2glue import BuiltinTemplateLoader
|
||||||
from sphinx.util import strip_colors
|
from sphinx.util.console import strip_colors
|
||||||
from sphinx.util.fileutil import _template_basename, copy_asset, copy_asset_file
|
from sphinx.util.fileutil import _template_basename, copy_asset, copy_asset_file
|
||||||
|
|
||||||
|
|
||||||
class DummyTemplateLoader(BuiltinTemplateLoader):
|
class DummyTemplateLoader(BuiltinTemplateLoader):
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
builder = mock.Mock()
|
builder = mock.Mock()
|
||||||
builder.config.templates_path = []
|
builder.config.templates_path = []
|
||||||
|
Loading…
Reference in New Issue
Block a user