[lint] use `types-docutils instead of docutils-stubs for docutils` type annotations (#12012)

Co-authored-by: daniel.eades <daniel.eades@seebyte.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
danieleades 2024-03-23 20:09:18 +00:00 committed by GitHub
parent 42a0d73160
commit 22cee42094
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 176 additions and 172 deletions

View File

@ -85,7 +85,7 @@ lint = [
"ruff==0.3.4",
"mypy==1.9.0",
"sphinx-lint",
"docutils-stubs",
"types-docutils",
"types-requests",
"pytest>=6.0",
]

View File

@ -16,8 +16,8 @@ if TYPE_CHECKING:
# deprecated name -> (object to return, canonical path or empty string)
_DEPRECATED_OBJECTS = {
'meta': (nodes.meta, 'docutils.nodes.meta'), # type: ignore[attr-defined]
'docutils_meta': (nodes.meta, 'docutils.nodes.meta'), # type: ignore[attr-defined]
'meta': (nodes.meta, 'docutils.nodes.meta'),
'docutils_meta': (nodes.meta, 'docutils.nodes.meta'),
}
@ -45,7 +45,7 @@ class document(nodes.document):
def set_id(self, node: Element, msgnode: Element | None = None,
suggested_prefix: str = '') -> str:
return super().set_id(node, msgnode, suggested_prefix) # type: ignore[call-arg]
return super().set_id(node, msgnode, suggested_prefix)
class translatable(nodes.Node):
@ -89,7 +89,7 @@ class toctree(nodes.General, nodes.Element, translatable):
def preserve_original_messages(self) -> None:
# toctree entries
rawentries = self.setdefault('rawentries', [])
rawentries: list[str] = self.setdefault('rawentries', [])
for title, _docname in self['entries']:
if title:
rawentries.append(title)

View File

@ -520,7 +520,7 @@ class Builder:
doctree.settings = doctree.settings.copy()
doctree.settings.warning_stream = None
doctree.settings.env = None
doctree.settings.record_dependencies = None # type: ignore[assignment]
doctree.settings.record_dependencies = None
doctree_filename = path.join(self.doctreedir, docname + '.doctree')
ensuredir(path.dirname(doctree_filename))

View File

@ -67,7 +67,7 @@ class Catalog:
line = origin.line
if line is None:
line = -1
self.metadata[msg].append((origin.source, line, origin.uid))
self.metadata[msg].append((origin.source, line, origin.uid)) # type: ignore[arg-type]
def __iter__(self) -> Generator[Message, None, None]:
for message in self.messages:

View File

@ -53,6 +53,7 @@ if TYPE_CHECKING:
from collections.abc import Iterable, Iterator, Set
from docutils.nodes import Node
from docutils.readers import Reader
from sphinx.application import Sphinx
from sphinx.config import _ConfigRebuild
@ -200,7 +201,7 @@ class StandaloneHTMLBuilder(Builder):
self._js_files: list[_JavaScript] = []
# Cached Publisher for writing doctrees to HTML
reader = docutils.readers.doctree.Reader(parser_name='restructuredtext')
reader: Reader = docutils.readers.doctree.Reader(parser_name='restructuredtext')
pub = Publisher(
reader=reader,
parser=reader.parser,
@ -437,7 +438,7 @@ class StandaloneHTMLBuilder(Builder):
doc.append(node)
self._publisher.set_source(doc)
self._publisher.publish()
return self._publisher.writer.parts # type: ignore[union-attr]
return self._publisher.writer.parts
def prepare_writing(self, docnames: set[str]) -> None:
# create the search indexer
@ -767,7 +768,7 @@ class StandaloneHTMLBuilder(Builder):
def copy_download_files(self) -> None:
def to_relpath(f: str) -> str:
return relative_path(self.srcdir, f) # type: ignore[arg-type]
return relative_path(self.srcdir, f)
# copy downloadable files
if self.env.dlfiles:

View File

@ -115,7 +115,7 @@ class ShowUrlsTransform(SphinxPostTransform):
node = node.parent
try:
source = node['source'] # type: ignore[index]
source = node['source']
except TypeError:
raise ValueError(__('Failed to get a docname!')) from None
raise ValueError(__('Failed to get a docname '
@ -523,7 +523,7 @@ class BibliographyTransform(SphinxPostTransform):
citations += node
if len(citations) > 0:
self.document += citations
self.document += citations # type: ignore[attr-defined]
class CitationReferenceTransform(SphinxPostTransform):

View File

@ -3,7 +3,7 @@
from __future__ import annotations
import re
from typing import TYPE_CHECKING, Generic, TypeVar, cast
from typing import TYPE_CHECKING, ClassVar, Generic, TypeVar, cast
from docutils import nodes
from docutils.parsers.rst import directives, roles
@ -55,7 +55,7 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'no-index': directives.flag,
'no-index-entry': directives.flag,
'no-contents-entry': directives.flag,
@ -296,7 +296,7 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
# If ``:no-index:`` is set, or there are no ids on the node
# or any of its children, then just return the index node,
# as Docutils expects a target node to have at least one id.
if node_ids := [node_id for el in node.findall(nodes.Element)
if node_ids := [node_id for el in node.findall(nodes.Element) # type: ignore[var-annotated]
for node_id in el.get('ids', ())]:
target_node = nodes.target(ids=node_ids)
self.set_source_info(target_node)
@ -320,7 +320,7 @@ class DefaultRole(SphinxDirective):
role_name = self.arguments[0]
role, messages = roles.role(role_name, self.state_machine.language,
self.lineno, self.state.reporter)
if role: # type: ignore[truthy-function]
if role:
docutils.register_role('', role) # type: ignore[arg-type]
self.env.temp_data['default_role'] = role_name
else:
@ -342,7 +342,7 @@ class DefaultDomain(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = False
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
domain_name = self.arguments[0].lower()

View File

@ -3,7 +3,7 @@ from __future__ import annotations
import sys
import textwrap
from difflib import unified_diff
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING, Any, ClassVar
from docutils import nodes
from docutils.parsers.rst import directives
@ -35,7 +35,7 @@ class Highlight(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = False
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'force': directives.flag,
'linenothreshold': directives.positive_int,
}
@ -102,7 +102,7 @@ class CodeBlock(SphinxDirective):
required_arguments = 0
optional_arguments = 1
final_argument_whitespace = False
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'force': directives.flag,
'linenos': directives.flag,
'dedent': optional_int,
@ -393,7 +393,7 @@ class LiteralInclude(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'dedent': optional_int,
'linenos': directives.flag,
'lineno-start': int,

View File

@ -3,7 +3,7 @@ from __future__ import annotations
import re
from os.path import abspath, relpath
from pathlib import Path
from typing import TYPE_CHECKING, Any, cast
from typing import TYPE_CHECKING, Any, ClassVar, cast
from docutils import nodes
from docutils.parsers.rst import directives
@ -22,6 +22,8 @@ from sphinx.util.matching import Matcher, patfilter
from sphinx.util.nodes import explicit_title_re
if TYPE_CHECKING:
from collections.abc import Sequence
from docutils.nodes import Element, Node
from sphinx.application import Sphinx
@ -179,7 +181,7 @@ class Author(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
if not self.config.show_authors:
@ -221,7 +223,7 @@ class TabularColumns(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
node = addnodes.tabular_col_spec()
@ -239,7 +241,7 @@ class Centered(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
if not self.arguments:
@ -262,7 +264,7 @@ class Acks(SphinxDirective):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = False
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
node = addnodes.acks()
@ -285,7 +287,7 @@ class HList(SphinxDirective):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = False
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'columns': int,
}
@ -323,7 +325,7 @@ class Only(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
node = addnodes.only()
@ -379,7 +381,7 @@ class Include(BaseInclude, SphinxDirective):
"correctly", i.e. relative to source directory.
"""
def run(self) -> list[Node]:
def run(self) -> Sequence[Node]:
# To properly emit "include-read" events from included RST text,
# we must patch the ``StateMachine.insert_input()`` method.
@ -413,7 +415,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[assignment]
self.state_machine.insert_input = _insert_input
if self.arguments[0].startswith('<') and \
self.arguments[0].endswith('>'):

View File

@ -2,13 +2,13 @@ from __future__ import annotations
import os
from os import path
from typing import TYPE_CHECKING, cast
from typing import TYPE_CHECKING, ClassVar, cast
from docutils import nodes
from docutils.nodes import Node, make_id
from docutils.parsers.rst import directives
from docutils.parsers.rst.directives import images, tables
from docutils.parsers.rst.directives.misc import Meta # type: ignore[attr-defined]
from docutils.parsers.rst.directives.misc import Meta
from docutils.parsers.rst.roles import set_classes
from sphinx.directives import optional_int
@ -82,7 +82,7 @@ class Code(SphinxDirective):
"""
optional_arguments = 1
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'class': directives.class_option,
'force': directives.flag,
'name': directives.unchanged,
@ -127,7 +127,7 @@ class MathDirective(SphinxDirective):
required_arguments = 0
optional_arguments = 1
final_argument_whitespace = True
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'label': directives.unchanged,
'name': directives.unchanged,
'class': directives.class_option,

View File

@ -2,7 +2,7 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING, Any, ClassVar
from docutils import nodes
from docutils.parsers.rst import directives
@ -56,7 +56,7 @@ class CObject(ObjectDescription[ASTDeclaration]):
Description of a C language object.
"""
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'no-index-entry': directives.flag,
'no-contents-entry': directives.flag,
'no-typesetting': directives.flag,
@ -297,7 +297,7 @@ class CNamespaceObject(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
rootSymbol = self.env.domaindata['c']['root_symbol']
@ -327,7 +327,7 @@ class CNamespacePushObject(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
@ -358,7 +358,7 @@ class CNamespacePopObject(SphinxDirective):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
stack = self.env.temp_data.get('c:namespace_stack', None)
@ -517,7 +517,7 @@ class AliasTransform(SphinxTransform):
class CAliasObject(ObjectDescription):
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'maxdepth': directives.nonnegative_int,
'noroot': directives.flag,
}

View File

@ -2,7 +2,7 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Any, NamedTuple, cast
from typing import TYPE_CHECKING, Any, ClassVar, NamedTuple, cast
from docutils import nodes
@ -52,7 +52,7 @@ class VersionChange(SphinxDirective):
required_arguments = 1
optional_arguments = 1
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
node = addnodes.versionmodified()
@ -123,7 +123,7 @@ class ChangeSetDomain(Domain):
version = node['version']
module = self.env.ref_context.get('py:module')
objname = self.env.temp_data.get('object')
changeset = ChangeSet(node['type'], self.env.docname, node.line,
changeset = ChangeSet(node['type'], self.env.docname, node.line, # type: ignore[arg-type]
module, objname, node.astext())
self.changesets.setdefault(version, []).append(changeset)

View File

@ -70,7 +70,7 @@ class CitationDomain(Domain):
path = self.env.doc2path(self.citations[label][0])
logger.warning(__('duplicate citation %s, other instance in %s'), label, path,
location=node, type='ref', subtype='citation')
self.citations[label] = (node['docname'], node['ids'][0], node.line)
self.citations[label] = (node['docname'], node['ids'][0], node.line) # type: ignore[assignment]
def note_citation_reference(self, node: pending_xref) -> None:
docnames = self.citation_refs.setdefault(node['reftarget'], set())

View File

@ -3,7 +3,7 @@
from __future__ import annotations
import re
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING, Any, ClassVar
from docutils import nodes
from docutils.parsers.rst import directives
@ -65,7 +65,7 @@ class CPPObject(ObjectDescription[ASTDeclaration]):
can_collapse=True),
]
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'no-index-entry': directives.flag,
'no-contents-entry': directives.flag,
'no-typesetting': directives.flag,
@ -394,7 +394,7 @@ class CPPNamespaceObject(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
rootSymbol = self.env.domaindata['cpp']['root_symbol']
@ -425,7 +425,7 @@ class CPPNamespacePushObject(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
@ -457,7 +457,7 @@ class CPPNamespacePopObject(SphinxDirective):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
stack = self.env.temp_data.get('cpp:namespace_stack', None)
@ -634,7 +634,7 @@ class AliasTransform(SphinxTransform):
class CPPAliasObject(ObjectDescription):
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'maxdepth': directives.nonnegative_int,
'noroot': directives.flag,
}

View File

@ -2,7 +2,7 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING, Any, ClassVar
from docutils import nodes
from docutils.parsers.rst import directives
@ -68,7 +68,7 @@ class IndexDirective(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'name': directives.unchanged,
}

View File

@ -3,7 +3,7 @@
from __future__ import annotations
import contextlib
from typing import TYPE_CHECKING, Any, cast
from typing import TYPE_CHECKING, Any, ClassVar, cast
from docutils import nodes
from docutils.parsers.rst import directives
@ -46,7 +46,7 @@ class JSObject(ObjectDescription[tuple[str, str]]):
#: based on directive nesting
allow_nesting = False
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'no-index': directives.flag,
'no-index-entry': directives.flag,
'no-contents-entry': directives.flag,
@ -298,7 +298,7 @@ class JSModule(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = False
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'no-index': directives.flag,
'no-contents-entry': directives.flag,
'no-typesetting': directives.flag,

View File

@ -5,7 +5,7 @@ from __future__ import annotations
import builtins
import inspect
import typing
from typing import TYPE_CHECKING, Any, NamedTuple, cast
from typing import TYPE_CHECKING, Any, ClassVar, NamedTuple, cast
from docutils import nodes
from docutils.parsers.rst import directives
@ -67,7 +67,7 @@ class ModuleEntry(NamedTuple):
class PyFunction(PyObject):
"""Description of a function."""
option_spec: OptionSpec = PyObject.option_spec.copy()
option_spec: ClassVar[OptionSpec] = PyObject.option_spec.copy() # noqa: F821
option_spec.update({
'async': directives.flag,
})
@ -122,7 +122,7 @@ class PyDecoratorFunction(PyFunction):
class PyVariable(PyObject):
"""Description of a variable."""
option_spec: OptionSpec = PyObject.option_spec.copy()
option_spec: ClassVar[OptionSpec] = PyObject.option_spec.copy()
option_spec.update({
'type': directives.unchanged,
'value': directives.unchanged,
@ -161,7 +161,7 @@ class PyClasslike(PyObject):
Description of a class-like object (classes, interfaces, exceptions).
"""
option_spec: OptionSpec = PyObject.option_spec.copy()
option_spec: ClassVar[OptionSpec] = PyObject.option_spec.copy()
option_spec.update({
'final': directives.flag,
})
@ -189,7 +189,7 @@ class PyClasslike(PyObject):
class PyMethod(PyObject):
"""Description of a method."""
option_spec: OptionSpec = PyObject.option_spec.copy()
option_spec: ClassVar[OptionSpec] = PyObject.option_spec.copy()
option_spec.update({
'abstractmethod': directives.flag,
'async': directives.flag,
@ -243,7 +243,7 @@ class PyMethod(PyObject):
class PyClassMethod(PyMethod):
"""Description of a classmethod."""
option_spec: OptionSpec = PyObject.option_spec.copy()
option_spec: ClassVar[OptionSpec] = PyObject.option_spec.copy()
def run(self) -> list[Node]:
self.name = 'py:method'
@ -255,7 +255,7 @@ class PyClassMethod(PyMethod):
class PyStaticMethod(PyMethod):
"""Description of a staticmethod."""
option_spec: OptionSpec = PyObject.option_spec.copy()
option_spec: ClassVar[OptionSpec] = PyObject.option_spec.copy()
def run(self) -> list[Node]:
self.name = 'py:method'
@ -283,7 +283,7 @@ class PyDecoratorMethod(PyMethod):
class PyAttribute(PyObject):
"""Description of an attribute."""
option_spec: OptionSpec = PyObject.option_spec.copy()
option_spec: ClassVar[OptionSpec] = PyObject.option_spec.copy()
option_spec.update({
'type': directives.unchanged,
'value': directives.unchanged,
@ -385,7 +385,7 @@ class PyModule(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = False
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'platform': lambda x: x,
'synopsis': lambda x: x,
'no-index': directives.flag,
@ -444,7 +444,7 @@ class PyCurrentModule(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = False
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
modname = self.arguments[0].strip()

View File

@ -2,7 +2,7 @@ from __future__ import annotations
import contextlib
import re
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, ClassVar
from docutils import nodes
from docutils.parsers.rst import directives
@ -76,13 +76,13 @@ class PyXrefMixin:
result['reftarget'] = reftarget
result.clear()
result += innernode(reftitle, reftitle)
result += innernode(reftitle, reftitle) # type: ignore[call-arg]
elif env.config.python_use_unqualified_type_names:
children = result.children
result.clear()
shortname = target.split('.')[-1]
textnode = innernode('', shortname)
textnode = innernode('', shortname) # type: ignore[call-arg]
contnodes = [pending_xref_condition('', '', textnode, condition='resolved'),
pending_xref_condition('', '', *children, condition='*')]
result.extend(contnodes)
@ -113,7 +113,7 @@ class PyXrefMixin:
contnode = nodes.Text(sub_target)
if in_literal or delims_re.match(sub_target):
results.append(contnode or innernode(sub_target, sub_target))
results.append(contnode or innernode(sub_target, sub_target)) # type: ignore[call-arg]
else:
results.append(self.make_xref(rolename, domain, sub_target,
innernode, contnode, env, inliner, location))
@ -144,7 +144,7 @@ class PyObject(ObjectDescription[tuple[str, str]]):
:vartype allow_nesting: bool
"""
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'no-index': directives.flag,
'no-index-entry': directives.flag,
'no-contents-entry': directives.flag,

View File

@ -3,7 +3,7 @@
from __future__ import annotations
import re
from typing import TYPE_CHECKING, Any, cast
from typing import TYPE_CHECKING, Any, ClassVar, cast
from docutils.parsers.rst import directives
@ -36,7 +36,7 @@ class ReSTMarkup(ObjectDescription[str]):
Description of generic reST markup.
"""
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'no-index': directives.flag,
'no-index-entry': directives.flag,
'no-contents-entry': directives.flag,
@ -142,7 +142,7 @@ class ReSTDirectiveOption(ReSTMarkup):
Description of an option for reST directive.
"""
option_spec: OptionSpec = ReSTMarkup.option_spec.copy()
option_spec: ClassVar[OptionSpec] = ReSTMarkup.option_spec.copy()
option_spec.update({
'type': directives.unchanged,
})

View File

@ -4,7 +4,7 @@ from __future__ import annotations
import re
from copy import copy
from typing import TYPE_CHECKING, Any, Callable, Final, cast
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Final, cast
from docutils import nodes
from docutils.nodes import Element, Node, system_message
@ -112,7 +112,7 @@ class Target(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
# normalize whitespace in fullname like XRefRole does
@ -206,7 +206,7 @@ class Cmdoption(ObjectDescription[str]):
def add_target_and_index(self, firstname: str, sig: str, signode: desc_signature) -> None:
currprogram = self.env.ref_context.get('std:program')
for optname in signode.get('allnames', []):
for optname in signode.get('allnames', []): # type: ignore[var-annotated]
prefixes = ['cmdoption']
if currprogram:
prefixes.append(currprogram)
@ -228,7 +228,7 @@ class Cmdoption(ObjectDescription[str]):
descr = _('%s command line option') % currprogram
else:
descr = _('command line option')
for option in signode.get('allnames', []):
for option in signode.get('allnames', []): # type: ignore[var-annotated]
entry = f'{descr}; {option}'
self.indexnode['entries'].append(('pair', entry, signode['ids'][0], '', None))
@ -242,7 +242,7 @@ class Program(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
program = ws_re.sub('-', self.arguments[0].strip())
@ -306,7 +306,7 @@ class Glossary(SphinxDirective):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = False
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'sorted': directives.flag,
}
@ -385,7 +385,7 @@ class Glossary(SphinxDirective):
parts = split_term_classifiers(line)
# parse the term with inline markup
# classifiers (parts[1:]) will not be shown on doctree
textnodes, sysmsg = self.state.inline_text(parts[0], # type: ignore[arg-type]
textnodes, sysmsg = self.state.inline_text(parts[0],
lineno)
# use first classifier as a index key
@ -453,7 +453,7 @@ class ProductionList(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
domain = cast(StandardDomain, self.env.get_domain('std'))

View File

@ -30,7 +30,7 @@ class MetadataCollector(EnvironmentCollector):
Keep processing minimal -- just return what docutils says.
"""
index = doctree.first_child_not_matching_class(nodes.PreBibliographic)
index = doctree.first_child_not_matching_class(nodes.PreBibliographic) # type: ignore[arg-type]
if index is None:
return
elif isinstance(doctree[index], nodes.docinfo):

View File

@ -13,7 +13,7 @@ import re
import sys
import warnings
from inspect import Parameter, Signature
from typing import TYPE_CHECKING, Any, Callable, TypeVar
from typing import TYPE_CHECKING, Any, Callable, ClassVar, TypeVar
from docutils.statemachine import StringList
@ -319,7 +319,7 @@ class Documenter:
#: true if the generated content may contain titles
titles_allowed = True
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'no-index': bool_option,
'noindex': bool_option,
}
@ -980,7 +980,7 @@ class ModuleDocumenter(Documenter):
content_indent = ''
_extra_indent = ' '
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'members': members_option, 'undoc-members': bool_option,
'no-index': bool_option, 'inherited-members': inherited_members_option,
'show-inheritance': bool_option, 'synopsis': identity,
@ -1466,7 +1466,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
objtype = 'class'
member_order = 20
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'members': members_option, 'undoc-members': bool_option,
'no-index': bool_option, 'inherited-members': inherited_members_option,
'show-inheritance': bool_option, 'member-order': member_order_option,
@ -2042,7 +2042,7 @@ class DataDocumenter(GenericAliasMixin,
objtype = 'data'
member_order = 40
priority = -10
option_spec: OptionSpec = dict(ModuleLevelDocumenter.option_spec)
option_spec: ClassVar[OptionSpec] = dict(ModuleLevelDocumenter.option_spec)
option_spec["annotation"] = annotation_option
option_spec["no-value"] = bool_option
@ -2589,7 +2589,7 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
objtype = 'attribute'
member_order = 60
option_spec: OptionSpec = dict(ModuleLevelDocumenter.option_spec)
option_spec: ClassVar[OptionSpec] = dict(ModuleLevelDocumenter.option_spec)
option_spec["annotation"] = annotation_option
option_spec["no-value"] = bool_option

View File

@ -115,7 +115,7 @@ class AutodocDirective(SphinxDirective):
reporter = self.state.document.reporter
try:
source, lineno = reporter.get_source_and_line( # type: ignore[attr-defined]
source, lineno = reporter.get_source_and_line(
self.lineno)
except AttributeError:
source, lineno = (None, None)

View File

@ -58,7 +58,7 @@ import sys
from inspect import Parameter
from os import path
from types import ModuleType
from typing import TYPE_CHECKING, Any, cast
from typing import TYPE_CHECKING, Any, ClassVar, cast
from docutils import nodes
from docutils.parsers.rst import directives
@ -218,7 +218,7 @@ class Autosummary(SphinxDirective):
optional_arguments = 0
final_argument_whitespace = False
has_content = True
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'caption': directives.unchanged_required,
'toctree': directives.unchanged,
'nosignatures': directives.flag,

View File

@ -11,7 +11,7 @@ import sys
import time
from io import StringIO
from os import path
from typing import TYPE_CHECKING, Any, Callable
from typing import TYPE_CHECKING, Any, Callable, ClassVar
from docutils import nodes
from docutils.parsers.rst import directives
@ -143,19 +143,19 @@ class TestDirective(SphinxDirective):
class TestsetupDirective(TestDirective):
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'skipif': directives.unchanged_required,
}
class TestcleanupDirective(TestDirective):
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'skipif': directives.unchanged_required,
}
class DoctestDirective(TestDirective):
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'hide': directives.flag,
'no-trim-doctest-flags': directives.flag,
'options': directives.unchanged,
@ -166,7 +166,7 @@ class DoctestDirective(TestDirective):
class TestcodeDirective(TestDirective):
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'hide': directives.flag,
'no-trim-doctest-flags': directives.flag,
'pyversion': directives.unchanged_required,
@ -176,7 +176,7 @@ class TestcodeDirective(TestDirective):
class TestoutputDirective(TestDirective):
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'hide': directives.flag,
'no-trim-doctest-flags': directives.flag,
'options': directives.unchanged,
@ -371,14 +371,13 @@ Doctest summary
filename of the document it's included in.
"""
try:
filename = relpath(node.source, self.env.srcdir)\
.rsplit(':docstring of ', maxsplit=1)[0]
filename = relpath(node.source, self.env.srcdir).rsplit(':docstring of ', maxsplit=1)[0] # type: ignore[arg-type] # noqa: E501
except Exception:
filename = self.env.doc2path(docname, False)
return filename
@staticmethod
def get_line_number(node: Node) -> int:
def get_line_number(node: Node) -> int | None:
"""Get the real line number or admit we don't know."""
# TODO: Work out how to store or calculate real (file-relative)
# line numbers for doctest blocks in docstrings.
@ -387,7 +386,7 @@ Doctest summary
# not the file. This is correct where it is set, in
# `docutils.nodes.Node.setup_child`, but Sphinx should report
# relative to the file, not the docstring.
return None # type: ignore[return-value]
return None
if node.line is not None:
# TODO: find the root cause of this off by one error.
return node.line - 1
@ -428,21 +427,21 @@ Doctest summary
def condition(node: Node) -> bool:
return isinstance(node, (nodes.literal_block, nodes.comment)) \
and 'testnodetype' in node
for node in doctree.findall(condition): # type: Element
if self.skipped(node):
for node in doctree.findall(condition):
if self.skipped(node): # type: ignore[arg-type]
continue
source = node['test'] if 'test' in node else node.astext()
source = node['test'] if 'test' in node else node.astext() # type: ignore[index, operator]
filename = self.get_filename_for_node(node, docname)
line_number = self.get_line_number(node)
if not source:
logger.warning(__('no code/output in %s block at %s:%s'),
node.get('testnodetype', 'doctest'),
node.get('testnodetype', 'doctest'), # type: ignore[attr-defined]
filename, line_number)
code = TestCode(source, type=node.get('testnodetype', 'doctest'),
filename=filename, lineno=line_number,
options=node.get('options'))
node_groups = node.get('groups', ['default'])
code = TestCode(source, type=node.get('testnodetype', 'doctest'), # type: ignore[attr-defined]
filename=filename, lineno=line_number, # type: ignore[arg-type]
options=node.get('options')) # type: ignore[attr-defined]
node_groups = node.get('groups', ['default']) # type: ignore[attr-defined]
if '*' in node_groups:
add_to_all_groups.append(code)
continue

View File

@ -11,7 +11,7 @@ from hashlib import sha1
from itertools import chain
from os import path
from subprocess import CalledProcessError
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING, Any, ClassVar
from urllib.parse import urlsplit, urlunsplit
from docutils import nodes
@ -117,7 +117,7 @@ class Graphviz(SphinxDirective):
required_arguments = 0
optional_arguments = 1
final_argument_whitespace = False
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'alt': directives.unchanged,
'align': align_spec,
'caption': directives.unchanged,
@ -186,7 +186,7 @@ class GraphvizSimple(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = False
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'alt': directives.unchanged,
'align': align_spec,
'caption': directives.unchanged,

View File

@ -16,7 +16,7 @@ namespace of the project configuration (that is, all variables from
from __future__ import annotations
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, ClassVar
from docutils import nodes
@ -41,7 +41,7 @@ class IfConfig(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
node = ifconfig()

View File

@ -37,7 +37,7 @@ import re
from collections.abc import Iterable, Sequence
from importlib import import_module
from os import path
from typing import TYPE_CHECKING, Any, cast
from typing import TYPE_CHECKING, Any, ClassVar, cast
from docutils import nodes
from docutils.parsers.rst import directives
@ -348,7 +348,7 @@ class InheritanceDiagram(SphinxDirective):
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'parts': int,
'private-bases': directives.flag,
'caption': directives.unchanged,
@ -378,7 +378,7 @@ class InheritanceDiagram(SphinxDirective):
aliases=self.config.inheritance_alias,
top_classes=node['top-classes'])
except InheritanceException as err:
return [node.document.reporter.warning(err, line=self.lineno)]
return [node.document.reporter.warning(err, line=self.lineno)] # type: ignore[union-attr]
# Create xref nodes for each target of the graph's image map and
# add them to the doc tree so that Sphinx can resolve the
@ -386,7 +386,7 @@ class InheritanceDiagram(SphinxDirective):
# removed from the doctree after we're done with them.
for name in graph.get_all_class_names():
refnodes, x = class_role( # type: ignore[call-arg,misc]
'class', ':class:`%s`' % name, name, 0, self.state) # type: ignore[arg-type]
'class', ':class:`%s`' % name, name, 0, self.state)
node.extend(refnodes)
# Store the graph object so we can use it to generate the
# dot file later

View File

@ -9,7 +9,7 @@ from __future__ import annotations
import functools
import operator
from typing import TYPE_CHECKING, Any, cast
from typing import TYPE_CHECKING, Any, ClassVar, cast
from docutils import nodes
from docutils.parsers.rst import directives
@ -53,7 +53,7 @@ class Todo(BaseAdmonition, SphinxDirective):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = False
option_spec: OptionSpec = {
option_spec: ClassVar[OptionSpec] = {
'class': directives.class_option,
'name': directives.unchanged,
}
@ -112,7 +112,7 @@ class TodoList(SphinxDirective):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = False
option_spec: OptionSpec = {}
option_spec: ClassVar[OptionSpec] = {}
def run(self) -> list[Node]:
# Simply insert an empty todolist node which will be replaced later

View File

@ -98,9 +98,9 @@ class SphinxStandaloneReader(SphinxBaseReader):
self.transforms = self.transforms + app.registry.get_transforms()
super().setup(app)
def read(self, source: Input, parser: Parser, settings: Values) -> nodes.document:
def read(self, source: Input, parser: Parser, settings: Values) -> nodes.document: # type: ignore[type-arg]
self.source = source
if not self.parser:
if not self.parser: # type: ignore[has-type]
self.parser = parser
self.settings = settings
self.input = self.read_source(settings.env)
@ -179,7 +179,7 @@ def create_publisher(app: Sphinx, filetype: str) -> Publisher:
# CommonMarkParser.
from docutils.parsers.rst import Parser as RSTParser
parser.settings_spec = RSTParser.settings_spec
parser.settings_spec = RSTParser.settings_spec # type: ignore[misc]
pub = Publisher(
reader=reader,

View File

@ -462,15 +462,15 @@ def setup(app: Sphinx) -> ExtensionMetadata:
for rolename, nodeclass in generic_docroles.items():
generic = roles.GenericRole(rolename, nodeclass)
role = roles.CustomRole(rolename, generic, {'classes': [rolename]})
roles.register_local_role(rolename, role)
role = roles.CustomRole(rolename, generic, {'classes': [rolename]}) # type: ignore[arg-type]
roles.register_local_role(rolename, role) # type: ignore[arg-type]
for rolename, func in specific_docroles.items():
roles.register_local_role(rolename, func)
roles.register_local_role(rolename, func) # type: ignore[arg-type]
# Since docutils registers it as a canonical role, override it as a
# canonical role as well.
roles.register_canonical_role('code', code_role)
roles.register_canonical_role('code', code_role) # type: ignore[arg-type]
return {
'version': 'builtin',

View File

@ -182,7 +182,7 @@ js_index = _JavaScriptIndex()
def _is_meta_keywords(
node: nodes.meta, # type: ignore[name-defined]
node: nodes.meta,
lang: str | None,
) -> bool:
if node.get('name') == 'keywords':
@ -234,7 +234,7 @@ class WordCollector(nodes.NodeVisitor):
ids = node.parent['ids']
self.found_titles.append((title, ids[0] if ids else None))
self.found_title_words.extend(self.lang.split(title))
elif isinstance(node, Element) and _is_meta_keywords(node, self.lang.lang):
elif isinstance(node, Element) and _is_meta_keywords(node, self.lang.lang): # type: ignore[arg-type]
keywords = node['content']
keywords = [keyword.strip() for keyword in keywords.split(',')]
self.found_words.extend(keywords)
@ -495,7 +495,7 @@ class IndexBuilder:
nodetext = re.sub(r'<[^<]+?>', '', nodetext)
word_store.words.extend(split(nodetext))
return
elif (isinstance(node, nodes.meta) # type: ignore[attr-defined]
elif (isinstance(node, nodes.meta)
and _is_meta_keywords(node, language)):
keywords = [keyword.strip() for keyword in node['content'].split(',')]
word_store.words.extend(keywords)

View File

@ -81,7 +81,7 @@ class SphinxTransformer(Transformer):
if not hasattr(self.document.settings, 'env') and self.env:
self.document.settings.env = self.env
super().apply_transforms()
super().apply_transforms() # type: ignore[misc]
else:
# wrap the target node by document node during transforming
try:

View File

@ -78,7 +78,7 @@ def publish_msgstr(app: Sphinx, source: str, source_path: str, source_line: int,
settings=settings,
)
with contextlib.suppress(IndexError): # empty node
return doc[0] # type: ignore[return-value]
return doc[0]
return doc
finally:
config.rst_prolog = rst_prolog # type: ignore[attr-defined]
@ -138,7 +138,7 @@ class _NodeUpdater:
if old_name != new_name:
# if name would be changed, replace node names and
# document nameids mapping with new name.
names = section_node.setdefault('names', [])
names: list[str] = section_node.setdefault('names', [])
names.append(new_name)
# Original section name (reference target name) should be kept to refer
# from other nodes which is still not translated or uses explicit target
@ -394,7 +394,7 @@ class Locale(SphinxTransform):
msgstr = '::\n\n' + indent(msgstr, ' ' * 3)
patch = publish_msgstr(self.app, msgstr, source,
node.line, self.config, settings)
node.line, self.config, settings) # type: ignore[arg-type]
# FIXME: no warnings about inconsistent references in this part
# XXX doctest and other block markup
if not isinstance(patch, nodes.paragraph):
@ -408,10 +408,10 @@ class Locale(SphinxTransform):
for _id in node['ids']:
parts = split_term_classifiers(msgstr)
patch = publish_msgstr(
self.app, parts[0] or '', source, node.line, self.config, settings,
self.app, parts[0] or '', source, node.line, self.config, settings, # type: ignore[arg-type]
)
updater.patch = make_glossary_term(
self.env, patch, parts[1] or '', source, node.line, _id, self.document,
self.env, patch, parts[1] or '', source, node.line, _id, self.document, # type: ignore[arg-type]
)
processed = True
@ -440,11 +440,11 @@ class Locale(SphinxTransform):
# update translatable nodes
if isinstance(node, addnodes.translatable):
node.apply_translated_message(msg, msgstr) # type: ignore[attr-defined]
node.apply_translated_message(msg, msgstr)
continue
# update meta nodes
if isinstance(node, nodes.meta): # type: ignore[attr-defined]
if isinstance(node, nodes.meta):
node['content'] = msgstr
node['translated'] = True
continue
@ -474,11 +474,11 @@ class Locale(SphinxTransform):
msgstr = msgstr + '\n' + '=' * len(msgstr) * 2
patch = publish_msgstr(self.app, msgstr, source,
node.line, self.config, settings)
node.line, self.config, settings) # type: ignore[arg-type]
# Structural Subelements phase2
if isinstance(node, nodes.title):
# get <title> node that placed as a first child
patch = patch.next_node()
patch = patch.next_node() # type: ignore[assignment]
# ignore unexpected markups in translation message
unexpected: tuple[type[nodes.Element], ...] = (
@ -588,10 +588,10 @@ class AddTranslationClasses(SphinxTransform):
for node in NodeMatcher(nodes.Element, translated=Any).findall(self.document):
if node['translated']:
if add_translated:
node.setdefault('classes', []).append('translated')
node.setdefault('classes', []).append('translated') # type: ignore[arg-type]
else:
if add_untranslated:
node.setdefault('classes', []).append('untranslated')
node.setdefault('classes', []).append('untranslated') # type: ignore[arg-type]
class RemoveTranslatableInline(SphinxTransform):

View File

@ -78,7 +78,7 @@ class Field:
assert env is not None
assert (inliner is None) == (location is None), (inliner, location)
if not rolename:
return contnode or innernode(target, target)
return contnode or innernode(target, target) # type: ignore[call-arg]
# The domain is passed from DocFieldTransformer. So it surely exists.
# So we don't need to take care the env.get_domain() raises an exception.
role = env.get_domain(domain).role(rolename)
@ -89,7 +89,7 @@ class Field:
logger.warning(__(msg), domain, rolename, location=location)
refnode = addnodes.pending_xref('', refdomain=domain, refexplicit=False,
reftype=rolename, reftarget=target)
refnode += contnode or innernode(target, target)
refnode += contnode or innernode(target, target) # type: ignore[call-arg]
env.get_domain(domain).process_field_xref(refnode)
return refnode
lineno = -1

View File

@ -101,7 +101,7 @@ def register_role(name: str, role: RoleFunction) -> None:
This modifies global state of docutils. So it is better to use this
inside ``docutils_namespace()`` to prevent side-effects.
"""
roles.register_local_role(name, role)
roles.register_local_role(name, role) # type: ignore[arg-type]
def unregister_role(name: str) -> None:
@ -150,7 +150,7 @@ def patched_get_language() -> Generator[None, None, None]:
return get_language(language_code)
try:
docutils.languages.get_language = patched_get_language
docutils.languages.get_language = patched_get_language # type: ignore[assignment]
yield
finally:
# restore original implementations
@ -174,7 +174,7 @@ def patched_rst_get_language() -> Generator[None, None, None]:
return get_language(language_code)
try:
docutils.parsers.rst.languages.get_language = patched_get_language
docutils.parsers.rst.languages.get_language = patched_get_language # type: ignore[assignment]
yield
finally:
# restore original implementations
@ -201,7 +201,7 @@ def using_user_docutils_conf(confdir: str | None) -> Generator[None, None, None]
def du19_footnotes() -> Generator[None, None, None]:
def visit_footnote(self: HTMLTranslator, node: Element) -> None:
label_style = self.settings.footnote_references
if not isinstance(node.previous_sibling(), type(node)): # type: ignore[attr-defined]
if not isinstance(node.previous_sibling(), type(node)):
self.body.append(f'<aside class="footnote-list {label_style}">\n')
self.body.append(self.starttag(node, 'aside',
classes=[node.tagname, label_style],
@ -263,8 +263,8 @@ class CustomReSTDispatcher:
self.directive_func = directives.directive
self.role_func = roles.role
directives.directive = self.directive
roles.role = self.role
directives.directive = self.directive # type: ignore[assignment]
roles.role = self.role # type: ignore[assignment]
def disable(self) -> None:
directives.directive = self.directive_func
@ -383,7 +383,7 @@ def switch_source_input(state: State, content: StringList) -> Generator[None, No
gsal = state.memo.reporter.get_source_and_line # type: ignore[attr-defined]
# replace it by new one
state_machine = StateMachine([], None) # type: ignore[arg-type]
state_machine: StateMachine[None] = StateMachine([], None) # type: ignore[arg-type]
state_machine.input_lines = content
state.memo.reporter.get_source_and_line = state_machine.get_source_and_line # type: ignore[attr-defined] # NoQA: E501

View File

@ -80,7 +80,7 @@ def copy_asset(source: str | os.PathLike[str], destination: str | os.PathLike[st
return
for root, dirs, files in os.walk(source, followlinks=True):
reldir = relative_path(source, root) # type: ignore[arg-type]
reldir = relative_path(source, root)
for dir in dirs.copy():
if excluded(posixpath.join(reldir, dir)):
dirs.remove(dir)

View File

@ -5,7 +5,7 @@ from __future__ import annotations
import contextlib
import re
import unicodedata
from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar
from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar, cast
from docutils import nodes
from docutils.nodes import Node
@ -93,7 +93,8 @@ class NodeMatcher(Generic[N]):
While the `NodeMatcher` object can be used as an argument to `Node.findall`, doing so
confounds type checkers' ability to determine the return type of the iterator.
"""
return node.findall(self)
for found in node.findall(self):
yield cast(N, found)
def get_full_module_name(node: Node) -> str:
@ -137,7 +138,7 @@ def apply_source_workaround(node: Element) -> None:
get_full_module_name(node), repr_domxml(node))
definition_list_item = node.parent
node.source = definition_list_item.source
node.line = definition_list_item.line - 1
node.line = definition_list_item.line - 1 # type: ignore[operator]
node.rawsource = node.astext() # set 'classifier1' (or 'classifier2')
elif isinstance(node, nodes.classifier) and not node.source:
# docutils-0.15 fills in rawsource attribute, but not in source.
@ -236,7 +237,7 @@ def is_translatable(node: Node) -> bool:
return False
return True
return isinstance(node, nodes.meta) # type: ignore[attr-defined]
return isinstance(node, nodes.meta)
LITERAL_TYPE_NODES = (
@ -252,10 +253,10 @@ IMAGE_TYPE_NODES = (
def extract_messages(doctree: Element) -> Iterable[tuple[Element, str]]:
"""Extract translatable messages from a document tree."""
for node in doctree.findall(is_translatable): # type: Element
for node in doctree.findall(is_translatable):
if isinstance(node, addnodes.translatable):
for msg in node.extract_original_messages():
yield node, msg
yield node, msg # type: ignore[misc]
continue
if isinstance(node, LITERAL_TYPE_NODES):
msg = node.rawsource
@ -269,14 +270,14 @@ def extract_messages(doctree: Element) -> Iterable[tuple[Element, str]]:
msg = f'.. image:: {image_uri}'
else:
msg = ''
elif isinstance(node, nodes.meta): # type: ignore[attr-defined]
elif isinstance(node, nodes.meta):
msg = node["content"]
else:
msg = node.rawsource.replace('\n', ' ').strip()
msg = node.rawsource.replace('\n', ' ').strip() # type: ignore[attr-defined]
# XXX nodes rendering empty are likely a bug in sphinx.addnodes
if msg:
yield node, msg
yield node, msg # type: ignore[misc]
def get_node_source(node: Element) -> str:

View File

@ -5,11 +5,11 @@ from __future__ import annotations
import re
from collections import defaultdict
from contextlib import contextmanager
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, cast
from unicodedata import east_asian_width
from docutils.parsers.rst import roles
from docutils.parsers.rst.languages import en as english
from docutils.parsers.rst.languages import en as english # type: ignore[attr-defined]
from docutils.parsers.rst.states import Body
from docutils.utils import Reporter
from jinja2 import Environment, pass_environment
@ -65,7 +65,7 @@ def default_role(docname: str, name: str) -> Generator[None, None, None]:
if name:
dummy_reporter = Reporter('', 4, 4)
role_fn, _ = roles.role(name, english, 0, dummy_reporter)
if role_fn: # type: ignore[truthy-function]
if role_fn:
docutils.register_role('', role_fn) # type: ignore[arg-type]
else:
logger.warning(__('default role %s not found'), name, location=docname)
@ -103,6 +103,7 @@ def append_epilog(content: StringList, epilog: str) -> None:
if epilog:
if len(content) > 0:
source, lineno = content.info(-1)
lineno = cast(int, lineno) # lineno will never be None, since len(content) > 0
else:
source = '<generated>'
lineno = 0

View File

@ -338,7 +338,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
self.depart_reference(node)
# overwritten -- we don't want source comments to show up in the HTML
def visit_comment(self, node: Element) -> None: # type: ignore[override]
def visit_comment(self, node: Element) -> None:
raise nodes.SkipNode
# overwritten

View File

@ -2121,7 +2121,7 @@ class LaTeXTranslator(SphinxTranslator):
self.body.append('}}$')
def visit_inline(self, node: Element) -> None:
classes = node.get('classes', [])
classes = node.get('classes', []) # type: ignore[var-annotated]
if classes == ['menuselection']:
self.body.append(r'\sphinxmenuselection{')
self.context.append('}')
@ -2153,12 +2153,12 @@ class LaTeXTranslator(SphinxTranslator):
pass
def visit_container(self, node: Element) -> None:
classes = node.get('classes', [])
classes = node.get('classes', []) # type: ignore[var-annotated]
for c in classes:
self.body.append('\n\\begin{sphinxuseclass}{%s}' % c)
def depart_container(self, node: Element) -> None:
classes = node.get('classes', [])
classes = node.get('classes', []) # type: ignore[var-annotated]
for _c in classes:
self.body.append('\n\\end{sphinxuseclass}')

View File

@ -245,7 +245,7 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator):
super().visit_term(node)
# overwritten -- we don't want source comments to show up
def visit_comment(self, node: Element) -> None: # type: ignore[override]
def visit_comment(self, node: Element) -> None:
raise nodes.SkipNode
# overwritten -- added ensure_eol()
@ -316,7 +316,7 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator):
self.body.append(self.defs['reference'][0])
# avoid repeating escaping code... fine since
# visit_Text calls astext() and only works on that afterwards
self.visit_Text(node) # type: ignore[arg-type]
self.visit_Text(node)
self.body.append(self.defs['reference'][1])
if uri.startswith(('mailto:', 'http:', 'https:', 'ftp:')):

View File

@ -281,7 +281,7 @@ class TexinfoTranslator(SphinxTranslator):
for name, content in self.indices]
# each section is also a node
for section in self.document.findall(nodes.section):
title = cast(nodes.TextElement, section.next_node(nodes.Titular))
title = cast(nodes.TextElement, section.next_node(nodes.Titular)) # type: ignore[type-var]
name = title.astext() if title else '<untitled>'
section['node_name'] = add_node_name(name)