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,12 +2,11 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import posixpath
6
5
  import re
6
+ from pathlib import Path
7
7
  from typing import TYPE_CHECKING, cast
8
8
 
9
9
  from docutils import nodes
10
- from docutils.utils import relative_path
11
10
 
12
11
  from sphinx.addnodes import pending_xref
13
12
  from sphinx.deprecation import _deprecation_warning
@@ -16,9 +15,10 @@ from sphinx.ext.intersphinx._shared import LOGGER, InventoryAdapter
16
15
  from sphinx.locale import _, __
17
16
  from sphinx.transforms.post_transforms import ReferencesResolver
18
17
  from sphinx.util.docutils import CustomReSTDispatcher, SphinxRole
18
+ from sphinx.util.osutil import _relative_path
19
19
 
20
20
  if TYPE_CHECKING:
21
- from collections.abc import Iterable
21
+ from collections.abc import Iterable, Sequence, Set
22
22
  from types import ModuleType
23
23
  from typing import Any
24
24
 
@@ -27,31 +27,36 @@ if TYPE_CHECKING:
27
27
 
28
28
  from sphinx.application import Sphinx
29
29
  from sphinx.domains import Domain
30
+ from sphinx.domains._domains_container import _DomainsContainer
30
31
  from sphinx.environment import BuildEnvironment
31
32
  from sphinx.ext.intersphinx._shared import InventoryName
32
- from sphinx.util.typing import Inventory, InventoryItem, RoleFunction
33
+ from sphinx.util.inventory import _InventoryItem
34
+ from sphinx.util.typing import Inventory, RoleFunction
33
35
 
34
36
 
35
37
  def _create_element_from_result(
36
- domain: Domain,
38
+ domain_name: str,
37
39
  inv_name: InventoryName | None,
38
- data: InventoryItem,
40
+ inv_item: _InventoryItem,
39
41
  node: pending_xref,
40
42
  contnode: TextElement,
41
43
  ) -> nodes.reference:
42
- proj, version, uri, dispname = data
44
+ uri = inv_item.uri
43
45
  if '://' not in uri and node.get('refdoc'):
44
46
  # get correct path in case of subdirectories
45
- uri = posixpath.join(relative_path(node['refdoc'], '.'), uri)
46
- if version:
47
- reftitle = _('(in %s v%s)') % (proj, version)
47
+ uri = (_relative_path(Path(), Path(node['refdoc']).parent) / uri).as_posix()
48
+ if inv_item.project_version:
49
+ reftitle = _('(in %s v%s)') % (inv_item.project_name, inv_item.project_version)
48
50
  else:
49
- reftitle = _('(in %s)') % (proj,)
51
+ reftitle = _('(in %s)') % (inv_item.project_name,)
52
+
50
53
  newnode = nodes.reference('', '', internal=False, refuri=uri, reftitle=reftitle)
51
54
  if node.get('refexplicit'):
52
55
  # use whatever title was given
53
56
  newnode.append(contnode)
54
- elif dispname == '-' or (domain.name == 'std' and node['reftype'] == 'keyword'):
57
+ elif inv_item.display_name == '-' or (
58
+ domain_name == 'std' and node['reftype'] == 'keyword'
59
+ ):
55
60
  # use whatever title was given, but strip prefix
56
61
  title = contnode.astext()
57
62
  if inv_name is not None and title.startswith(inv_name + ':'):
@@ -64,14 +69,14 @@ def _create_element_from_result(
64
69
  newnode.append(contnode)
65
70
  else:
66
71
  # else use the given display name (used for :ref:)
67
- newnode.append(contnode.__class__(dispname, dispname))
72
+ newnode.append(contnode.__class__(inv_item.display_name, inv_item.display_name))
68
73
  return newnode
69
74
 
70
75
 
71
76
  def _resolve_reference_in_domain_by_target(
72
77
  inv_name: InventoryName | None,
73
78
  inventory: Inventory,
74
- domain: Domain,
79
+ domain_name: str,
75
80
  objtypes: Iterable[str],
76
81
  target: str,
77
82
  node: pending_xref,
@@ -128,46 +133,47 @@ def _resolve_reference_in_domain_by_target(
128
133
  # This is a fix for terms specifically, but potentially should apply to
129
134
  # other types.
130
135
  continue
131
- return _create_element_from_result(domain, inv_name, data, node, contnode)
136
+ return _create_element_from_result(domain_name, inv_name, data, node, contnode)
132
137
  return None
133
138
 
134
139
 
135
140
  def _resolve_reference_in_domain(
136
- env: BuildEnvironment,
137
141
  inv_name: InventoryName | None,
138
142
  inventory: Inventory,
139
143
  honor_disabled_refs: bool,
144
+ disabled_reftypes: Set[str],
140
145
  domain: Domain,
141
146
  objtypes: Iterable[str],
142
147
  node: pending_xref,
143
148
  contnode: TextElement,
144
149
  ) -> nodes.reference | None:
145
- obj_types: dict[str, None] = {}.fromkeys(objtypes)
150
+ domain_name = domain.name
151
+ obj_types: dict[str, None] = dict.fromkeys(objtypes)
146
152
 
147
153
  # we adjust the object types for backwards compatibility
148
- if domain.name == 'std' and 'cmdoption' in obj_types:
154
+ if domain_name == 'std' and 'cmdoption' in obj_types:
149
155
  # cmdoptions were stored as std:option until Sphinx 1.6
150
156
  obj_types['option'] = None
151
- if domain.name == 'py' and 'attribute' in obj_types:
157
+ if domain_name == 'py' and 'attribute' in obj_types:
152
158
  # properties are stored as py:method since Sphinx 2.1
153
159
  obj_types['method'] = None
154
160
 
155
161
  # the inventory contains domain:type as objtype
156
- domain_name = domain.name
157
162
  obj_types = {f'{domain_name}:{obj_type}': None for obj_type in obj_types}
158
163
 
159
164
  # now that the objtypes list is complete we can remove the disabled ones
160
165
  if honor_disabled_refs:
161
- disabled = set(env.config.intersphinx_disabled_reftypes)
162
166
  obj_types = {
163
- obj_type: None for obj_type in obj_types if obj_type not in disabled
167
+ obj_type: None
168
+ for obj_type in obj_types
169
+ if obj_type not in disabled_reftypes
164
170
  }
165
171
 
166
172
  objtypes = [*obj_types.keys()]
167
173
 
168
174
  # without qualification
169
175
  res = _resolve_reference_in_domain_by_target(
170
- inv_name, inventory, domain, objtypes, node['reftarget'], node, contnode
176
+ inv_name, inventory, domain_name, objtypes, node['reftarget'], node, contnode
171
177
  )
172
178
  if res is not None:
173
179
  return res
@@ -177,39 +183,36 @@ def _resolve_reference_in_domain(
177
183
  if full_qualified_name is None:
178
184
  return None
179
185
  return _resolve_reference_in_domain_by_target(
180
- inv_name, inventory, domain, objtypes, full_qualified_name, node, contnode
186
+ inv_name, inventory, domain_name, objtypes, full_qualified_name, node, contnode
181
187
  )
182
188
 
183
189
 
184
190
  def _resolve_reference(
185
- env: BuildEnvironment,
186
191
  inv_name: InventoryName | None,
192
+ domains: _DomainsContainer,
187
193
  inventory: Inventory,
188
194
  honor_disabled_refs: bool,
195
+ disabled_reftypes: Set[str],
189
196
  node: pending_xref,
190
197
  contnode: TextElement,
191
198
  ) -> nodes.reference | None:
192
199
  # disabling should only be done if no inventory is given
193
200
  honor_disabled_refs = honor_disabled_refs and inv_name is None
194
- intersphinx_disabled_reftypes = env.config.intersphinx_disabled_reftypes
195
201
 
196
- if honor_disabled_refs and '*' in intersphinx_disabled_reftypes:
202
+ if honor_disabled_refs and '*' in disabled_reftypes:
197
203
  return None
198
204
 
199
205
  typ = node['reftype']
200
206
  if typ == 'any':
201
- for domain in env.domains.sorted():
202
- if (
203
- honor_disabled_refs
204
- and f'{domain.name}:*' in intersphinx_disabled_reftypes
205
- ):
207
+ for domain in domains.sorted():
208
+ if honor_disabled_refs and f'{domain.name}:*' in disabled_reftypes:
206
209
  continue
207
210
  objtypes: Iterable[str] = domain.object_types.keys()
208
211
  res = _resolve_reference_in_domain(
209
- env,
210
212
  inv_name,
211
213
  inventory,
212
214
  honor_disabled_refs,
215
+ disabled_reftypes,
213
216
  domain,
214
217
  objtypes,
215
218
  node,
@@ -223,17 +226,22 @@ def _resolve_reference(
223
226
  if not domain_name:
224
227
  # only objects in domains are in the inventory
225
228
  return None
226
- if honor_disabled_refs and f'{domain_name}:*' in intersphinx_disabled_reftypes:
229
+ if honor_disabled_refs and f'{domain_name}:*' in disabled_reftypes:
227
230
  return None
228
- domain = env.get_domain(domain_name)
231
+ try:
232
+ domain = domains[domain_name]
233
+ except KeyError as exc:
234
+ msg = __('Domain %r is not registered') % domain_name
235
+ raise ExtensionError(msg) from exc
236
+
229
237
  objtypes = domain.objtypes_for_role(typ) or ()
230
238
  if not objtypes:
231
239
  return None
232
240
  return _resolve_reference_in_domain(
233
- env,
234
241
  inv_name,
235
242
  inventory,
236
243
  honor_disabled_refs,
244
+ disabled_reftypes,
237
245
  domain,
238
246
  objtypes,
239
247
  node,
@@ -259,10 +267,11 @@ def resolve_reference_in_inventory(
259
267
  """
260
268
  assert inventory_exists(env, inv_name)
261
269
  return _resolve_reference(
262
- env,
263
270
  inv_name,
271
+ env.domains,
264
272
  InventoryAdapter(env).named_inventory[inv_name],
265
273
  False,
274
+ frozenset(env.config.intersphinx_disabled_reftypes),
266
275
  node,
267
276
  contnode,
268
277
  )
@@ -279,10 +288,11 @@ def resolve_reference_any_inventory(
279
288
  Resolution is tried with the target as is in any inventory.
280
289
  """
281
290
  return _resolve_reference(
282
- env,
283
291
  None,
292
+ env.domains,
284
293
  InventoryAdapter(env).main_inventory,
285
294
  honor_disabled_refs,
295
+ frozenset(env.config.intersphinx_disabled_reftypes),
286
296
  node,
287
297
  contnode,
288
298
  )
@@ -295,9 +305,11 @@ def resolve_reference_detect_inventory(
295
305
 
296
306
  Resolution is tried first with the target as is in any inventory.
297
307
  If this does not succeed, then the target is split by the first ``:``,
298
- to form ``inv_name:newtarget``. If ``inv_name`` is a named inventory, then resolution
308
+ to form ``inv_name:new_target``. If ``inv_name`` is a named inventory, then resolution
299
309
  is tried in that inventory with the new target.
300
310
  """
311
+ resolve_self = env.config.intersphinx_resolve_self
312
+
301
313
  # ordinary direct lookup, use data as is
302
314
  res = resolve_reference_any_inventory(env, True, node, contnode)
303
315
  if res is not None:
@@ -307,10 +319,18 @@ def resolve_reference_detect_inventory(
307
319
  target = node['reftarget']
308
320
  if ':' not in target:
309
321
  return None
310
- inv_name, newtarget = target.split(':', 1)
322
+ inv_name, _, new_target = target.partition(':')
323
+
324
+ # check if the target is self-referential
325
+ self_referential = bool(resolve_self) and resolve_self == inv_name
326
+ if self_referential:
327
+ node['reftarget'] = new_target
328
+ node['intersphinx_self_referential'] = True
329
+ return None
330
+
311
331
  if not inventory_exists(env, inv_name):
312
332
  return None
313
- node['reftarget'] = newtarget
333
+ node['reftarget'] = new_target
314
334
  res_inv = resolve_reference_in_inventory(env, inv_name, node, contnode)
315
335
  node['reftarget'] = target
316
336
  return res_inv
@@ -354,11 +374,16 @@ class IntersphinxRole(SphinxRole):
354
374
  def run(self) -> tuple[list[Node], list[system_message]]:
355
375
  assert self.name == self.orig_name.lower()
356
376
  inventory, name_suffix = self.get_inventory_and_name_suffix(self.orig_name)
357
- if inventory and not inventory_exists(self.env, inventory):
358
- self._emit_warning(
359
- __('inventory for external cross-reference not found: %r'), inventory
360
- )
361
- return [], []
377
+ resolve_self = self.env.config.intersphinx_resolve_self
378
+ self_referential = bool(resolve_self) and resolve_self == inventory
379
+
380
+ if not self_referential:
381
+ if inventory and not inventory_exists(self.env, inventory):
382
+ self._emit_warning(
383
+ __('inventory for external cross-reference not found: %r'),
384
+ inventory,
385
+ )
386
+ return [], []
362
387
 
363
388
  domain_name, role_name = self._get_domain_role(name_suffix)
364
389
 
@@ -397,27 +422,30 @@ class IntersphinxRole(SphinxRole):
397
422
  else:
398
423
  # the user did not specify a domain,
399
424
  # so we check first the default (if available) then standard domains
400
- domains: list[Domain] = []
401
- if default_domain := self.env.temp_data.get('default_domain'):
402
- domains.append(default_domain)
403
- if (
404
- std_domain := self.env.domains.standard_domain
405
- ) is not None and std_domain not in domains:
406
- domains.append(std_domain)
425
+ default_domain = self.env.current_document.default_domain
426
+ std_domain = self.env.domains.standard_domain
427
+ domains: Sequence[Domain]
428
+ if default_domain is None or std_domain == default_domain:
429
+ domains = (std_domain,)
430
+ else:
431
+ domains = (default_domain, std_domain)
407
432
 
408
433
  role_func = None
409
434
  for domain in domains:
410
- if (role_func := domain.roles.get(role_name)) is not None:
435
+ role_func = domain.roles.get(role_name)
436
+ if role_func is not None:
411
437
  domain_name = domain.name
412
438
  break
413
439
 
414
440
  if role_func is None or domain_name is None:
415
- domains_str = self._concat_strings(d.name for d in domains)
441
+ domains_str = self._concat_strings(domain.name for domain in domains)
416
442
  msg = 'role for external cross-reference not found in domains %s: %r'
417
- possible_roles: set[str] = set()
418
- for d in domains:
419
- if o := d.object_types.get(role_name):
420
- possible_roles.update(f'{d.name}:{r}' for r in o.roles)
443
+ possible_roles: set[str] = {
444
+ f'{domain.name}:{r}'
445
+ for domain in domains
446
+ if (object_types := domain.object_types.get(role_name))
447
+ for r in object_types.roles
448
+ }
421
449
  if possible_roles:
422
450
  msg = f'{msg} (perhaps you meant one of: %s)'
423
451
  self._emit_warning(
@@ -440,10 +468,14 @@ class IntersphinxRole(SphinxRole):
440
468
  self.content,
441
469
  )
442
470
 
443
- for node in result:
444
- if isinstance(node, pending_xref):
445
- node['intersphinx'] = True
446
- node['inventory'] = inventory
471
+ if not self_referential:
472
+ # We do the intersphinx resolution by inserting our
473
+ # 'intersphinx' and 'inventory' attributes into the nodes.
474
+ # Only do this when it is an external reference.
475
+ for node in result:
476
+ if isinstance(node, pending_xref):
477
+ node['intersphinx'] = True
478
+ node['inventory'] = inventory
447
479
 
448
480
  return result, messages
449
481
 
@@ -505,20 +537,21 @@ class IntersphinxRole(SphinxRole):
505
537
  names = name.split(':')
506
538
  if len(names) == 1:
507
539
  # role
508
- default_domain = self.env.temp_data.get('default_domain')
509
- domain = default_domain.name if default_domain else None
540
+ if (domain := self.env.current_document.default_domain) is not None:
541
+ domain_name = domain.name
542
+ else:
543
+ domain_name = None
510
544
  role = names[0]
511
545
  elif len(names) == 2:
512
546
  # domain:role:
513
- domain = names[0]
514
- role = names[1]
547
+ domain_name, role = names
515
548
  else:
516
549
  return None
517
550
 
518
- if domain and self.is_existent_role(domain, role):
519
- return (domain, role)
551
+ if domain_name and self.is_existent_role(domain_name, role):
552
+ return domain_name, role
520
553
  elif self.is_existent_role('std', role):
521
- return ('std', role)
554
+ return 'std', role
522
555
  else:
523
556
  return None
524
557
 
@@ -527,10 +560,11 @@ class IntersphinxRole(SphinxRole):
527
560
  __name__, f'{self.__class__.__name__}.is_existent_role', '', remove=(9, 0)
528
561
  )
529
562
  try:
530
- domain = self.env.get_domain(domain_name)
531
- return role_name in domain.roles
532
- except ExtensionError:
563
+ domain = self.env.domains[domain_name]
564
+ except KeyError:
533
565
  return False
566
+ else:
567
+ return role_name in domain.roles
534
568
 
535
569
  def invoke_role(
536
570
  self, role: tuple[str, str]
@@ -569,7 +603,7 @@ class IntersphinxRoleResolver(ReferencesResolver):
569
603
  for node in self.document.findall(pending_xref):
570
604
  if 'intersphinx' not in node:
571
605
  continue
572
- contnode = cast(nodes.TextElement, node[0].deepcopy())
606
+ contnode = cast('nodes.TextElement', node[0].deepcopy())
573
607
  inv_name = node['inventory']
574
608
  if inv_name is not None:
575
609
  assert inventory_exists(self.env, inv_name)
@@ -2,13 +2,13 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Any, Final, NoReturn
5
+ from typing import TYPE_CHECKING
6
6
 
7
7
  from sphinx.util import logging
8
8
 
9
9
  if TYPE_CHECKING:
10
10
  from collections.abc import Sequence
11
- from typing import TypeAlias
11
+ from typing import Any, Final, NoReturn, TypeAlias
12
12
 
13
13
  from sphinx.environment import BuildEnvironment
14
14
  from sphinx.util.typing import Inventory
sphinx/ext/linkcode.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from types import FunctionType, NoneType
5
6
  from typing import TYPE_CHECKING
6
7
 
7
8
  from docutils import nodes
@@ -18,12 +19,29 @@ if TYPE_CHECKING:
18
19
  from sphinx.util.typing import ExtensionMetadata
19
20
 
20
21
 
22
+ _DOMAIN_KEYS = {
23
+ 'py': ['module', 'fullname'],
24
+ 'c': ['names'],
25
+ 'cpp': ['names'],
26
+ 'js': ['object', 'fullname'],
27
+ }
28
+
29
+
30
+ def add_linkcode_domain(domain: str, keys: list[str], override: bool = False) -> None:
31
+ """Register a new list of keys to use for a domain.
32
+
33
+ .. versionadded:: 8.2
34
+ """
35
+ if override or domain not in _DOMAIN_KEYS:
36
+ _DOMAIN_KEYS[domain] = list(keys)
37
+
38
+
21
39
  class LinkcodeError(SphinxError):
22
- category = "linkcode error"
40
+ category = 'linkcode error'
23
41
 
24
42
 
25
43
  def doctree_read(app: Sphinx, doctree: Node) -> None:
26
- env = app.builder.env
44
+ env = app.env
27
45
 
28
46
  resolve_target = getattr(env.config, 'linkcode_resolve', None)
29
47
  if not callable(env.config.linkcode_resolve):
@@ -37,13 +55,6 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
37
55
  # ``supported_linkcode`` attribute.
38
56
  node_only_expr = getattr(app.builder, 'supported_linkcode', 'html')
39
57
 
40
- domain_keys = {
41
- 'py': ['module', 'fullname'],
42
- 'c': ['names'],
43
- 'cpp': ['names'],
44
- 'js': ['object', 'fullname'],
45
- }
46
-
47
58
  for objnode in list(doctree.findall(addnodes.desc)):
48
59
  domain = objnode.get('domain')
49
60
  uris: set[str] = set()
@@ -53,7 +64,7 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
53
64
 
54
65
  # Convert signode to a specified format
55
66
  info = {}
56
- for key in domain_keys.get(domain, []):
67
+ for key in _DOMAIN_KEYS.get(domain, ()):
57
68
  value = signode.get(key)
58
69
  if not value:
59
70
  value = ''
@@ -80,5 +91,10 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
80
91
 
81
92
  def setup(app: Sphinx) -> ExtensionMetadata:
82
93
  app.connect('doctree-read', doctree_read)
83
- app.add_config_value('linkcode_resolve', None, '')
84
- return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
94
+ app.add_config_value(
95
+ 'linkcode_resolve', None, '', types=frozenset({FunctionType, NoneType})
96
+ )
97
+ return {
98
+ 'version': sphinx.__display_version__,
99
+ 'parallel_read_safe': True,
100
+ }
sphinx/ext/mathjax.py CHANGED
@@ -8,18 +8,21 @@ This requires the MathJax JavaScript library on your webserver/computer.
8
8
  from __future__ import annotations
9
9
 
10
10
  import json
11
- from typing import TYPE_CHECKING, Any, cast
11
+ from types import NoneType
12
+ from typing import TYPE_CHECKING, cast
12
13
 
13
14
  from docutils import nodes
14
15
 
15
16
  import sphinx
16
- from sphinx.builders.html import StandaloneHTMLBuilder
17
17
  from sphinx.errors import ExtensionError
18
18
  from sphinx.locale import _
19
19
  from sphinx.util.math import get_node_equation_number
20
20
 
21
21
  if TYPE_CHECKING:
22
+ from typing import Any
23
+
22
24
  from sphinx.application import Sphinx
25
+ from sphinx.builders.html import StandaloneHTMLBuilder
23
26
  from sphinx.util.typing import ExtensionMetadata
24
27
  from sphinx.writers.html5 import HTML5Translator
25
28
 
@@ -31,16 +34,21 @@ logger = sphinx.util.logging.getLogger(__name__)
31
34
 
32
35
 
33
36
  def html_visit_math(self: HTML5Translator, node: nodes.math) -> None:
34
- self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate nohighlight'))
35
- self.body.append(self.builder.config.mathjax_inline[0] +
36
- self.encode(node.astext()) +
37
- self.builder.config.mathjax_inline[1] + '</span>')
37
+ self.body.append(
38
+ self.starttag(node, 'span', '', CLASS='math notranslate nohighlight')
39
+ )
40
+ self.body.append(
41
+ self.builder.config.mathjax_inline[0]
42
+ + self.encode(node.astext())
43
+ + self.builder.config.mathjax_inline[1]
44
+ + '</span>'
45
+ )
38
46
  raise nodes.SkipNode
39
47
 
40
48
 
41
49
  def html_visit_displaymath(self: HTML5Translator, node: nodes.math_block) -> None:
42
50
  self.body.append(self.starttag(node, 'div', CLASS='math notranslate nohighlight'))
43
- if node['nowrap']:
51
+ if node.get('no-wrap', node.get('nowrap', False)):
44
52
  self.body.append(self.encode(node.astext()))
45
53
  self.body.append('</div>')
46
54
  raise nodes.SkipNode
@@ -70,26 +78,31 @@ def html_visit_displaymath(self: HTML5Translator, node: nodes.math_block) -> Non
70
78
  raise nodes.SkipNode
71
79
 
72
80
 
73
- def install_mathjax(app: Sphinx, pagename: str, templatename: str, context: dict[str, Any],
74
- event_arg: Any) -> None:
75
- if (
76
- app.builder.format != 'html' or
77
- app.builder.math_renderer_name != 'mathjax' # type: ignore[attr-defined]
78
- ):
81
+ def install_mathjax(
82
+ app: Sphinx,
83
+ pagename: str,
84
+ templatename: str,
85
+ context: dict[str, Any],
86
+ event_arg: Any,
87
+ ) -> None:
88
+ if app.builder.format != 'html':
89
+ return
90
+ if app.builder.math_renderer_name != 'mathjax': # type: ignore[attr-defined]
79
91
  return
80
92
  if not app.config.mathjax_path:
81
93
  msg = 'mathjax_path config value must be set for the mathjax extension to work'
82
94
  raise ExtensionError(msg)
83
95
 
84
- domain = app.env.domains.math_domain
85
- builder = cast(StandaloneHTMLBuilder, app.builder)
86
- if app.registry.html_assets_policy == 'always' or domain.has_equations(pagename):
96
+ builder = cast('StandaloneHTMLBuilder', app.builder)
97
+ page_has_equations = context.get('has_maths_elements', False)
98
+ if app.registry.html_assets_policy == 'always' or page_has_equations:
87
99
  # Enable mathjax only if equations exists
88
100
  if app.config.mathjax2_config:
89
101
  if app.config.mathjax_path == MATHJAX_URL:
90
102
  logger.warning(
91
103
  'mathjax_config/mathjax2_config does not work '
92
- 'for the current MathJax version, use mathjax3_config instead')
104
+ 'for the current MathJax version, use mathjax3_config instead'
105
+ )
93
106
  body = 'MathJax.Hub.Config(%s)' % json.dumps(app.config.mathjax2_config)
94
107
  builder.add_js_file('', type='text/x-mathjax-config', body=body)
95
108
  if app.config.mathjax3_config:
@@ -110,17 +123,35 @@ def install_mathjax(app: Sphinx, pagename: str, templatename: str, context: dict
110
123
 
111
124
 
112
125
  def setup(app: Sphinx) -> ExtensionMetadata:
113
- app.add_html_math_renderer('mathjax',
114
- (html_visit_math, None),
115
- (html_visit_displaymath, None))
116
-
117
- app.add_config_value('mathjax_path', MATHJAX_URL, 'html')
118
- app.add_config_value('mathjax_options', {}, 'html')
119
- app.add_config_value('mathjax_inline', [r'\(', r'\)'], 'html')
120
- app.add_config_value('mathjax_display', [r'\[', r'\]'], 'html')
121
- app.add_config_value('mathjax_config', None, 'html')
122
- app.add_config_value('mathjax2_config', lambda c: c.mathjax_config, 'html')
123
- app.add_config_value('mathjax3_config', None, 'html')
126
+ app.add_html_math_renderer(
127
+ 'mathjax',
128
+ inline_renderers=(html_visit_math, None),
129
+ block_renderers=(html_visit_displaymath, None),
130
+ )
131
+
132
+ app.add_config_value('mathjax_path', MATHJAX_URL, 'html', types=frozenset({str}))
133
+ app.add_config_value('mathjax_options', {}, 'html', types=frozenset({dict}))
134
+ app.add_config_value(
135
+ 'mathjax_inline', [r'\(', r'\)'], 'html', types=frozenset({list, tuple})
136
+ )
137
+ app.add_config_value(
138
+ 'mathjax_display', [r'\[', r'\]'], 'html', types=frozenset({list, tuple})
139
+ )
140
+ app.add_config_value(
141
+ 'mathjax_config', None, 'html', types=frozenset({dict, NoneType})
142
+ )
143
+ app.add_config_value(
144
+ 'mathjax2_config',
145
+ lambda c: c.mathjax_config,
146
+ 'html',
147
+ types=frozenset({dict, NoneType}),
148
+ )
149
+ app.add_config_value(
150
+ 'mathjax3_config', None, 'html', types=frozenset({dict, NoneType})
151
+ )
124
152
  app.connect('html-page-context', install_mathjax)
125
153
 
126
- return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
154
+ return {
155
+ 'version': sphinx.__display_version__,
156
+ 'parallel_read_safe': True,
157
+ }