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 ('AIR')
# Airflow is not used in Sphinx # Airflow is not used in Sphinx
# flake8-annotations ('ANN') # 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}` "ANN002", # Missing type annotation for `*{name}`
"ANN003", # Missing type annotation for `**{name}` "ANN003", # Missing type annotation for `**{name}`
# "ANN101", # Missing type annotation for `{name}` in method # "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}` "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}` # "ANN204", # Missing return type annotation for special method `{name}`
"ANN205", # Missing return type annotation for staticmethod `{name}` "ANN205", # Missing return type annotation for staticmethod `{name}`
"ANN206", # Missing return type annotation for classmethod `{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: if name not in _DEPRECATED_OBJECTS:
msg = f'module {__name__!r} has no attribute {name!r}' msg = f'module {__name__!r} has no attribute {name!r}'
raise AttributeError(msg) raise AttributeError(msg)

View File

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

View File

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

View File

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

View File

@ -378,7 +378,7 @@ class Include(BaseInclude, SphinxDirective):
# In the future, docutils will hopefully offer a way for Sphinx # In the future, docutils will hopefully offer a way for Sphinx
# to provide the RST parser to use # to provide the RST parser to use
# when parsing RST text that comes in via Include directive. # 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 # First, we need to combine the lines back into text so that
# we can send it with the include-read event. # we can send it with the include-read event.
# In docutils 0.18 and later, there are two lines at the end # 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'. # Only enable this patch if there are listeners for 'include-read'.
if self.env.app.events.listeners.get('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 # 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 \ if self.arguments[0].startswith('<') and \
self.arguments[0].endswith('>'): self.arguments[0].endswith('>'):

View File

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

View File

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

View File

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

View File

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

View File

@ -277,7 +277,7 @@ class ObjectMember:
self.skipped = skipped self.skipped = skipped
self.class_ = class_ self.class_ = class_
def __getitem__(self, index): def __getitem__(self, index: int) -> Any:
warnings.warn('The tuple interface of ObjectMember is deprecated. ' warnings.warn('The tuple interface of ObjectMember is deprecated. '
'Use (obj.__name__, obj.object) instead.', 'Use (obj.__name__, obj.object) instead.',
RemovedInSphinx80Warning, stacklevel=2) RemovedInSphinx80Warning, stacklevel=2)
@ -321,7 +321,8 @@ class Documenter:
return autodoc_attrgetter(self.env.app, obj, name, *defargs) return autodoc_attrgetter(self.env.app, obj, name, *defargs)
@classmethod @classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any, def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool: ) -> bool:
"""Called to see if a member can be documented by this Documenter.""" """Called to see if a member can be documented by this Documenter."""
msg = 'must be implemented in subclasses' msg = 'must be implemented in subclasses'
@ -999,7 +1000,8 @@ class ModuleDocumenter(Documenter):
self.add_line(line, src[0], src[1]) self.add_line(line, src[0], src[1])
@classmethod @classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any, def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool: ) -> bool:
# don't document submodules automatically # don't document submodules automatically
return False return False
@ -1292,7 +1294,8 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
member_order = 30 member_order = 30
@classmethod @classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any, def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool: ) -> bool:
# supports functions, builtins and bound methods exported at the module level # supports functions, builtins and bound methods exported at the module level
return (inspect.isfunction(member) or inspect.isbuiltin(member) or return (inspect.isfunction(member) or inspect.isbuiltin(member) or
@ -1395,7 +1398,7 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
if len(sig.parameters) == 0: if len(sig.parameters) == 0:
return None return None
def dummy(): def dummy() -> None:
pass pass
params = list(sig.parameters.values()) params = list(sig.parameters.values())
@ -1483,7 +1486,8 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
merge_members_option(self.options) merge_members_option(self.options)
@classmethod @classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any, def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool: ) -> bool:
return isinstance(member, type) or ( return isinstance(member, type) or (
isattr and (inspect.isNewType(member) or isinstance(member, TypeVar))) isattr and (inspect.isNewType(member) or isinstance(member, TypeVar)))
@ -1913,7 +1917,8 @@ class ExceptionDocumenter(ClassDocumenter):
priority = ClassDocumenter.priority + 5 priority = ClassDocumenter.priority + 5
@classmethod @classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any, def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool: ) -> bool:
try: try:
return isinstance(member, type) and issubclass(member, BaseException) return isinstance(member, type) and issubclass(member, BaseException)
@ -2026,7 +2031,8 @@ class DataDocumenter(GenericAliasMixin,
option_spec["no-value"] = bool_option option_spec["no-value"] = bool_option
@classmethod @classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any, def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool: ) -> bool:
return isinstance(parent, ModuleDocumenter) and isattr return isinstance(parent, ModuleDocumenter) and isattr
@ -2144,7 +2150,8 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
priority = 1 # must be more than FunctionDocumenter priority = 1 # must be more than FunctionDocumenter
@classmethod @classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any, def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool: ) -> bool:
return inspect.isroutine(member) and not isinstance(parent, ModuleDocumenter) return inspect.isroutine(member) and not isinstance(parent, ModuleDocumenter)
@ -2295,7 +2302,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
if len(sig.parameters) == 1: if len(sig.parameters) == 1:
return None return None
def dummy(): def dummy() -> None:
pass pass
params = list(sig.parameters.values()) params = list(sig.parameters.values())
@ -2574,7 +2581,8 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
return inspect.isfunction(obj) or inspect.isbuiltin(obj) or inspect.ismethod(obj) return inspect.isfunction(obj) or inspect.isbuiltin(obj) or inspect.ismethod(obj)
@classmethod @classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any, def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool: ) -> bool:
if isinstance(parent, ModuleDocumenter): if isinstance(parent, ModuleDocumenter):
return False return False
@ -2722,7 +2730,8 @@ class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
priority = AttributeDocumenter.priority + 1 priority = AttributeDocumenter.priority + 1
@classmethod @classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any, def can_document_member(
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
) -> bool: ) -> bool:
if isinstance(parent, ClassDocumenter): if isinstance(parent, ClassDocumenter):
if inspect.isproperty(member): if inspect.isproperty(member):
@ -2797,7 +2806,7 @@ class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
except ValueError: except ValueError:
pass pass
def _get_property_getter(self): def _get_property_getter(self) -> Callable | None:
if safe_getattr(self.object, 'fget', None): # property if safe_getattr(self.object, 'fget', None): # property
return self.object.fget return self.object.fget
if safe_getattr(self.object, 'func', None): # cached_property 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) 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 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 from sphinx.util.typing import get_type_hints, stringify_annotation
if TYPE_CHECKING: if TYPE_CHECKING:
from collections.abc import Iterator
from sphinx.application import Sphinx from sphinx.application import Sphinx
from sphinx.config import Config as SphinxConfig 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) token_queue = collections.deque(tokens)
keywords = ("optional", "default") keywords = ("optional", "default")
def takewhile_set(tokens): def takewhile_set(tokens: collections.deque[str]) -> Iterator[str]:
open_braces = 0 open_braces = 0
previous_token = None previous_token = None
while True: while True:
@ -924,7 +926,7 @@ def _recombine_set_tokens(tokens: list[str]) -> list[str]:
if open_braces == 0: if open_braces == 0:
break break
def combine_set(tokens): def combine_set(tokens: collections.deque[str]) -> Iterator[str]:
while True: while True:
try: try:
token = tokens.popleft() 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 _tokenize_type_spec(spec: str) -> list[str]:
def postprocess(item): def postprocess(item: str) -> list[str]:
if _default_regex.match(item): if _default_regex.match(item):
default = item[:7] default = item[:7]
# can't be separated by anything other than a single space # 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 _token_type(token: str, location: str | None = None) -> str:
def is_numeric(token): def is_numeric(token: str) -> bool:
try: try:
# use complex to make sure every numeric value is detected as literal # use complex to make sure every numeric value is detected as literal
complex(token) complex(token)
@ -1026,7 +1028,7 @@ def _convert_numpy_type_spec(
if translations is None: if translations is None:
translations = {} 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) translation = translations.get(obj, obj)
# use :class: (the default) only if obj is not a standard singleton # 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 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]: def parse_item_name(text: str) -> tuple[str, str | None]:
"""Match ':role:`name`' or 'name'""" """Match ':role:`name`' or 'name'"""
@ -1289,7 +1291,9 @@ class NumpyDocstring(GoogleDocstring):
items.append((name, rest.copy(), role)) items.append((name, rest.copy(), role))
rest.clear() 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 translations = self._config.napoleon_type_aliases
if role is not None or not translations: if role is not None or not translations:
return func, description, role return func, description, role

View File

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

View File

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

View File

@ -3,7 +3,7 @@
from __future__ import annotations from __future__ import annotations
import ast import ast
from typing import overload from typing import NoReturn, overload
OPERATORS: dict[type[ast.AST], str] = { OPERATORS: dict[type[ast.AST], str] = {
ast.Add: "+", ast.Add: "+",
@ -183,5 +183,5 @@ class _UnparseVisitor(ast.NodeVisitor):
else: else:
return "(" + ", ".join(self.visit(e) for e in node.elts) + ")" 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__) 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 return bool(url) and '://' in url
def _xml_name_checker(): def _xml_name_checker() -> re.Pattern[str]:
# to prevent import cycles # to prevent import cycles
from sphinx.builders.epub3 import _XML_NAME_PATTERN 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: if name not in _DEPRECATED_OBJECTS:
msg = f'module {__name__!r} has no attribute {name!r}' msg = f'module {__name__!r} has no attribute {name!r}'
raise AttributeError(msg) raise AttributeError(msg)

View File

@ -5,6 +5,7 @@ from __future__ import annotations
import sys import sys
import warnings import warnings
from pathlib import Path, PosixPath, PurePath, WindowsPath from pathlib import Path, PosixPath, PurePath, WindowsPath
from typing import Any
from sphinx.deprecation import RemovedInSphinx80Warning from sphinx.deprecation import RemovedInSphinx80Warning
@ -21,34 +22,34 @@ _MSG = (
if sys.platform == 'win32': if sys.platform == 'win32':
class _StrPath(WindowsPath): 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; # replace exists in both Path and str;
# in Path it makes filesystem changes, so we use the safer str version # in Path it makes filesystem changes, so we use the safer str version
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return self.__str__().replace(old, new, count) return self.__str__().replace(old, new, count)
def __getattr__(self, item): def __getattr__(self, item: str) -> Any:
if item in _STR_METHODS: if item in _STR_METHODS:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return getattr(self.__str__(), item) return getattr(self.__str__(), item)
msg = f'{_PATH_NAME!r} has no attribute {item!r}' msg = f'{_PATH_NAME!r} has no attribute {item!r}'
raise AttributeError(msg) raise AttributeError(msg)
def __add__(self, other): def __add__(self, other: str) -> str:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return self.__str__() + other return self.__str__() + other
def __bool__(self): def __bool__(self) -> bool:
if not self.__str__(): if not self.__str__():
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return False return False
return True return True
def __contains__(self, item): def __contains__(self, item: str) -> bool:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return item in self.__str__() return item in self.__str__()
def __eq__(self, other): def __eq__(self, other: object) -> bool:
if isinstance(other, PurePath): if isinstance(other, PurePath):
return super().__eq__(other) return super().__eq__(other)
if isinstance(other, str): if isinstance(other, str):
@ -56,46 +57,46 @@ if sys.platform == 'win32':
return self.__str__() == other return self.__str__() == other
return NotImplemented return NotImplemented
def __hash__(self): def __hash__(self) -> int:
return super().__hash__() return super().__hash__()
def __getitem__(self, item): def __getitem__(self, item: int | slice) -> str:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return self.__str__()[item] return self.__str__()[item]
def __len__(self): def __len__(self) -> int:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return len(self.__str__()) return len(self.__str__())
else: else:
class _StrPath(PosixPath): 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; # replace exists in both Path and str;
# in Path it makes filesystem changes, so we use the safer str version # in Path it makes filesystem changes, so we use the safer str version
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return self.__str__().replace(old, new, count) return self.__str__().replace(old, new, count)
def __getattr__(self, item): def __getattr__(self, item: str) -> Any:
if item in _STR_METHODS: if item in _STR_METHODS:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return getattr(self.__str__(), item) return getattr(self.__str__(), item)
msg = f'{_PATH_NAME!r} has no attribute {item!r}' msg = f'{_PATH_NAME!r} has no attribute {item!r}'
raise AttributeError(msg) raise AttributeError(msg)
def __add__(self, other): def __add__(self, other: str) -> str:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return self.__str__() + other return self.__str__() + other
def __bool__(self): def __bool__(self) -> bool:
if not self.__str__(): if not self.__str__():
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return False return False
return True return True
def __contains__(self, item): def __contains__(self, item: str) -> bool:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return item in self.__str__() return item in self.__str__()
def __eq__(self, other): def __eq__(self, other: PurePath | str) -> bool:
if isinstance(other, PurePath): if isinstance(other, PurePath):
return super().__eq__(other) return super().__eq__(other)
if isinstance(other, str): if isinstance(other, str):
@ -103,13 +104,13 @@ else:
return self.__str__() == other return self.__str__() == other
return NotImplemented return NotImplemented
def __hash__(self): def __hash__(self) -> int:
return super().__hash__() return super().__hash__()
def __getitem__(self, item): def __getitem__(self, item: int | slice) -> str:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return self.__str__()[item] return self.__str__()[item]
def __len__(self): def __len__(self) -> int:
warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2) warnings.warn(_MSG, RemovedInSphinx80Warning, stacklevel=2)
return len(self.__str__()) 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: if name not in _DEPRECATED_OBJECTS:
msg = f'module {__name__!r} has no attribute {name!r}' msg = f'module {__name__!r} has no attribute {name!r}'
raise AttributeError(msg) raise AttributeError(msg)
@ -199,15 +199,15 @@ def using_user_docutils_conf(confdir: str | None) -> Generator[None, None, None]
@contextmanager @contextmanager
def du19_footnotes() -> Generator[None, None, None]: 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 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(f'<aside class="footnote-list {label_style}">\n')
self.body.append(self.starttag(node, 'aside', self.body.append(self.starttag(node, 'aside',
classes=[node.tagname, label_style], classes=[node.tagname, label_style],
role="note")) role="note"))
def depart_footnote(self, node): def depart_footnote(self: HTMLTranslator, node: Element) -> None:
self.body.append('</aside>\n') self.body.append('</aside>\n')
if not isinstance(node.next_node(descend=False, siblings=True), if not isinstance(node.next_node(descend=False, siblings=True),
type(node)): type(node)):
@ -354,7 +354,7 @@ class WarningStream:
class LoggingReporter(Reporter): class LoggingReporter(Reporter):
@classmethod @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.""" """Create an instance of LoggingReporter from other reporter object."""
return cls(reporter.source, reporter.report_level, reporter.halt_level, return cls(reporter.source, reporter.report_level, reporter.halt_level,
reporter.debug_flag, reporter.error_handler) reporter.debug_flag, reporter.error_handler)

View File

@ -77,7 +77,7 @@ class InventoryFileReader:
class InventoryFile: class InventoryFile:
@classmethod @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) reader = InventoryFileReader(stream)
line = reader.readline().rstrip() line = reader.readline().rstrip()
if line == '# Sphinx inventory version 1': if line == '# Sphinx inventory version 1':
@ -88,7 +88,9 @@ class InventoryFile:
raise ValueError('invalid inventory header: %s' % line) raise ValueError('invalid inventory header: %s' % line)
@classmethod @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 = {} invdata: Inventory = {}
projname = stream.readline().rstrip()[11:] projname = stream.readline().rstrip()[11:]
version = stream.readline().rstrip()[11:] version = stream.readline().rstrip()[11:]
@ -106,7 +108,9 @@ class InventoryFile:
return invdata return invdata
@classmethod @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 = {} invdata: Inventory = {}
projname = stream.readline().rstrip()[11:] projname = stream.readline().rstrip()[11:]
version = stream.readline().rstrip()[11:] version = stream.readline().rstrip()[11:]
@ -140,7 +144,9 @@ class InventoryFile:
return invdata return invdata
@classmethod @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: def escape(string: str) -> str:
return re.sub("\\s+", " ", string) return re.sub("\\s+", " ", string)

View File

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

View File

@ -47,7 +47,9 @@ class FileRenderer(BaseRenderer):
super().__init__(loader) super().__init__(loader)
@classmethod @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) dirname = os.path.dirname(filename)
basename = os.path.basename(filename) basename = os.path.basename(filename)
return cls(dirname).render(basename, context) return cls(dirname).render(basename, context)
@ -60,7 +62,9 @@ class SphinxRenderer(FileRenderer):
super().__init__(template_path) super().__init__(template_path)
@classmethod @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) return FileRenderer.render_from_file(filename, context)

View File

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