Remove top-level modules from the no-any-generics whitelist

This commit is contained in:
Adam Turner 2025-01-22 02:24:55 +00:00
parent 7154672c2e
commit 1b607502d5
15 changed files with 119 additions and 76 deletions

View File

@ -187,9 +187,16 @@ nitpick_ignore = {
('py:attr', 'srcline'),
('py:class', '_AutodocProcessDocstringListener'),
('py:class', '_ConfigRebuild'), # sphinx.application.Sphinx.add_config_value
# sphinx.application.Sphinx.add_html_math_renderer
('py:class', '_MathsBlockRenderers'),
# sphinx.application.Sphinx.add_html_math_renderer
('py:class', '_MathsInlineRenderers'),
('py:class', '_NodeHandler'), # sphinx.application.Sphinx.add_enumerable_node
('py:class', '_NodeHandlerPair'), # sphinx.application.Sphinx.add_node
('py:class', '_StrPath'), # sphinx.environment.BuildEnvironment.doc2path
('py:class', 'Element'), # sphinx.domains.Domain
('py:class', 'Documenter'), # sphinx.application.Sphinx.add_autodocumenter
('py:class', 'Field'), # sphinx.application.Sphinx.add_object_type
('py:class', 'IndexEntry'), # sphinx.domains.IndexEntry
('py:class', 'Inliner'), # sphinx.util.docutils.SphinxRole.inliner
('py:class', 'Lexer'), # sphinx.application.Sphinx.add_lexer
@ -200,10 +207,10 @@ nitpick_ignore = {
('py:class', 'Path'), # sphinx.application.Sphinx.connect
('py:class', 'RoleFunction'), # sphinx.domains.Domain
('py:class', 'RSTState'), # sphinx.utils.parsing.nested_parse_to_nodes
('py:class', 'Theme'), # sphinx.application.TemplateBridge
('py:class', 'SearchLanguage'), # sphinx.application.Sphinx.add_search_language
('py:class', 'StringList'), # sphinx.utils.parsing.nested_parse_to_nodes
('py:class', 'system_message'), # sphinx.utils.docutils.SphinxDirective
('py:class', 'Theme'), # sphinx.application.TemplateBridge
('py:class', 'TitleGetter'), # sphinx.domains.Domain
('py:class', 'todo_node'), # sphinx.application.Sphinx.connect
('py:class', 'Transform'), # sphinx.application.Sphinx.add_transform

View File

@ -231,21 +231,14 @@ strict_optional = false
[[tool.mypy.overrides]]
module = [
"sphinx.application",
"sphinx.config",
"sphinx.domains",
"sphinx.domains.c",
"sphinx.domains.cpp",
"sphinx.events",
"sphinx.ext.autodoc",
"sphinx.ext.autodoc.importer",
"sphinx.ext.doctest",
"sphinx.ext.graphviz",
"sphinx.ext.inheritance_diagram",
"sphinx.highlighting",
"sphinx.jinja2glue",
"sphinx.registry",
"sphinx.search",
"sphinx.util.docfields",
"sphinx.util.docutils",
"sphinx.util.inspect",

View File

@ -55,9 +55,16 @@ if TYPE_CHECKING:
from sphinx.ext.autodoc import Documenter, _AutodocProcessDocstringListener
from sphinx.ext.todo import todo_node
from sphinx.extension import Extension
from sphinx.registry import (
_MathsBlockRenderers,
_MathsInlineRenderers,
_NodeHandler,
_NodeHandlerPair,
)
from sphinx.roles import XRefRole
from sphinx.search import SearchLanguage
from sphinx.theming import Theme
from sphinx.util.docfields import Field
from sphinx.util.typing import RoleFunction, TitleGetter
@ -154,7 +161,7 @@ class Sphinx:
outdir: str | os.PathLike[str],
doctreedir: str | os.PathLike[str],
buildername: str,
confoverrides: dict | None = None,
confoverrides: dict[str, Any] | None = None,
status: IO[str] | None = sys.stdout,
warning: IO[str] | None = sys.stderr,
freshenv: bool = False,
@ -792,7 +799,9 @@ class Sphinx:
) -> int: ...
# event interface
def connect(self, event: str, callback: Callable, priority: int = 500) -> int:
def connect(
self, event: str, callback: Callable[..., Any], priority: int = 500
) -> int:
"""Register *callback* to be called when *event* is emitted.
For details on available core events and the arguments of callback
@ -831,7 +840,7 @@ class Sphinx:
event: str,
*args: Any,
allowed_exceptions: tuple[type[Exception], ...] = (),
) -> list:
) -> list[Any]:
"""Emit *event* and pass *arguments* to the callback functions.
Return the return values of all callbacks as a list. Do not emit core
@ -974,7 +983,7 @@ class Sphinx:
self,
node: type[Element],
override: bool = False,
**kwargs: tuple[Callable, Callable | None],
**kwargs: _NodeHandlerPair,
) -> None:
"""Register a Docutils node class.
@ -1031,7 +1040,7 @@ class Sphinx:
figtype: str,
title_getter: TitleGetter | None = None,
override: bool = False,
**kwargs: tuple[Callable, Callable],
**kwargs: tuple[_NodeHandler, _NodeHandler],
) -> None:
"""Register a Docutils node class as a numfig target.
@ -1254,10 +1263,11 @@ class Sphinx:
directivename: str,
rolename: str,
indextemplate: str = '',
parse_node: Callable | None = None,
parse_node: Callable[[BuildEnvironment, str, addnodes.desc_signature], str]
| None = None,
ref_nodeclass: type[nodes.TextElement] | None = None,
objname: str = '',
doc_field_types: Sequence = (),
doc_field_types: Sequence[Field] = (),
override: bool = False,
) -> None:
"""Register a new object type.
@ -1718,8 +1728,8 @@ class Sphinx:
def add_html_math_renderer(
self,
name: str,
inline_renderers: tuple[Callable, Callable | None] | None = None,
block_renderers: tuple[Callable, Callable | None] | None = None,
inline_renderers: _MathsInlineRenderers | None = None,
block_renderers: _MathsBlockRenderers | None = None,
) -> None:
"""Register a math renderer for HTML.
@ -1838,7 +1848,7 @@ class TemplateBridge:
msg = 'must be implemented in subclasses'
raise NotImplementedError(msg)
def render_string(self, template: str, context: dict) -> str:
def render_string(self, template: str, context: dict[str, Any]) -> str:
"""Called by the builder to render a template given as a string with a
specified context (a Python dictionary).
"""

View File

@ -88,7 +88,7 @@ class ENUM:
def __repr__(self) -> str:
return f'ENUM({", ".join(sorted(map(repr, self._candidates)))})'
def match(self, value: str | list | tuple) -> bool:
def match(self, value: str | Sequence[str | bool | None]) -> bool:
if isinstance(value, frozenset | list | set | tuple):
return all(item in self._candidates for item in value)
return value in self._candidates
@ -345,7 +345,7 @@ class Config:
def read(
cls: type[Config],
confdir: str | os.PathLike[str],
overrides: dict | None = None,
overrides: dict[str, Any] | None = None,
tags: Tags | None = None,
) -> Config:
"""Create a Config object from configuration file."""
@ -532,7 +532,7 @@ class Config:
return (value for value in self if value.rebuild == rebuild)
return (value for value in self if value.rebuild in rebuild)
def __getstate__(self) -> dict:
def __getstate__(self) -> dict[str, Any]:
"""Obtains serializable data for pickling."""
# remove potentially pickling-problematic values from config
__dict__ = {
@ -569,7 +569,7 @@ class Config:
return __dict__
def __setstate__(self, state: dict) -> None:
def __setstate__(self, state: dict[str, Any]) -> None:
self._overrides = {}
self._options = {
name: _Opt(real_value, rebuild, ())

View File

@ -31,21 +31,18 @@ if TYPE_CHECKING:
_IndexEntryCategoryKey,
]
_IndexEntryMap: TypeAlias = dict[str, _IndexEntry]
_Index: TypeAlias = list[
# Used by ``create_index()`` for 'the real index'
_RealIndexEntry: TypeAlias = tuple[
str,
tuple[
str,
list[
tuple[
str,
tuple[
_IndexEntryTargets,
list[tuple[str, _IndexEntryTargets]],
_IndexEntryCategoryKey,
],
]
],
]
_IndexEntryTargets,
list[tuple[str, _IndexEntryTargets]],
_IndexEntryCategoryKey,
],
]
_RealIndexEntries: TypeAlias = list[_RealIndexEntry]
_Index: TypeAlias = list[tuple[str, _RealIndexEntries]]
logger = logging.getLogger(__name__)

View File

@ -36,7 +36,7 @@ logger = logging.getLogger(__name__)
class EventListener(NamedTuple):
id: int
handler: Callable
handler: Callable[..., Any]
priority: int
@ -364,7 +364,7 @@ class EventManager:
priority: int,
) -> int: ...
def connect(self, name: str, callback: Callable, priority: int) -> int:
def connect(self, name: str, callback: Callable[..., Any], priority: int) -> int:
"""Connect a handler to specific event."""
if name not in self.events:
raise ExtensionError(__('Unknown event name: %s') % name)
@ -386,7 +386,7 @@ class EventManager:
name: str,
*args: Any,
allowed_exceptions: tuple[type[Exception], ...] = (),
) -> list:
) -> list[Any]:
"""Emit a Sphinx event."""
# not every object likes to be repr()'d (think
# random stuff coming via autodoc)

View File

@ -129,7 +129,7 @@ class PygmentsBridge:
else:
return get_style_by_name(stylename)
def get_formatter(self, **kwargs: Any) -> Formatter:
def get_formatter(self, **kwargs: Any) -> Formatter[str]:
kwargs.update(self.formatter_args)
return self.formatter(**kwargs)
@ -137,7 +137,7 @@ class PygmentsBridge:
self,
source: str,
lang: str,
opts: dict | None = None,
opts: dict[str, Any] | None = None,
force: bool = False,
location: Any = None,
) -> Lexer:
@ -180,7 +180,7 @@ class PygmentsBridge:
self,
source: str,
lang: str,
opts: dict | None = None,
opts: dict[str, Any] | None = None,
force: bool = False,
location: Any = None,
**kwargs: Any,

View File

@ -24,6 +24,10 @@ if TYPE_CHECKING:
from jinja2.environment import Environment
from sphinx.builders import Builder
from sphinx.environment.adapters.indexentries import (
_RealIndexEntries,
_RealIndexEntry,
)
from sphinx.theming import Theme
@ -57,7 +61,9 @@ def _todim(val: int | str) -> str:
return val # type: ignore[return-value]
def _slice_index(values: list, slices: int) -> Iterator[list]:
def _slice_index(
values: _RealIndexEntries, slices: int
) -> Iterator[list[_RealIndexEntry]]:
seq = values.copy()
length = 0
for value in values:

View File

@ -23,7 +23,7 @@ from sphinx.util.logging import prefixed_warnings
if TYPE_CHECKING:
import os
from collections.abc import Callable, Iterator, Mapping, Sequence
from typing import Any
from typing import Any, TypeAlias
from docutils import nodes
from docutils.core import Publisher
@ -32,18 +32,34 @@ if TYPE_CHECKING:
from docutils.parsers.rst import Directive
from docutils.transforms import Transform
from sphinx import addnodes
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.config import Config
from sphinx.domains import Domain, Index
from sphinx.environment import BuildEnvironment
from sphinx.ext.autodoc import Documenter
from sphinx.util.docfields import Field
from sphinx.util.typing import (
ExtensionMetadata,
RoleFunction,
TitleGetter,
_ExtensionSetupFunc,
)
from sphinx.writers.html5 import HTML5Translator
# visit/depart function
# the parameters should be (SphinxTranslator, Element)
# or any subtype of either, but mypy rejects this.
_NodeHandler: TypeAlias = Callable[[Any, Any], None]
_NodeHandlerPair: TypeAlias = tuple[_NodeHandler, _NodeHandler | None]
_MathsRenderer: TypeAlias = Callable[[HTML5Translator, nodes.math], None]
_MathsBlockRenderer: TypeAlias = Callable[[HTML5Translator, nodes.math_block], None]
_MathsInlineRenderers: TypeAlias = tuple[_MathsRenderer, _MathsRenderer | None]
_MathsBlockRenderers: TypeAlias = tuple[
_MathsBlockRenderer, _MathsBlockRenderer | None
]
logger = logging.getLogger(__name__)
@ -96,9 +112,13 @@ class SphinxComponentRegistry:
#: HTML inline and block math renderers
#: a dict of name -> tuple of visit function and depart function
self.html_inline_math_renderers: dict[
str, tuple[Callable, Callable | None]
str,
_MathsInlineRenderers,
] = {}
self.html_block_math_renderers: dict[
str,
_MathsBlockRenderers,
] = {}
self.html_block_math_renderers: dict[str, tuple[Callable, Callable | None]] = {}
#: HTML assets
self.html_assets_policy: str = 'per_page'
@ -128,9 +148,7 @@ class SphinxComponentRegistry:
#: custom handlers for translators
#: a dict of builder name -> dict of node name -> visitor and departure functions
self.translation_handlers: dict[
str, dict[str, tuple[Callable, Callable | None]]
] = {}
self.translation_handlers: dict[str, dict[str, _NodeHandlerPair]] = {}
#: additional transforms; list of transforms
self.transforms: list[type[Transform]] = []
@ -255,10 +273,11 @@ class SphinxComponentRegistry:
directivename: str,
rolename: str,
indextemplate: str = '',
parse_node: Callable | None = None,
parse_node: Callable[[BuildEnvironment, str, addnodes.desc_signature], str]
| None = None,
ref_nodeclass: type[TextElement] | None = None,
objname: str = '',
doc_field_types: Sequence = (),
doc_field_types: Sequence[Field] = (),
override: bool = False,
) -> None:
logger.debug(
@ -372,9 +391,7 @@ class SphinxComponentRegistry:
self.translators[name] = translator
def add_translation_handlers(
self,
node: type[Element],
**kwargs: tuple[Callable, Callable | None],
self, node: type[Element], **kwargs: _NodeHandlerPair
) -> None:
logger.debug('[app] adding translation_handlers: %r, %r', node, kwargs)
for builder_name, handlers in kwargs.items():
@ -482,8 +499,8 @@ class SphinxComponentRegistry:
def add_html_math_renderer(
self,
name: str,
inline_renderers: tuple[Callable, Callable | None] | None,
block_renderers: tuple[Callable, Callable | None] | None,
inline_renderers: _MathsInlineRenderers | None,
block_renderers: _MathsBlockRenderers | None,
) -> None:
logger.debug(
'[app] adding html_math_renderer: %s, %r, %r',

View File

@ -22,12 +22,23 @@ from sphinx.util.index_entries import split_index_msg
if TYPE_CHECKING:
from collections.abc import Callable, Iterable
from typing import IO, Any
from typing import Any, Protocol, TypeVar
from docutils.nodes import Node
from sphinx.environment import BuildEnvironment
_T_co = TypeVar('_T_co', covariant=True)
_T_contra = TypeVar('_T_contra', contravariant=True)
class _ReadableStream(Protocol[_T_co]):
def read(self, n: int = ..., /) -> _T_co: ...
def readline(self, n: int = ..., /) -> _T_co: ...
class _WritableStream(Protocol[_T_contra]):
def write(self, s: _T_contra, /) -> object: ...
_NON_MINIFIED_JS_PATH = Path(package_dir, 'search', 'non-minified-js')
_MINIFIED_JS_PATH = Path(package_dir, 'search', 'minified-js')
@ -173,10 +184,10 @@ class _JavaScriptIndex:
raise ValueError(msg)
return json.loads(data)
def dump(self, data: Any, f: IO[str]) -> None:
def dump(self, data: Any, f: _WritableStream[str]) -> None:
f.write(self.dumps(data))
def load(self, f: IO[str]) -> Any:
def load(self, f: _ReadableStream[str]) -> Any:
return self.loads(f.read())
@ -310,7 +321,7 @@ class IndexBuilder:
self.js_scorer_code = ''
self.js_splitter_code = ''
def load(self, stream: IO, format: Any) -> None:
def load(self, stream: _ReadableStream[str | bytes], format: Any) -> None:
"""Reconstruct from frozen data."""
if isinstance(format, str):
format = self.formats[format]
@ -346,7 +357,9 @@ class IndexBuilder:
self._title_mapping = load_terms(frozen['titleterms'])
# no need to load keywords/objtypes
def dump(self, stream: IO, format: Any) -> None:
def dump(
self, stream: _WritableStream[str] | _WritableStream[bytes], format: Any
) -> None:
"""Dump the frozen index to a stream."""
if isinstance(format, str):
format = self.formats[format]

View File

@ -962,7 +962,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): # type: ignore[misc]
else:
node['classes'].append('field-odd')
def visit_math(self, node: Element, math_env: str = '') -> None:
def visit_math(self, node: nodes.math, math_env: str = '') -> None:
self._has_maths_elements = True
# see validate_math_renderer
@ -970,14 +970,14 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): # type: ignore[misc]
visit, _ = self.builder.app.registry.html_inline_math_renderers[name]
visit(self, node)
def depart_math(self, node: Element, math_env: str = '') -> None:
def depart_math(self, node: nodes.math, math_env: str = '') -> None:
# see validate_math_renderer
name: str = self.builder.math_renderer_name # type: ignore[assignment]
_, depart = self.builder.app.registry.html_inline_math_renderers[name]
if depart:
depart(self, node)
def visit_math_block(self, node: Element, math_env: str = '') -> None:
def visit_math_block(self, node: nodes.math_block, math_env: str = '') -> None:
self._has_maths_elements = True
# see validate_math_renderer
@ -985,7 +985,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): # type: ignore[misc]
visit, _ = self.builder.app.registry.html_block_math_renderers[name]
visit(self, node)
def depart_math_block(self, node: Element, math_env: str = '') -> None:
def depart_math_block(self, node: nodes.math_block, math_env: str = '') -> None:
# see validate_math_renderer
name: str = self.builder.math_renderer_name # type: ignore[assignment]
_, depart = self.builder.app.registry.html_block_math_renderers[name]

View File

@ -2452,14 +2452,14 @@ class LaTeXTranslator(SphinxTranslator):
def depart_system_message(self, node: Element) -> None:
self.body.append(CR)
def visit_math(self, node: Element) -> None:
def visit_math(self, node: nodes.math) -> None:
if self.in_title:
self.body.append(r'\protect\(%s\protect\)' % node.astext())
else:
self.body.append(r'\(%s\)' % node.astext())
raise nodes.SkipNode
def visit_math_block(self, node: Element) -> None:
def visit_math_block(self, node: nodes.math_block) -> None:
if node.get('label'):
label = f'equation:{node["docname"]}:{node["label"]}'
else:

View File

@ -476,14 +476,14 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): # type: ignore[mi
def depart_inline(self, node: Element) -> None:
pass
def visit_math(self, node: Element) -> None:
def visit_math(self, node: nodes.math) -> None:
pass
def depart_math(self, node: Element) -> None:
def depart_math(self, node: nodes.math) -> None:
pass
def visit_math_block(self, node: Element) -> None:
def visit_math_block(self, node: nodes.math_block) -> None:
self.visit_centered(node)
def depart_math_block(self, node: Element) -> None:
def depart_math_block(self, node: nodes.math_block) -> None:
self.depart_centered(node)

View File

@ -1581,11 +1581,11 @@ class TexinfoTranslator(SphinxTranslator):
def depart_pending_xref(self, node: Element) -> None:
pass
def visit_math(self, node: Element) -> None:
def visit_math(self, node: nodes.math) -> None:
self.body.append('@math{' + self.escape_arg(node.astext()) + '}')
raise nodes.SkipNode
def visit_math_block(self, node: Element) -> None:
def visit_math_block(self, node: nodes.math_block) -> None:
if node.get('label'):
self.add_anchor(node['label'], node)
self.body.append(

View File

@ -1327,14 +1327,14 @@ class TextTranslator(SphinxTranslator):
self.end_state(wrap=False)
raise nodes.SkipNode
def visit_math(self, node: Element) -> None:
def visit_math(self, node: nodes.math) -> None:
pass
def depart_math(self, node: Element) -> None:
def depart_math(self, node: nodes.math) -> None:
pass
def visit_math_block(self, node: Element) -> None:
def visit_math_block(self, node: nodes.math_block) -> None:
self.new_state()
def depart_math_block(self, node: Element) -> None:
def depart_math_block(self, node: nodes.math_block) -> None:
self.end_state()