Sphinx 8.1.2__py3-none-any.whl → 8.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of Sphinx might be problematic. Click here for more details.
- sphinx/__init__.py +8 -4
- sphinx/__main__.py +2 -0
- sphinx/_cli/__init__.py +2 -5
- sphinx/_cli/util/colour.py +34 -11
- sphinx/_cli/util/errors.py +128 -61
- sphinx/addnodes.py +51 -35
- sphinx/application.py +362 -230
- sphinx/builders/__init__.py +87 -64
- sphinx/builders/_epub_base.py +65 -56
- sphinx/builders/changes.py +17 -23
- sphinx/builders/dirhtml.py +8 -13
- sphinx/builders/epub3.py +70 -38
- sphinx/builders/gettext.py +93 -73
- sphinx/builders/html/__init__.py +240 -186
- sphinx/builders/html/_assets.py +9 -2
- sphinx/builders/html/_build_info.py +3 -0
- sphinx/builders/latex/__init__.py +64 -54
- sphinx/builders/latex/constants.py +14 -11
- sphinx/builders/latex/nodes.py +2 -0
- sphinx/builders/latex/theming.py +8 -9
- sphinx/builders/latex/transforms.py +7 -5
- sphinx/builders/linkcheck.py +193 -149
- sphinx/builders/manpage.py +17 -17
- sphinx/builders/singlehtml.py +28 -16
- sphinx/builders/texinfo.py +28 -21
- sphinx/builders/text.py +10 -15
- sphinx/builders/xml.py +10 -19
- sphinx/cmd/build.py +49 -119
- sphinx/cmd/make_mode.py +35 -31
- sphinx/cmd/quickstart.py +78 -62
- sphinx/config.py +265 -163
- sphinx/directives/__init__.py +51 -54
- sphinx/directives/admonitions.py +107 -0
- sphinx/directives/code.py +24 -19
- sphinx/directives/other.py +21 -42
- sphinx/directives/patches.py +28 -16
- sphinx/domains/__init__.py +54 -31
- sphinx/domains/_domains_container.py +22 -17
- sphinx/domains/_index.py +5 -8
- sphinx/domains/c/__init__.py +366 -245
- sphinx/domains/c/_ast.py +378 -256
- sphinx/domains/c/_ids.py +89 -31
- sphinx/domains/c/_parser.py +283 -214
- sphinx/domains/c/_symbol.py +269 -198
- sphinx/domains/changeset.py +39 -24
- sphinx/domains/citation.py +54 -24
- sphinx/domains/cpp/__init__.py +517 -362
- sphinx/domains/cpp/_ast.py +999 -682
- sphinx/domains/cpp/_ids.py +133 -65
- sphinx/domains/cpp/_parser.py +746 -588
- sphinx/domains/cpp/_symbol.py +692 -489
- sphinx/domains/index.py +10 -8
- sphinx/domains/javascript.py +152 -74
- sphinx/domains/math.py +50 -40
- sphinx/domains/python/__init__.py +402 -211
- sphinx/domains/python/_annotations.py +134 -61
- sphinx/domains/python/_object.py +155 -68
- sphinx/domains/rst.py +94 -49
- sphinx/domains/std/__init__.py +510 -249
- sphinx/environment/__init__.py +345 -61
- sphinx/environment/adapters/asset.py +7 -1
- sphinx/environment/adapters/indexentries.py +15 -20
- sphinx/environment/adapters/toctree.py +19 -9
- sphinx/environment/collectors/__init__.py +3 -1
- sphinx/environment/collectors/asset.py +18 -15
- sphinx/environment/collectors/dependencies.py +8 -10
- sphinx/environment/collectors/metadata.py +6 -4
- sphinx/environment/collectors/title.py +3 -1
- sphinx/environment/collectors/toctree.py +4 -4
- sphinx/errors.py +1 -3
- sphinx/events.py +4 -4
- sphinx/ext/apidoc/__init__.py +66 -0
- sphinx/ext/apidoc/__main__.py +9 -0
- sphinx/ext/apidoc/_cli.py +356 -0
- sphinx/ext/apidoc/_extension.py +262 -0
- sphinx/ext/apidoc/_generate.py +356 -0
- sphinx/ext/apidoc/_shared.py +99 -0
- sphinx/ext/autodoc/__init__.py +837 -483
- sphinx/ext/autodoc/directive.py +57 -21
- sphinx/ext/autodoc/importer.py +184 -67
- sphinx/ext/autodoc/mock.py +25 -10
- sphinx/ext/autodoc/preserve_defaults.py +17 -9
- sphinx/ext/autodoc/type_comment.py +56 -29
- sphinx/ext/autodoc/typehints.py +49 -26
- sphinx/ext/autosectionlabel.py +28 -11
- sphinx/ext/autosummary/__init__.py +281 -142
- sphinx/ext/autosummary/generate.py +121 -51
- sphinx/ext/coverage.py +152 -91
- sphinx/ext/doctest.py +169 -101
- sphinx/ext/duration.py +12 -6
- sphinx/ext/extlinks.py +33 -21
- sphinx/ext/githubpages.py +8 -8
- sphinx/ext/graphviz.py +175 -109
- sphinx/ext/ifconfig.py +11 -6
- sphinx/ext/imgconverter.py +48 -25
- sphinx/ext/imgmath.py +127 -97
- sphinx/ext/inheritance_diagram.py +177 -103
- sphinx/ext/intersphinx/__init__.py +22 -13
- sphinx/ext/intersphinx/__main__.py +3 -1
- sphinx/ext/intersphinx/_cli.py +18 -14
- sphinx/ext/intersphinx/_load.py +91 -82
- sphinx/ext/intersphinx/_resolve.py +108 -74
- sphinx/ext/intersphinx/_shared.py +2 -2
- sphinx/ext/linkcode.py +28 -12
- sphinx/ext/mathjax.py +60 -29
- sphinx/ext/napoleon/__init__.py +19 -7
- sphinx/ext/napoleon/docstring.py +229 -231
- sphinx/ext/todo.py +44 -49
- sphinx/ext/viewcode.py +105 -57
- sphinx/extension.py +3 -1
- sphinx/highlighting.py +13 -7
- sphinx/io.py +9 -13
- sphinx/jinja2glue.py +29 -26
- sphinx/locale/__init__.py +8 -9
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +2155 -2050
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +2175 -2070
- sphinx/locale/ca/LC_MESSAGES/sphinx.js +3 -3
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +2690 -2585
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.js +63 -0
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.po +4216 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +2096 -1991
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +2248 -2143
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +2201 -2096
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +2282 -2177
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +2261 -2156
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +2604 -2499
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2631 -2526
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +2078 -1973
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +2633 -2528
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +2449 -2344
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +2241 -2136
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +504 -500
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr/LC_MESSAGES/sphinx.po +513 -509
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +2644 -2539
- sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +504 -500
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +501 -497
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +2609 -2504
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +2265 -2160
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +2621 -2516
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +2567 -2462
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +2631 -2526
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +2214 -2109
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +2218 -2113
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +2088 -1983
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2247 -2142
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +2227 -2122
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +2316 -2211
- sphinx/locale/pl/LC_MESSAGES/sphinx.js +2 -2
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +2442 -2336
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2657 -2552
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2243 -2138
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +2244 -2139
- sphinx/locale/ru/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +2660 -2555
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +2134 -2029
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +2614 -2509
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +2167 -2062
- sphinx/locale/sphinx.pot +2069 -1964
- sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sq/LC_MESSAGES/sphinx.po +2661 -2556
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +2213 -2108
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +2229 -2124
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +2608 -2503
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2167 -2062
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +2204 -2099
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +2659 -2554
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/parsers.py +8 -7
- sphinx/project.py +2 -2
- sphinx/pycode/__init__.py +31 -21
- sphinx/pycode/ast.py +6 -3
- sphinx/pycode/parser.py +14 -8
- sphinx/pygments_styles.py +4 -5
- sphinx/registry.py +192 -92
- sphinx/roles.py +58 -7
- sphinx/search/__init__.py +75 -54
- sphinx/search/en.py +11 -13
- sphinx/search/fi.py +1 -1
- sphinx/search/ja.py +8 -6
- sphinx/search/nl.py +1 -1
- sphinx/search/zh.py +19 -21
- sphinx/testing/fixtures.py +26 -29
- sphinx/testing/path.py +26 -62
- sphinx/testing/restructuredtext.py +14 -8
- sphinx/testing/util.py +21 -19
- sphinx/texinputs/make.bat.jinja +50 -50
- sphinx/texinputs/sphinx.sty +4 -3
- sphinx/texinputs/sphinxlatexadmonitions.sty +1 -1
- sphinx/texinputs/sphinxlatexobjects.sty +29 -10
- sphinx/themes/basic/static/searchtools.js +8 -5
- sphinx/theming.py +49 -61
- sphinx/transforms/__init__.py +17 -38
- sphinx/transforms/compact_bullet_list.py +5 -3
- sphinx/transforms/i18n.py +8 -21
- sphinx/transforms/post_transforms/__init__.py +142 -93
- sphinx/transforms/post_transforms/code.py +5 -5
- sphinx/transforms/post_transforms/images.py +28 -24
- sphinx/transforms/references.py +3 -1
- sphinx/util/__init__.py +109 -60
- sphinx/util/_files.py +39 -23
- sphinx/util/_importer.py +4 -1
- sphinx/util/_inventory_file_reader.py +76 -0
- sphinx/util/_io.py +2 -2
- sphinx/util/_lines.py +6 -3
- sphinx/util/_pathlib.py +40 -2
- sphinx/util/build_phase.py +2 -0
- sphinx/util/cfamily.py +19 -14
- sphinx/util/console.py +44 -179
- sphinx/util/display.py +9 -10
- sphinx/util/docfields.py +140 -122
- sphinx/util/docstrings.py +1 -1
- sphinx/util/docutils.py +118 -77
- sphinx/util/fileutil.py +25 -26
- sphinx/util/http_date.py +2 -0
- sphinx/util/i18n.py +77 -64
- sphinx/util/images.py +8 -6
- sphinx/util/inspect.py +147 -38
- sphinx/util/inventory.py +215 -116
- sphinx/util/logging.py +33 -33
- sphinx/util/matching.py +12 -4
- sphinx/util/nodes.py +18 -13
- sphinx/util/osutil.py +38 -39
- sphinx/util/parallel.py +22 -13
- sphinx/util/parsing.py +2 -1
- sphinx/util/png.py +6 -2
- sphinx/util/requests.py +33 -2
- sphinx/util/rst.py +3 -2
- sphinx/util/tags.py +1 -1
- sphinx/util/template.py +18 -10
- sphinx/util/texescape.py +8 -6
- sphinx/util/typing.py +148 -122
- sphinx/versioning.py +3 -3
- sphinx/writers/html.py +3 -1
- sphinx/writers/html5.py +63 -52
- sphinx/writers/latex.py +83 -67
- sphinx/writers/manpage.py +19 -38
- sphinx/writers/texinfo.py +47 -47
- sphinx/writers/text.py +50 -32
- sphinx/writers/xml.py +11 -8
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/LICENSE.rst +1 -1
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/METADATA +25 -15
- sphinx-8.2.0.dist-info/RECORD +606 -0
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/WHEEL +1 -1
- sphinx/builders/html/transforms.py +0 -90
- sphinx/ext/apidoc.py +0 -721
- sphinx/util/exceptions.py +0 -74
- sphinx-8.1.2.dist-info/RECORD +0 -598
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/entry_points.txt +0 -0
sphinx/domains/std/__init__.py
CHANGED
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import operator
|
|
5
6
|
import re
|
|
6
7
|
from copy import copy
|
|
7
|
-
from typing import TYPE_CHECKING,
|
|
8
|
+
from typing import TYPE_CHECKING, cast
|
|
8
9
|
|
|
9
10
|
from docutils import nodes
|
|
10
|
-
from docutils.
|
|
11
|
-
from docutils.parsers.rst import Directive, directives
|
|
11
|
+
from docutils.parsers.rst import directives
|
|
12
12
|
from docutils.statemachine import StringList
|
|
13
13
|
|
|
14
14
|
from sphinx import addnodes
|
|
15
|
-
from sphinx.addnodes import
|
|
15
|
+
from sphinx.addnodes import pending_xref
|
|
16
16
|
from sphinx.directives import ObjectDescription
|
|
17
17
|
from sphinx.domains import Domain, ObjType
|
|
18
18
|
from sphinx.locale import _, __
|
|
@@ -23,8 +23,13 @@ from sphinx.util.nodes import clean_astext, make_id, make_refnode
|
|
|
23
23
|
from sphinx.util.parsing import nested_parse_to_nodes
|
|
24
24
|
|
|
25
25
|
if TYPE_CHECKING:
|
|
26
|
-
from collections.abc import Callable, Iterable, Iterator, Set
|
|
26
|
+
from collections.abc import Callable, Iterable, Iterator, MutableSequence, Set
|
|
27
|
+
from typing import Any, ClassVar, Final
|
|
27
28
|
|
|
29
|
+
from docutils.nodes import Element, Node, system_message
|
|
30
|
+
from docutils.parsers.rst import Directive
|
|
31
|
+
|
|
32
|
+
from sphinx.addnodes import desc_signature
|
|
28
33
|
from sphinx.application import Sphinx
|
|
29
34
|
from sphinx.builders import Builder
|
|
30
35
|
from sphinx.environment import BuildEnvironment
|
|
@@ -46,9 +51,7 @@ samp_role = EmphasizedLiteral()
|
|
|
46
51
|
|
|
47
52
|
|
|
48
53
|
class GenericObject(ObjectDescription[str]):
|
|
49
|
-
"""
|
|
50
|
-
A generic x-ref directive registered with Sphinx.add_object_type().
|
|
51
|
-
"""
|
|
54
|
+
"""A generic x-ref directive registered with Sphinx.add_object_type()."""
|
|
52
55
|
|
|
53
56
|
indextemplate: str = ''
|
|
54
57
|
parse_node: Callable[[BuildEnvironment, str, desc_signature], str] | None = None
|
|
@@ -63,7 +66,9 @@ class GenericObject(ObjectDescription[str]):
|
|
|
63
66
|
name = ws_re.sub(' ', sig)
|
|
64
67
|
return name
|
|
65
68
|
|
|
66
|
-
def add_target_and_index(
|
|
69
|
+
def add_target_and_index(
|
|
70
|
+
self, name: str, sig: str, signode: desc_signature
|
|
71
|
+
) -> None:
|
|
67
72
|
node_id = make_id(self.env, self.state.document, self.objtype, name)
|
|
68
73
|
signode['ids'].append(node_id)
|
|
69
74
|
self.state.document.note_explicit_target(signode)
|
|
@@ -72,7 +77,7 @@ class GenericObject(ObjectDescription[str]):
|
|
|
72
77
|
colon = self.indextemplate.find(':')
|
|
73
78
|
if colon != -1:
|
|
74
79
|
indextype = self.indextemplate[:colon].strip()
|
|
75
|
-
indexentry = self.indextemplate[colon + 1:].strip() % (name,)
|
|
80
|
+
indexentry = self.indextemplate[colon + 1 :].strip() % (name,)
|
|
76
81
|
else:
|
|
77
82
|
indextype = 'single'
|
|
78
83
|
indexentry = self.indextemplate % (name,)
|
|
@@ -87,12 +92,15 @@ class EnvVar(GenericObject):
|
|
|
87
92
|
|
|
88
93
|
|
|
89
94
|
class EnvVarXRefRole(XRefRole):
|
|
90
|
-
"""
|
|
91
|
-
Cross-referencing role for environment variables (adds an index entry).
|
|
92
|
-
"""
|
|
95
|
+
"""Cross-referencing role for environment variables (adds an index entry)."""
|
|
93
96
|
|
|
94
|
-
def result_nodes(
|
|
95
|
-
|
|
97
|
+
def result_nodes(
|
|
98
|
+
self,
|
|
99
|
+
document: nodes.document,
|
|
100
|
+
env: BuildEnvironment,
|
|
101
|
+
node: Element,
|
|
102
|
+
is_ref: bool,
|
|
103
|
+
) -> tuple[list[Node], list[system_message]]:
|
|
96
104
|
if not is_ref:
|
|
97
105
|
return [node], []
|
|
98
106
|
varname = node['reftarget']
|
|
@@ -131,10 +139,12 @@ class ConfigurationValue(ObjectDescription[str]):
|
|
|
131
139
|
def _toc_entry_name(self, sig_node: desc_signature) -> str:
|
|
132
140
|
if not sig_node.get('_toc_parts'):
|
|
133
141
|
return ''
|
|
134
|
-
name, = sig_node['_toc_parts']
|
|
142
|
+
(name,) = sig_node['_toc_parts']
|
|
135
143
|
return name
|
|
136
144
|
|
|
137
|
-
def add_target_and_index(
|
|
145
|
+
def add_target_and_index(
|
|
146
|
+
self, name: str, sig: str, signode: desc_signature
|
|
147
|
+
) -> None:
|
|
138
148
|
node_id = make_id(self.env, self.state.document, self.objtype, name)
|
|
139
149
|
signode['ids'].append(node_id)
|
|
140
150
|
self.state.document.note_explicit_target(signode)
|
|
@@ -179,9 +189,7 @@ class ConfigurationValue(ObjectDescription[str]):
|
|
|
179
189
|
|
|
180
190
|
|
|
181
191
|
class Target(SphinxDirective):
|
|
182
|
-
"""
|
|
183
|
-
Generic target for user-defined cross-reference types.
|
|
184
|
-
"""
|
|
192
|
+
"""Generic target for user-defined cross-reference types."""
|
|
185
193
|
|
|
186
194
|
indextemplate = ''
|
|
187
195
|
|
|
@@ -205,7 +213,7 @@ class Target(SphinxDirective):
|
|
|
205
213
|
colon = indexentry.find(':')
|
|
206
214
|
if colon != -1:
|
|
207
215
|
indextype = indexentry[:colon].strip()
|
|
208
|
-
indexentry = indexentry[colon + 1:].strip()
|
|
216
|
+
indexentry = indexentry[colon + 1 :].strip()
|
|
209
217
|
inode = addnodes.index(entries=[(indextype, indexentry, node_id, '', None)])
|
|
210
218
|
ret.insert(0, inode)
|
|
211
219
|
name = self.name
|
|
@@ -219,9 +227,7 @@ class Target(SphinxDirective):
|
|
|
219
227
|
|
|
220
228
|
|
|
221
229
|
class Cmdoption(ObjectDescription[str]):
|
|
222
|
-
"""
|
|
223
|
-
Description of a command-line option (.. option).
|
|
224
|
-
"""
|
|
230
|
+
"""Description of a command-line option (.. option)."""
|
|
225
231
|
|
|
226
232
|
def handle_signature(self, sig: str, signode: desc_signature) -> str:
|
|
227
233
|
"""Transform an option description into RST nodes."""
|
|
@@ -231,10 +237,15 @@ class Cmdoption(ObjectDescription[str]):
|
|
|
231
237
|
potential_option = potential_option.strip()
|
|
232
238
|
m = option_desc_re.match(potential_option)
|
|
233
239
|
if not m:
|
|
234
|
-
logger.warning(
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
240
|
+
logger.warning(
|
|
241
|
+
__(
|
|
242
|
+
'Malformed option description %r, should '
|
|
243
|
+
'look like "opt", "-opt args", "--opt args", '
|
|
244
|
+
'"/opt args" or "+opt args"'
|
|
245
|
+
),
|
|
246
|
+
potential_option,
|
|
247
|
+
location=signode,
|
|
248
|
+
)
|
|
238
249
|
continue
|
|
239
250
|
optname, args = m.groups()
|
|
240
251
|
if optname[-1] == '[' and args[-1] == ']':
|
|
@@ -243,13 +254,13 @@ class Cmdoption(ObjectDescription[str]):
|
|
|
243
254
|
args = '[' + args
|
|
244
255
|
|
|
245
256
|
if count:
|
|
246
|
-
if self.
|
|
257
|
+
if self.config.option_emphasise_placeholders:
|
|
247
258
|
signode += addnodes.desc_sig_punctuation(',', ',')
|
|
248
259
|
signode += addnodes.desc_sig_space()
|
|
249
260
|
else:
|
|
250
261
|
signode += addnodes.desc_addname(', ', ', ')
|
|
251
262
|
signode += addnodes.desc_name(optname, optname)
|
|
252
|
-
if self.
|
|
263
|
+
if self.config.option_emphasise_placeholders:
|
|
253
264
|
add_end_bracket = False
|
|
254
265
|
if args:
|
|
255
266
|
if args[0] == '[' and args[-1] == ']':
|
|
@@ -281,7 +292,9 @@ class Cmdoption(ObjectDescription[str]):
|
|
|
281
292
|
raise ValueError
|
|
282
293
|
return firstname
|
|
283
294
|
|
|
284
|
-
def add_target_and_index(
|
|
295
|
+
def add_target_and_index(
|
|
296
|
+
self, firstname: str, sig: str, signode: desc_signature
|
|
297
|
+
) -> None:
|
|
285
298
|
currprogram = self.env.ref_context.get('std:program')
|
|
286
299
|
for optname in signode.get('allnames', []): # type: ignore[var-annotated]
|
|
287
300
|
prefixes = ['cmdoption']
|
|
@@ -296,24 +309,29 @@ class Cmdoption(ObjectDescription[str]):
|
|
|
296
309
|
self.state.document.note_explicit_target(signode)
|
|
297
310
|
|
|
298
311
|
domain = self.env.domains.standard_domain
|
|
299
|
-
for optname in signode.get('allnames',
|
|
300
|
-
domain.add_program_option(
|
|
301
|
-
|
|
312
|
+
for optname in signode.get('allnames', ()):
|
|
313
|
+
domain.add_program_option(
|
|
314
|
+
currprogram, optname, self.env.docname, signode['ids'][0]
|
|
315
|
+
)
|
|
302
316
|
|
|
303
317
|
# create an index entry
|
|
304
318
|
if currprogram:
|
|
305
319
|
descr = _('%s command line option') % currprogram
|
|
306
320
|
else:
|
|
307
321
|
descr = _('command line option')
|
|
308
|
-
for option in signode.get('allnames',
|
|
322
|
+
for option in signode.get('allnames', ()): # type: ignore[var-annotated]
|
|
309
323
|
entry = f'{descr}; {option}'
|
|
310
|
-
self.indexnode['entries'].append((
|
|
324
|
+
self.indexnode['entries'].append((
|
|
325
|
+
'pair',
|
|
326
|
+
entry,
|
|
327
|
+
signode['ids'][0],
|
|
328
|
+
'',
|
|
329
|
+
None,
|
|
330
|
+
))
|
|
311
331
|
|
|
312
332
|
|
|
313
333
|
class Program(SphinxDirective):
|
|
314
|
-
"""
|
|
315
|
-
Directive to name the program for which options are documented.
|
|
316
|
-
"""
|
|
334
|
+
"""Directive to name the program for which options are documented."""
|
|
317
335
|
|
|
318
336
|
has_content = False
|
|
319
337
|
required_arguments = 1
|
|
@@ -331,8 +349,14 @@ class Program(SphinxDirective):
|
|
|
331
349
|
|
|
332
350
|
|
|
333
351
|
class OptionXRefRole(XRefRole):
|
|
334
|
-
def process_link(
|
|
335
|
-
|
|
352
|
+
def process_link(
|
|
353
|
+
self,
|
|
354
|
+
env: BuildEnvironment,
|
|
355
|
+
refnode: Element,
|
|
356
|
+
has_explicit_title: bool,
|
|
357
|
+
title: str,
|
|
358
|
+
target: str,
|
|
359
|
+
) -> tuple[str, str]:
|
|
336
360
|
refnode['std:program'] = env.ref_context.get('std:program')
|
|
337
361
|
return title, target
|
|
338
362
|
|
|
@@ -348,9 +372,15 @@ def split_term_classifiers(line: str) -> tuple[str, str | None]:
|
|
|
348
372
|
return term, first_classifier
|
|
349
373
|
|
|
350
374
|
|
|
351
|
-
def make_glossary_term(
|
|
352
|
-
|
|
353
|
-
|
|
375
|
+
def make_glossary_term(
|
|
376
|
+
env: BuildEnvironment,
|
|
377
|
+
textnodes: Iterable[Node],
|
|
378
|
+
index_key: str | None,
|
|
379
|
+
source: str,
|
|
380
|
+
lineno: int,
|
|
381
|
+
node_id: str | None,
|
|
382
|
+
document: nodes.document,
|
|
383
|
+
) -> nodes.term:
|
|
354
384
|
# get a text-only representation of the term and register it
|
|
355
385
|
# as a cross-reference target
|
|
356
386
|
term = nodes.term('', '', *textnodes)
|
|
@@ -378,8 +408,7 @@ def make_glossary_term(env: BuildEnvironment, textnodes: Iterable[Node], index_k
|
|
|
378
408
|
|
|
379
409
|
|
|
380
410
|
class Glossary(SphinxDirective):
|
|
381
|
-
"""
|
|
382
|
-
Directive to create a glossary with cross-reference targets for :term:
|
|
411
|
+
"""Directive to create a glossary with cross-reference targets for :term:
|
|
383
412
|
roles.
|
|
384
413
|
"""
|
|
385
414
|
|
|
@@ -394,7 +423,7 @@ class Glossary(SphinxDirective):
|
|
|
394
423
|
def run(self) -> list[Node]:
|
|
395
424
|
node = addnodes.glossary()
|
|
396
425
|
node.document = self.state.document
|
|
397
|
-
node['sorted'] =
|
|
426
|
+
node['sorted'] = 'sorted' in self.options
|
|
398
427
|
|
|
399
428
|
# This directive implements a custom format of the reST definition list
|
|
400
429
|
# that allows multiple lines of terms before the definition. This is
|
|
@@ -407,7 +436,9 @@ class Glossary(SphinxDirective):
|
|
|
407
436
|
in_comment = False
|
|
408
437
|
was_empty = True
|
|
409
438
|
messages: list[Node] = []
|
|
410
|
-
for line, (source, lineno) in zip(
|
|
439
|
+
for line, (source, lineno) in zip(
|
|
440
|
+
self.content, self.content.items, strict=True
|
|
441
|
+
):
|
|
411
442
|
# empty line -> add to last definition
|
|
412
443
|
if not line:
|
|
413
444
|
if in_definition and entries:
|
|
@@ -425,23 +456,39 @@ class Glossary(SphinxDirective):
|
|
|
425
456
|
# first term of definition
|
|
426
457
|
if in_definition:
|
|
427
458
|
if not was_empty:
|
|
428
|
-
messages.append(
|
|
429
|
-
|
|
430
|
-
|
|
459
|
+
messages.append(
|
|
460
|
+
self.state.reporter.warning(
|
|
461
|
+
_('glossary term must be preceded by empty line'),
|
|
462
|
+
source=source,
|
|
463
|
+
line=lineno,
|
|
464
|
+
)
|
|
465
|
+
)
|
|
431
466
|
entries.append(([(line, source, lineno)], StringList()))
|
|
432
467
|
in_definition = False
|
|
433
468
|
# second term and following
|
|
434
469
|
else:
|
|
435
470
|
if was_empty:
|
|
436
|
-
messages.append(
|
|
437
|
-
|
|
438
|
-
|
|
471
|
+
messages.append(
|
|
472
|
+
self.state.reporter.warning(
|
|
473
|
+
_(
|
|
474
|
+
'glossary terms must not be separated by empty lines'
|
|
475
|
+
),
|
|
476
|
+
source=source,
|
|
477
|
+
line=lineno,
|
|
478
|
+
)
|
|
479
|
+
)
|
|
439
480
|
if entries:
|
|
440
481
|
entries[-1][0].append((line, source, lineno))
|
|
441
482
|
else:
|
|
442
|
-
messages.append(
|
|
443
|
-
|
|
444
|
-
|
|
483
|
+
messages.append(
|
|
484
|
+
self.state.reporter.warning(
|
|
485
|
+
_(
|
|
486
|
+
'glossary seems to be misformatted, check indentation'
|
|
487
|
+
),
|
|
488
|
+
source=source,
|
|
489
|
+
line=lineno,
|
|
490
|
+
)
|
|
491
|
+
)
|
|
445
492
|
elif in_comment:
|
|
446
493
|
pass
|
|
447
494
|
else:
|
|
@@ -452,9 +499,13 @@ class Glossary(SphinxDirective):
|
|
|
452
499
|
if entries:
|
|
453
500
|
entries[-1][1].append(line[indent_len:], source, lineno)
|
|
454
501
|
else:
|
|
455
|
-
messages.append(
|
|
456
|
-
|
|
457
|
-
|
|
502
|
+
messages.append(
|
|
503
|
+
self.state.reporter.warning(
|
|
504
|
+
_('glossary seems to be misformatted, check indentation'),
|
|
505
|
+
source=source,
|
|
506
|
+
line=lineno,
|
|
507
|
+
)
|
|
508
|
+
)
|
|
458
509
|
was_empty = False
|
|
459
510
|
|
|
460
511
|
# now, parse all the entries into a big definition list
|
|
@@ -469,9 +520,15 @@ class Glossary(SphinxDirective):
|
|
|
469
520
|
textnodes, sysmsg = self.parse_inline(term_, lineno=lineno)
|
|
470
521
|
|
|
471
522
|
# use first classifier as a index key
|
|
472
|
-
term = make_glossary_term(
|
|
473
|
-
|
|
474
|
-
|
|
523
|
+
term = make_glossary_term(
|
|
524
|
+
self.env,
|
|
525
|
+
textnodes,
|
|
526
|
+
first_classifier,
|
|
527
|
+
source,
|
|
528
|
+
lineno,
|
|
529
|
+
node_id=None,
|
|
530
|
+
document=self.state.document,
|
|
531
|
+
)
|
|
475
532
|
term.rawsource = line
|
|
476
533
|
system_messages.extend(sysmsg)
|
|
477
534
|
termnodes.append(term)
|
|
@@ -481,7 +538,10 @@ class Glossary(SphinxDirective):
|
|
|
481
538
|
if definition:
|
|
482
539
|
offset = definition.items[0][1]
|
|
483
540
|
definition_nodes = nested_parse_to_nodes(
|
|
484
|
-
self.state,
|
|
541
|
+
self.state,
|
|
542
|
+
definition,
|
|
543
|
+
offset=offset,
|
|
544
|
+
allow_section_headings=False,
|
|
485
545
|
)
|
|
486
546
|
else:
|
|
487
547
|
definition_nodes = []
|
|
@@ -494,14 +554,14 @@ class Glossary(SphinxDirective):
|
|
|
494
554
|
return [*messages, node]
|
|
495
555
|
|
|
496
556
|
|
|
497
|
-
def token_xrefs(text: str,
|
|
498
|
-
if len(
|
|
499
|
-
|
|
557
|
+
def token_xrefs(text: str, production_group: str = '') -> Iterable[Node]:
|
|
558
|
+
if len(production_group) != 0:
|
|
559
|
+
production_group += ':'
|
|
500
560
|
retnodes: list[Node] = []
|
|
501
561
|
pos = 0
|
|
502
562
|
for m in token_re.finditer(text):
|
|
503
563
|
if m.start() > pos:
|
|
504
|
-
txt = text[pos:m.start()]
|
|
564
|
+
txt = text[pos : m.start()]
|
|
505
565
|
retnodes.append(nodes.Text(txt))
|
|
506
566
|
token = m.group(1)
|
|
507
567
|
if ':' in token:
|
|
@@ -516,9 +576,10 @@ def token_xrefs(text: str, productionGroup: str = '') -> list[Node]:
|
|
|
516
576
|
target = token
|
|
517
577
|
else:
|
|
518
578
|
title = token
|
|
519
|
-
target =
|
|
520
|
-
refnode = pending_xref(
|
|
521
|
-
|
|
579
|
+
target = production_group + token
|
|
580
|
+
refnode = pending_xref(
|
|
581
|
+
title, reftype='token', refdomain='std', reftarget=target
|
|
582
|
+
)
|
|
522
583
|
refnode += nodes.literal(token, title, classes=['xref'])
|
|
523
584
|
retnodes.append(refnode)
|
|
524
585
|
pos = m.end()
|
|
@@ -528,9 +589,7 @@ def token_xrefs(text: str, productionGroup: str = '') -> list[Node]:
|
|
|
528
589
|
|
|
529
590
|
|
|
530
591
|
class ProductionList(SphinxDirective):
|
|
531
|
-
"""
|
|
532
|
-
Directive to list grammar productions.
|
|
533
|
-
"""
|
|
592
|
+
"""Directive to list grammar productions."""
|
|
534
593
|
|
|
535
594
|
has_content = False
|
|
536
595
|
required_arguments = 1
|
|
@@ -538,47 +597,117 @@ class ProductionList(SphinxDirective):
|
|
|
538
597
|
final_argument_whitespace = True
|
|
539
598
|
option_spec: ClassVar[OptionSpec] = {}
|
|
540
599
|
|
|
600
|
+
# The backslash handling is from ObjectDescription.get_signatures
|
|
601
|
+
_nl_escape_re: Final = re.compile(r'\\\n')
|
|
602
|
+
|
|
603
|
+
# Get 'name' from triples of rawsource, name, definition (tokens)
|
|
604
|
+
_name_getter = operator.itemgetter(1)
|
|
605
|
+
|
|
541
606
|
def run(self) -> list[Node]:
|
|
542
|
-
|
|
543
|
-
|
|
607
|
+
name_getter = self._name_getter
|
|
608
|
+
lines = self._nl_escape_re.sub('', self.arguments[0]).splitlines()
|
|
609
|
+
|
|
610
|
+
# Extract production_group argument.
|
|
611
|
+
# Must be before extracting production definition triples.
|
|
612
|
+
production_group = self.production_group(lines=lines, options=self.options)
|
|
613
|
+
production_lines = list(self.production_definitions(lines))
|
|
614
|
+
max_name_len = max(map(len, map(name_getter, production_lines)))
|
|
615
|
+
node_location = self.get_location()
|
|
616
|
+
|
|
617
|
+
productions = [
|
|
618
|
+
self.make_production(
|
|
619
|
+
rawsource=rule,
|
|
620
|
+
name=name,
|
|
621
|
+
tokens=tokens,
|
|
622
|
+
production_group=production_group,
|
|
623
|
+
max_len=max_name_len,
|
|
624
|
+
location=node_location,
|
|
625
|
+
)
|
|
626
|
+
for rule, name, tokens in production_lines
|
|
627
|
+
]
|
|
628
|
+
node = addnodes.productionlist('', *productions)
|
|
544
629
|
self.set_source_info(node)
|
|
545
|
-
# The backslash handling is from ObjectDescription.get_signatures
|
|
546
|
-
nl_escape_re = re.compile(r'\\\n')
|
|
547
|
-
lines = nl_escape_re.sub('', self.arguments[0]).split('\n')
|
|
548
|
-
|
|
549
|
-
productionGroup = ""
|
|
550
|
-
first_rule_seen = False
|
|
551
|
-
for rule in lines:
|
|
552
|
-
if not first_rule_seen and ':' not in rule:
|
|
553
|
-
productionGroup = rule.strip()
|
|
554
|
-
continue
|
|
555
|
-
first_rule_seen = True
|
|
556
|
-
try:
|
|
557
|
-
name, tokens = rule.split(':', 1)
|
|
558
|
-
except ValueError:
|
|
559
|
-
break
|
|
560
|
-
subnode = addnodes.production(rule)
|
|
561
|
-
name = name.strip()
|
|
562
|
-
subnode['tokenname'] = name
|
|
563
|
-
if subnode['tokenname']:
|
|
564
|
-
prefix = 'grammar-token-%s' % productionGroup
|
|
565
|
-
node_id = make_id(self.env, self.state.document, prefix, name)
|
|
566
|
-
subnode['ids'].append(node_id)
|
|
567
|
-
self.state.document.note_implicit_target(subnode, subnode)
|
|
568
|
-
|
|
569
|
-
if len(productionGroup) != 0:
|
|
570
|
-
objName = f"{productionGroup}:{name}"
|
|
571
|
-
else:
|
|
572
|
-
objName = name
|
|
573
|
-
domain.note_object('token', objName, node_id, location=node)
|
|
574
|
-
subnode.extend(token_xrefs(tokens, productionGroup))
|
|
575
|
-
node.append(subnode)
|
|
576
630
|
return [node]
|
|
577
631
|
|
|
632
|
+
@staticmethod
|
|
633
|
+
def production_group(
|
|
634
|
+
*,
|
|
635
|
+
lines: MutableSequence[str],
|
|
636
|
+
options: dict[str, Any], # NoQA: ARG004
|
|
637
|
+
) -> str:
|
|
638
|
+
# get production_group
|
|
639
|
+
if not lines or ':' in lines[0]:
|
|
640
|
+
return ''
|
|
641
|
+
production_group = lines[0].strip()
|
|
642
|
+
lines[:] = lines[1:]
|
|
643
|
+
return production_group
|
|
644
|
+
|
|
645
|
+
@staticmethod
|
|
646
|
+
def production_definitions(
|
|
647
|
+
lines: Iterable[str], /
|
|
648
|
+
) -> Iterator[tuple[str, str, str]]:
|
|
649
|
+
"""Yield triples of rawsource, name, definition (tokens)."""
|
|
650
|
+
for line in lines:
|
|
651
|
+
if ':' not in line:
|
|
652
|
+
break
|
|
653
|
+
name, _, tokens = line.partition(':')
|
|
654
|
+
yield line, name.strip(), tokens.strip()
|
|
655
|
+
|
|
656
|
+
def make_production(
|
|
657
|
+
self,
|
|
658
|
+
*,
|
|
659
|
+
rawsource: str,
|
|
660
|
+
name: str,
|
|
661
|
+
tokens: str,
|
|
662
|
+
production_group: str,
|
|
663
|
+
max_len: int,
|
|
664
|
+
location: str,
|
|
665
|
+
) -> addnodes.production:
|
|
666
|
+
production_node = addnodes.production(rawsource, tokenname=name)
|
|
667
|
+
if name:
|
|
668
|
+
production_node += self.make_name_target(
|
|
669
|
+
name=name, production_group=production_group, location=location
|
|
670
|
+
)
|
|
671
|
+
production_node.append(self.separator_node(name=name, max_len=max_len))
|
|
672
|
+
production_node += token_xrefs(text=tokens, production_group=production_group)
|
|
673
|
+
production_node.append(nodes.Text('\n'))
|
|
674
|
+
return production_node
|
|
675
|
+
|
|
676
|
+
def make_name_target(
|
|
677
|
+
self,
|
|
678
|
+
*,
|
|
679
|
+
name: str,
|
|
680
|
+
production_group: str,
|
|
681
|
+
location: str,
|
|
682
|
+
) -> addnodes.literal_strong:
|
|
683
|
+
"""Make a link target for the given production."""
|
|
684
|
+
name_node = addnodes.literal_strong(name, name)
|
|
685
|
+
prefix = f'grammar-token-{production_group}'
|
|
686
|
+
node_id = make_id(self.env, self.state.document, prefix, name)
|
|
687
|
+
name_node['ids'].append(node_id)
|
|
688
|
+
self.state.document.note_implicit_target(name_node, name_node)
|
|
689
|
+
obj_name = f'{production_group}:{name}' if production_group else name
|
|
690
|
+
std = self.env.domains.standard_domain
|
|
691
|
+
std.note_object('token', obj_name, node_id, location=location)
|
|
692
|
+
return name_node
|
|
693
|
+
|
|
694
|
+
@staticmethod
|
|
695
|
+
def separator_node(*, name: str, max_len: int) -> nodes.Text:
|
|
696
|
+
"""Return seperator between 'name' and 'tokens'."""
|
|
697
|
+
if name:
|
|
698
|
+
return nodes.Text(' ::= '.rjust(max_len - len(name) + 5))
|
|
699
|
+
return nodes.Text(' ' * (max_len + 5))
|
|
700
|
+
|
|
578
701
|
|
|
579
702
|
class TokenXRefRole(XRefRole):
|
|
580
|
-
def process_link(
|
|
581
|
-
|
|
703
|
+
def process_link(
|
|
704
|
+
self,
|
|
705
|
+
env: BuildEnvironment,
|
|
706
|
+
refnode: Element,
|
|
707
|
+
has_explicit_title: bool,
|
|
708
|
+
title: str,
|
|
709
|
+
target: str,
|
|
710
|
+
) -> tuple[str, str]:
|
|
582
711
|
target = target.lstrip('~') # a title-specific thing
|
|
583
712
|
if not self.has_explicit_title and title[0] == '~':
|
|
584
713
|
if ':' in title:
|
|
@@ -589,8 +718,7 @@ class TokenXRefRole(XRefRole):
|
|
|
589
718
|
|
|
590
719
|
|
|
591
720
|
class StandardDomain(Domain):
|
|
592
|
-
"""
|
|
593
|
-
Domain for all objects that don't fit into another domain or are added
|
|
721
|
+
"""Domain for all objects that don't fit into another domain or are added
|
|
594
722
|
via the application interface.
|
|
595
723
|
"""
|
|
596
724
|
|
|
@@ -600,8 +728,7 @@ class StandardDomain(Domain):
|
|
|
600
728
|
object_types: dict[str, ObjType] = {
|
|
601
729
|
'term': ObjType(_('glossary term'), 'term', searchprio=-1),
|
|
602
730
|
'token': ObjType(_('grammar token'), 'token', searchprio=-1),
|
|
603
|
-
'label': ObjType(_('reference label'), 'ref', 'keyword',
|
|
604
|
-
searchprio=-1),
|
|
731
|
+
'label': ObjType(_('reference label'), 'ref', 'keyword', searchprio=-1),
|
|
605
732
|
'confval': ObjType('configuration value', 'confval'),
|
|
606
733
|
'envvar': ObjType(_('environment variable'), 'envvar'),
|
|
607
734
|
'cmdoption': ObjType(_('program option'), 'option'),
|
|
@@ -618,42 +745,42 @@ class StandardDomain(Domain):
|
|
|
618
745
|
'productionlist': ProductionList,
|
|
619
746
|
}
|
|
620
747
|
roles: dict[str, RoleFunction | XRefRole] = {
|
|
621
|
-
'option':
|
|
748
|
+
'option': OptionXRefRole(warn_dangling=True),
|
|
622
749
|
'confval': XRefRole(warn_dangling=True),
|
|
623
|
-
'envvar':
|
|
750
|
+
'envvar': EnvVarXRefRole(),
|
|
624
751
|
# links to tokens in grammar productions
|
|
625
|
-
'token':
|
|
752
|
+
'token': TokenXRefRole(),
|
|
626
753
|
# links to terms in glossary
|
|
627
|
-
'term':
|
|
628
|
-
warn_dangling=True),
|
|
754
|
+
'term': XRefRole(innernodeclass=nodes.inline, warn_dangling=True),
|
|
629
755
|
# links to headings or arbitrary labels
|
|
630
|
-
'ref':
|
|
631
|
-
|
|
756
|
+
'ref': XRefRole(
|
|
757
|
+
lowercase=True, innernodeclass=nodes.inline, warn_dangling=True
|
|
758
|
+
),
|
|
632
759
|
# links to labels of numbered figures, tables and code-blocks
|
|
633
|
-
'numref':
|
|
634
|
-
warn_dangling=True),
|
|
760
|
+
'numref': XRefRole(lowercase=True, warn_dangling=True),
|
|
635
761
|
# links to labels, without a different title
|
|
636
762
|
'keyword': XRefRole(warn_dangling=True),
|
|
637
763
|
# links to documents
|
|
638
|
-
'doc':
|
|
764
|
+
'doc': XRefRole(warn_dangling=True, innernodeclass=nodes.inline),
|
|
639
765
|
}
|
|
640
766
|
|
|
641
767
|
initial_data: Final = { # type: ignore[misc]
|
|
642
|
-
'progoptions': {},
|
|
643
|
-
'objects': {},
|
|
644
|
-
'labels': {
|
|
768
|
+
'progoptions': {}, # (program, name) -> docname, labelid
|
|
769
|
+
'objects': {}, # (type, name) -> docname, labelid
|
|
770
|
+
'labels': { # labelname -> docname, labelid, sectionname
|
|
645
771
|
'genindex': ('genindex', '', _('Index')),
|
|
646
772
|
'modindex': ('py-modindex', '', _('Module Index')),
|
|
647
|
-
'search':
|
|
773
|
+
'search': ('search', '', _('Search Page')),
|
|
648
774
|
},
|
|
649
|
-
'anonlabels': {
|
|
775
|
+
'anonlabels': { # labelname -> docname, labelid
|
|
650
776
|
'genindex': ('genindex', ''),
|
|
651
777
|
'modindex': ('py-modindex', ''),
|
|
652
|
-
'search':
|
|
778
|
+
'search': ('search', ''),
|
|
653
779
|
},
|
|
654
780
|
}
|
|
655
781
|
|
|
656
|
-
|
|
782
|
+
# labelname -> docname, sectionname
|
|
783
|
+
_virtual_doc_names: dict[str, tuple[str, str]] = {
|
|
657
784
|
'genindex': ('genindex', _('Index')),
|
|
658
785
|
'modindex': ('py-modindex', _('Module Index')),
|
|
659
786
|
'search': ('search', _('Search Page')),
|
|
@@ -661,7 +788,7 @@ class StandardDomain(Domain):
|
|
|
661
788
|
|
|
662
789
|
dangling_warnings = {
|
|
663
790
|
'term': 'term not in glossary: %(target)r',
|
|
664
|
-
'numref':
|
|
791
|
+
'numref': 'undefined label: %(target)r',
|
|
665
792
|
'keyword': 'unknown keyword: %(target)r',
|
|
666
793
|
'doc': 'unknown document: %(target)r',
|
|
667
794
|
'option': 'unknown option: %(target)r',
|
|
@@ -678,12 +805,15 @@ class StandardDomain(Domain):
|
|
|
678
805
|
super().__init__(env)
|
|
679
806
|
|
|
680
807
|
# set up enumerable nodes
|
|
681
|
-
self.enumerable_nodes = copy(
|
|
682
|
-
|
|
808
|
+
self.enumerable_nodes = copy(
|
|
809
|
+
self.enumerable_nodes
|
|
810
|
+
) # create a copy for this instance
|
|
811
|
+
for node, settings in env._registry.enumerable_nodes.items():
|
|
683
812
|
self.enumerable_nodes[node] = settings
|
|
684
813
|
|
|
685
|
-
def note_hyperlink_target(
|
|
686
|
-
|
|
814
|
+
def note_hyperlink_target(
|
|
815
|
+
self, name: str, docname: str, node_id: str, title: str = ''
|
|
816
|
+
) -> None:
|
|
687
817
|
"""Add a hyperlink target for cross reference.
|
|
688
818
|
|
|
689
819
|
.. warning::
|
|
@@ -699,8 +829,11 @@ class StandardDomain(Domain):
|
|
|
699
829
|
.. versionadded:: 3.0
|
|
700
830
|
"""
|
|
701
831
|
if name in self.anonlabels and self.anonlabels[name] != (docname, node_id):
|
|
702
|
-
logger.warning(
|
|
703
|
-
|
|
832
|
+
logger.warning(
|
|
833
|
+
__('duplicate label %s, other instance in %s'),
|
|
834
|
+
name,
|
|
835
|
+
self.env.doc2path(self.anonlabels[name][0]),
|
|
836
|
+
)
|
|
704
837
|
|
|
705
838
|
self.anonlabels[name] = (docname, node_id)
|
|
706
839
|
if title:
|
|
@@ -708,18 +841,25 @@ class StandardDomain(Domain):
|
|
|
708
841
|
|
|
709
842
|
@property
|
|
710
843
|
def objects(self) -> dict[tuple[str, str], tuple[str, str]]:
|
|
711
|
-
|
|
844
|
+
# (objtype, name) -> docname, labelid
|
|
845
|
+
return self.data.setdefault('objects', {})
|
|
712
846
|
|
|
713
|
-
def note_object(
|
|
714
|
-
|
|
847
|
+
def note_object(
|
|
848
|
+
self, objtype: str, name: str, labelid: str, location: Any = None
|
|
849
|
+
) -> None:
|
|
715
850
|
"""Note a generic object for cross reference.
|
|
716
851
|
|
|
717
852
|
.. versionadded:: 3.0
|
|
718
853
|
"""
|
|
719
854
|
if (objtype, name) in self.objects:
|
|
720
855
|
docname = self.objects[objtype, name][0]
|
|
721
|
-
logger.warning(
|
|
722
|
-
|
|
856
|
+
logger.warning(
|
|
857
|
+
__('duplicate %s description of %s, other instance in %s'),
|
|
858
|
+
objtype,
|
|
859
|
+
name,
|
|
860
|
+
docname,
|
|
861
|
+
location=location,
|
|
862
|
+
)
|
|
723
863
|
self.objects[objtype, name] = (self.env.docname, labelid)
|
|
724
864
|
|
|
725
865
|
@property
|
|
@@ -738,33 +878,42 @@ class StandardDomain(Domain):
|
|
|
738
878
|
|
|
739
879
|
@property
|
|
740
880
|
def progoptions(self) -> dict[tuple[str | None, str], tuple[str, str]]:
|
|
741
|
-
return self.data.setdefault(
|
|
881
|
+
return self.data.setdefault(
|
|
882
|
+
'progoptions', {}
|
|
883
|
+
) # (program, name) -> docname, labelid
|
|
742
884
|
|
|
743
885
|
@property
|
|
744
886
|
def labels(self) -> dict[str, tuple[str, str, str]]:
|
|
745
|
-
return self.data.setdefault(
|
|
887
|
+
return self.data.setdefault(
|
|
888
|
+
'labels', {}
|
|
889
|
+
) # labelname -> docname, labelid, sectionname
|
|
746
890
|
|
|
747
891
|
@property
|
|
748
892
|
def anonlabels(self) -> dict[str, tuple[str, str]]:
|
|
749
893
|
return self.data.setdefault('anonlabels', {}) # labelname -> docname, labelid
|
|
750
894
|
|
|
751
895
|
def clear_doc(self, docname: str) -> None:
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
for
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
for key, (fn, _l
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
896
|
+
to_remove1 = [
|
|
897
|
+
key for key, (fn, _l) in self.progoptions.items() if fn == docname
|
|
898
|
+
]
|
|
899
|
+
for key1 in to_remove1:
|
|
900
|
+
del self.progoptions[key1]
|
|
901
|
+
|
|
902
|
+
to_remove2 = [key for key, (fn, _l) in self.objects.items() if fn == docname]
|
|
903
|
+
for key2 in to_remove2:
|
|
904
|
+
del self.objects[key2]
|
|
905
|
+
|
|
906
|
+
to_remove3 = [key for key, (fn, _l) in self._terms.items() if fn == docname]
|
|
907
|
+
for key3 in to_remove3:
|
|
908
|
+
del self._terms[key3]
|
|
909
|
+
|
|
910
|
+
to_remove3 = [key for key, (fn, _l, _l) in self.labels.items() if fn == docname]
|
|
911
|
+
for key3 in to_remove3:
|
|
912
|
+
del self.labels[key3]
|
|
913
|
+
|
|
914
|
+
to_remove3 = [key for key, (fn, _l) in self.anonlabels.items() if fn == docname]
|
|
915
|
+
for key3 in to_remove3:
|
|
916
|
+
del self.anonlabels[key3]
|
|
768
917
|
|
|
769
918
|
def merge_domaindata(self, docnames: Set[str], otherdata: dict[str, Any]) -> None:
|
|
770
919
|
# XXX duplicates?
|
|
@@ -785,7 +934,7 @@ class StandardDomain(Domain):
|
|
|
785
934
|
self.anonlabels[key] = data
|
|
786
935
|
|
|
787
936
|
def process_doc(
|
|
788
|
-
self, env: BuildEnvironment, docname: str, document: nodes.document
|
|
937
|
+
self, env: BuildEnvironment, docname: str, document: nodes.document
|
|
789
938
|
) -> None:
|
|
790
939
|
for name, explicit in document.nametypes.items():
|
|
791
940
|
if not explicit:
|
|
@@ -798,19 +947,24 @@ class StandardDomain(Domain):
|
|
|
798
947
|
# indirect hyperlink targets
|
|
799
948
|
node = document.ids.get(node['refid']) # type: ignore[assignment]
|
|
800
949
|
labelid = node['names'][0]
|
|
801
|
-
if (
|
|
802
|
-
|
|
803
|
-
|
|
950
|
+
if (
|
|
951
|
+
node.tagname == 'footnote'
|
|
952
|
+
or 'refuri' in node
|
|
953
|
+
or node.tagname.startswith('desc_')
|
|
954
|
+
):
|
|
804
955
|
# ignore footnote labels, labels automatically generated from a
|
|
805
956
|
# link and object descriptions
|
|
806
957
|
continue
|
|
807
958
|
if name in self.labels:
|
|
808
|
-
logger.warning(
|
|
809
|
-
|
|
810
|
-
|
|
959
|
+
logger.warning(
|
|
960
|
+
__('duplicate label %s, other instance in %s'),
|
|
961
|
+
name,
|
|
962
|
+
env.doc2path(self.labels[name][0]),
|
|
963
|
+
location=node,
|
|
964
|
+
)
|
|
811
965
|
self.anonlabels[name] = docname, labelid
|
|
812
966
|
if node.tagname == 'section':
|
|
813
|
-
title = cast(nodes.title, node[0])
|
|
967
|
+
title = cast('nodes.title', node[0])
|
|
814
968
|
sectname = clean_astext(title)
|
|
815
969
|
elif node.tagname == 'rubric':
|
|
816
970
|
sectname = clean_astext(node)
|
|
@@ -819,11 +973,13 @@ class StandardDomain(Domain):
|
|
|
819
973
|
if not sectname:
|
|
820
974
|
continue
|
|
821
975
|
else:
|
|
822
|
-
if (
|
|
823
|
-
|
|
824
|
-
|
|
976
|
+
if (
|
|
977
|
+
isinstance(node, nodes.definition_list | nodes.field_list)
|
|
978
|
+
and node.children
|
|
979
|
+
):
|
|
980
|
+
node = cast('nodes.Element', node.children[0])
|
|
825
981
|
if isinstance(node, nodes.field | nodes.definition_list_item):
|
|
826
|
-
node = cast(nodes.Element, node.children[0])
|
|
982
|
+
node = cast('nodes.Element', node.children[0])
|
|
827
983
|
if isinstance(node, nodes.term | nodes.field_name):
|
|
828
984
|
sectname = clean_astext(node)
|
|
829
985
|
else:
|
|
@@ -835,17 +991,26 @@ class StandardDomain(Domain):
|
|
|
835
991
|
continue
|
|
836
992
|
self.labels[name] = docname, labelid, sectname
|
|
837
993
|
|
|
838
|
-
def add_program_option(
|
|
839
|
-
|
|
994
|
+
def add_program_option(
|
|
995
|
+
self, program: str | None, name: str, docname: str, labelid: str
|
|
996
|
+
) -> None:
|
|
840
997
|
# prefer first command option entry
|
|
841
998
|
if (program, name) not in self.progoptions:
|
|
842
999
|
self.progoptions[program, name] = (docname, labelid)
|
|
843
1000
|
|
|
844
|
-
def build_reference_node(
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
1001
|
+
def build_reference_node(
|
|
1002
|
+
self,
|
|
1003
|
+
fromdocname: str,
|
|
1004
|
+
builder: Builder,
|
|
1005
|
+
docname: str,
|
|
1006
|
+
labelid: str,
|
|
1007
|
+
sectname: str,
|
|
1008
|
+
rolename: str,
|
|
1009
|
+
*,
|
|
1010
|
+
node_class: type[nodes.reference] = nodes.reference,
|
|
1011
|
+
**options: Any,
|
|
1012
|
+
) -> nodes.reference:
|
|
1013
|
+
newnode = node_class('', '', internal=True, **options)
|
|
849
1014
|
innernode = nodes.inline(sectname, sectname)
|
|
850
1015
|
if innernode.get('classes') is not None:
|
|
851
1016
|
innernode['classes'].append('std')
|
|
@@ -859,20 +1024,26 @@ class StandardDomain(Domain):
|
|
|
859
1024
|
contnode = pending_xref('')
|
|
860
1025
|
contnode['refdocname'] = docname
|
|
861
1026
|
contnode['refsectname'] = sectname
|
|
862
|
-
newnode['refuri'] = builder.get_relative_uri(
|
|
863
|
-
fromdocname, docname)
|
|
1027
|
+
newnode['refuri'] = builder.get_relative_uri(fromdocname, docname)
|
|
864
1028
|
if labelid:
|
|
865
1029
|
newnode['refuri'] += '#' + labelid
|
|
866
1030
|
newnode.append(innernode)
|
|
867
1031
|
return newnode
|
|
868
1032
|
|
|
869
|
-
def resolve_xref(
|
|
870
|
-
|
|
871
|
-
|
|
1033
|
+
def resolve_xref(
|
|
1034
|
+
self,
|
|
1035
|
+
env: BuildEnvironment,
|
|
1036
|
+
fromdocname: str,
|
|
1037
|
+
builder: Builder,
|
|
1038
|
+
typ: str,
|
|
1039
|
+
target: str,
|
|
1040
|
+
node: pending_xref,
|
|
1041
|
+
contnode: Element,
|
|
1042
|
+
) -> nodes.reference | None:
|
|
872
1043
|
if typ == 'ref':
|
|
873
1044
|
resolver = self._resolve_ref_xref
|
|
874
1045
|
elif typ == 'numref':
|
|
875
|
-
resolver = self._resolve_numref_xref
|
|
1046
|
+
resolver = self._resolve_numref_xref # type: ignore[assignment]
|
|
876
1047
|
elif typ == 'keyword':
|
|
877
1048
|
resolver = self._resolve_keyword_xref
|
|
878
1049
|
elif typ == 'doc':
|
|
@@ -886,9 +1057,16 @@ class StandardDomain(Domain):
|
|
|
886
1057
|
|
|
887
1058
|
return resolver(env, fromdocname, builder, typ, target, node, contnode)
|
|
888
1059
|
|
|
889
|
-
def _resolve_ref_xref(
|
|
890
|
-
|
|
891
|
-
|
|
1060
|
+
def _resolve_ref_xref(
|
|
1061
|
+
self,
|
|
1062
|
+
env: BuildEnvironment,
|
|
1063
|
+
fromdocname: str,
|
|
1064
|
+
builder: Builder,
|
|
1065
|
+
typ: str,
|
|
1066
|
+
target: str,
|
|
1067
|
+
node: pending_xref,
|
|
1068
|
+
contnode: Element,
|
|
1069
|
+
) -> nodes.reference | None:
|
|
892
1070
|
if node['refexplicit']:
|
|
893
1071
|
# reference to anonymous label; the reference uses
|
|
894
1072
|
# the supplied link caption
|
|
@@ -901,12 +1079,20 @@ class StandardDomain(Domain):
|
|
|
901
1079
|
if not docname:
|
|
902
1080
|
return None
|
|
903
1081
|
|
|
904
|
-
return self.build_reference_node(
|
|
905
|
-
|
|
1082
|
+
return self.build_reference_node(
|
|
1083
|
+
fromdocname, builder, docname, labelid, sectname, 'ref'
|
|
1084
|
+
)
|
|
906
1085
|
|
|
907
|
-
def _resolve_numref_xref(
|
|
908
|
-
|
|
909
|
-
|
|
1086
|
+
def _resolve_numref_xref(
|
|
1087
|
+
self,
|
|
1088
|
+
env: BuildEnvironment,
|
|
1089
|
+
fromdocname: str,
|
|
1090
|
+
builder: Builder,
|
|
1091
|
+
typ: str,
|
|
1092
|
+
target: str,
|
|
1093
|
+
node: pending_xref,
|
|
1094
|
+
contnode: Element,
|
|
1095
|
+
) -> nodes.reference | Element | None:
|
|
910
1096
|
if target in self.labels:
|
|
911
1097
|
docname, labelid, figname = self.labels.get(target, ('', '', ''))
|
|
912
1098
|
else:
|
|
@@ -923,7 +1109,9 @@ class StandardDomain(Domain):
|
|
|
923
1109
|
return None
|
|
924
1110
|
|
|
925
1111
|
if figtype != 'section' and env.config.numfig is False:
|
|
926
|
-
logger.warning(
|
|
1112
|
+
logger.warning(
|
|
1113
|
+
__('numfig is disabled. :numref: is ignored.'), location=node
|
|
1114
|
+
)
|
|
927
1115
|
return contnode
|
|
928
1116
|
|
|
929
1117
|
try:
|
|
@@ -931,9 +1119,13 @@ class StandardDomain(Domain):
|
|
|
931
1119
|
if fignumber is None:
|
|
932
1120
|
return contnode
|
|
933
1121
|
except ValueError:
|
|
934
|
-
logger.warning(
|
|
935
|
-
|
|
936
|
-
|
|
1122
|
+
logger.warning(
|
|
1123
|
+
__(
|
|
1124
|
+
'Failed to create a cross reference. Any number is not assigned: %s'
|
|
1125
|
+
),
|
|
1126
|
+
labelid,
|
|
1127
|
+
location=node,
|
|
1128
|
+
)
|
|
937
1129
|
return contnode
|
|
938
1130
|
|
|
939
1131
|
try:
|
|
@@ -957,30 +1149,51 @@ class StandardDomain(Domain):
|
|
|
957
1149
|
# old style format (cf. "Fig.%s")
|
|
958
1150
|
newtitle = title % fignum
|
|
959
1151
|
except KeyError as exc:
|
|
960
|
-
logger.warning(
|
|
1152
|
+
logger.warning(
|
|
1153
|
+
__('invalid numfig_format: %s (%r)'), title, exc, location=node
|
|
1154
|
+
)
|
|
961
1155
|
return contnode
|
|
962
1156
|
except TypeError:
|
|
963
1157
|
logger.warning(__('invalid numfig_format: %s'), title, location=node)
|
|
964
1158
|
return contnode
|
|
965
1159
|
|
|
966
|
-
return self.build_reference_node(
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1160
|
+
return self.build_reference_node(
|
|
1161
|
+
fromdocname,
|
|
1162
|
+
builder,
|
|
1163
|
+
docname,
|
|
1164
|
+
labelid,
|
|
1165
|
+
newtitle,
|
|
1166
|
+
'numref',
|
|
1167
|
+
node_class=addnodes.number_reference,
|
|
1168
|
+
title=title,
|
|
1169
|
+
)
|
|
970
1170
|
|
|
971
|
-
def _resolve_keyword_xref(
|
|
972
|
-
|
|
973
|
-
|
|
1171
|
+
def _resolve_keyword_xref(
|
|
1172
|
+
self,
|
|
1173
|
+
env: BuildEnvironment,
|
|
1174
|
+
fromdocname: str,
|
|
1175
|
+
builder: Builder,
|
|
1176
|
+
typ: str,
|
|
1177
|
+
target: str,
|
|
1178
|
+
node: pending_xref,
|
|
1179
|
+
contnode: Element,
|
|
1180
|
+
) -> nodes.reference | None:
|
|
974
1181
|
# keywords are oddballs: they are referenced by named labels
|
|
975
1182
|
docname, labelid, _ = self.labels.get(target, ('', '', ''))
|
|
976
1183
|
if not docname:
|
|
977
1184
|
return None
|
|
978
|
-
return make_refnode(builder, fromdocname, docname,
|
|
979
|
-
labelid, contnode)
|
|
1185
|
+
return make_refnode(builder, fromdocname, docname, labelid, contnode)
|
|
980
1186
|
|
|
981
|
-
def _resolve_doc_xref(
|
|
982
|
-
|
|
983
|
-
|
|
1187
|
+
def _resolve_doc_xref(
|
|
1188
|
+
self,
|
|
1189
|
+
env: BuildEnvironment,
|
|
1190
|
+
fromdocname: str,
|
|
1191
|
+
builder: Builder,
|
|
1192
|
+
typ: str,
|
|
1193
|
+
target: str,
|
|
1194
|
+
node: pending_xref,
|
|
1195
|
+
contnode: Element,
|
|
1196
|
+
) -> nodes.reference | None:
|
|
984
1197
|
# directly reference to document by source name; can be absolute or relative
|
|
985
1198
|
refdoc = node.get('refdoc', fromdocname)
|
|
986
1199
|
docname = docname_join(refdoc, node['reftarget'])
|
|
@@ -995,9 +1208,16 @@ class StandardDomain(Domain):
|
|
|
995
1208
|
innernode = nodes.inline(caption, caption, classes=['doc'])
|
|
996
1209
|
return make_refnode(builder, fromdocname, docname, None, innernode)
|
|
997
1210
|
|
|
998
|
-
def _resolve_option_xref(
|
|
999
|
-
|
|
1000
|
-
|
|
1211
|
+
def _resolve_option_xref(
|
|
1212
|
+
self,
|
|
1213
|
+
env: BuildEnvironment,
|
|
1214
|
+
fromdocname: str,
|
|
1215
|
+
builder: Builder,
|
|
1216
|
+
typ: str,
|
|
1217
|
+
target: str,
|
|
1218
|
+
node: pending_xref,
|
|
1219
|
+
contnode: Element,
|
|
1220
|
+
) -> nodes.reference | None:
|
|
1001
1221
|
progname = node.get('std:program')
|
|
1002
1222
|
target = target.strip()
|
|
1003
1223
|
docname, labelid = self.progoptions.get((progname, target), ('', ''))
|
|
@@ -1017,7 +1237,7 @@ class StandardDomain(Domain):
|
|
|
1017
1237
|
while ws_re.search(target):
|
|
1018
1238
|
subcommand, target = ws_re.split(target, 1)
|
|
1019
1239
|
commands.append(subcommand)
|
|
1020
|
-
progname =
|
|
1240
|
+
progname = '-'.join(commands)
|
|
1021
1241
|
|
|
1022
1242
|
docname, labelid = self.progoptions.get((progname, target), ('', ''))
|
|
1023
1243
|
if docname:
|
|
@@ -1025,14 +1245,21 @@ class StandardDomain(Domain):
|
|
|
1025
1245
|
else:
|
|
1026
1246
|
return None
|
|
1027
1247
|
|
|
1028
|
-
return make_refnode(builder, fromdocname, docname,
|
|
1029
|
-
labelid, contnode)
|
|
1248
|
+
return make_refnode(builder, fromdocname, docname, labelid, contnode)
|
|
1030
1249
|
|
|
1031
|
-
def _resolve_term_xref(
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1250
|
+
def _resolve_term_xref(
|
|
1251
|
+
self,
|
|
1252
|
+
env: BuildEnvironment,
|
|
1253
|
+
fromdocname: str,
|
|
1254
|
+
builder: Builder,
|
|
1255
|
+
typ: str,
|
|
1256
|
+
target: str,
|
|
1257
|
+
node: pending_xref,
|
|
1258
|
+
contnode: Element,
|
|
1259
|
+
) -> nodes.reference | None:
|
|
1260
|
+
result = self._resolve_obj_xref(
|
|
1261
|
+
env, fromdocname, builder, typ, target, node, contnode
|
|
1262
|
+
)
|
|
1036
1263
|
if result:
|
|
1037
1264
|
return result
|
|
1038
1265
|
else:
|
|
@@ -1043,9 +1270,16 @@ class StandardDomain(Domain):
|
|
|
1043
1270
|
else:
|
|
1044
1271
|
return None
|
|
1045
1272
|
|
|
1046
|
-
def _resolve_obj_xref(
|
|
1047
|
-
|
|
1048
|
-
|
|
1273
|
+
def _resolve_obj_xref(
|
|
1274
|
+
self,
|
|
1275
|
+
env: BuildEnvironment,
|
|
1276
|
+
fromdocname: str,
|
|
1277
|
+
builder: Builder,
|
|
1278
|
+
typ: str,
|
|
1279
|
+
target: str,
|
|
1280
|
+
node: pending_xref,
|
|
1281
|
+
contnode: Element,
|
|
1282
|
+
) -> nodes.reference | None:
|
|
1049
1283
|
objtypes = self.objtypes_for_role(typ) or []
|
|
1050
1284
|
for objtype in objtypes:
|
|
1051
1285
|
if (objtype, target) in self.objects:
|
|
@@ -1055,18 +1289,29 @@ class StandardDomain(Domain):
|
|
|
1055
1289
|
docname, labelid = '', ''
|
|
1056
1290
|
if not docname:
|
|
1057
1291
|
return None
|
|
1058
|
-
return make_refnode(builder, fromdocname, docname,
|
|
1059
|
-
labelid, contnode)
|
|
1292
|
+
return make_refnode(builder, fromdocname, docname, labelid, contnode)
|
|
1060
1293
|
|
|
1061
|
-
def resolve_any_xref(
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1294
|
+
def resolve_any_xref(
|
|
1295
|
+
self,
|
|
1296
|
+
env: BuildEnvironment,
|
|
1297
|
+
fromdocname: str,
|
|
1298
|
+
builder: Builder,
|
|
1299
|
+
target: str,
|
|
1300
|
+
node: pending_xref,
|
|
1301
|
+
contnode: Element,
|
|
1302
|
+
) -> list[tuple[str, nodes.reference]]:
|
|
1303
|
+
results: list[tuple[str, nodes.reference]] = []
|
|
1065
1304
|
ltarget = target.lower() # :ref: lowercases its target automatically
|
|
1066
1305
|
for role in ('ref', 'option'): # do not try "keyword"
|
|
1067
|
-
res = self.resolve_xref(
|
|
1068
|
-
|
|
1069
|
-
|
|
1306
|
+
res = self.resolve_xref(
|
|
1307
|
+
env,
|
|
1308
|
+
fromdocname,
|
|
1309
|
+
builder,
|
|
1310
|
+
role,
|
|
1311
|
+
ltarget if role == 'ref' else target,
|
|
1312
|
+
node,
|
|
1313
|
+
contnode,
|
|
1314
|
+
)
|
|
1070
1315
|
if res:
|
|
1071
1316
|
results.append(('std:' + role, res))
|
|
1072
1317
|
# all others
|
|
@@ -1077,30 +1322,38 @@ class StandardDomain(Domain):
|
|
|
1077
1322
|
if key in self.objects:
|
|
1078
1323
|
docname, labelid = self.objects[key]
|
|
1079
1324
|
role = 'std:' + self.role_for_objtype(objtype) # type: ignore[operator]
|
|
1080
|
-
results.append((
|
|
1081
|
-
|
|
1325
|
+
results.append((
|
|
1326
|
+
role,
|
|
1327
|
+
make_refnode(builder, fromdocname, docname, labelid, contnode),
|
|
1328
|
+
))
|
|
1082
1329
|
return results
|
|
1083
1330
|
|
|
1084
1331
|
def get_objects(self) -> Iterator[tuple[str, str, str, str, str, int]]:
|
|
1085
1332
|
# handle the special 'doc' reference here
|
|
1086
1333
|
for doc in self.env.all_docs:
|
|
1087
|
-
yield
|
|
1334
|
+
yield doc, clean_astext(self.env.titles[doc]), 'doc', doc, '', -1
|
|
1088
1335
|
for (prog, option), info in self.progoptions.items():
|
|
1089
1336
|
if prog:
|
|
1090
1337
|
fullname = f'{prog}.{option}'
|
|
1091
|
-
yield
|
|
1338
|
+
yield fullname, fullname, 'cmdoption', info[0], info[1], 1
|
|
1092
1339
|
else:
|
|
1093
|
-
yield
|
|
1340
|
+
yield option, option, 'cmdoption', info[0], info[1], 1
|
|
1094
1341
|
for (type, name), info in self.objects.items():
|
|
1095
|
-
yield (
|
|
1096
|
-
|
|
1342
|
+
yield (
|
|
1343
|
+
name,
|
|
1344
|
+
name,
|
|
1345
|
+
type,
|
|
1346
|
+
info[0],
|
|
1347
|
+
info[1],
|
|
1348
|
+
self.object_types[type].attrs['searchprio'],
|
|
1349
|
+
)
|
|
1097
1350
|
for name, (docname, labelid, sectionname) in self.labels.items():
|
|
1098
|
-
yield
|
|
1351
|
+
yield name, sectionname, 'label', docname, labelid, -1
|
|
1099
1352
|
# add anonymous-only labels as well
|
|
1100
1353
|
non_anon_labels = set(self.labels)
|
|
1101
1354
|
for name, (docname, labelid) in self.anonlabels.items():
|
|
1102
1355
|
if name not in non_anon_labels:
|
|
1103
|
-
yield
|
|
1356
|
+
yield name, name, 'label', docname, labelid, -1
|
|
1104
1357
|
|
|
1105
1358
|
def get_type_name(self, type: ObjType, primary: bool = False) -> str:
|
|
1106
1359
|
# never prepend "Default"
|
|
@@ -1112,7 +1365,7 @@ class StandardDomain(Domain):
|
|
|
1112
1365
|
def get_numfig_title(self, node: Node) -> str | None:
|
|
1113
1366
|
"""Get the title of enumerable nodes to refer them using its title"""
|
|
1114
1367
|
if self.is_enumerable_node(node):
|
|
1115
|
-
elem = cast(Element, node)
|
|
1368
|
+
elem = cast('Element', node)
|
|
1116
1369
|
_, title_getter = self.enumerable_nodes.get(elem.__class__, (None, None))
|
|
1117
1370
|
if title_getter:
|
|
1118
1371
|
return title_getter(elem)
|
|
@@ -1125,14 +1378,17 @@ class StandardDomain(Domain):
|
|
|
1125
1378
|
|
|
1126
1379
|
def get_enumerable_node_type(self, node: Node) -> str | None:
|
|
1127
1380
|
"""Get type of enumerable nodes."""
|
|
1381
|
+
|
|
1128
1382
|
def has_child(node: Element, cls: type) -> bool:
|
|
1129
1383
|
return any(isinstance(child, cls) for child in node)
|
|
1130
1384
|
|
|
1131
1385
|
if isinstance(node, nodes.section):
|
|
1132
1386
|
return 'section'
|
|
1133
|
-
elif (
|
|
1134
|
-
|
|
1135
|
-
|
|
1387
|
+
elif (
|
|
1388
|
+
isinstance(node, nodes.container)
|
|
1389
|
+
and 'literal_block' in node
|
|
1390
|
+
and has_child(node, nodes.literal_block)
|
|
1391
|
+
):
|
|
1136
1392
|
# given node is a code-block having caption
|
|
1137
1393
|
return 'code-block'
|
|
1138
1394
|
else:
|
|
@@ -1184,8 +1440,11 @@ class StandardDomain(Domain):
|
|
|
1184
1440
|
return None
|
|
1185
1441
|
|
|
1186
1442
|
|
|
1187
|
-
def warn_missing_reference(
|
|
1188
|
-
|
|
1443
|
+
def warn_missing_reference(
|
|
1444
|
+
app: Sphinx,
|
|
1445
|
+
domain: Domain,
|
|
1446
|
+
node: pending_xref,
|
|
1447
|
+
) -> bool | None:
|
|
1189
1448
|
if (domain and domain.name != 'std') or node['reftype'] != 'ref':
|
|
1190
1449
|
return None
|
|
1191
1450
|
else:
|
|
@@ -1193,7 +1452,9 @@ def warn_missing_reference(app: Sphinx, domain: Domain, node: pending_xref,
|
|
|
1193
1452
|
if target not in domain.anonlabels: # type: ignore[attr-defined]
|
|
1194
1453
|
msg = __('undefined label: %r')
|
|
1195
1454
|
else:
|
|
1196
|
-
msg = __(
|
|
1455
|
+
msg = __(
|
|
1456
|
+
'Failed to create a cross reference. A title or caption not found: %r'
|
|
1457
|
+
)
|
|
1197
1458
|
|
|
1198
1459
|
logger.warning(msg, target, location=node, type='ref', subtype=node['reftype'])
|
|
1199
1460
|
return True
|