Disallow untyped calls (#12640)

Co-authored-by: Adam Turner <9087854+aa-turner@users.noreply.github.com>
This commit is contained in:
danieleades 2024-07-23 02:22:58 +01:00 committed by GitHub
parent e8f8247e0c
commit 58d4224227
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 80 additions and 28 deletions

View File

@ -211,6 +211,7 @@ disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_defs = true
python_version = "3.10"
disallow_untyped_calls = true
show_column_numbers = true
show_error_context = true
strict_optional = true

View File

@ -108,8 +108,8 @@ class NavPoint(NamedTuple):
def sphinx_smarty_pants(t: str, language: str = 'en') -> str:
t = t.replace('&quot;', '"')
t = smartquotes.educateDashesOldSchool(t)
t = smartquotes.educateQuotes(t, language)
t = smartquotes.educateDashesOldSchool(t) # type: ignore[no-untyped-call]
t = smartquotes.educateQuotes(t, language) # type: ignore[no-untyped-call]
t = t.replace('"', '&quot;')
return t

View File

@ -43,7 +43,7 @@ class TitleCollector(EnvironmentCollector):
for node in doctree.findall(nodes.section):
visitor = SphinxContentsFilter(doctree)
node[0].walkabout(visitor)
titlenode += visitor.get_entry_text()
titlenode += visitor.get_entry_text() # type: ignore[no-untyped-call]
break
else:
# document has no title

View File

@ -78,7 +78,7 @@ class TocTreeCollector(EnvironmentCollector):
# and unnecessary stuff
visitor = SphinxContentsFilter(doctree)
title.walkabout(visitor)
nodetext = visitor.get_entry_text()
nodetext = visitor.get_entry_text() # type: ignore[no-untyped-call]
anchorname = _make_anchor_name(sectionnode['ids'], numentries)
# make these nodes:
# list_item -> compact_paragraph -> reference

View File

@ -9,6 +9,7 @@ from os import path
from typing import TYPE_CHECKING
if TYPE_CHECKING:
import os
from collections.abc import Callable, Iterable
from typing import Any
@ -98,7 +99,7 @@ translators: dict[tuple[str, str], NullTranslations] = {}
def init(
locale_dirs: Iterable[str | None],
locale_dirs: Iterable[str | os.PathLike[str] | None],
language: str | None,
catalog: str = 'sphinx',
namespace: str = 'general',

View File

@ -364,7 +364,7 @@ class SphinxSmartQuotes(SmartQuotes, SphinxTransform):
# override default settings with :confval:`smartquotes_action`
self.smartquotes_action = self.config.smartquotes_action
super().apply()
super().apply() # type: ignore[no-untyped-call]
def is_available(self) -> bool:
builders = self.config.smartquotes_excludes.get('builders', [])

View File

@ -23,7 +23,7 @@ class SphinxDanglingReferences(DanglingReferences):
# suppress INFO level messages for a while
reporter.report_level = max(reporter.WARNING_LEVEL, reporter.report_level)
super().apply()
super().apply() # type: ignore[no-untyped-call]
finally:
reporter.report_level = report_level

View File

@ -1276,8 +1276,8 @@ class LaTeXTranslator(SphinxTranslator):
else:
return get_nested_level(node.parent)
enum = "enum%s" % toRoman(get_nested_level(node)).lower()
enumnext = "enum%s" % toRoman(get_nested_level(node) + 1).lower()
enum = "enum%s" % toRoman(get_nested_level(node)).lower() # type: ignore[no-untyped-call]
enumnext = "enum%s" % toRoman(get_nested_level(node) + 1).lower() # type: ignore[no-untyped-call]
style = ENUMERATE_LIST_STYLE.get(get_enumtype(node))
prefix = node.get('prefix', '')
suffix = node.get('suffix', '.')

View File

@ -1,17 +1,25 @@
"""Test the HTML builder and check output against XPath."""
from __future__ import annotations
import re
from typing import TYPE_CHECKING
import pytest
from docutils import nodes
from tests.test_builders.xpath_util import check_xpath
if TYPE_CHECKING:
from collections.abc import Callable, Iterable
from typing import Literal
from xml.etree.ElementTree import Element
def tail_check(check):
def tail_check(check: str) -> Callable[[Iterable[Element]], Literal[True]]:
rex = re.compile(check)
def checker(nodes):
def checker(nodes: Iterable[Element]) -> Literal[True]:
for node in nodes:
if node.tail and rex.search(node.tail):
return True

View File

@ -37,6 +37,9 @@ ts_re = re.compile(r".*\[(?P<ts>.*)\].*")
if TYPE_CHECKING:
from collections.abc import Callable, Iterable
from io import StringIO
from typing import Any
from urllib3 import HTTPConnectionPool
from sphinx.application import Sphinx
@ -77,8 +80,8 @@ class DefaultsHandler(BaseHTTPRequestHandler):
class ConnectionMeasurement:
"""Measure the number of distinct host connections created during linkchecking"""
def __init__(self):
self.connections = set()
def __init__(self) -> None:
self.connections: set[HTTPConnectionPool] = set()
self.urllib3_connection_from_url = PoolManager.connection_from_url
self.patcher = mock.patch.object(
target=PoolManager,
@ -86,7 +89,7 @@ class ConnectionMeasurement:
new=self._collect_connections(),
)
def _collect_connections(self):
def _collect_connections(self) -> Callable[[object, str], HTTPConnectionPool]:
def connection_collector(obj, url):
connection = self.urllib3_connection_from_url(obj, url)
self.connections.add(connection)
@ -436,7 +439,10 @@ def test_decoding_error_anchor_ignored(app):
assert row['status'] == 'ignored'
def custom_handler(valid_credentials=(), success_criteria=lambda _: True):
def custom_handler(
valid_credentials: tuple[str, str] | None = None,
success_criteria: Callable[[Any], bool] = lambda _: True
) -> type[BaseHTTPRequestHandler]:
"""
Returns an HTTP request handler that authenticates the client and then determines
an appropriate HTTP response code, based on caller-provided credentials and optional
@ -591,11 +597,11 @@ def test_linkcheck_request_headers_default(app: Sphinx) -> None:
assert content["status"] == "working"
def make_redirect_handler(*, support_head):
def make_redirect_handler(*, support_head: bool) -> type[BaseHTTPRequestHandler]:
class RedirectOnceHandler(BaseHTTPRequestHandler):
protocol_version = "HTTP/1.1"
def do_HEAD(self):
def do_HEAD(self) -> None:
if support_head:
self.do_GET()
else:
@ -603,7 +609,7 @@ def make_redirect_handler(*, support_head):
self.send_header("Content-Length", "0")
self.end_headers()
def do_GET(self):
def do_GET(self) -> None:
if self.path == "/?redirected=1":
self.send_response(204, "No content")
else:
@ -843,7 +849,7 @@ def test_TooManyRedirects_on_HEAD(app, monkeypatch):
}
def make_retry_after_handler(responses):
def make_retry_after_handler(responses: list[tuple[int, str | None]]) -> type[BaseHTTPRequestHandler]:
class RetryAfterHandler(BaseHTTPRequestHandler):
protocol_version = "HTTP/1.1"

View File

@ -1,12 +1,19 @@
"""Test the build process with Text builder with the test root."""
from __future__ import annotations
from typing import TYPE_CHECKING
import pytest
from docutils.utils import column_width
from sphinx.writers.text import MAXWIDTH, Cell, Table
if TYPE_CHECKING:
from typing import Any
def with_text_app(*args, **kw):
def with_text_app(*args: Any, **kw: Any) -> pytest.MarkDecorator:
default_kw = {
'buildername': 'text',
'testroot': 'build-text',

View File

@ -12,7 +12,7 @@ from sphinx.ext.mathjax import MATHJAX_URL
from sphinx.testing.util import assert_node
def has_binary(binary):
def has_binary(binary: str) -> bool:
try:
subprocess.check_output([binary])
except FileNotFoundError:

View File

@ -1,12 +1,20 @@
"""Test sphinx.ext.viewcode extension."""
from __future__ import annotations
import re
import shutil
from typing import TYPE_CHECKING
import pytest
if TYPE_CHECKING:
from io import StringIO
def check_viewcode_output(app, warning):
from sphinx.application import Sphinx
def check_viewcode_output(app: Sphinx, warning: StringIO) -> str:
warnings = re.sub(r'\\+', '/', warning.getvalue())
assert re.findall(
r"index.rst:\d+: WARNING: Object named 'func1' not found in include " +

View File

@ -1,9 +1,17 @@
"""Test locale."""
from __future__ import annotations
from typing import TYPE_CHECKING
import pytest
from sphinx import locale
if TYPE_CHECKING:
from collections.abc import Callable
from pathlib import Path
@pytest.fixture(autouse=True)
def _cleanup_translations():
@ -57,7 +65,7 @@ def test_add_message_catalog(app, rootdir):
assert _('Hello reST') == 'Hello reST'
def _empty_language_translation(rootdir):
def _empty_language_translation(rootdir: Path) -> Callable[[str], str]:
locale_dirs, catalog = [rootdir / 'test-locale' / 'locale1'], 'myext'
locale.translators.clear()
locale.init(locale_dirs, language=None, catalog=catalog)

View File

@ -1,6 +1,9 @@
"""Tests util.utils functions."""
from __future__ import annotations
import os
from typing import TYPE_CHECKING
from docutils import nodes
@ -12,6 +15,9 @@ from sphinx.util.docutils import (
register_node,
)
if TYPE_CHECKING:
from sphinx.builders import Builder
def test_register_node():
class custom_node(nodes.Element):
@ -66,9 +72,9 @@ def test_SphinxTranslator(app):
pass
class MyTranslator(SphinxTranslator):
def __init__(self, *args):
self.called = []
super().__init__(*args)
def __init__(self, document: nodes.document, builder: Builder):
self.called: list[str] = []
super().__init__(document, builder)
def visit_document(self, node):
pass

View File

@ -1,7 +1,11 @@
"""Test inventory util functions."""
from __future__ import annotations
import os
import posixpath
from io import BytesIO
from typing import TYPE_CHECKING
import sphinx.locale
from sphinx.testing.util import SphinxTestApp
@ -14,6 +18,9 @@ from tests.test_util.intersphinx_data import (
INVENTORY_V2_NO_VERSION,
)
if TYPE_CHECKING:
from pathlib import Path
def test_read_inventory_v1():
f = BytesIO(INVENTORY_V1)
@ -67,7 +74,7 @@ def test_ambiguous_definition_warning(warning, status):
assert mult_defs_b in status.getvalue().lower()
def _write_appconfig(dir, language, prefix=None):
def _write_appconfig(dir: Path, language: str, prefix: str | None = None) -> Path:
prefix = prefix or language
os.makedirs(dir / prefix, exist_ok=True)
(dir / prefix / 'conf.py').write_text(f'language = "{language}"', encoding='utf8')
@ -77,7 +84,7 @@ def _write_appconfig(dir, language, prefix=None):
return dir / prefix
def _build_inventory(srcdir):
def _build_inventory(srcdir: Path) -> Path:
app = SphinxTestApp(srcdir=srcdir)
app.build()
sphinx.locale.translators.clear()