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.

Files changed (328) hide show
  1. sphinx/__init__.py +8 -4
  2. sphinx/__main__.py +2 -0
  3. sphinx/_cli/__init__.py +2 -5
  4. sphinx/_cli/util/colour.py +34 -11
  5. sphinx/_cli/util/errors.py +128 -61
  6. sphinx/addnodes.py +51 -35
  7. sphinx/application.py +362 -230
  8. sphinx/builders/__init__.py +87 -64
  9. sphinx/builders/_epub_base.py +65 -56
  10. sphinx/builders/changes.py +17 -23
  11. sphinx/builders/dirhtml.py +8 -13
  12. sphinx/builders/epub3.py +70 -38
  13. sphinx/builders/gettext.py +93 -73
  14. sphinx/builders/html/__init__.py +240 -186
  15. sphinx/builders/html/_assets.py +9 -2
  16. sphinx/builders/html/_build_info.py +3 -0
  17. sphinx/builders/latex/__init__.py +64 -54
  18. sphinx/builders/latex/constants.py +14 -11
  19. sphinx/builders/latex/nodes.py +2 -0
  20. sphinx/builders/latex/theming.py +8 -9
  21. sphinx/builders/latex/transforms.py +7 -5
  22. sphinx/builders/linkcheck.py +193 -149
  23. sphinx/builders/manpage.py +17 -17
  24. sphinx/builders/singlehtml.py +28 -16
  25. sphinx/builders/texinfo.py +28 -21
  26. sphinx/builders/text.py +10 -15
  27. sphinx/builders/xml.py +10 -19
  28. sphinx/cmd/build.py +49 -119
  29. sphinx/cmd/make_mode.py +35 -31
  30. sphinx/cmd/quickstart.py +78 -62
  31. sphinx/config.py +265 -163
  32. sphinx/directives/__init__.py +51 -54
  33. sphinx/directives/admonitions.py +107 -0
  34. sphinx/directives/code.py +24 -19
  35. sphinx/directives/other.py +21 -42
  36. sphinx/directives/patches.py +28 -16
  37. sphinx/domains/__init__.py +54 -31
  38. sphinx/domains/_domains_container.py +22 -17
  39. sphinx/domains/_index.py +5 -8
  40. sphinx/domains/c/__init__.py +366 -245
  41. sphinx/domains/c/_ast.py +378 -256
  42. sphinx/domains/c/_ids.py +89 -31
  43. sphinx/domains/c/_parser.py +283 -214
  44. sphinx/domains/c/_symbol.py +269 -198
  45. sphinx/domains/changeset.py +39 -24
  46. sphinx/domains/citation.py +54 -24
  47. sphinx/domains/cpp/__init__.py +517 -362
  48. sphinx/domains/cpp/_ast.py +999 -682
  49. sphinx/domains/cpp/_ids.py +133 -65
  50. sphinx/domains/cpp/_parser.py +746 -588
  51. sphinx/domains/cpp/_symbol.py +692 -489
  52. sphinx/domains/index.py +10 -8
  53. sphinx/domains/javascript.py +152 -74
  54. sphinx/domains/math.py +50 -40
  55. sphinx/domains/python/__init__.py +402 -211
  56. sphinx/domains/python/_annotations.py +134 -61
  57. sphinx/domains/python/_object.py +155 -68
  58. sphinx/domains/rst.py +94 -49
  59. sphinx/domains/std/__init__.py +510 -249
  60. sphinx/environment/__init__.py +345 -61
  61. sphinx/environment/adapters/asset.py +7 -1
  62. sphinx/environment/adapters/indexentries.py +15 -20
  63. sphinx/environment/adapters/toctree.py +19 -9
  64. sphinx/environment/collectors/__init__.py +3 -1
  65. sphinx/environment/collectors/asset.py +18 -15
  66. sphinx/environment/collectors/dependencies.py +8 -10
  67. sphinx/environment/collectors/metadata.py +6 -4
  68. sphinx/environment/collectors/title.py +3 -1
  69. sphinx/environment/collectors/toctree.py +4 -4
  70. sphinx/errors.py +1 -3
  71. sphinx/events.py +4 -4
  72. sphinx/ext/apidoc/__init__.py +66 -0
  73. sphinx/ext/apidoc/__main__.py +9 -0
  74. sphinx/ext/apidoc/_cli.py +356 -0
  75. sphinx/ext/apidoc/_extension.py +262 -0
  76. sphinx/ext/apidoc/_generate.py +356 -0
  77. sphinx/ext/apidoc/_shared.py +99 -0
  78. sphinx/ext/autodoc/__init__.py +837 -483
  79. sphinx/ext/autodoc/directive.py +57 -21
  80. sphinx/ext/autodoc/importer.py +184 -67
  81. sphinx/ext/autodoc/mock.py +25 -10
  82. sphinx/ext/autodoc/preserve_defaults.py +17 -9
  83. sphinx/ext/autodoc/type_comment.py +56 -29
  84. sphinx/ext/autodoc/typehints.py +49 -26
  85. sphinx/ext/autosectionlabel.py +28 -11
  86. sphinx/ext/autosummary/__init__.py +281 -142
  87. sphinx/ext/autosummary/generate.py +121 -51
  88. sphinx/ext/coverage.py +152 -91
  89. sphinx/ext/doctest.py +169 -101
  90. sphinx/ext/duration.py +12 -6
  91. sphinx/ext/extlinks.py +33 -21
  92. sphinx/ext/githubpages.py +8 -8
  93. sphinx/ext/graphviz.py +175 -109
  94. sphinx/ext/ifconfig.py +11 -6
  95. sphinx/ext/imgconverter.py +48 -25
  96. sphinx/ext/imgmath.py +127 -97
  97. sphinx/ext/inheritance_diagram.py +177 -103
  98. sphinx/ext/intersphinx/__init__.py +22 -13
  99. sphinx/ext/intersphinx/__main__.py +3 -1
  100. sphinx/ext/intersphinx/_cli.py +18 -14
  101. sphinx/ext/intersphinx/_load.py +91 -82
  102. sphinx/ext/intersphinx/_resolve.py +108 -74
  103. sphinx/ext/intersphinx/_shared.py +2 -2
  104. sphinx/ext/linkcode.py +28 -12
  105. sphinx/ext/mathjax.py +60 -29
  106. sphinx/ext/napoleon/__init__.py +19 -7
  107. sphinx/ext/napoleon/docstring.py +229 -231
  108. sphinx/ext/todo.py +44 -49
  109. sphinx/ext/viewcode.py +105 -57
  110. sphinx/extension.py +3 -1
  111. sphinx/highlighting.py +13 -7
  112. sphinx/io.py +9 -13
  113. sphinx/jinja2glue.py +29 -26
  114. sphinx/locale/__init__.py +8 -9
  115. sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
  116. sphinx/locale/ar/LC_MESSAGES/sphinx.po +2155 -2050
  117. sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
  118. sphinx/locale/bg/LC_MESSAGES/sphinx.po +2045 -1940
  119. sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
  120. sphinx/locale/bn/LC_MESSAGES/sphinx.po +2175 -2070
  121. sphinx/locale/ca/LC_MESSAGES/sphinx.js +3 -3
  122. sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
  123. sphinx/locale/ca/LC_MESSAGES/sphinx.po +2690 -2585
  124. sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.js +63 -0
  125. sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.mo +0 -0
  126. sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.po +4216 -0
  127. sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
  128. sphinx/locale/cak/LC_MESSAGES/sphinx.po +2096 -1991
  129. sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
  130. sphinx/locale/cs/LC_MESSAGES/sphinx.po +2248 -2143
  131. sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
  132. sphinx/locale/cy/LC_MESSAGES/sphinx.po +2201 -2096
  133. sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
  134. sphinx/locale/da/LC_MESSAGES/sphinx.po +2282 -2177
  135. sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
  136. sphinx/locale/de/LC_MESSAGES/sphinx.po +2261 -2156
  137. sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
  138. sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2045 -1940
  139. sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
  140. sphinx/locale/el/LC_MESSAGES/sphinx.po +2604 -2499
  141. sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
  142. sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2045 -1940
  143. sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
  144. sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2045 -1940
  145. sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
  146. sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2631 -2526
  147. sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
  148. sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2045 -1940
  149. sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
  150. sphinx/locale/eo/LC_MESSAGES/sphinx.po +2078 -1973
  151. sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
  152. sphinx/locale/es/LC_MESSAGES/sphinx.po +2633 -2528
  153. sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
  154. sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2045 -1940
  155. sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
  156. sphinx/locale/et/LC_MESSAGES/sphinx.po +2449 -2344
  157. sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
  158. sphinx/locale/eu/LC_MESSAGES/sphinx.po +2241 -2136
  159. sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
  160. sphinx/locale/fa/LC_MESSAGES/sphinx.po +504 -500
  161. sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
  162. sphinx/locale/fi/LC_MESSAGES/sphinx.po +499 -495
  163. sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
  164. sphinx/locale/fr/LC_MESSAGES/sphinx.po +513 -509
  165. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
  166. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +499 -495
  167. sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
  168. sphinx/locale/gl/LC_MESSAGES/sphinx.po +2644 -2539
  169. sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
  170. sphinx/locale/he/LC_MESSAGES/sphinx.po +499 -495
  171. sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
  172. sphinx/locale/hi/LC_MESSAGES/sphinx.po +504 -500
  173. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
  174. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +499 -495
  175. sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
  176. sphinx/locale/hr/LC_MESSAGES/sphinx.po +501 -497
  177. sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
  178. sphinx/locale/hu/LC_MESSAGES/sphinx.po +499 -495
  179. sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
  180. sphinx/locale/id/LC_MESSAGES/sphinx.po +2609 -2504
  181. sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
  182. sphinx/locale/is/LC_MESSAGES/sphinx.po +499 -495
  183. sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
  184. sphinx/locale/it/LC_MESSAGES/sphinx.po +2265 -2160
  185. sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
  186. sphinx/locale/ja/LC_MESSAGES/sphinx.po +2621 -2516
  187. sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
  188. sphinx/locale/ka/LC_MESSAGES/sphinx.po +2567 -2462
  189. sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
  190. sphinx/locale/ko/LC_MESSAGES/sphinx.po +2631 -2526
  191. sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
  192. sphinx/locale/lt/LC_MESSAGES/sphinx.po +2214 -2109
  193. sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
  194. sphinx/locale/lv/LC_MESSAGES/sphinx.po +2218 -2113
  195. sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
  196. sphinx/locale/mk/LC_MESSAGES/sphinx.po +2088 -1983
  197. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
  198. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2247 -2142
  199. sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
  200. sphinx/locale/ne/LC_MESSAGES/sphinx.po +2227 -2122
  201. sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
  202. sphinx/locale/nl/LC_MESSAGES/sphinx.po +2316 -2211
  203. sphinx/locale/pl/LC_MESSAGES/sphinx.js +2 -2
  204. sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
  205. sphinx/locale/pl/LC_MESSAGES/sphinx.po +2442 -2336
  206. sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
  207. sphinx/locale/pt/LC_MESSAGES/sphinx.po +2045 -1940
  208. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
  209. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2657 -2552
  210. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
  211. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2243 -2138
  212. sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
  213. sphinx/locale/ro/LC_MESSAGES/sphinx.po +2244 -2139
  214. sphinx/locale/ru/LC_MESSAGES/sphinx.js +1 -1
  215. sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
  216. sphinx/locale/ru/LC_MESSAGES/sphinx.po +2660 -2555
  217. sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
  218. sphinx/locale/si/LC_MESSAGES/sphinx.po +2134 -2029
  219. sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
  220. sphinx/locale/sk/LC_MESSAGES/sphinx.po +2614 -2509
  221. sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
  222. sphinx/locale/sl/LC_MESSAGES/sphinx.po +2167 -2062
  223. sphinx/locale/sphinx.pot +2069 -1964
  224. sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
  225. sphinx/locale/sq/LC_MESSAGES/sphinx.po +2661 -2556
  226. sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
  227. sphinx/locale/sr/LC_MESSAGES/sphinx.po +2213 -2108
  228. sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
  229. sphinx/locale/sv/LC_MESSAGES/sphinx.po +2229 -2124
  230. sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
  231. sphinx/locale/te/LC_MESSAGES/sphinx.po +2045 -1940
  232. sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
  233. sphinx/locale/tr/LC_MESSAGES/sphinx.po +2608 -2503
  234. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
  235. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2167 -2062
  236. sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
  237. sphinx/locale/ur/LC_MESSAGES/sphinx.po +2045 -1940
  238. sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
  239. sphinx/locale/vi/LC_MESSAGES/sphinx.po +2204 -2099
  240. sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
  241. sphinx/locale/yue/LC_MESSAGES/sphinx.po +2045 -1940
  242. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
  243. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2045 -1940
  244. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
  245. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +2659 -2554
  246. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
  247. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2045 -1940
  248. sphinx/parsers.py +8 -7
  249. sphinx/project.py +2 -2
  250. sphinx/pycode/__init__.py +31 -21
  251. sphinx/pycode/ast.py +6 -3
  252. sphinx/pycode/parser.py +14 -8
  253. sphinx/pygments_styles.py +4 -5
  254. sphinx/registry.py +192 -92
  255. sphinx/roles.py +58 -7
  256. sphinx/search/__init__.py +75 -54
  257. sphinx/search/en.py +11 -13
  258. sphinx/search/fi.py +1 -1
  259. sphinx/search/ja.py +8 -6
  260. sphinx/search/nl.py +1 -1
  261. sphinx/search/zh.py +19 -21
  262. sphinx/testing/fixtures.py +26 -29
  263. sphinx/testing/path.py +26 -62
  264. sphinx/testing/restructuredtext.py +14 -8
  265. sphinx/testing/util.py +21 -19
  266. sphinx/texinputs/make.bat.jinja +50 -50
  267. sphinx/texinputs/sphinx.sty +4 -3
  268. sphinx/texinputs/sphinxlatexadmonitions.sty +1 -1
  269. sphinx/texinputs/sphinxlatexobjects.sty +29 -10
  270. sphinx/themes/basic/static/searchtools.js +8 -5
  271. sphinx/theming.py +49 -61
  272. sphinx/transforms/__init__.py +17 -38
  273. sphinx/transforms/compact_bullet_list.py +5 -3
  274. sphinx/transforms/i18n.py +8 -21
  275. sphinx/transforms/post_transforms/__init__.py +142 -93
  276. sphinx/transforms/post_transforms/code.py +5 -5
  277. sphinx/transforms/post_transforms/images.py +28 -24
  278. sphinx/transforms/references.py +3 -1
  279. sphinx/util/__init__.py +109 -60
  280. sphinx/util/_files.py +39 -23
  281. sphinx/util/_importer.py +4 -1
  282. sphinx/util/_inventory_file_reader.py +76 -0
  283. sphinx/util/_io.py +2 -2
  284. sphinx/util/_lines.py +6 -3
  285. sphinx/util/_pathlib.py +40 -2
  286. sphinx/util/build_phase.py +2 -0
  287. sphinx/util/cfamily.py +19 -14
  288. sphinx/util/console.py +44 -179
  289. sphinx/util/display.py +9 -10
  290. sphinx/util/docfields.py +140 -122
  291. sphinx/util/docstrings.py +1 -1
  292. sphinx/util/docutils.py +118 -77
  293. sphinx/util/fileutil.py +25 -26
  294. sphinx/util/http_date.py +2 -0
  295. sphinx/util/i18n.py +77 -64
  296. sphinx/util/images.py +8 -6
  297. sphinx/util/inspect.py +147 -38
  298. sphinx/util/inventory.py +215 -116
  299. sphinx/util/logging.py +33 -33
  300. sphinx/util/matching.py +12 -4
  301. sphinx/util/nodes.py +18 -13
  302. sphinx/util/osutil.py +38 -39
  303. sphinx/util/parallel.py +22 -13
  304. sphinx/util/parsing.py +2 -1
  305. sphinx/util/png.py +6 -2
  306. sphinx/util/requests.py +33 -2
  307. sphinx/util/rst.py +3 -2
  308. sphinx/util/tags.py +1 -1
  309. sphinx/util/template.py +18 -10
  310. sphinx/util/texescape.py +8 -6
  311. sphinx/util/typing.py +148 -122
  312. sphinx/versioning.py +3 -3
  313. sphinx/writers/html.py +3 -1
  314. sphinx/writers/html5.py +63 -52
  315. sphinx/writers/latex.py +83 -67
  316. sphinx/writers/manpage.py +19 -38
  317. sphinx/writers/texinfo.py +47 -47
  318. sphinx/writers/text.py +50 -32
  319. sphinx/writers/xml.py +11 -8
  320. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/LICENSE.rst +1 -1
  321. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/METADATA +25 -15
  322. sphinx-8.2.0.dist-info/RECORD +606 -0
  323. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/WHEEL +1 -1
  324. sphinx/builders/html/transforms.py +0 -90
  325. sphinx/ext/apidoc.py +0 -721
  326. sphinx/util/exceptions.py +0 -74
  327. sphinx-8.1.2.dist-info/RECORD +0 -598
  328. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/entry_points.txt +0 -0
@@ -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, Any, ClassVar, Final, cast
8
+ from typing import TYPE_CHECKING, cast
8
9
 
9
10
  from docutils import nodes
10
- from docutils.nodes import Element, Node, system_message
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 desc_signature, pending_xref
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(self, name: str, sig: str, signode: desc_signature) -> None:
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(self, document: nodes.document, env: BuildEnvironment, node: Element,
95
- is_ref: bool) -> tuple[list[Node], list[system_message]]:
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(self, name: str, sig: str, signode: desc_signature) -> None:
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(__('Malformed option description %r, should '
235
- 'look like "opt", "-opt args", "--opt args", '
236
- '"/opt args" or "+opt args"'), potential_option,
237
- location=signode)
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.env.config.option_emphasise_placeholders:
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.env.config.option_emphasise_placeholders:
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(self, firstname: str, sig: str, signode: desc_signature) -> None:
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(currprogram, optname,
301
- self.env.docname, signode['ids'][0])
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', []): # type: ignore[var-annotated]
322
+ for option in signode.get('allnames', ()): # type: ignore[var-annotated]
309
323
  entry = f'{descr}; {option}'
310
- self.indexnode['entries'].append(('pair', entry, signode['ids'][0], '', None))
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(self, env: BuildEnvironment, refnode: Element, has_explicit_title: bool,
335
- title: str, target: str) -> tuple[str, str]:
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(env: BuildEnvironment, textnodes: Iterable[Node], index_key: str | None,
352
- source: str, lineno: int, node_id: str | None, document: nodes.document,
353
- ) -> nodes.term:
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'] = ('sorted' in self.options)
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(self.content, self.content.items, strict=True):
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(self.state.reporter.warning(
429
- _('glossary term must be preceded by empty line'),
430
- source=source, line=lineno))
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(self.state.reporter.warning(
437
- _('glossary terms must not be separated by empty lines'),
438
- source=source, line=lineno))
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(self.state.reporter.warning(
443
- _('glossary seems to be misformatted, check indentation'),
444
- source=source, line=lineno))
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(self.state.reporter.warning(
456
- _('glossary seems to be misformatted, check indentation'),
457
- source=source, line=lineno))
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(self.env, textnodes,
473
- first_classifier, source, lineno,
474
- node_id=None, document=self.state.document)
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, definition, offset=offset, allow_section_headings=False,
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, productionGroup: str = '') -> list[Node]:
498
- if len(productionGroup) != 0:
499
- productionGroup += ':'
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 = productionGroup + token
520
- refnode = pending_xref(title, reftype='token', refdomain='std',
521
- reftarget=target)
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
- domain = self.env.domains.standard_domain
543
- node: Element = addnodes.productionlist()
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(self, env: BuildEnvironment, refnode: Element, has_explicit_title: bool,
581
- title: str, target: str) -> tuple[str, str]:
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': OptionXRefRole(warn_dangling=True),
748
+ 'option': OptionXRefRole(warn_dangling=True),
622
749
  'confval': XRefRole(warn_dangling=True),
623
- 'envvar': EnvVarXRefRole(),
750
+ 'envvar': EnvVarXRefRole(),
624
751
  # links to tokens in grammar productions
625
- 'token': TokenXRefRole(),
752
+ 'token': TokenXRefRole(),
626
753
  # links to terms in glossary
627
- 'term': XRefRole(innernodeclass=nodes.inline,
628
- warn_dangling=True),
754
+ 'term': XRefRole(innernodeclass=nodes.inline, warn_dangling=True),
629
755
  # links to headings or arbitrary labels
630
- 'ref': XRefRole(lowercase=True, innernodeclass=nodes.inline,
631
- warn_dangling=True),
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': XRefRole(lowercase=True,
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': XRefRole(warn_dangling=True, innernodeclass=nodes.inline),
764
+ 'doc': XRefRole(warn_dangling=True, innernodeclass=nodes.inline),
639
765
  }
640
766
 
641
767
  initial_data: Final = { # type: ignore[misc]
642
- 'progoptions': {}, # (program, name) -> docname, labelid
643
- 'objects': {}, # (type, name) -> docname, labelid
644
- 'labels': { # labelname -> docname, labelid, sectionname
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': ('search', '', _('Search Page')),
773
+ 'search': ('search', '', _('Search Page')),
648
774
  },
649
- 'anonlabels': { # labelname -> docname, labelid
775
+ 'anonlabels': { # labelname -> docname, labelid
650
776
  'genindex': ('genindex', ''),
651
777
  'modindex': ('py-modindex', ''),
652
- 'search': ('search', ''),
778
+ 'search': ('search', ''),
653
779
  },
654
780
  }
655
781
 
656
- _virtual_doc_names: dict[str, tuple[str, str]] = { # labelname -> docname, sectionname
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': 'undefined label: %(target)r',
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(self.enumerable_nodes) # create a copy for this instance
682
- for node, settings in env.app.registry.enumerable_nodes.items():
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(self, name: str, docname: str, node_id: str,
686
- title: str = '') -> None:
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(__('duplicate label %s, other instance in %s'),
703
- name, self.env.doc2path(self.anonlabels[name][0]))
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
- return self.data.setdefault('objects', {}) # (objtype, name) -> docname, labelid
844
+ # (objtype, name) -> docname, labelid
845
+ return self.data.setdefault('objects', {})
712
846
 
713
- def note_object(self, objtype: str, name: str, labelid: str, location: Any = None,
714
- ) -> None:
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(__('duplicate %s description of %s, other instance in %s'),
722
- objtype, name, docname, location=location)
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('progoptions', {}) # (program, name) -> docname, labelid
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('labels', {}) # labelname -> docname, labelid, sectionname
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
- key: Any = None
753
- for key, (fn, _l) in list(self.progoptions.items()):
754
- if fn == docname:
755
- del self.progoptions[key]
756
- for key, (fn, _l) in list(self.objects.items()):
757
- if fn == docname:
758
- del self.objects[key]
759
- for key, (fn, _l) in list(self._terms.items()):
760
- if fn == docname:
761
- del self._terms[key]
762
- for key, (fn, _l, _l) in list(self.labels.items()):
763
- if fn == docname:
764
- del self.labels[key]
765
- for key, (fn, _l) in list(self.anonlabels.items()):
766
- if fn == docname:
767
- del self.anonlabels[key]
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 (node.tagname == 'footnote' or
802
- 'refuri' in node or
803
- node.tagname.startswith('desc_')):
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(__('duplicate label %s, other instance in %s'),
809
- name, env.doc2path(self.labels[name][0]),
810
- location=node)
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 (isinstance(node, nodes.definition_list | nodes.field_list) and
823
- node.children):
824
- node = cast(nodes.Element, node.children[0])
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(self, program: str | None, name: str,
839
- docname: str, labelid: str) -> None:
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(self, fromdocname: str, builder: Builder, docname: str,
845
- labelid: str, sectname: str, rolename: str, **options: Any,
846
- ) -> Element:
847
- nodeclass = options.pop('nodeclass', nodes.reference)
848
- newnode = nodeclass('', '', internal=True, **options)
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(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
870
- typ: str, target: str, node: pending_xref, contnode: Element,
871
- ) -> Element | None:
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(self, env: BuildEnvironment, fromdocname: str,
890
- builder: Builder, typ: str, target: str, node: pending_xref,
891
- contnode: Element) -> Element | None:
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(fromdocname, builder,
905
- docname, labelid, sectname, 'ref')
1082
+ return self.build_reference_node(
1083
+ fromdocname, builder, docname, labelid, sectname, 'ref'
1084
+ )
906
1085
 
907
- def _resolve_numref_xref(self, env: BuildEnvironment, fromdocname: str,
908
- builder: Builder, typ: str, target: str,
909
- node: pending_xref, contnode: Element) -> Element | None:
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(__('numfig is disabled. :numref: is ignored.'), location=node)
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(__("Failed to create a cross reference. Any number is not "
935
- "assigned: %s"),
936
- labelid, location=node)
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(__('invalid numfig_format: %s (%r)'), title, exc, location=node)
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(fromdocname, builder,
967
- docname, labelid, newtitle, 'numref',
968
- nodeclass=addnodes.number_reference,
969
- title=title)
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(self, env: BuildEnvironment, fromdocname: str,
972
- builder: Builder, typ: str, target: str,
973
- node: pending_xref, contnode: Element) -> Element | None:
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(self, env: BuildEnvironment, fromdocname: str,
982
- builder: Builder, typ: str, target: str,
983
- node: pending_xref, contnode: Element) -> Element | None:
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(self, env: BuildEnvironment, fromdocname: str,
999
- builder: Builder, typ: str, target: str,
1000
- node: pending_xref, contnode: Element) -> Element | None:
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 = "-".join(commands)
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(self, env: BuildEnvironment, fromdocname: str,
1032
- builder: Builder, typ: str, target: str,
1033
- node: pending_xref, contnode: Element) -> Element | None:
1034
- result = self._resolve_obj_xref(env, fromdocname, builder, typ,
1035
- target, node, contnode)
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(self, env: BuildEnvironment, fromdocname: str,
1047
- builder: Builder, typ: str, target: str,
1048
- node: pending_xref, contnode: Element) -> Element | None:
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(self, env: BuildEnvironment, fromdocname: str,
1062
- builder: Builder, target: str, node: pending_xref,
1063
- contnode: Element) -> list[tuple[str, Element]]:
1064
- results: list[tuple[str, Element]] = []
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(env, fromdocname, builder, role,
1068
- ltarget if role == 'ref' else target,
1069
- node, contnode)
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((role, make_refnode(builder, fromdocname, docname,
1081
- labelid, contnode)))
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 (doc, clean_astext(self.env.titles[doc]), 'doc', doc, '', -1)
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 (fullname, fullname, 'cmdoption', info[0], info[1], 1)
1338
+ yield fullname, fullname, 'cmdoption', info[0], info[1], 1
1092
1339
  else:
1093
- yield (option, option, 'cmdoption', info[0], info[1], 1)
1340
+ yield option, option, 'cmdoption', info[0], info[1], 1
1094
1341
  for (type, name), info in self.objects.items():
1095
- yield (name, name, type, info[0], info[1],
1096
- self.object_types[type].attrs['searchprio'])
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 (name, sectionname, 'label', docname, labelid, -1)
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 (name, name, 'label', docname, labelid, -1)
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 (isinstance(node, nodes.container) and
1134
- 'literal_block' in node and
1135
- has_child(node, nodes.literal_block)):
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(app: Sphinx, domain: Domain, node: pending_xref,
1188
- ) -> bool | None:
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 = __('Failed to create a cross reference. A title or caption not found: %r')
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