Sphinx 7.2.6__py3-none-any.whl → 7.3.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 (388) hide show
  1. sphinx/__init__.py +8 -9
  2. sphinx/addnodes.py +31 -28
  3. sphinx/application.py +9 -15
  4. sphinx/builders/__init__.py +5 -6
  5. sphinx/builders/_epub_base.py +17 -9
  6. sphinx/builders/changes.py +10 -5
  7. sphinx/builders/dirhtml.py +4 -2
  8. sphinx/builders/dummy.py +3 -2
  9. sphinx/builders/epub3.py +5 -3
  10. sphinx/builders/gettext.py +24 -7
  11. sphinx/builders/html/__init__.py +88 -96
  12. sphinx/builders/html/_assets.py +16 -16
  13. sphinx/builders/html/transforms.py +4 -2
  14. sphinx/builders/latex/__init__.py +40 -33
  15. sphinx/builders/latex/nodes.py +6 -2
  16. sphinx/builders/latex/transforms.py +17 -8
  17. sphinx/builders/latex/util.py +1 -1
  18. sphinx/builders/linkcheck.py +86 -27
  19. sphinx/builders/manpage.py +8 -6
  20. sphinx/builders/singlehtml.py +5 -4
  21. sphinx/builders/texinfo.py +18 -14
  22. sphinx/builders/text.py +3 -2
  23. sphinx/builders/xml.py +5 -2
  24. sphinx/cmd/build.py +119 -76
  25. sphinx/cmd/make_mode.py +4 -9
  26. sphinx/cmd/quickstart.py +13 -16
  27. sphinx/config.py +432 -250
  28. sphinx/deprecation.py +23 -13
  29. sphinx/directives/__init__.py +8 -8
  30. sphinx/directives/code.py +7 -7
  31. sphinx/directives/other.py +23 -13
  32. sphinx/directives/patches.py +7 -6
  33. sphinx/domains/__init__.py +2 -2
  34. sphinx/domains/c/__init__.py +796 -0
  35. sphinx/domains/c/_ast.py +1421 -0
  36. sphinx/domains/c/_ids.py +65 -0
  37. sphinx/domains/c/_parser.py +1048 -0
  38. sphinx/domains/c/_symbol.py +700 -0
  39. sphinx/domains/changeset.py +11 -7
  40. sphinx/domains/citation.py +5 -2
  41. sphinx/domains/cpp/__init__.py +1089 -0
  42. sphinx/domains/cpp/_ast.py +3635 -0
  43. sphinx/domains/cpp/_ids.py +537 -0
  44. sphinx/domains/cpp/_parser.py +2117 -0
  45. sphinx/domains/cpp/_symbol.py +1092 -0
  46. sphinx/domains/index.py +6 -4
  47. sphinx/domains/javascript.py +16 -13
  48. sphinx/domains/math.py +9 -4
  49. sphinx/domains/python/__init__.py +890 -0
  50. sphinx/domains/python/_annotations.py +507 -0
  51. sphinx/domains/python/_object.py +426 -0
  52. sphinx/domains/rst.py +12 -7
  53. sphinx/domains/{std.py → std/__init__.py} +19 -16
  54. sphinx/environment/__init__.py +21 -19
  55. sphinx/environment/adapters/indexentries.py +2 -2
  56. sphinx/environment/adapters/toctree.py +10 -9
  57. sphinx/environment/collectors/__init__.py +6 -3
  58. sphinx/environment/collectors/asset.py +4 -3
  59. sphinx/environment/collectors/dependencies.py +3 -2
  60. sphinx/environment/collectors/metadata.py +6 -5
  61. sphinx/environment/collectors/title.py +3 -2
  62. sphinx/environment/collectors/toctree.py +5 -4
  63. sphinx/errors.py +13 -2
  64. sphinx/events.py +14 -9
  65. sphinx/ext/apidoc.py +9 -11
  66. sphinx/ext/autodoc/__init__.py +105 -71
  67. sphinx/ext/autodoc/directive.py +7 -6
  68. sphinx/ext/autodoc/importer.py +102 -36
  69. sphinx/ext/autodoc/mock.py +7 -5
  70. sphinx/ext/autodoc/preserve_defaults.py +4 -3
  71. sphinx/ext/autodoc/type_comment.py +2 -1
  72. sphinx/ext/autodoc/typehints.py +5 -4
  73. sphinx/ext/autosectionlabel.py +3 -2
  74. sphinx/ext/autosummary/__init__.py +21 -17
  75. sphinx/ext/autosummary/generate.py +9 -9
  76. sphinx/ext/coverage.py +26 -20
  77. sphinx/ext/doctest.py +38 -33
  78. sphinx/ext/duration.py +1 -0
  79. sphinx/ext/extlinks.py +4 -3
  80. sphinx/ext/githubpages.py +3 -2
  81. sphinx/ext/graphviz.py +10 -7
  82. sphinx/ext/ifconfig.py +5 -5
  83. sphinx/ext/imgconverter.py +6 -5
  84. sphinx/ext/imgmath.py +9 -8
  85. sphinx/ext/inheritance_diagram.py +31 -31
  86. sphinx/ext/intersphinx.py +140 -23
  87. sphinx/ext/linkcode.py +3 -2
  88. sphinx/ext/mathjax.py +2 -1
  89. sphinx/ext/napoleon/__init__.py +12 -7
  90. sphinx/ext/napoleon/docstring.py +34 -32
  91. sphinx/ext/todo.py +10 -7
  92. sphinx/ext/viewcode.py +12 -11
  93. sphinx/extension.py +18 -8
  94. sphinx/highlighting.py +39 -20
  95. sphinx/io.py +17 -8
  96. sphinx/jinja2glue.py +16 -15
  97. sphinx/locale/__init__.py +30 -23
  98. sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
  99. sphinx/locale/ar/LC_MESSAGES/sphinx.po +818 -761
  100. sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
  101. sphinx/locale/bg/LC_MESSAGES/sphinx.po +811 -754
  102. sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
  103. sphinx/locale/bn/LC_MESSAGES/sphinx.po +835 -778
  104. sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
  105. sphinx/locale/ca/LC_MESSAGES/sphinx.po +864 -807
  106. sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
  107. sphinx/locale/cak/LC_MESSAGES/sphinx.po +816 -759
  108. sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
  109. sphinx/locale/cs/LC_MESSAGES/sphinx.po +837 -780
  110. sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
  111. sphinx/locale/cy/LC_MESSAGES/sphinx.po +819 -762
  112. sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
  113. sphinx/locale/da/LC_MESSAGES/sphinx.po +838 -781
  114. sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
  115. sphinx/locale/de/LC_MESSAGES/sphinx.po +838 -781
  116. sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
  117. sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +811 -754
  118. sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
  119. sphinx/locale/el/LC_MESSAGES/sphinx.po +853 -796
  120. sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
  121. sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +811 -754
  122. sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
  123. sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +811 -754
  124. sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
  125. sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +856 -799
  126. sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
  127. sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +811 -754
  128. sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
  129. sphinx/locale/eo/LC_MESSAGES/sphinx.po +820 -763
  130. sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
  131. sphinx/locale/es/LC_MESSAGES/sphinx.po +856 -799
  132. sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
  133. sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +811 -754
  134. sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
  135. sphinx/locale/et/LC_MESSAGES/sphinx.po +845 -788
  136. sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
  137. sphinx/locale/eu/LC_MESSAGES/sphinx.po +837 -780
  138. sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
  139. sphinx/locale/fa/LC_MESSAGES/sphinx.po +854 -797
  140. sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
  141. sphinx/locale/fi/LC_MESSAGES/sphinx.po +816 -759
  142. sphinx/locale/fr/LC_MESSAGES/sphinx.js +1 -1
  143. sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
  144. sphinx/locale/fr/LC_MESSAGES/sphinx.po +904 -847
  145. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
  146. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +811 -754
  147. sphinx/locale/gl/LC_MESSAGES/sphinx.js +54 -54
  148. sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
  149. sphinx/locale/gl/LC_MESSAGES/sphinx.po +1506 -1449
  150. sphinx/locale/he/LC_MESSAGES/sphinx.js +1 -1
  151. sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
  152. sphinx/locale/he/LC_MESSAGES/sphinx.po +823 -766
  153. sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
  154. sphinx/locale/hi/LC_MESSAGES/sphinx.po +853 -796
  155. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
  156. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +811 -754
  157. sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
  158. sphinx/locale/hr/LC_MESSAGES/sphinx.po +844 -787
  159. sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
  160. sphinx/locale/hu/LC_MESSAGES/sphinx.po +837 -780
  161. sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
  162. sphinx/locale/id/LC_MESSAGES/sphinx.po +854 -797
  163. sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
  164. sphinx/locale/is/LC_MESSAGES/sphinx.po +811 -754
  165. sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
  166. sphinx/locale/it/LC_MESSAGES/sphinx.po +837 -780
  167. sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
  168. sphinx/locale/ja/LC_MESSAGES/sphinx.po +853 -796
  169. sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
  170. sphinx/locale/ka/LC_MESSAGES/sphinx.po +848 -791
  171. sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
  172. sphinx/locale/ko/LC_MESSAGES/sphinx.po +855 -798
  173. sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
  174. sphinx/locale/lt/LC_MESSAGES/sphinx.po +837 -780
  175. sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
  176. sphinx/locale/lv/LC_MESSAGES/sphinx.po +837 -780
  177. sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
  178. sphinx/locale/mk/LC_MESSAGES/sphinx.po +825 -768
  179. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js +27 -27
  180. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
  181. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +876 -818
  182. sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
  183. sphinx/locale/ne/LC_MESSAGES/sphinx.po +837 -780
  184. sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
  185. sphinx/locale/nl/LC_MESSAGES/sphinx.po +844 -787
  186. sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
  187. sphinx/locale/pl/LC_MESSAGES/sphinx.po +845 -788
  188. sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
  189. sphinx/locale/pt/LC_MESSAGES/sphinx.po +811 -754
  190. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
  191. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +908 -851
  192. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
  193. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +837 -780
  194. sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
  195. sphinx/locale/ro/LC_MESSAGES/sphinx.po +837 -780
  196. sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
  197. sphinx/locale/ru/LC_MESSAGES/sphinx.po +838 -781
  198. sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
  199. sphinx/locale/si/LC_MESSAGES/sphinx.po +823 -766
  200. sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
  201. sphinx/locale/sk/LC_MESSAGES/sphinx.po +854 -797
  202. sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
  203. sphinx/locale/sl/LC_MESSAGES/sphinx.po +832 -775
  204. sphinx/locale/sphinx.pot +813 -755
  205. sphinx/locale/sq/LC_MESSAGES/sphinx.js +1 -1
  206. sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
  207. sphinx/locale/sq/LC_MESSAGES/sphinx.po +865 -808
  208. sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
  209. sphinx/locale/sr/LC_MESSAGES/sphinx.po +835 -778
  210. sphinx/locale/sr@latin/LC_MESSAGES/sphinx.mo +0 -0
  211. sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo +0 -0
  212. sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
  213. sphinx/locale/sv/LC_MESSAGES/sphinx.po +837 -780
  214. sphinx/locale/ta/LC_MESSAGES/sphinx.js +54 -54
  215. sphinx/locale/ta/LC_MESSAGES/sphinx.mo +0 -0
  216. sphinx/locale/ta/LC_MESSAGES/sphinx.po +1530 -1473
  217. sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
  218. sphinx/locale/te/LC_MESSAGES/sphinx.po +811 -754
  219. sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
  220. sphinx/locale/tr/LC_MESSAGES/sphinx.po +853 -796
  221. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
  222. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +833 -776
  223. sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
  224. sphinx/locale/ur/LC_MESSAGES/sphinx.po +811 -754
  225. sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
  226. sphinx/locale/vi/LC_MESSAGES/sphinx.po +837 -780
  227. sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
  228. sphinx/locale/yue/LC_MESSAGES/sphinx.po +811 -754
  229. sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo +0 -0
  230. sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +855 -798
  231. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
  232. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +811 -754
  233. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js +1 -1
  234. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
  235. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +879 -822
  236. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
  237. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +811 -754
  238. sphinx/parsers.py +7 -5
  239. sphinx/project.py +18 -11
  240. sphinx/pycode/__init__.py +6 -5
  241. sphinx/pycode/ast.py +23 -8
  242. sphinx/pycode/parser.py +6 -5
  243. sphinx/registry.py +12 -6
  244. sphinx/roles.py +103 -57
  245. sphinx/search/__init__.py +17 -18
  246. sphinx/search/da.py +2 -2
  247. sphinx/search/de.py +2 -2
  248. sphinx/search/en.py +1 -1
  249. sphinx/search/es.py +2 -2
  250. sphinx/search/fi.py +2 -2
  251. sphinx/search/fr.py +2 -2
  252. sphinx/search/hu.py +2 -2
  253. sphinx/search/it.py +2 -2
  254. sphinx/search/ja.py +13 -22
  255. sphinx/search/nl.py +2 -2
  256. sphinx/search/no.py +2 -2
  257. sphinx/search/pt.py +2 -2
  258. sphinx/search/ro.py +1 -1
  259. sphinx/search/ru.py +2 -2
  260. sphinx/search/sv.py +2 -2
  261. sphinx/search/tr.py +1 -1
  262. sphinx/search/zh.py +2 -3
  263. sphinx/templates/graphviz/graphviz.css +1 -1
  264. sphinx/testing/fixtures.py +41 -24
  265. sphinx/testing/path.py +1 -1
  266. sphinx/testing/util.py +142 -53
  267. sphinx/texinputs/sphinx.xdy +1 -1
  268. sphinx/texinputs/sphinxlatextables.sty +1 -1
  269. sphinx/texinputs/sphinxpackagesubstitutefont.sty +21 -0
  270. sphinx/themes/agogo/layout.html +4 -4
  271. sphinx/themes/agogo/static/agogo.css_t +1 -1
  272. sphinx/themes/agogo/theme.toml +22 -0
  273. sphinx/themes/basic/defindex.html +1 -1
  274. sphinx/themes/basic/domainindex.html +1 -1
  275. sphinx/themes/basic/genindex-single.html +1 -1
  276. sphinx/themes/basic/genindex-split.html +1 -1
  277. sphinx/themes/basic/genindex.html +1 -1
  278. sphinx/themes/basic/globaltoc.html +1 -1
  279. sphinx/themes/basic/layout.html +1 -1
  280. sphinx/themes/basic/localtoc.html +1 -1
  281. sphinx/themes/basic/page.html +1 -1
  282. sphinx/themes/basic/relations.html +1 -1
  283. sphinx/themes/basic/search.html +5 -20
  284. sphinx/themes/basic/searchbox.html +3 -3
  285. sphinx/themes/basic/searchfield.html +3 -3
  286. sphinx/themes/basic/sourcelink.html +1 -1
  287. sphinx/themes/basic/static/basic.css_t +1 -1
  288. sphinx/themes/basic/static/doctools.js +1 -1
  289. sphinx/themes/basic/static/language_data.js_t +2 -2
  290. sphinx/themes/basic/static/searchtools.js +105 -60
  291. sphinx/themes/basic/theme.toml +23 -0
  292. sphinx/themes/bizstyle/layout.html +1 -6
  293. sphinx/themes/bizstyle/static/bizstyle.css_t +1 -1
  294. sphinx/themes/bizstyle/static/bizstyle.js_t +1 -1
  295. sphinx/themes/bizstyle/static/css3-mediaqueries_src.js +3 -3
  296. sphinx/themes/bizstyle/theme.toml +12 -0
  297. sphinx/themes/classic/layout.html +1 -1
  298. sphinx/themes/classic/static/classic.css_t +1 -1
  299. sphinx/themes/classic/static/sidebar.js_t +1 -1
  300. sphinx/themes/classic/theme.toml +34 -0
  301. sphinx/themes/default/theme.toml +2 -0
  302. sphinx/themes/epub/epub-cover.html +1 -1
  303. sphinx/themes/epub/layout.html +1 -1
  304. sphinx/themes/epub/static/epub.css_t +1 -1
  305. sphinx/themes/epub/theme.toml +10 -0
  306. sphinx/themes/haiku/layout.html +3 -3
  307. sphinx/themes/haiku/static/haiku.css_t +2 -2
  308. sphinx/themes/haiku/theme.toml +16 -0
  309. sphinx/themes/nature/static/nature.css_t +1 -1
  310. sphinx/themes/nature/theme.toml +6 -0
  311. sphinx/themes/nonav/layout.html +1 -1
  312. sphinx/themes/nonav/static/nonav.css_t +1 -1
  313. sphinx/themes/nonav/theme.toml +10 -0
  314. sphinx/themes/pyramid/static/epub.css_t +1 -1
  315. sphinx/themes/pyramid/static/pyramid.css_t +1 -1
  316. sphinx/themes/pyramid/theme.toml +6 -0
  317. sphinx/themes/scrolls/artwork/logo.svg +1 -1
  318. sphinx/themes/scrolls/layout.html +2 -2
  319. sphinx/themes/scrolls/static/scrolls.css_t +1 -1
  320. sphinx/themes/scrolls/theme.toml +15 -0
  321. sphinx/themes/sphinxdoc/static/sphinxdoc.css_t +1 -1
  322. sphinx/themes/sphinxdoc/theme.toml +6 -0
  323. sphinx/themes/traditional/static/traditional.css_t +1 -1
  324. sphinx/themes/traditional/theme.toml +9 -0
  325. sphinx/theming.py +427 -131
  326. sphinx/transforms/__init__.py +21 -24
  327. sphinx/transforms/compact_bullet_list.py +5 -5
  328. sphinx/transforms/i18n.py +30 -28
  329. sphinx/transforms/post_transforms/__init__.py +9 -7
  330. sphinx/transforms/post_transforms/code.py +4 -1
  331. sphinx/transforms/post_transforms/images.py +17 -13
  332. sphinx/transforms/references.py +3 -1
  333. sphinx/util/__init__.py +15 -11
  334. sphinx/util/_io.py +34 -0
  335. sphinx/util/_pathlib.py +23 -18
  336. sphinx/util/build_phase.py +1 -0
  337. sphinx/util/cfamily.py +19 -11
  338. sphinx/util/console.py +101 -21
  339. sphinx/util/display.py +3 -2
  340. sphinx/util/docfields.py +12 -8
  341. sphinx/util/docutils.py +21 -35
  342. sphinx/util/exceptions.py +3 -2
  343. sphinx/util/fileutil.py +5 -5
  344. sphinx/util/http_date.py +9 -2
  345. sphinx/util/i18n.py +40 -9
  346. sphinx/util/inspect.py +317 -245
  347. sphinx/util/inventory.py +22 -5
  348. sphinx/util/logging.py +81 -7
  349. sphinx/util/matching.py +2 -1
  350. sphinx/util/math.py +1 -2
  351. sphinx/util/nodes.py +39 -29
  352. sphinx/util/osutil.py +25 -6
  353. sphinx/util/parallel.py +6 -1
  354. sphinx/util/requests.py +8 -5
  355. sphinx/util/rst.py +8 -6
  356. sphinx/util/tags.py +3 -3
  357. sphinx/util/template.py +8 -3
  358. sphinx/util/typing.py +76 -42
  359. sphinx/versioning.py +6 -2
  360. sphinx/writers/html.py +1 -1
  361. sphinx/writers/html5.py +17 -13
  362. sphinx/writers/latex.py +12 -12
  363. sphinx/writers/manpage.py +13 -7
  364. sphinx/writers/texinfo.py +13 -10
  365. sphinx/writers/text.py +13 -23
  366. sphinx/writers/xml.py +1 -1
  367. sphinx-7.2.6.dist-info/LICENSE → sphinx-7.3.0.dist-info/LICENSE.rst +1 -1
  368. {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/METADATA +13 -12
  369. sphinx-7.3.0.dist-info/RECORD +581 -0
  370. sphinx/domains/c.py +0 -3906
  371. sphinx/domains/cpp.py +0 -8233
  372. sphinx/domains/python.py +0 -1769
  373. sphinx/themes/agogo/theme.conf +0 -20
  374. sphinx/themes/basic/theme.conf +0 -16
  375. sphinx/themes/bizstyle/theme.conf +0 -10
  376. sphinx/themes/classic/theme.conf +0 -32
  377. sphinx/themes/default/theme.conf +0 -2
  378. sphinx/themes/epub/theme.conf +0 -8
  379. sphinx/themes/haiku/theme.conf +0 -14
  380. sphinx/themes/nature/theme.conf +0 -4
  381. sphinx/themes/nonav/theme.conf +0 -8
  382. sphinx/themes/pyramid/theme.conf +0 -4
  383. sphinx/themes/scrolls/theme.conf +0 -13
  384. sphinx/themes/sphinxdoc/theme.conf +0 -4
  385. sphinx/themes/traditional/theme.conf +0 -7
  386. sphinx-7.2.6.dist-info/RECORD +0 -569
  387. {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/WHEEL +0 -0
  388. {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/entry_points.txt +0 -0
@@ -7,6 +7,7 @@ import json
7
7
  import re
8
8
  import socket
9
9
  import time
10
+ import warnings
10
11
  from html.parser import HTMLParser
11
12
  from os import path
12
13
  from queue import PriorityQueue, Queue
@@ -16,29 +17,26 @@ from urllib.parse import unquote, urlparse, urlsplit, urlunparse
16
17
 
17
18
  from docutils import nodes
18
19
  from requests.exceptions import ConnectionError, HTTPError, SSLError, TooManyRedirects
20
+ from requests.exceptions import Timeout as RequestTimeout
19
21
 
20
22
  from sphinx.builders.dummy import DummyBuilder
23
+ from sphinx.deprecation import RemovedInSphinx80Warning
21
24
  from sphinx.locale import __
22
25
  from sphinx.transforms.post_transforms import SphinxPostTransform
23
26
  from sphinx.util import encode_uri, logging, requests
24
- from sphinx.util.console import ( # type: ignore[attr-defined]
25
- darkgray,
26
- darkgreen,
27
- purple,
28
- red,
29
- turquoise,
30
- )
27
+ from sphinx.util.console import darkgray, darkgreen, purple, red, turquoise
31
28
  from sphinx.util.http_date import rfc1123_to_epoch
32
29
  from sphinx.util.nodes import get_node_line
33
30
 
34
31
  if TYPE_CHECKING:
35
- from collections.abc import Generator, Iterator
32
+ from collections.abc import Iterator
36
33
  from typing import Any, Callable
37
34
 
38
35
  from requests import Response
39
36
 
40
37
  from sphinx.application import Sphinx
41
38
  from sphinx.config import Config
39
+ from sphinx.util.typing import ExtensionMetadata
42
40
 
43
41
  logger = logging.getLogger(__name__)
44
42
 
@@ -56,16 +54,37 @@ class CheckExternalLinksBuilder(DummyBuilder):
56
54
  """
57
55
  Checks for broken external links.
58
56
  """
57
+
59
58
  name = 'linkcheck'
60
59
  epilog = __('Look for any errors in the above output or in '
61
60
  '%(outdir)s/output.txt')
62
61
 
63
62
  def init(self) -> None:
64
63
  self.broken_hyperlinks = 0
64
+ self.timed_out_hyperlinks = 0
65
65
  self.hyperlinks: dict[str, Hyperlink] = {}
66
66
  # set a timeout for non-responding servers
67
67
  socket.setdefaulttimeout(5.0)
68
68
 
69
+ if not self.config.linkcheck_allow_unauthorized:
70
+ deprecation_msg = (
71
+ "The default value for 'linkcheck_allow_unauthorized' will change "
72
+ "from `True` in Sphinx 7.3+ to `False`, meaning that HTTP 401 "
73
+ "unauthorized responses will be reported as broken by default. "
74
+ "See https://github.com/sphinx-doc/sphinx/issues/11433 for details."
75
+ )
76
+ warnings.warn(deprecation_msg, RemovedInSphinx80Warning, stacklevel=1)
77
+
78
+ if self.config.linkcheck_report_timeouts_as_broken:
79
+ deprecation_msg = (
80
+ "The default value for 'linkcheck_report_timeouts_as_broken' will change "
81
+ 'to False in Sphinx 8, meaning that request timeouts '
82
+ "will be reported with a new 'timeout' status, instead of as 'broken'. "
83
+ 'This is intended to provide more detail as to the failure mode. '
84
+ 'See https://github.com/sphinx-doc/sphinx/issues/11868 for details.'
85
+ )
86
+ warnings.warn(deprecation_msg, RemovedInSphinx80Warning, stacklevel=1)
87
+
69
88
  def finish(self) -> None:
70
89
  checker = HyperlinkAvailabilityChecker(self.config)
71
90
  logger.info('')
@@ -77,7 +96,7 @@ class CheckExternalLinksBuilder(DummyBuilder):
77
96
  for result in checker.check(self.hyperlinks):
78
97
  self.process_result(result)
79
98
 
80
- if self.broken_hyperlinks:
99
+ if self.broken_hyperlinks or self.timed_out_hyperlinks:
81
100
  self.app.statuscode = 1
82
101
 
83
102
  def process_result(self, result: CheckResult) -> None:
@@ -104,6 +123,15 @@ class CheckExternalLinksBuilder(DummyBuilder):
104
123
  self.write_entry('local', result.docname, filename, result.lineno, result.uri)
105
124
  elif result.status == 'working':
106
125
  logger.info(darkgreen('ok ') + result.uri + result.message)
126
+ elif result.status == 'timeout':
127
+ if self.app.quiet or self.app.warningiserror:
128
+ logger.warning('timeout ' + result.uri + result.message,
129
+ location=(result.docname, result.lineno))
130
+ else:
131
+ logger.info(red('timeout ') + result.uri + red(' - ' + result.message))
132
+ self.write_entry('timeout', result.docname, filename, result.lineno,
133
+ result.uri + ': ' + result.message)
134
+ self.timed_out_hyperlinks += 1
107
135
  elif result.status == 'broken':
108
136
  if self.app.quiet or self.app.warningiserror:
109
137
  logger.warning(__('broken link: %s (%s)'), result.uri, result.message,
@@ -206,7 +234,7 @@ class HyperlinkAvailabilityChecker:
206
234
  self.to_ignore: list[re.Pattern[str]] = list(map(re.compile,
207
235
  self.config.linkcheck_ignore))
208
236
 
209
- def check(self, hyperlinks: dict[str, Hyperlink]) -> Generator[CheckResult, None, None]:
237
+ def check(self, hyperlinks: dict[str, Hyperlink]) -> Iterator[CheckResult]:
210
238
  self.invoke_threads()
211
239
 
212
240
  total_links = 0
@@ -283,6 +311,11 @@ class HyperlinkAvailabilityCheckWorker(Thread):
283
311
  self.allowed_redirects = config.linkcheck_allowed_redirects
284
312
  self.retries: int = config.linkcheck_retries
285
313
  self.rate_limit_timeout = config.linkcheck_rate_limit_timeout
314
+ self._allow_unauthorized = config.linkcheck_allow_unauthorized
315
+ if config.linkcheck_report_timeouts_as_broken:
316
+ self._timeout_status = 'broken'
317
+ else:
318
+ self._timeout_status = 'timeout'
286
319
 
287
320
  self.user_agent = config.user_agent
288
321
  self.tls_verify = config.tls_verify
@@ -384,7 +417,7 @@ class HyperlinkAvailabilityCheckWorker(Thread):
384
417
  req_url = encode_uri(req_url)
385
418
 
386
419
  # Get auth info, if any
387
- for pattern, auth_info in self.auth: # noqa: B007 (false positive)
420
+ for pattern, auth_info in self.auth: # NoQA: B007 (false positive)
388
421
  if pattern.match(uri):
389
422
  break
390
423
  else:
@@ -424,6 +457,9 @@ class HyperlinkAvailabilityCheckWorker(Thread):
424
457
  del response
425
458
  break
426
459
 
460
+ except RequestTimeout as err:
461
+ return self._timeout_status, str(err), 0
462
+
427
463
  except SSLError as err:
428
464
  # SSL failure; report that the link is broken.
429
465
  return 'broken', str(err), 0
@@ -437,9 +473,31 @@ class HyperlinkAvailabilityCheckWorker(Thread):
437
473
  except HTTPError as err:
438
474
  error_message = str(err)
439
475
 
440
- # Unauthorised: the reference probably exists
476
+ # Unauthorized: the client did not provide required credentials
441
477
  if status_code == 401:
442
- return 'working', 'unauthorized', 0
478
+ if self._allow_unauthorized:
479
+ deprecation_msg = (
480
+ "\n---\n"
481
+ "The linkcheck builder encountered an HTTP 401 "
482
+ "(unauthorized) response, and will report it as "
483
+ "'working' in this version of Sphinx to maintain "
484
+ "backwards-compatibility."
485
+ "\n"
486
+ "This logic will change in Sphinx 8.0 which will "
487
+ "report the hyperlink as 'broken'."
488
+ "\n"
489
+ "To explicitly continue treating unauthorized "
490
+ "hyperlink responses as 'working', set the "
491
+ "'linkcheck_allow_unauthorized' config option to "
492
+ "``True``."
493
+ "\n"
494
+ "See https://github.com/sphinx-doc/sphinx/issues/11433 "
495
+ "for details."
496
+ "\n---"
497
+ )
498
+ warnings.warn(deprecation_msg, RemovedInSphinx80Warning, stacklevel=1)
499
+ status = 'working' if self._allow_unauthorized else 'broken'
500
+ return status, 'unauthorized', 0
443
501
 
444
502
  # Rate limiting; back-off if allowed, or report failure otherwise
445
503
  if status_code == 429:
@@ -534,7 +592,6 @@ def _get_request_headers(
534
592
 
535
593
  def contains_anchor(response: Response, anchor: str) -> bool:
536
594
  """Determine if an anchor is contained within an HTTP response."""
537
-
538
595
  parser = AnchorCheckParser(unquote(anchor))
539
596
  # Read file in chunks. If we find a matching anchor, we break
540
597
  # the loop early in hopes not to have to download the whole thing.
@@ -607,24 +664,26 @@ def compile_linkcheck_allowed_redirects(app: Sphinx, config: Config) -> None:
607
664
  app.config.linkcheck_allowed_redirects.pop(url)
608
665
 
609
666
 
610
- def setup(app: Sphinx) -> dict[str, Any]:
667
+ def setup(app: Sphinx) -> ExtensionMetadata:
611
668
  app.add_builder(CheckExternalLinksBuilder)
612
669
  app.add_post_transform(HyperlinkCollector)
613
670
 
614
- app.add_config_value('linkcheck_ignore', [], False)
615
- app.add_config_value('linkcheck_exclude_documents', [], False)
616
- app.add_config_value('linkcheck_allowed_redirects', {}, False)
617
- app.add_config_value('linkcheck_auth', [], False)
618
- app.add_config_value('linkcheck_request_headers', {}, False)
619
- app.add_config_value('linkcheck_retries', 1, False)
620
- app.add_config_value('linkcheck_timeout', None, False, [int, float])
621
- app.add_config_value('linkcheck_workers', 5, False)
622
- app.add_config_value('linkcheck_anchors', True, False)
671
+ app.add_config_value('linkcheck_ignore', [], '')
672
+ app.add_config_value('linkcheck_exclude_documents', [], '')
673
+ app.add_config_value('linkcheck_allowed_redirects', {}, '')
674
+ app.add_config_value('linkcheck_auth', [], '')
675
+ app.add_config_value('linkcheck_request_headers', {}, '')
676
+ app.add_config_value('linkcheck_retries', 1, '')
677
+ app.add_config_value('linkcheck_timeout', 30, '', (int, float))
678
+ app.add_config_value('linkcheck_workers', 5, '')
679
+ app.add_config_value('linkcheck_anchors', True, '')
623
680
  # Anchors starting with ! are ignored since they are
624
681
  # commonly used for dynamic pages
625
- app.add_config_value('linkcheck_anchors_ignore', ['^!'], False)
626
- app.add_config_value('linkcheck_anchors_ignore_for_url', (), False, (tuple, list))
627
- app.add_config_value('linkcheck_rate_limit_timeout', 300.0, False)
682
+ app.add_config_value('linkcheck_anchors_ignore', ['^!'], '')
683
+ app.add_config_value('linkcheck_anchors_ignore_for_url', (), '', (tuple, list))
684
+ app.add_config_value('linkcheck_rate_limit_timeout', 300.0, '')
685
+ app.add_config_value('linkcheck_allow_unauthorized', True, '')
686
+ app.add_config_value('linkcheck_report_timeouts_as_broken', True, '', bool)
628
687
 
629
688
  app.add_event('linkcheck-process-uri')
630
689
 
@@ -13,7 +13,7 @@ from sphinx import addnodes
13
13
  from sphinx.builders import Builder
14
14
  from sphinx.locale import __
15
15
  from sphinx.util import logging
16
- from sphinx.util.console import darkgreen # type: ignore[attr-defined]
16
+ from sphinx.util.console import darkgreen
17
17
  from sphinx.util.display import progress_message
18
18
  from sphinx.util.nodes import inline_all_toctrees
19
19
  from sphinx.util.osutil import ensuredir, make_filename_from_project
@@ -22,6 +22,7 @@ from sphinx.writers.manpage import ManualPageTranslator, ManualPageWriter
22
22
  if TYPE_CHECKING:
23
23
  from sphinx.application import Sphinx
24
24
  from sphinx.config import Config
25
+ from sphinx.util.typing import ExtensionMetadata
25
26
 
26
27
  logger = logging.getLogger(__name__)
27
28
 
@@ -30,6 +31,7 @@ class ManualPageBuilder(Builder):
30
31
  """
31
32
  Builds groff output in manual page format.
32
33
  """
34
+
33
35
  name = 'man'
34
36
  format = 'man'
35
37
  epilog = __('The manual pages are in %(outdir)s.')
@@ -107,18 +109,18 @@ class ManualPageBuilder(Builder):
107
109
 
108
110
 
109
111
  def default_man_pages(config: Config) -> list[tuple[str, str, str, list[str], int]]:
110
- """ Better default man_pages settings. """
112
+ """Better default man_pages settings."""
111
113
  filename = make_filename_from_project(config.project)
112
114
  return [(config.root_doc, filename, f'{config.project} {config.release}',
113
115
  [config.author], 1)]
114
116
 
115
117
 
116
- def setup(app: Sphinx) -> dict[str, Any]:
118
+ def setup(app: Sphinx) -> ExtensionMetadata:
117
119
  app.add_builder(ManualPageBuilder)
118
120
 
119
- app.add_config_value('man_pages', default_man_pages, False)
120
- app.add_config_value('man_show_urls', False, False)
121
- app.add_config_value('man_make_section_directory', False, False)
121
+ app.add_config_value('man_pages', default_man_pages, '')
122
+ app.add_config_value('man_show_urls', False, '')
123
+ app.add_config_value('man_make_section_directory', False, '')
122
124
 
123
125
  return {
124
126
  'version': 'builtin',
@@ -11,7 +11,7 @@ from sphinx.builders.html import StandaloneHTMLBuilder
11
11
  from sphinx.environment.adapters.toctree import global_toctree_for_doc
12
12
  from sphinx.locale import __
13
13
  from sphinx.util import logging
14
- from sphinx.util.console import darkgreen # type: ignore[attr-defined]
14
+ from sphinx.util.console import darkgreen
15
15
  from sphinx.util.display import progress_message
16
16
  from sphinx.util.nodes import inline_all_toctrees
17
17
 
@@ -19,6 +19,7 @@ if TYPE_CHECKING:
19
19
  from docutils.nodes import Node
20
20
 
21
21
  from sphinx.application import Sphinx
22
+ from sphinx.util.typing import ExtensionMetadata
22
23
 
23
24
  logger = logging.getLogger(__name__)
24
25
 
@@ -28,6 +29,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
28
29
  A StandaloneHTMLBuilder subclass that puts the whole document tree on one
29
30
  HTML page.
30
31
  """
32
+
31
33
  name = 'singlehtml'
32
34
  epilog = __('The HTML page is in %(outdir)s.')
33
35
 
@@ -39,8 +41,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
39
41
  def get_target_uri(self, docname: str, typ: str | None = None) -> str:
40
42
  if docname in self.env.all_docs:
41
43
  # all references are on the same page...
42
- return self.config.root_doc + self.out_suffix + \
43
- '#document-' + docname
44
+ return '#document-' + docname
44
45
  else:
45
46
  # chances are this is a html_additional_page
46
47
  return docname + self.out_suffix
@@ -189,7 +190,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
189
190
  self.handle_page('opensearch', {}, 'opensearch.xml', outfilename=fn)
190
191
 
191
192
 
192
- def setup(app: Sphinx) -> dict[str, Any]:
193
+ def setup(app: Sphinx) -> ExtensionMetadata:
193
194
  app.setup_extension('sphinx.builders.html')
194
195
 
195
196
  app.add_builder(SingleFileHTMLBuilder)
@@ -17,7 +17,7 @@ from sphinx.environment.adapters.asset import ImageAdapter
17
17
  from sphinx.errors import NoUri
18
18
  from sphinx.locale import _, __
19
19
  from sphinx.util import logging
20
- from sphinx.util.console import darkgreen # type: ignore[attr-defined]
20
+ from sphinx.util.console import darkgreen
21
21
  from sphinx.util.display import progress_message, status_iterator
22
22
  from sphinx.util.docutils import new_document
23
23
  from sphinx.util.fileutil import copy_asset_file
@@ -32,6 +32,7 @@ if TYPE_CHECKING:
32
32
 
33
33
  from sphinx.application import Sphinx
34
34
  from sphinx.config import Config
35
+ from sphinx.util.typing import ExtensionMetadata
35
36
 
36
37
  logger = logging.getLogger(__name__)
37
38
  template_dir = os.path.join(package_dir, 'templates', 'texinfo')
@@ -41,6 +42,7 @@ class TexinfoBuilder(Builder):
41
42
  """
42
43
  Builds Texinfo output to create Info documentation.
43
44
  """
45
+
44
46
  name = 'texinfo'
45
47
  format = 'texinfo'
46
48
  epilog = __('The Texinfo files are in %(outdir)s.')
@@ -133,7 +135,7 @@ class TexinfoBuilder(Builder):
133
135
  def assemble_doctree(
134
136
  self, indexfile: str, toctree_only: bool, appendices: list[str],
135
137
  ) -> nodes.document:
136
- self.docnames = set([indexfile] + appendices)
138
+ self.docnames = {indexfile, *appendices}
137
139
  logger.info(darkgreen(indexfile) + " ", nonl=True)
138
140
  tree = self.env.get_doctree(indexfile)
139
141
  tree['docname'] = indexfile
@@ -165,9 +167,11 @@ class TexinfoBuilder(Builder):
165
167
  newnodes: list[Node] = [nodes.emphasis(sectname, sectname)]
166
168
  for subdir, title in self.titles:
167
169
  if docname.startswith(subdir):
168
- newnodes.append(nodes.Text(_(' (in ')))
169
- newnodes.append(nodes.emphasis(title, title))
170
- newnodes.append(nodes.Text(')'))
170
+ newnodes.extend((
171
+ nodes.Text(_(' (in ')),
172
+ nodes.emphasis(title, title),
173
+ nodes.Text(')'),
174
+ ))
171
175
  break
172
176
  else:
173
177
  pass
@@ -205,22 +209,22 @@ class TexinfoBuilder(Builder):
205
209
  def default_texinfo_documents(
206
210
  config: Config,
207
211
  ) -> list[tuple[str, str, str, str, str, str, str]]:
208
- """ Better default texinfo_documents settings. """
212
+ """Better default texinfo_documents settings."""
209
213
  filename = make_filename_from_project(config.project)
210
214
  return [(config.root_doc, filename, config.project, config.author, filename,
211
215
  'One line description of project', 'Miscellaneous')]
212
216
 
213
217
 
214
- def setup(app: Sphinx) -> dict[str, Any]:
218
+ def setup(app: Sphinx) -> ExtensionMetadata:
215
219
  app.add_builder(TexinfoBuilder)
216
220
 
217
- app.add_config_value('texinfo_documents', default_texinfo_documents, False)
218
- app.add_config_value('texinfo_appendices', [], False)
219
- app.add_config_value('texinfo_elements', {}, False)
220
- app.add_config_value('texinfo_domain_indices', True, False, [list])
221
- app.add_config_value('texinfo_show_urls', 'footnote', False)
222
- app.add_config_value('texinfo_no_detailmenu', False, False)
223
- app.add_config_value('texinfo_cross_references', True, False)
221
+ app.add_config_value('texinfo_documents', default_texinfo_documents, '')
222
+ app.add_config_value('texinfo_appendices', [], '')
223
+ app.add_config_value('texinfo_elements', {}, '')
224
+ app.add_config_value('texinfo_domain_indices', True, '', list)
225
+ app.add_config_value('texinfo_show_urls', 'footnote', '')
226
+ app.add_config_value('texinfo_no_detailmenu', False, '')
227
+ app.add_config_value('texinfo_cross_references', True, '')
224
228
 
225
229
  return {
226
230
  'version': 'builtin',
sphinx/builders/text.py CHANGED
@@ -3,7 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from os import path
6
- from typing import TYPE_CHECKING, Any
6
+ from typing import TYPE_CHECKING
7
7
 
8
8
  from docutils.io import StringOutput
9
9
 
@@ -19,6 +19,7 @@ if TYPE_CHECKING:
19
19
  from docutils.nodes import Node
20
20
 
21
21
  from sphinx.application import Sphinx
22
+ from sphinx.util.typing import ExtensionMetadata
22
23
 
23
24
  logger = logging.getLogger(__name__)
24
25
 
@@ -79,7 +80,7 @@ class TextBuilder(Builder):
79
80
  pass
80
81
 
81
82
 
82
- def setup(app: Sphinx) -> dict[str, Any]:
83
+ def setup(app: Sphinx) -> ExtensionMetadata:
83
84
  app.add_builder(TextBuilder)
84
85
 
85
86
  app.add_config_value('text_sectionchars', '*=-~"+`', 'env')
sphinx/builders/xml.py CHANGED
@@ -3,7 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from os import path
6
- from typing import TYPE_CHECKING, Any
6
+ from typing import TYPE_CHECKING
7
7
 
8
8
  from docutils import nodes
9
9
  from docutils.io import StringOutput
@@ -21,6 +21,7 @@ if TYPE_CHECKING:
21
21
  from docutils.nodes import Node
22
22
 
23
23
  from sphinx.application import Sphinx
24
+ from sphinx.util.typing import ExtensionMetadata
24
25
 
25
26
  logger = logging.getLogger(__name__)
26
27
 
@@ -29,6 +30,7 @@ class XMLBuilder(Builder):
29
30
  """
30
31
  Builds Docutils-native XML.
31
32
  """
33
+
32
34
  name = 'xml'
33
35
  format = 'xml'
34
36
  epilog = __('The XML files are in %(outdir)s.')
@@ -101,6 +103,7 @@ class PseudoXMLBuilder(XMLBuilder):
101
103
  """
102
104
  Builds pseudo-XML for display purposes.
103
105
  """
106
+
104
107
  name = 'pseudoxml'
105
108
  format = 'pseudoxml'
106
109
  epilog = __('The pseudo-XML files are in %(outdir)s.')
@@ -110,7 +113,7 @@ class PseudoXMLBuilder(XMLBuilder):
110
113
  _writer_class = PseudoXMLWriter
111
114
 
112
115
 
113
- def setup(app: Sphinx) -> dict[str, Any]:
116
+ def setup(app: Sphinx) -> ExtensionMetadata:
114
117
  app.add_builder(XMLBuilder)
115
118
  app.add_builder(PseudoXMLBuilder)
116
119