xref: /qemu/docs/sphinx/compat.py (revision 1a0c090a5bb3f7bd526224cd166703d6c80ab1ee)
1"""
2Sphinx cross-version compatibility goop
3"""
4
5from typing import Callable
6
7from docutils.nodes import Element, Node, Text
8
9import sphinx
10from sphinx import addnodes
11from sphinx.util import nodes
12from sphinx.util.docutils import SphinxDirective, switch_source_input
13
14
15SpaceNode: Callable[[str], Node]
16KeywordNode: Callable[[str, str], Node]
17
18if sphinx.version_info[:3] >= (4, 0, 0):
19    SpaceNode = addnodes.desc_sig_space
20    KeywordNode = addnodes.desc_sig_keyword
21else:
22    SpaceNode = Text
23    KeywordNode = addnodes.desc_annotation
24
25
26def nested_parse_with_titles(
27    directive: SphinxDirective, content_node: Element
28) -> None:
29    """
30    This helper preserves error parsing context across sphinx versions.
31    """
32
33    # necessary so that the child nodes get the right source/line set
34    content_node.document = directive.state.document
35
36    try:
37        # Modern sphinx (6.2.0+) supports proper offsetting for
38        # nested parse error context management
39        nodes.nested_parse_with_titles(
40            directive.state,
41            directive.content,
42            content_node,
43            content_offset=directive.content_offset,
44        )
45    except TypeError:
46        # No content_offset argument. Fall back to SSI method.
47        with switch_source_input(directive.state, directive.content):
48            nodes.nested_parse_with_titles(
49                directive.state, directive.content, content_node
50            )
51