summaryrefslogtreecommitdiff
path: root/sphinx/util/nodes.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/util/nodes.py')
-rw-r--r--sphinx/util/nodes.py98
1 files changed, 38 insertions, 60 deletions
diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py
index 58c6a6698..e0aaaa14e 100644
--- a/sphinx/util/nodes.py
+++ b/sphinx/util/nodes.py
@@ -10,9 +10,14 @@
import re
import warnings
-from typing import Any, cast
+from typing import Any, Callable, Iterable, List, Set, Tuple, Type
+from typing import cast
from docutils import nodes
+from docutils.nodes import Element, Node
+from docutils.parsers.rst import Directive
+from docutils.parsers.rst.states import Inliner
+from docutils.statemachine import StringList
from sphinx import addnodes
from sphinx.deprecation import RemovedInSphinx40Warning
@@ -21,11 +26,8 @@ from sphinx.util import logging
if False:
# For type annotation
- from typing import Callable, Iterable, List, Optional, Set, Tuple, Type # NOQA
- from docutils.parsers.rst.states import Inliner # NOQA
- from docutils.statemachine import StringList # NOQA
- from sphinx.builders import Builder # NOQA
- from sphinx.utils.tags import Tags # NOQA
+ from sphinx.builders import Builder
+ from sphinx.utils.tags import Tags
logger = logging.getLogger(__name__)
@@ -57,13 +59,11 @@ class NodeMatcher:
# => [<reference ...>, <reference ...>, ...]
"""
- def __init__(self, *classes, **attrs):
- # type: (Type[nodes.Node], Any) -> None
+ def __init__(self, *classes: Type[Node], **attrs) -> None:
self.classes = classes
self.attrs = attrs
- def match(self, node):
- # type: (nodes.Node) -> bool
+ def match(self, node: Node) -> bool:
try:
if self.classes and not isinstance(node, self.classes):
return False
@@ -85,13 +85,11 @@ class NodeMatcher:
# for non-Element nodes
return False
- def __call__(self, node):
- # type: (nodes.Node) -> bool
+ def __call__(self, node: Node) -> bool:
return self.match(node)
-def get_full_module_name(node):
- # type: (nodes.Node) -> str
+def get_full_module_name(node: Node) -> str:
"""
return full module dotted path like: 'docutils.nodes.paragraph'
@@ -101,8 +99,7 @@ def get_full_module_name(node):
return '{}.{}'.format(node.__module__, node.__class__.__name__)
-def repr_domxml(node, length=80):
- # type: (nodes.Node, Optional[int]) -> str
+def repr_domxml(node: Node, length: int = 80) -> str:
"""
return DOM XML representation of the specified node like:
'<paragraph translatable="False"><inline classes="versionmodified">New in version...'
@@ -122,8 +119,7 @@ def repr_domxml(node, length=80):
return text
-def apply_source_workaround(node):
- # type: (nodes.Element) -> None
+def apply_source_workaround(node: Element) -> None:
# workaround: nodes.term have wrong rawsource if classifier is specified.
# The behavior of docutils-0.11, 0.12 is:
# * when ``term text : classifier1 : classifier2`` is specified,
@@ -186,8 +182,7 @@ IGNORED_NODES = (
)
-def is_pending_meta(node):
- # type: (nodes.Node) -> bool
+def is_pending_meta(node: Node) -> bool:
if (isinstance(node, nodes.pending) and
isinstance(node.details.get('nodes', [None])[0], addnodes.meta)):
return True
@@ -195,8 +190,7 @@ def is_pending_meta(node):
return False
-def is_translatable(node):
- # type: (nodes.Node) -> bool
+def is_translatable(node: Node) -> bool:
if isinstance(node, addnodes.translatable):
return True
@@ -251,8 +245,7 @@ META_TYPE_NODES = (
)
-def extract_messages(doctree):
- # type: (nodes.Element) -> Iterable[Tuple[nodes.Element, str]]
+def extract_messages(doctree: Element) -> Iterable[Tuple[Element, str]]:
"""Extract translatable messages from a document tree."""
for node in doctree.traverse(is_translatable): # type: nodes.Element
if isinstance(node, addnodes.translatable):
@@ -279,39 +272,34 @@ def extract_messages(doctree):
yield node, msg
-def find_source_node(node):
- # type: (nodes.Element) -> str
+def find_source_node(node: Element) -> str:
warnings.warn('find_source_node() is deprecated.',
RemovedInSphinx40Warning)
return get_node_source(node)
-def get_node_source(node):
- # type: (nodes.Element) -> str
+def get_node_source(node: Element) -> str:
for pnode in traverse_parent(node):
if pnode.source:
return pnode.source
return None
-def get_node_line(node):
- # type: (nodes.Element) -> int
+def get_node_line(node: Element) -> int:
for pnode in traverse_parent(node):
if pnode.line:
return pnode.line
return None
-def traverse_parent(node, cls=None):
- # type: (nodes.Element, Any) -> Iterable[nodes.Element]
+def traverse_parent(node: Element, cls: Any = None) -> Iterable[Element]:
while node:
if cls is None or isinstance(node, cls):
yield node
node = node.parent
-def get_prev_node(node):
- # type: (nodes.Node) -> nodes.Node
+def get_prev_node(node: Node) -> Node:
pos = node.parent.index(node)
if pos > 0:
return node.parent[pos - 1]
@@ -319,8 +307,7 @@ def get_prev_node(node):
return None
-def traverse_translatable_index(doctree):
- # type: (nodes.Element) -> Iterable[Tuple[nodes.Element, List[str]]]
+def traverse_translatable_index(doctree: Element) -> Iterable[Tuple[Element, List[str]]]:
"""Traverse translatable index node from a document tree."""
for node in doctree.traverse(NodeMatcher(addnodes.index, inline=False)): # type: addnodes.index # NOQA
if 'raw_entries' in node:
@@ -330,8 +317,7 @@ def traverse_translatable_index(doctree):
yield node, entries
-def nested_parse_with_titles(state, content, node):
- # type: (Any, StringList, nodes.Node) -> str
+def nested_parse_with_titles(state: Any, content: StringList, node: Node) -> str:
"""Version of state.nested_parse() that allows titles and does not require
titles to have the same decoration as the calling document.
@@ -350,8 +336,7 @@ def nested_parse_with_titles(state, content, node):
state.memo.section_level = surrounding_section_level
-def clean_astext(node):
- # type: (nodes.Element) -> str
+def clean_astext(node: Element) -> str:
"""Like node.astext(), but ignore images."""
node = node.deepcopy()
for img in node.traverse(nodes.image):
@@ -361,8 +346,7 @@ def clean_astext(node):
return node.astext()
-def split_explicit_title(text):
- # type: (str) -> Tuple[bool, str, str]
+def split_explicit_title(text: str) -> Tuple[bool, str, str]:
"""Split role content into title and target, if given."""
match = explicit_title_re.match(text)
if match:
@@ -375,8 +359,7 @@ indextypes = [
]
-def process_index_entry(entry, targetid):
- # type: (str, str) -> List[Tuple[str, str, str, str, str]]
+def process_index_entry(entry: str, targetid: str) -> List[Tuple[str, str, str, str, str]]:
from sphinx.domains.python import pairindextypes
indexentries = [] # type: List[Tuple[str, str, str, str, str]]
@@ -414,8 +397,9 @@ def process_index_entry(entry, targetid):
return indexentries
-def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc, traversed):
- # type: (Builder, Set[str], str, nodes.document, Callable, List[str]) -> nodes.document
+def inline_all_toctrees(builder: "Builder", docnameset: Set[str], docname: str,
+ tree: nodes.document, colorfunc: Callable, traversed: List[str]
+ ) -> nodes.document:
"""Inline all toctrees in the *tree*.
Record all docnames in *docnameset*, and output docnames with *colorfunc*.
@@ -447,8 +431,8 @@ def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc, traversed
return tree
-def make_refnode(builder, fromdocname, todocname, targetid, child, title=None):
- # type: (Builder, str, str, str, nodes.Node, str) -> nodes.reference
+def make_refnode(builder: "Builder", fromdocname: str, todocname: str, targetid: str,
+ child: Node, title: str = None) -> nodes.reference:
"""Shortcut to create a reference node."""
node = nodes.reference('', '', internal=True)
if fromdocname == todocname and targetid:
@@ -465,19 +449,16 @@ def make_refnode(builder, fromdocname, todocname, targetid, child, title=None):
return node
-def set_source_info(directive, node):
- # type: (Any, nodes.Node) -> None
+def set_source_info(directive: Directive, node: Node) -> None:
node.source, node.line = \
directive.state_machine.get_source_and_line(directive.lineno)
-def set_role_source_info(inliner, lineno, node):
- # type: (Inliner, int, nodes.Node) -> None
+def set_role_source_info(inliner: Inliner, lineno: int, node: Node) -> None:
node.source, node.line = inliner.reporter.get_source_and_line(lineno) # type: ignore
-def copy_source_info(src, dst):
- # type: (nodes.Element, nodes.Element) -> None
+def copy_source_info(src: Element, dst: Element) -> None:
dst.source = get_node_source(src)
dst.line = get_node_line(src)
@@ -493,8 +474,7 @@ NON_SMARTQUOTABLE_PARENT_NODES = (
)
-def is_smartquotable(node):
- # type: (nodes.Node) -> bool
+def is_smartquotable(node: Node) -> bool:
"""Check the node is smart-quotable or not."""
if isinstance(node.parent, NON_SMARTQUOTABLE_PARENT_NODES):
return False
@@ -506,8 +486,7 @@ def is_smartquotable(node):
return True
-def process_only_nodes(document, tags):
- # type: (nodes.Node, Tags) -> None
+def process_only_nodes(document: Node, tags: "Tags") -> None:
"""Filter ``only`` nodes which does not match *tags*."""
for node in document.traverse(addnodes.only):
try:
@@ -530,8 +509,7 @@ def process_only_nodes(document, tags):
# monkey-patch Element.copy to copy the rawsource and line
# for docutils-0.14 or older versions.
-def _new_copy(self):
- # type: (nodes.Element) -> nodes.Element
+def _new_copy(self: Element) -> Element:
newnode = self.__class__(self.rawsource, **self.attributes)
if isinstance(self, nodes.Element):
newnode.source = self.source