Enable ANN001, ANN102, ANN202

This commit is contained in:
Adam Turner 2024-01-13 22:12:16 +00:00
parent 0a76199f99
commit f8e8b4745e
24 changed files with 181 additions and 144 deletions

View File

@ -33,13 +33,13 @@ select = [
# airflow ('AIR')
# Airflow is not used in Sphinx
# flake8-annotations ('ANN')
# "ANN001", # Missing type annotation for function argument `{name}`
"ANN001", # Missing type annotation for function argument `{name}`
"ANN002", # Missing type annotation for `*{name}`
"ANN003", # Missing type annotation for `**{name}`
# "ANN101", # Missing type annotation for `{name}` in method
# "ANN102", # Missing type annotation for `{name}` in classmethod
"ANN102", # Missing type annotation for `{name}` in classmethod
"ANN201", # Missing return type annotation for public function `{name}`
# "ANN202", # Missing return type annotation for private function `{name}`
"ANN202", # Missing return type annotation for private function `{name}`
# "ANN204", # Missing return type annotation for special method `{name}`
"ANN205", # Missing return type annotation for staticmethod `{name}`
"ANN206", # Missing return type annotation for classmethod `{name}`

View File

@ -20,7 +20,7 @@ _DEPRECATED_OBJECTS = {
}
def __getattr__(name):
def __getattr__(name: str) -> Any:
if name not in _DEPRECATED_OBJECTS:
msg = f'module {__name__!r} has no attribute {name!r}'
raise AttributeError(msg)

View File

@ -113,7 +113,7 @@ class BuildInfo:
"""
@classmethod
def load(cls, f: IO) -> BuildInfo:
def load(cls: type[BuildInfo], f: IO) -> BuildInfo:
try:
lines = f.readlines()
assert lines[0].rstrip() == '# Sphinx build info version 1'
@ -1372,7 +1372,7 @@ _DEPRECATED_OBJECTS = {
}
def __getattr__(name):
def __getattr__(name: str) -> Any:
if name not in _DEPRECATED_OBJECTS:
msg = f'module {__name__!r} has no attribute {name!r}'
raise AttributeError(msg)

View File

@ -3,7 +3,7 @@ from __future__ import annotations
import os
import warnings
import zlib
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any, NoReturn
from sphinx.deprecation import RemovedInSphinx90Warning
from sphinx.errors import ThemeError
@ -29,13 +29,13 @@ class _CascadingStyleSheet:
object.__setattr__(self, 'priority', priority)
object.__setattr__(self, 'attributes', {'rel': rel, 'type': type} | attributes)
def __str__(self):
def __str__(self) -> str:
attr = ', '.join(f'{k}={v!r}' for k, v in self.attributes.items())
return (f'{self.__class__.__name__}({self.filename!r}, '
f'priority={self.priority}, '
f'{attr})')
def __eq__(self, other):
def __eq__(self, other: object) -> bool:
if isinstance(other, str):
warnings.warn('The str interface for _CascadingStyleSheet objects is deprecated. '
'Use css.filename instead.', RemovedInSphinx90Warning, stacklevel=2)
@ -46,23 +46,23 @@ class _CascadingStyleSheet:
and self.priority == other.priority
and self.attributes == other.attributes)
def __hash__(self):
def __hash__(self) -> int:
return hash((self.filename, self.priority, *sorted(self.attributes.items())))
def __setattr__(self, key, value):
def __setattr__(self, key: str, value: Any) -> NoReturn:
msg = f'{self.__class__.__name__} is immutable'
raise AttributeError(msg)
def __delattr__(self, key):
def __delattr__(self, key: str) -> NoReturn:
msg = f'{self.__class__.__name__} is immutable'
raise AttributeError(msg)
def __getattr__(self, key):
def __getattr__(self, key: str) -> str:
warnings.warn('The str interface for _CascadingStyleSheet objects is deprecated. '
'Use css.filename instead.', RemovedInSphinx90Warning, stacklevel=2)
return getattr(os.fspath(self.filename), key)
def __getitem__(self, key):
def __getitem__(self, key: int | slice) -> str:
warnings.warn('The str interface for _CascadingStyleSheet objects is deprecated. '
'Use css.filename instead.', RemovedInSphinx90Warning, stacklevel=2)
return os.fspath(self.filename)[key]
@ -83,7 +83,7 @@ class _JavaScript:
object.__setattr__(self, 'priority', priority)
object.__setattr__(self, 'attributes', attributes)
def __str__(self):
def __str__(self) -> str:
attr = ''
if self.attributes:
attr = ', ' + ', '.join(f'{k}={v!r}' for k, v in self.attributes.items())
@ -91,7 +91,7 @@ class _JavaScript:
f'priority={self.priority}'
f'{attr})')
def __eq__(self, other):
def __eq__(self, other: object) -> bool:
if isinstance(other, str):
warnings.warn('The str interface for _JavaScript objects is deprecated. '
'Use js.filename instead.', RemovedInSphinx90Warning, stacklevel=2)
@ -102,23 +102,23 @@ class _JavaScript:
and self.priority == other.priority
and self.attributes == other.attributes)
def __hash__(self):
def __hash__(self) -> int:
return hash((self.filename, self.priority, *sorted(self.attributes.items())))
def __setattr__(self, key, value):
def __setattr__(self, key: str, value: Any) -> NoReturn:
msg = f'{self.__class__.__name__} is immutable'
raise AttributeError(msg)
def __delattr__(self, key):
def __delattr__(self, key: str) -> NoReturn:
msg = f'{self.__class__.__name__} is immutable'
raise AttributeError(msg)
def __getattr__(self, key):
def __getattr__(self, key: str) -> str:
warnings.warn('The str interface for _JavaScript objects is deprecated. '
'Use js.filename instead.', RemovedInSphinx90Warning, stacklevel=2)
return getattr(os.fspath(self.filename), key)
def __getitem__(self, key):
def __getitem__(self, key: int | slice) -> str:
warnings.warn('The str interface for _JavaScript objects is deprecated. '
'Use js.filename instead.', RemovedInSphinx90Warning, stacklevel=2)
return os.fspath(self.filename)[key]

View File

@ -8,7 +8,7 @@ import traceback
import types
import warnings
from os import getenv, path
from typing import TYPE_CHECKING, Any, Literal, NamedTuple
from typing import TYPE_CHECKING, Any, Literal, NamedTuple, Union
from sphinx.deprecation import RemovedInSphinx90Warning
from sphinx.errors import ConfigError, ExtensionError
@ -81,18 +81,21 @@ class ENUM:
return value in self.candidates
_OptValidTypes = Union[tuple[()], tuple[type, ...], frozenset[type], ENUM]
class _Opt:
__slots__ = 'default', 'rebuild', 'valid_types'
default: Any
rebuild: _ConfigRebuild
valid_types: tuple[()] | tuple[type, ...] | frozenset[type] | ENUM
valid_types: _OptValidTypes
def __init__(
self,
default: Any,
rebuild: _ConfigRebuild,
valid_types: tuple[()] | tuple[type, ...] | frozenset[type] | ENUM,
valid_types: _OptValidTypes,
) -> None:
"""Configuration option type for Sphinx.
@ -106,7 +109,7 @@ class _Opt:
super().__setattr__('rebuild', rebuild)
super().__setattr__('valid_types', valid_types)
def __repr__(self):
def __repr__(self) -> str:
return (
f'{self.__class__.__qualname__}('
f'default={self.default!r}, '
@ -114,45 +117,45 @@ class _Opt:
f'valid_types={self.valid_types!r})'
)
def __eq__(self, other):
if self.__class__ is other.__class__:
def __eq__(self, other: object) -> bool:
if isinstance(other, _Opt):
self_tpl = (self.default, self.rebuild, self.valid_types)
other_tpl = (other.default, other.rebuild, other.valid_types)
return self_tpl == other_tpl
return NotImplemented
def __lt__(self, other):
def __lt__(self, other: _Opt) -> bool:
if self.__class__ is other.__class__:
self_tpl = (self.default, self.rebuild, self.valid_types)
other_tpl = (other.default, other.rebuild, other.valid_types)
return self_tpl > other_tpl
return NotImplemented
def __hash__(self):
def __hash__(self) -> int:
return hash((self.default, self.rebuild, self.valid_types))
def __setattr__(self, key, value):
def __setattr__(self, key: str, value: Any) -> None:
if key in {'default', 'rebuild', 'valid_types'}:
msg = f'{self.__class__.__name__!r} object does not support assignment to {key!r}'
raise TypeError(msg)
super().__setattr__(key, value)
def __delattr__(self, key):
def __delattr__(self, key: str) -> None:
if key in {'default', 'rebuild', 'valid_types'}:
msg = f'{self.__class__.__name__!r} object does not support deletion of {key!r}'
raise TypeError(msg)
super().__delattr__(key)
def __getstate__(self):
def __getstate__(self) -> tuple[Any, _ConfigRebuild, _OptValidTypes]:
return self.default, self.rebuild, self.valid_types
def __setstate__(self, state):
def __setstate__(self, state: tuple[Any, _ConfigRebuild, _OptValidTypes]) -> None:
default, rebuild, valid_types = state
super().__setattr__('default', default)
super().__setattr__('rebuild', rebuild)
super().__setattr__('valid_types', valid_types)
def __getitem__(self, item):
def __getitem__(self, item: int | slice) -> Any:
warnings.warn(
f'The {self.__class__.__name__!r} object tuple interface is deprecated, '
"use attribute access instead for 'default', 'rebuild', and 'valid_types'.",
@ -283,7 +286,7 @@ class Config:
return self._overrides
@classmethod
def read(cls, confdir: str | os.PathLike[str], overrides: dict | None = None,
def read(cls: type[Config], confdir: str | os.PathLike[str], overrides: dict | None = None,
tags: Tags | None = None) -> Config:
"""Create a Config object from configuration file."""
filename = path.join(confdir, CONFIG_FILENAME)

View File

@ -35,7 +35,7 @@ def _deprecation_warning(
}
def __getattr__(name):
def __getattr__(name: str) -> Any:
if name not in _DEPRECATED_OBJECTS:
msg = f'module {__name__!r} has no attribute {name!r}'
raise AttributeError(msg)

View File

@ -378,7 +378,7 @@ class Include(BaseInclude, SphinxDirective):
# In the future, docutils will hopefully offer a way for Sphinx
# to provide the RST parser to use
# when parsing RST text that comes in via Include directive.
def _insert_input(include_lines, source):
def _insert_input(include_lines: list[str], source: str) -> None:
# First, we need to combine the lines back into text so that
# we can send it with the include-read event.
# In docutils 0.18 and later, there are two lines at the end
@ -405,7 +405,7 @@ class Include(BaseInclude, SphinxDirective):
# Only enable this patch if there are listeners for 'include-read'.
if self.env.app.events.listeners.get('include-read'):
# See https://github.com/python/mypy/issues/2427 for details on the mypy issue
self.state_machine.insert_input = _insert_input # type: ignore[method-assign]
self.state_machine.insert_input = _insert_input # type: ignore[assignment]
if self.arguments[0].startswith('<') and \
self.arguments[0].endswith('>'):

View File

@ -365,14 +365,14 @@ class ASTIdExpression(ASTExpression):
class ASTParenExpr(ASTExpression):
def __init__(self, expr):
def __init__(self, expr: ASTExpression) -> None:
self.expr = expr
def _stringify(self, transform: StringifyTransform) -> str:
return '(' + transform(self.expr) + ')'
def get_id(self, version: int) -> str:
return self.expr.get_id(version)
return self.expr.get_id(version) # type: ignore[attr-defined]
def describe_signature(self, signode: TextElement, mode: str,
env: BuildEnvironment, symbol: Symbol) -> None:
@ -433,7 +433,7 @@ class ASTPostfixDec(ASTPostfixOp):
class ASTPostfixMemberOfPointer(ASTPostfixOp):
def __init__(self, name):
def __init__(self, name: ASTNestedName) -> None:
self.name = name
def _stringify(self, transform: StringifyTransform) -> str:
@ -488,7 +488,7 @@ class ASTUnaryOpExpr(ASTExpression):
class ASTSizeofType(ASTExpression):
def __init__(self, typ):
def __init__(self, typ: ASTType) -> None:
self.typ = typ
def _stringify(self, transform: StringifyTransform) -> str:
@ -1547,7 +1547,7 @@ class Symbol:
def __copy__(self):
raise AssertionError # shouldn't happen
def __deepcopy__(self, memo):
def __deepcopy__(self, memo: Any) -> Symbol:
if self.parent:
raise AssertionError # shouldn't happen
# the domain base class makes a copy of the initial data, which is fine
@ -2457,7 +2457,7 @@ class DefinitionParser(BaseParser):
# additive = multiplicative +, -
# multiplicative = pm *, /, %
# pm = cast .*, ->*
def _parse_bin_op_expr(self, opId):
def _parse_bin_op_expr(self: DefinitionParser, opId: int) -> ASTExpression:
if opId + 1 == len(_expression_bin_ops):
def parser() -> ASTExpression:
return self._parse_cast_expression()
@ -2493,7 +2493,7 @@ class DefinitionParser(BaseParser):
self.pos = pos
if not oneMore:
break
return ASTBinOpExpr(exprs, ops)
return ASTBinOpExpr(exprs, ops) # type: ignore[return-value]
return _parse_bin_op_expr(self, 0)
def _parse_conditional_expression_tail(self, orExprHead: Any) -> ASTExpression | None:
@ -2827,7 +2827,7 @@ class DefinitionParser(BaseParser):
size = None
else:
def parser():
def parser() -> ASTExpression:
return self._parse_expression()
size = self._parse_expression_fallback([']'], parser)
self.skip_ws()
@ -2951,7 +2951,7 @@ class DefinitionParser(BaseParser):
self.fail("Internal error, initializer for outer '%s' not "
"implemented." % outer)
def parser():
def parser() -> ASTExpression:
return self._parse_assignment_expression()
value = self._parse_expression_fallback(fallbackEnd, parser, allow=allowFallback)

View File

@ -3,7 +3,7 @@
from __future__ import annotations
import re
from typing import TYPE_CHECKING, Any, Callable, TypeVar
from typing import TYPE_CHECKING, Any, Callable, NoReturn, TypeVar
from docutils import nodes
from docutils.parsers.rst import directives
@ -4228,10 +4228,10 @@ class Symbol:
debug_lookup = False # overridden by the corresponding config value
debug_show_tree = False # overridden by the corresponding config value
def __copy__(self):
def __copy__(self) -> NoReturn:
raise AssertionError # shouldn't happen
def __deepcopy__(self, memo):
def __deepcopy__(self, memo: Any) -> Symbol:
if self.parent:
raise AssertionError # shouldn't happen
# the domain base class makes a copy of the initial data, which is fine
@ -4856,7 +4856,7 @@ class Symbol:
Symbol.debug_print("merge_with:")
assert other is not None
def unconditionalAdd(self, otherChild):
def unconditionalAdd(self: Symbol, otherChild: Symbol) -> None:
# TODO: hmm, should we prune by docnames?
self._children.append(otherChild)
otherChild.parent = self
@ -8232,7 +8232,7 @@ def setup(app: Sphinx) -> dict[str, Any]:
app.add_config_value("cpp_debug_lookup", False, '')
app.add_config_value("cpp_debug_show_tree", False, '')
def initStuff(app):
def initStuff(app: Sphinx) -> None:
Symbol.debug_lookup = app.config.cpp_debug_lookup
Symbol.debug_show_tree = app.config.cpp_debug_show_tree
app.config.cpp_index_common_prefix.sort(reverse=True)

View File

@ -11,6 +11,7 @@ import operator
import re
import token
import typing
from collections import deque
from inspect import Parameter
from typing import TYPE_CHECKING, Any, NamedTuple, cast
@ -323,16 +324,17 @@ class _TypeParameterListParser(TokenProcessor):
self.type_params.append(type_param)
def _build_identifier(self, tokens: list[Token]) -> str:
from itertools import chain, tee
from itertools import chain, islice
def pairwise(iterable):
a, b = tee(iterable)
next(b, None)
return zip(a, b)
def triplewise(iterable):
for (a, _z), (b, c) in pairwise(pairwise(iterable)):
yield a, b, c
def triplewise(iterable: Iterable[Token]) -> Iterator[tuple[Token, ...]]:
# sliding_window('ABCDEFG', 4) --> ABCD BCDE CDEF DEFG
it = iter(iterable)
window = deque(islice(it, 3), maxlen=3)
if len(window) == 3:
yield tuple(window)
for x in it:
window.append(x)
yield tuple(window)
idents: list[str] = []
tokens: Iterable[Token] = iter(tokens) # type: ignore[no-redef]

View File

@ -9,7 +9,7 @@ import time
from collections import defaultdict
from copy import copy
from os import path
from typing import TYPE_CHECKING, Any, Callable
from typing import TYPE_CHECKING, Any, Callable, NoReturn
from sphinx import addnodes
from sphinx.environment.adapters import toctree as toctree_adapters
@ -126,10 +126,10 @@ if TYPE_CHECKING:
@overload
def __getitem__(self, key: str) -> Domain: ... # NoQA: E704
def __getitem__(self, key): raise NotImplementedError # NoQA: E704
def __setitem__(self, key, value): raise NotImplementedError # NoQA: E704
def __delitem__(self, key): raise NotImplementedError # NoQA: E704
def __iter__(self): raise NotImplementedError # NoQA: E704
def __len__(self): raise NotImplementedError # NoQA: E704
def __setitem__(self, key: str, value: Domain) -> NoReturn: raise NotImplementedError # NoQA: E704
def __delitem__(self, key: str) -> NoReturn: raise NotImplementedError # NoQA: E704
def __iter__(self) -> NoReturn: raise NotImplementedError # NoQA: E704
def __len__(self) -> NoReturn: raise NotImplementedError # NoQA: E704
else:
_DomainsType = dict

View File

@ -277,7 +277,7 @@ class ObjectMember:
self.skipped = skipped
self.class_ = class_
def __getitem__(self, index):
def __getitem__(self, index: int) -> Any:
warnings.warn('The tuple interface of ObjectMember is deprecated. '
'Use (obj.__name__, obj.object) instead.',
RemovedInSphinx80Warning, stacklevel=2)
@ -321,8 +321,9 @@ class Documenter:
return autodoc_attrgetter(self.env.app, obj, name, *defargs)
@classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
"""Called to see if a member can be documented by this Documenter."""
msg = 'must be implemented in subclasses'
raise NotImplementedError(msg)
@ -999,8 +1000,9 @@ class ModuleDocumenter(Documenter):
self.add_line(line, src[0], src[1])
@classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
# don't document submodules automatically
return False
@ -1292,8 +1294,9 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
member_order = 30
@classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
# supports functions, builtins and bound methods exported at the module level
return (inspect.isfunction(member) or inspect.isbuiltin(member) or
(inspect.isroutine(member) and isinstance(parent, ModuleDocumenter)))
@ -1395,7 +1398,7 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
if len(sig.parameters) == 0:
return None
def dummy():
def dummy() -> None:
pass
params = list(sig.parameters.values())
@ -1483,8 +1486,9 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
merge_members_option(self.options)
@classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
return isinstance(member, type) or (
isattr and (inspect.isNewType(member) or isinstance(member, TypeVar)))
@ -1913,8 +1917,9 @@ class ExceptionDocumenter(ClassDocumenter):
priority = ClassDocumenter.priority + 5
@classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
try:
return isinstance(member, type) and issubclass(member, BaseException)
except TypeError as exc:
@ -2026,8 +2031,9 @@ class DataDocumenter(GenericAliasMixin,
option_spec["no-value"] = bool_option
@classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
return isinstance(parent, ModuleDocumenter) and isattr
def update_annotations(self, parent: Any) -> None:
@ -2144,8 +2150,9 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
priority = 1 # must be more than FunctionDocumenter
@classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
return inspect.isroutine(member) and not isinstance(parent, ModuleDocumenter)
def import_object(self, raiseerror: bool = False) -> bool:
@ -2295,7 +2302,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
if len(sig.parameters) == 1:
return None
def dummy():
def dummy() -> None:
pass
params = list(sig.parameters.values())
@ -2574,8 +2581,9 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
return inspect.isfunction(obj) or inspect.isbuiltin(obj) or inspect.ismethod(obj)
@classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
if isinstance(parent, ModuleDocumenter):
return False
if inspect.isattributedescriptor(member):
@ -2722,8 +2730,9 @@ class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
priority = AttributeDocumenter.priority + 1
@classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool:
if isinstance(parent, ClassDocumenter):
if inspect.isproperty(member):
return True
@ -2797,7 +2806,7 @@ class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
except ValueError:
pass
def _get_property_getter(self):
def _get_property_getter(self) -> Callable | None:
if safe_getattr(self.object, 'fget', None): # property
return self.object.fget
if safe_getattr(self.object, 'func', None): # cached_property

View File

@ -96,7 +96,7 @@ def _get_arguments(obj: Any, /) -> ast.arguments | None:
return _get_arguments_inner(subject)
def _is_lambda(x, /):
def _is_lambda(x: Any, /) -> bool:
return isinstance(x, types.LambdaType) and x.__name__ == _LAMBDA_NAME

View File

@ -14,6 +14,8 @@ from sphinx.util import logging
from sphinx.util.typing import get_type_hints, stringify_annotation
if TYPE_CHECKING:
from collections.abc import Iterator
from sphinx.application import Sphinx
from sphinx.config import Config as SphinxConfig
@ -888,7 +890,7 @@ def _recombine_set_tokens(tokens: list[str]) -> list[str]:
token_queue = collections.deque(tokens)
keywords = ("optional", "default")
def takewhile_set(tokens):
def takewhile_set(tokens: collections.deque[str]) -> Iterator[str]:
open_braces = 0
previous_token = None
while True:
@ -924,7 +926,7 @@ def _recombine_set_tokens(tokens: list[str]) -> list[str]:
if open_braces == 0:
break
def combine_set(tokens):
def combine_set(tokens: collections.deque[str]) -> Iterator[str]:
while True:
try:
token = tokens.popleft()
@ -941,7 +943,7 @@ def _recombine_set_tokens(tokens: list[str]) -> list[str]:
def _tokenize_type_spec(spec: str) -> list[str]:
def postprocess(item):
def postprocess(item: str) -> list[str]:
if _default_regex.match(item):
default = item[:7]
# can't be separated by anything other than a single space
@ -962,7 +964,7 @@ def _tokenize_type_spec(spec: str) -> list[str]:
def _token_type(token: str, location: str | None = None) -> str:
def is_numeric(token):
def is_numeric(token: str) -> bool:
try:
# use complex to make sure every numeric value is detected as literal
complex(token)
@ -1026,7 +1028,7 @@ def _convert_numpy_type_spec(
if translations is None:
translations = {}
def convert_obj(obj, translations, default_translation):
def convert_obj(obj: str, translations: dict[str, str], default_translation: str) -> str:
translation = translations.get(obj, obj)
# use :class: (the default) only if obj is not a standard singleton
@ -1269,7 +1271,7 @@ class NumpyDocstring(GoogleDocstring):
func_name1, func_name2, :meth:`func_name`, func_name3
"""
items = []
items: list[tuple[str, list[str], str | None]] = []
def parse_item_name(text: str) -> tuple[str, str | None]:
"""Match ':role:`name`' or 'name'"""
@ -1289,7 +1291,9 @@ class NumpyDocstring(GoogleDocstring):
items.append((name, rest.copy(), role))
rest.clear()
def translate(func, description, role):
def translate(
func: str, description: list[str], role: str | None,
) -> tuple[str, list[str], str | None]:
translations = self._config.napoleon_type_aliases
if role is not None or not translations:
return func, description, role

View File

@ -71,22 +71,22 @@ class _TranslationProxy:
def __rmul__(self, other: Any) -> str:
return other * self.__str__()
def __hash__(self):
def __hash__(self) -> int:
return hash(self.__str__())
def __eq__(self, other):
def __eq__(self, other: object) -> bool:
return self.__str__() == other
def __lt__(self, string):
def __lt__(self, string: str) -> bool:
return self.__str__() < string
def __contains__(self, char):
def __contains__(self, char: str) -> bool:
return char in self.__str__()
def __len__(self):
def __len__(self) -> int:
return len(self.__str__())
def __getitem__(self, index):
def __getitem__(self, index: int | slice) -> str:
return self.__str__()[index]

View File

@ -69,12 +69,13 @@ class ModuleAnalyzer:
return filename, None
@classmethod
def for_string(cls, string: str, modname: str, srcname: str = '<string>',
) -> ModuleAnalyzer:
def for_string(
cls: type[ModuleAnalyzer], string: str, modname: str, srcname: str = '<string>',
) -> ModuleAnalyzer:
return cls(string, modname, srcname)
@classmethod
def for_file(cls, filename: str, modname: str) -> ModuleAnalyzer:
def for_file(cls: type[ModuleAnalyzer], filename: str, modname: str) -> ModuleAnalyzer:
if ('file', filename) in cls.cache:
return cls.cache['file', filename]
try:
@ -87,7 +88,7 @@ class ModuleAnalyzer:
return obj
@classmethod
def for_module(cls, modname: str) -> ModuleAnalyzer:
def for_module(cls: type[ModuleAnalyzer], modname: str) -> ModuleAnalyzer:
if ('module', modname) in cls.cache:
entry = cls.cache['module', modname]
if isinstance(entry, PycodeError):

View File

@ -3,7 +3,7 @@
from __future__ import annotations
import ast
from typing import overload
from typing import NoReturn, overload
OPERATORS: dict[type[ast.AST], str] = {
ast.Add: "+",
@ -183,5 +183,5 @@ class _UnparseVisitor(ast.NodeVisitor):
else:
return "(" + ", ".join(self.visit(e) for e in node.elts) + ")"
def generic_visit(self, node):
def generic_visit(self, node: ast.AST) -> NoReturn:
raise NotImplementedError('Unable to parse %s object' % type(node).__name__)

View File

@ -256,7 +256,7 @@ def isurl(url: str) -> bool:
return bool(url) and '://' in url
def _xml_name_checker():
def _xml_name_checker() -> re.Pattern[str]:
# to prevent import cycles
from sphinx.builders.epub3 import _XML_NAME_PATTERN
@ -285,7 +285,7 @@ _DEPRECATED_OBJECTS = {
}
def __getattr__(name):
def __getattr__(name: str) -> Any:
if name not in _DEPRECATED_OBJECTS:
msg = f'module {__name__!r} has no attribute {name!r}'
raise AttributeError(msg)

View File

@ -5,6 +5,7 @@ from __future__ import annotations
import sys
import warnings
from pathlib import Path, PosixPath, PurePath, WindowsPath
from typing import Any
from sphinx.deprecation import RemovedInSphinx80Warning
@ -21,34 +22,34 @@ _MSG = (
if sys.platform == 'win32':
class _StrPath(WindowsPath):
def replace(self, old, new, count=-1, /):
def replace(self, old: str, new: str, count: int = -1, /) -> str: # type: ignore[override]
# replace exists in both Path and str;
# in Path it makes filesystem changes, so we use the safer str version
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return self.__str__().replace(old, new, count)
def __getattr__(self, item):
def __getattr__(self, item: str) -> Any:
if item in _STR_METHODS:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return getattr(self.__str__(), item)
msg = f'{_PATH_NAME!r} has no attribute {item!r}'
raise AttributeError(msg)
def __add__(self, other):
def __add__(self, other: str) -> str:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return self.__str__() + other
def __bool__(self):
def __bool__(self) -> bool:
if not self.__str__():
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return False
return True
def __contains__(self, item):
def __contains__(self, item: str) -> bool:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return item in self.__str__()
def __eq__(self, other):
def __eq__(self, other: object) -> bool:
if isinstance(other, PurePath):
return super().__eq__(other)
if isinstance(other, str):
@ -56,46 +57,46 @@ if sys.platform == 'win32':
return self.__str__() == other
return NotImplemented
def __hash__(self):
def __hash__(self) -> int:
return super().__hash__()
def __getitem__(self, item):
def __getitem__(self, item: int | slice) -> str:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return self.__str__()[item]
def __len__(self):
def __len__(self) -> int:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return len(self.__str__())
else:
class _StrPath(PosixPath):
def replace(self, old, new, count=-1, /):
def replace(self, old: str, new: str, count: int = -1, /) -> str: # type: ignore[override]
# replace exists in both Path and str;
# in Path it makes filesystem changes, so we use the safer str version
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return self.__str__().replace(old, new, count)
def __getattr__(self, item):
def __getattr__(self, item: str) -> Any:
if item in _STR_METHODS:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return getattr(self.__str__(), item)
msg = f'{_PATH_NAME!r} has no attribute {item!r}'
raise AttributeError(msg)
def __add__(self, other):
def __add__(self, other: str) -> str:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return self.__str__() + other
def __bool__(self):
def __bool__(self) -> bool:
if not self.__str__():
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return False
return True
def __contains__(self, item):
def __contains__(self, item: str) -> bool:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return item in self.__str__()
def __eq__(self, other):
def __eq__(self, other: PurePath | str) -> bool:
if isinstance(other, PurePath):
return super().__eq__(other)
if isinstance(other, str):
@ -103,13 +104,13 @@ else:
return self.__str__() == other
return NotImplemented
def __hash__(self):
def __hash__(self) -> int:
return super().__hash__()
def __getitem__(self, item):
def __getitem__(self, item: int | slice) -> str:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return self.__str__()[item]
def __len__(self):
def __len__(self) -> int:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return len(self.__str__())

View File

@ -44,7 +44,7 @@ _DEPRECATED_OBJECTS = {
}
def __getattr__(name):
def __getattr__(name: str) -> Any:
if name not in _DEPRECATED_OBJECTS:
msg = f'module {__name__!r} has no attribute {name!r}'
raise AttributeError(msg)
@ -199,15 +199,15 @@ def using_user_docutils_conf(confdir: str | None) -> Generator[None, None, None]
@contextmanager
def du19_footnotes() -> Generator[None, None, None]:
def visit_footnote(self, node):
def visit_footnote(self: HTMLTranslator, node: Element) -> None:
label_style = self.settings.footnote_references
if not isinstance(node.previous_sibling(), type(node)):
if not isinstance(node.previous_sibling(), type(node)): # type: ignore[attr-defined]
self.body.append(f'<aside class="footnote-list {label_style}">\n')
self.body.append(self.starttag(node, 'aside',
classes=[node.tagname, label_style],
role="note"))
def depart_footnote(self, node):
def depart_footnote(self: HTMLTranslator, node: Element) -> None:
self.body.append('</aside>\n')
if not isinstance(node.next_node(descend=False, siblings=True),
type(node)):
@ -354,7 +354,7 @@ class WarningStream:
class LoggingReporter(Reporter):
@classmethod
def from_reporter(cls, reporter: Reporter) -> LoggingReporter:
def from_reporter(cls: type[LoggingReporter], reporter: Reporter) -> LoggingReporter:
"""Create an instance of LoggingReporter from other reporter object."""
return cls(reporter.source, reporter.report_level, reporter.halt_level,
reporter.debug_flag, reporter.error_handler)

View File

@ -77,7 +77,7 @@ class InventoryFileReader:
class InventoryFile:
@classmethod
def load(cls, stream: IO, uri: str, joinfunc: Callable) -> Inventory:
def load(cls: type[InventoryFile], stream: IO, uri: str, joinfunc: Callable) -> Inventory:
reader = InventoryFileReader(stream)
line = reader.readline().rstrip()
if line == '# Sphinx inventory version 1':
@ -88,7 +88,9 @@ class InventoryFile:
raise ValueError('invalid inventory header: %s' % line)
@classmethod
def load_v1(cls, stream: InventoryFileReader, uri: str, join: Callable) -> Inventory:
def load_v1(
cls: type[InventoryFile], stream: InventoryFileReader, uri: str, join: Callable,
) -> Inventory:
invdata: Inventory = {}
projname = stream.readline().rstrip()[11:]
version = stream.readline().rstrip()[11:]
@ -106,7 +108,9 @@ class InventoryFile:
return invdata
@classmethod
def load_v2(cls, stream: InventoryFileReader, uri: str, join: Callable) -> Inventory:
def load_v2(
cls: type[InventoryFile], stream: InventoryFileReader, uri: str, join: Callable,
) -> Inventory:
invdata: Inventory = {}
projname = stream.readline().rstrip()[11:]
version = stream.readline().rstrip()[11:]
@ -140,7 +144,9 @@ class InventoryFile:
return invdata
@classmethod
def dump(cls, filename: str, env: BuildEnvironment, builder: Builder) -> None:
def dump(
cls: type[InventoryFile], filename: str, env: BuildEnvironment, builder: Builder,
) -> None:
def escape(string: str) -> str:
return re.sub("\\s+", " ", string)

View File

@ -17,6 +17,7 @@ from sphinx.deprecation import _deprecation_warning
if TYPE_CHECKING:
from collections.abc import Iterator
from types import TracebackType
# SEP separates path elements in the canonical file names
#
@ -131,15 +132,21 @@ abspath = path.abspath
class _chdir:
"""Remove this fall-back once support for Python 3.10 is removed."""
def __init__(self, target_dir: str, /):
def __init__(self, target_dir: str, /) -> None:
self.path = target_dir
self._dirs: list[str] = []
def __enter__(self):
def __enter__(self) -> None:
self._dirs.append(os.getcwd())
os.chdir(self.path)
def __exit__(self, _exc_type, _exc_value, _traceback, /):
def __exit__(
self,
type: type[BaseException] | None,
value: BaseException | None,
traceback: TracebackType | None,
/,
) -> None:
os.chdir(self._dirs.pop())

View File

@ -47,7 +47,9 @@ class FileRenderer(BaseRenderer):
super().__init__(loader)
@classmethod
def render_from_file(cls, filename: str, context: dict[str, Any]) -> str:
def render_from_file(
cls: type[FileRenderer], filename: str, context: dict[str, Any],
) -> str:
dirname = os.path.dirname(filename)
basename = os.path.basename(filename)
return cls(dirname).render(basename, context)
@ -60,7 +62,9 @@ class SphinxRenderer(FileRenderer):
super().__init__(template_path)
@classmethod
def render_from_file(cls, filename: str, context: dict[str, Any]) -> str:
def render_from_file(
cls: type[FileRenderer], filename: str, context: dict[str, Any],
) -> str:
return FileRenderer.render_from_file(filename, context)

View File

@ -389,7 +389,7 @@ def stringify_annotation(
elif qualname == 'Literal':
from sphinx.util.inspect import isenumattribute # lazy loading
def format_literal_arg(arg):
def format_literal_arg(arg: Any) -> str:
if isenumattribute(arg):
enumcls = arg.__class__
@ -429,7 +429,7 @@ _DEPRECATED_OBJECTS = {
}
def __getattr__(name):
def __getattr__(name: str) -> Any:
if name not in _DEPRECATED_OBJECTS:
msg = f'module {__name__!r} has no attribute {name!r}'
raise AttributeError(msg)