Sphinx 8.0.1__py3-none-any.whl → 8.1.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 (424) hide show
  1. sphinx/__init__.py +6 -3
  2. sphinx/_cli/__init__.py +40 -20
  3. sphinx/_cli/util/colour.py +5 -4
  4. sphinx/_cli/util/errors.py +28 -11
  5. sphinx/application.py +361 -38
  6. sphinx/builders/__init__.py +229 -83
  7. sphinx/builders/_epub_base.py +118 -71
  8. sphinx/builders/changes.py +39 -21
  9. sphinx/builders/dirhtml.py +4 -4
  10. sphinx/builders/dummy.py +2 -5
  11. sphinx/builders/epub3.py +43 -22
  12. sphinx/builders/gettext.py +43 -25
  13. sphinx/builders/html/__init__.py +284 -218
  14. sphinx/builders/html/_assets.py +62 -26
  15. sphinx/builders/html/_build_info.py +76 -0
  16. sphinx/builders/html/transforms.py +11 -9
  17. sphinx/builders/latex/__init__.py +139 -81
  18. sphinx/builders/latex/constants.py +7 -7
  19. sphinx/builders/latex/nodes.py +3 -2
  20. sphinx/builders/latex/theming.py +7 -5
  21. sphinx/builders/latex/transforms.py +27 -19
  22. sphinx/builders/linkcheck.py +146 -72
  23. sphinx/builders/manpage.py +30 -13
  24. sphinx/builders/singlehtml.py +22 -14
  25. sphinx/builders/texinfo.py +67 -37
  26. sphinx/builders/text.py +5 -5
  27. sphinx/builders/xml.py +6 -9
  28. sphinx/cmd/build.py +282 -103
  29. sphinx/cmd/make_mode.py +106 -63
  30. sphinx/cmd/quickstart.py +341 -145
  31. sphinx/config.py +45 -12
  32. sphinx/deprecation.py +8 -2
  33. sphinx/directives/__init__.py +28 -19
  34. sphinx/directives/code.py +86 -56
  35. sphinx/directives/other.py +50 -36
  36. sphinx/directives/patches.py +29 -19
  37. sphinx/domains/__init__.py +20 -120
  38. sphinx/domains/_domains_container.py +281 -0
  39. sphinx/domains/_index.py +110 -0
  40. sphinx/domains/c/__init__.py +3 -3
  41. sphinx/domains/c/_parser.py +10 -6
  42. sphinx/domains/changeset.py +5 -3
  43. sphinx/domains/citation.py +5 -3
  44. sphinx/domains/cpp/__init__.py +9 -11
  45. sphinx/domains/cpp/_parser.py +8 -7
  46. sphinx/domains/index.py +3 -3
  47. sphinx/domains/javascript.py +12 -7
  48. sphinx/domains/math.py +2 -2
  49. sphinx/domains/python/__init__.py +10 -5
  50. sphinx/domains/python/_object.py +1 -1
  51. sphinx/domains/rst.py +5 -5
  52. sphinx/domains/std/__init__.py +16 -11
  53. sphinx/environment/__init__.py +206 -146
  54. sphinx/environment/adapters/asset.py +3 -2
  55. sphinx/environment/adapters/indexentries.py +74 -33
  56. sphinx/environment/adapters/toctree.py +100 -43
  57. sphinx/environment/collectors/__init__.py +19 -8
  58. sphinx/environment/collectors/asset.py +47 -15
  59. sphinx/environment/collectors/dependencies.py +8 -4
  60. sphinx/environment/collectors/metadata.py +7 -2
  61. sphinx/environment/collectors/title.py +7 -2
  62. sphinx/environment/collectors/toctree.py +54 -22
  63. sphinx/errors.py +4 -1
  64. sphinx/events.py +314 -7
  65. sphinx/ext/apidoc.py +42 -18
  66. sphinx/ext/autodoc/__init__.py +52 -24
  67. sphinx/ext/autodoc/importer.py +6 -9
  68. sphinx/ext/autosectionlabel.py +1 -2
  69. sphinx/ext/autosummary/__init__.py +3 -1
  70. sphinx/ext/autosummary/generate.py +28 -14
  71. sphinx/ext/coverage.py +7 -7
  72. sphinx/ext/doctest.py +4 -8
  73. sphinx/ext/duration.py +6 -5
  74. sphinx/ext/inheritance_diagram.py +1 -1
  75. sphinx/ext/intersphinx/_cli.py +6 -4
  76. sphinx/ext/intersphinx/_load.py +77 -32
  77. sphinx/ext/intersphinx/_resolve.py +173 -79
  78. sphinx/ext/intersphinx/_shared.py +7 -5
  79. sphinx/ext/linkcode.py +7 -1
  80. sphinx/ext/mathjax.py +1 -2
  81. sphinx/ext/napoleon/__init__.py +37 -24
  82. sphinx/ext/napoleon/docstring.py +202 -134
  83. sphinx/ext/todo.py +5 -3
  84. sphinx/highlighting.py +10 -3
  85. sphinx/io.py +1 -1
  86. sphinx/jinja2glue.py +27 -6
  87. sphinx/locale/__init__.py +6 -2
  88. sphinx/locale/ar/LC_MESSAGES/sphinx.js +8 -1
  89. sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
  90. sphinx/locale/ar/LC_MESSAGES/sphinx.po +2246 -2288
  91. sphinx/locale/bg/LC_MESSAGES/sphinx.js +4 -1
  92. sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
  93. sphinx/locale/bg/LC_MESSAGES/sphinx.po +2113 -2159
  94. sphinx/locale/bn/LC_MESSAGES/sphinx.js +4 -1
  95. sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
  96. sphinx/locale/bn/LC_MESSAGES/sphinx.po +2349 -2395
  97. sphinx/locale/ca/LC_MESSAGES/sphinx.js +4 -1
  98. sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
  99. sphinx/locale/ca/LC_MESSAGES/sphinx.po +2846 -2892
  100. sphinx/locale/cak/LC_MESSAGES/sphinx.js +4 -1
  101. sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
  102. sphinx/locale/cak/LC_MESSAGES/sphinx.po +2213 -2259
  103. sphinx/locale/cs/LC_MESSAGES/sphinx.js +6 -1
  104. sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
  105. sphinx/locale/cs/LC_MESSAGES/sphinx.po +2225 -2269
  106. sphinx/locale/cy/LC_MESSAGES/sphinx.js +6 -1
  107. sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
  108. sphinx/locale/cy/LC_MESSAGES/sphinx.po +2403 -2447
  109. sphinx/locale/da/LC_MESSAGES/sphinx.js +4 -1
  110. sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
  111. sphinx/locale/da/LC_MESSAGES/sphinx.po +2214 -2260
  112. sphinx/locale/de/LC_MESSAGES/sphinx.js +4 -1
  113. sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
  114. sphinx/locale/de/LC_MESSAGES/sphinx.po +2230 -2276
  115. sphinx/locale/de_DE/LC_MESSAGES/sphinx.js +4 -1
  116. sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
  117. sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2113 -2159
  118. sphinx/locale/el/LC_MESSAGES/sphinx.js +4 -1
  119. sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
  120. sphinx/locale/el/LC_MESSAGES/sphinx.po +2619 -2665
  121. sphinx/locale/en_DE/LC_MESSAGES/sphinx.js +4 -1
  122. sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
  123. sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2113 -2159
  124. sphinx/locale/en_FR/LC_MESSAGES/sphinx.js +4 -1
  125. sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
  126. sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2113 -2159
  127. sphinx/locale/en_GB/LC_MESSAGES/sphinx.js +4 -1
  128. sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
  129. sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2519 -2565
  130. sphinx/locale/en_HK/LC_MESSAGES/sphinx.js +4 -1
  131. sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
  132. sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2113 -2159
  133. sphinx/locale/eo/LC_MESSAGES/sphinx.js +4 -1
  134. sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
  135. sphinx/locale/eo/LC_MESSAGES/sphinx.po +2232 -2278
  136. sphinx/locale/es/LC_MESSAGES/sphinx.js +5 -1
  137. sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
  138. sphinx/locale/es/LC_MESSAGES/sphinx.po +2516 -2561
  139. sphinx/locale/es_CO/LC_MESSAGES/sphinx.js +5 -1
  140. sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
  141. sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2114 -2159
  142. sphinx/locale/et/LC_MESSAGES/sphinx.js +4 -1
  143. sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
  144. sphinx/locale/et/LC_MESSAGES/sphinx.po +2317 -2363
  145. sphinx/locale/eu/LC_MESSAGES/sphinx.js +4 -1
  146. sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
  147. sphinx/locale/eu/LC_MESSAGES/sphinx.po +2218 -2264
  148. sphinx/locale/fa/LC_MESSAGES/sphinx.js +4 -1
  149. sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
  150. sphinx/locale/fa/LC_MESSAGES/sphinx.po +2505 -2551
  151. sphinx/locale/fi/LC_MESSAGES/sphinx.js +4 -1
  152. sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
  153. sphinx/locale/fi/LC_MESSAGES/sphinx.po +2303 -2349
  154. sphinx/locale/fr/LC_MESSAGES/sphinx.js +6 -2
  155. sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
  156. sphinx/locale/fr/LC_MESSAGES/sphinx.po +2863 -2908
  157. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.js +5 -1
  158. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
  159. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +2114 -2159
  160. sphinx/locale/gl/LC_MESSAGES/sphinx.js +4 -1
  161. sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
  162. sphinx/locale/gl/LC_MESSAGES/sphinx.po +2571 -2617
  163. sphinx/locale/he/LC_MESSAGES/sphinx.js +5 -1
  164. sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
  165. sphinx/locale/he/LC_MESSAGES/sphinx.po +2307 -2352
  166. sphinx/locale/hi/LC_MESSAGES/sphinx.js +4 -1
  167. sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
  168. sphinx/locale/hi/LC_MESSAGES/sphinx.po +2580 -2626
  169. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.js +4 -1
  170. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
  171. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +2113 -2159
  172. sphinx/locale/hr/LC_MESSAGES/sphinx.js +5 -1
  173. sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
  174. sphinx/locale/hr/LC_MESSAGES/sphinx.po +2238 -2283
  175. sphinx/locale/hu/LC_MESSAGES/sphinx.js +4 -1
  176. sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
  177. sphinx/locale/hu/LC_MESSAGES/sphinx.po +2228 -2274
  178. sphinx/locale/id/LC_MESSAGES/sphinx.js +3 -1
  179. sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
  180. sphinx/locale/id/LC_MESSAGES/sphinx.po +2787 -2834
  181. sphinx/locale/is/LC_MESSAGES/sphinx.js +4 -1
  182. sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
  183. sphinx/locale/is/LC_MESSAGES/sphinx.po +2224 -2270
  184. sphinx/locale/it/LC_MESSAGES/sphinx.js +5 -1
  185. sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
  186. sphinx/locale/it/LC_MESSAGES/sphinx.po +2231 -2276
  187. sphinx/locale/ja/LC_MESSAGES/sphinx.js +3 -1
  188. sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
  189. sphinx/locale/ja/LC_MESSAGES/sphinx.po +2507 -2554
  190. sphinx/locale/ka/LC_MESSAGES/sphinx.js +4 -1
  191. sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
  192. sphinx/locale/ka/LC_MESSAGES/sphinx.po +2428 -2474
  193. sphinx/locale/ko/LC_MESSAGES/sphinx.js +3 -1
  194. sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
  195. sphinx/locale/ko/LC_MESSAGES/sphinx.po +2516 -2563
  196. sphinx/locale/lt/LC_MESSAGES/sphinx.js +6 -1
  197. sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
  198. sphinx/locale/lt/LC_MESSAGES/sphinx.po +2425 -2469
  199. sphinx/locale/lv/LC_MESSAGES/sphinx.js +5 -1
  200. sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
  201. sphinx/locale/lv/LC_MESSAGES/sphinx.po +2362 -2407
  202. sphinx/locale/mk/LC_MESSAGES/sphinx.js +4 -1
  203. sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
  204. sphinx/locale/mk/LC_MESSAGES/sphinx.po +2121 -2167
  205. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js +4 -1
  206. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
  207. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2220 -2266
  208. sphinx/locale/ne/LC_MESSAGES/sphinx.js +4 -1
  209. sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
  210. sphinx/locale/ne/LC_MESSAGES/sphinx.po +2221 -2267
  211. sphinx/locale/nl/LC_MESSAGES/sphinx.js +4 -1
  212. sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
  213. sphinx/locale/nl/LC_MESSAGES/sphinx.po +2240 -2286
  214. sphinx/locale/pl/LC_MESSAGES/sphinx.js +6 -1
  215. sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
  216. sphinx/locale/pl/LC_MESSAGES/sphinx.po +2319 -2363
  217. sphinx/locale/pt/LC_MESSAGES/sphinx.js +5 -1
  218. sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
  219. sphinx/locale/pt/LC_MESSAGES/sphinx.po +2114 -2159
  220. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js +5 -1
  221. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
  222. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2854 -2899
  223. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.js +5 -1
  224. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
  225. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2224 -2269
  226. sphinx/locale/ro/LC_MESSAGES/sphinx.js +5 -1
  227. sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
  228. sphinx/locale/ro/LC_MESSAGES/sphinx.po +2226 -2271
  229. sphinx/locale/ru/LC_MESSAGES/sphinx.js +8 -3
  230. sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
  231. sphinx/locale/ru/LC_MESSAGES/sphinx.po +2841 -2885
  232. sphinx/locale/si/LC_MESSAGES/sphinx.js +4 -1
  233. sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
  234. sphinx/locale/si/LC_MESSAGES/sphinx.po +2294 -2340
  235. sphinx/locale/sk/LC_MESSAGES/sphinx.js +6 -1
  236. sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
  237. sphinx/locale/sk/LC_MESSAGES/sphinx.po +2497 -2541
  238. sphinx/locale/sl/LC_MESSAGES/sphinx.js +6 -1
  239. sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
  240. sphinx/locale/sl/LC_MESSAGES/sphinx.po +2331 -2375
  241. sphinx/locale/sphinx.pot +2121 -2167
  242. sphinx/locale/sq/LC_MESSAGES/sphinx.js +4 -1
  243. sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
  244. sphinx/locale/sq/LC_MESSAGES/sphinx.po +2855 -2901
  245. sphinx/locale/sr/LC_MESSAGES/sphinx.js +5 -1
  246. sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
  247. sphinx/locale/sr/LC_MESSAGES/sphinx.po +2203 -2248
  248. sphinx/locale/sr@latin/LC_MESSAGES/sphinx.mo +0 -0
  249. sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo +0 -0
  250. sphinx/locale/sv/LC_MESSAGES/sphinx.js +4 -1
  251. sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
  252. sphinx/locale/sv/LC_MESSAGES/sphinx.po +2423 -2469
  253. sphinx/locale/te/LC_MESSAGES/sphinx.js +4 -1
  254. sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
  255. sphinx/locale/te/LC_MESSAGES/sphinx.po +2113 -2159
  256. sphinx/locale/tr/LC_MESSAGES/sphinx.js +4 -1
  257. sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
  258. sphinx/locale/tr/LC_MESSAGES/sphinx.po +2443 -2489
  259. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.js +6 -1
  260. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
  261. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2329 -2373
  262. sphinx/locale/ur/LC_MESSAGES/sphinx.js +4 -1
  263. sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
  264. sphinx/locale/ur/LC_MESSAGES/sphinx.po +2113 -2159
  265. sphinx/locale/vi/LC_MESSAGES/sphinx.js +3 -1
  266. sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
  267. sphinx/locale/vi/LC_MESSAGES/sphinx.po +2199 -2246
  268. sphinx/locale/yue/LC_MESSAGES/sphinx.js +3 -1
  269. sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
  270. sphinx/locale/yue/LC_MESSAGES/sphinx.po +2112 -2159
  271. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.js +3 -1
  272. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
  273. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2112 -2159
  274. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js +3 -1
  275. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
  276. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +2845 -2892
  277. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.js +3 -1
  278. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
  279. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2112 -2159
  280. sphinx/parsers.py +3 -1
  281. sphinx/project.py +6 -2
  282. sphinx/pycode/__init__.py +11 -4
  283. sphinx/pycode/ast.py +58 -58
  284. sphinx/pycode/parser.py +49 -28
  285. sphinx/pygments_styles.py +49 -49
  286. sphinx/registry.py +8 -3
  287. sphinx/roles.py +133 -13
  288. sphinx/search/__init__.py +146 -87
  289. sphinx/search/da.py +2 -4
  290. sphinx/search/de.py +2 -4
  291. sphinx/search/en.py +4 -4
  292. sphinx/search/es.py +2 -4
  293. sphinx/search/fi.py +2 -4
  294. sphinx/search/fr.py +2 -4
  295. sphinx/search/hu.py +2 -4
  296. sphinx/search/it.py +2 -4
  297. sphinx/search/ja.py +55 -32
  298. sphinx/search/nl.py +2 -4
  299. sphinx/search/no.py +2 -4
  300. sphinx/search/pt.py +2 -4
  301. sphinx/search/ro.py +0 -2
  302. sphinx/search/ru.py +2 -4
  303. sphinx/search/sv.py +2 -4
  304. sphinx/search/tr.py +0 -2
  305. sphinx/search/zh.py +18 -13
  306. sphinx/templates/graphviz/graphviz.css +0 -7
  307. sphinx/testing/fixtures.py +6 -5
  308. sphinx/testing/path.py +7 -5
  309. sphinx/testing/util.py +63 -29
  310. sphinx/texinputs/sphinx.sty +107 -39
  311. sphinx/texinputs/sphinxlatexadmonitions.sty +51 -35
  312. sphinx/texinputs/sphinxlatexcontainers.sty +1 -1
  313. sphinx/texinputs/sphinxlatexgraphics.sty +3 -2
  314. sphinx/texinputs/sphinxlatexindbibtoc.sty +1 -1
  315. sphinx/texinputs/sphinxlatexlists.sty +1 -1
  316. sphinx/texinputs/sphinxlatexliterals.sty +4 -1
  317. sphinx/texinputs/sphinxlatexnumfig.sty +22 -9
  318. sphinx/texinputs/sphinxlatexobjects.sty +1 -1
  319. sphinx/texinputs/sphinxlatexshadowbox.sty +72 -10
  320. sphinx/texinputs/sphinxlatexstyleheadings.sty +7 -2
  321. sphinx/texinputs/sphinxlatexstylepage.sty +2 -8
  322. sphinx/texinputs/sphinxlatexstyletext.sty +2 -4
  323. sphinx/texinputs/sphinxlatextables.sty +1 -1
  324. sphinx/texinputs/sphinxoptionsgeometry.sty +1 -1
  325. sphinx/texinputs/sphinxoptionshyperref.sty +1 -1
  326. sphinx/themes/agogo/layout.html +1 -10
  327. sphinx/themes/agogo/static/agogo.css.jinja +0 -7
  328. sphinx/themes/basic/defindex.html +1 -8
  329. sphinx/themes/basic/domainindex.html +1 -9
  330. sphinx/themes/basic/genindex-single.html +1 -9
  331. sphinx/themes/basic/genindex-split.html +1 -9
  332. sphinx/themes/basic/genindex.html +1 -9
  333. sphinx/themes/basic/globaltoc.html +1 -9
  334. sphinx/themes/basic/layout.html +1 -9
  335. sphinx/themes/basic/localtoc.html +1 -9
  336. sphinx/themes/basic/page.html +1 -9
  337. sphinx/themes/basic/relations.html +1 -9
  338. sphinx/themes/basic/search.html +1 -9
  339. sphinx/themes/basic/searchbox.html +1 -9
  340. sphinx/themes/basic/searchfield.html +4 -10
  341. sphinx/themes/basic/sourcelink.html +1 -9
  342. sphinx/themes/basic/static/basic.css.jinja +2 -13
  343. sphinx/themes/basic/static/doctools.js +0 -7
  344. sphinx/themes/basic/static/language_data.js.jinja +0 -7
  345. sphinx/themes/basic/static/searchtools.js +25 -13
  346. sphinx/themes/bizstyle/layout.html +1 -9
  347. sphinx/themes/bizstyle/static/bizstyle.css.jinja +0 -7
  348. sphinx/themes/bizstyle/static/bizstyle.js.jinja +5 -11
  349. sphinx/themes/classic/layout.html +1 -9
  350. sphinx/themes/classic/static/classic.css.jinja +0 -7
  351. sphinx/themes/classic/static/sidebar.js.jinja +0 -6
  352. sphinx/themes/epub/epub-cover.html +1 -9
  353. sphinx/themes/epub/layout.html +1 -9
  354. sphinx/themes/epub/static/epub.css.jinja +0 -7
  355. sphinx/themes/haiku/layout.html +1 -9
  356. sphinx/themes/haiku/static/haiku.css.jinja +0 -6
  357. sphinx/themes/nature/static/nature.css.jinja +0 -7
  358. sphinx/themes/nonav/layout.html +1 -9
  359. sphinx/themes/nonav/static/nonav.css.jinja +0 -7
  360. sphinx/themes/pyramid/static/epub.css.jinja +0 -7
  361. sphinx/themes/pyramid/static/pyramid.css.jinja +0 -7
  362. sphinx/themes/scrolls/layout.html +1 -10
  363. sphinx/themes/scrolls/static/scrolls.css.jinja +0 -7
  364. sphinx/themes/sphinxdoc/static/sphinxdoc.css.jinja +2 -7
  365. sphinx/themes/traditional/static/traditional.css.jinja +0 -7
  366. sphinx/theming.py +18 -6
  367. sphinx/transforms/__init__.py +56 -35
  368. sphinx/transforms/compact_bullet_list.py +3 -2
  369. sphinx/transforms/i18n.py +132 -50
  370. sphinx/transforms/post_transforms/__init__.py +94 -43
  371. sphinx/transforms/post_transforms/code.py +7 -6
  372. sphinx/transforms/post_transforms/images.py +71 -54
  373. sphinx/transforms/references.py +1 -2
  374. sphinx/util/__init__.py +23 -194
  375. sphinx/util/_files.py +80 -0
  376. sphinx/util/_importer.py +27 -0
  377. sphinx/util/_io.py +1 -2
  378. sphinx/util/_lines.py +26 -0
  379. sphinx/util/_pathlib.py +5 -2
  380. sphinx/util/_serialise.py +53 -0
  381. sphinx/util/_timestamps.py +2 -1
  382. sphinx/util/_uri.py +16 -0
  383. sphinx/util/cfamily.py +48 -25
  384. sphinx/util/console.py +1 -0
  385. sphinx/util/display.py +1 -1
  386. sphinx/util/docfields.py +125 -45
  387. sphinx/util/docstrings.py +1 -1
  388. sphinx/util/docutils.py +118 -44
  389. sphinx/util/exceptions.py +11 -5
  390. sphinx/util/fileutil.py +53 -32
  391. sphinx/util/http_date.py +9 -7
  392. sphinx/util/i18n.py +49 -16
  393. sphinx/util/images.py +7 -6
  394. sphinx/util/inspect.py +29 -12
  395. sphinx/util/inventory.py +47 -29
  396. sphinx/util/logging.py +58 -85
  397. sphinx/util/matching.py +3 -3
  398. sphinx/util/math.py +1 -1
  399. sphinx/util/nodes.py +176 -108
  400. sphinx/util/osutil.py +13 -10
  401. sphinx/util/parallel.py +5 -4
  402. sphinx/util/parsing.py +5 -3
  403. sphinx/util/png.py +3 -3
  404. sphinx/util/requests.py +8 -4
  405. sphinx/util/rst.py +5 -3
  406. sphinx/util/tags.py +5 -2
  407. sphinx/util/template.py +26 -11
  408. sphinx/util/texescape.py +2 -2
  409. sphinx/util/typing.py +89 -38
  410. sphinx/versioning.py +3 -1
  411. sphinx/writers/html.py +22 -7
  412. sphinx/writers/html5.py +113 -64
  413. sphinx/writers/latex.py +408 -221
  414. sphinx/writers/manpage.py +25 -15
  415. sphinx/writers/texinfo.py +94 -82
  416. sphinx/writers/text.py +87 -53
  417. sphinx/writers/xml.py +5 -4
  418. sphinx-8.1.0.dist-info/LICENSE.rst +31 -0
  419. {sphinx-8.0.1.dist-info → sphinx-8.1.0.dist-info}/METADATA +13 -11
  420. sphinx-8.1.0.dist-info/RECORD +598 -0
  421. sphinx-8.0.1.dist-info/LICENSE.rst +0 -67
  422. sphinx-8.0.1.dist-info/RECORD +0 -590
  423. {sphinx-8.0.1.dist-info → sphinx-8.1.0.dist-info}/WHEEL +0 -0
  424. {sphinx-8.0.1.dist-info → sphinx-8.1.0.dist-info}/entry_points.txt +0 -0
sphinx/roles.py CHANGED
@@ -88,15 +88,15 @@ class XRefRole(ReferenceRole):
88
88
 
89
89
  def update_title_and_target(self, title: str, target: str) -> tuple[str, str]:
90
90
  if not self.has_explicit_title:
91
- if title.endswith('()'):
92
- # remove parentheses
93
- title = title[:-2]
94
91
  if self.config.add_function_parentheses:
95
- # add them back to all occurrences if configured
96
- title += '()'
97
- # remove parentheses from the target too
98
- if target.endswith('()'):
99
- target = target[:-2]
92
+ if not title.endswith('()'):
93
+ # add parentheses to the title
94
+ title += '()'
95
+ else:
96
+ # remove parentheses
97
+ title = title.removesuffix('()')
98
+ # remove parentheses from the target
99
+ target = target.removesuffix('()')
100
100
  return title, target
101
101
 
102
102
  def run(self) -> tuple[list[Node], list[system_message]]:
@@ -167,7 +167,11 @@ class XRefRole(ReferenceRole):
167
167
  return title, ws_re.sub(' ', target)
168
168
 
169
169
  def result_nodes(
170
- self, document: nodes.document, env: BuildEnvironment, node: Element, is_ref: bool
170
+ self,
171
+ document: nodes.document,
172
+ env: BuildEnvironment,
173
+ node: Element,
174
+ is_ref: bool,
171
175
  ) -> tuple[list[Node], list[system_message]]:
172
176
  """Called before returning the finished nodes. *node* is the reference
173
177
  node if one was created (*is_ref* is then true), else the content node.
@@ -192,6 +196,94 @@ class AnyXRefRole(XRefRole):
192
196
  return result
193
197
 
194
198
 
199
+ class CVE(ReferenceRole):
200
+ def run(self) -> tuple[list[Node], list[system_message]]:
201
+ target_id = f'index-{self.env.new_serialno("index")}'
202
+ entries = [
203
+ (
204
+ 'single',
205
+ _('Common Vulnerabilities and Exposures; CVE %s') % self.target,
206
+ target_id,
207
+ '',
208
+ None,
209
+ )
210
+ ]
211
+
212
+ index = addnodes.index(entries=entries)
213
+ target = nodes.target('', '', ids=[target_id])
214
+ self.inliner.document.note_explicit_target(target)
215
+
216
+ try:
217
+ refuri = self.build_uri()
218
+ reference = nodes.reference(
219
+ '', '', internal=False, refuri=refuri, classes=['cve']
220
+ )
221
+ if self.has_explicit_title:
222
+ reference += nodes.strong(self.title, self.title)
223
+ else:
224
+ title = f'CVE {self.title}'
225
+ reference += nodes.strong(title, title)
226
+ except ValueError:
227
+ msg = self.inliner.reporter.error(
228
+ __('invalid CVE number %s') % self.target, line=self.lineno
229
+ )
230
+ prb = self.inliner.problematic(self.rawtext, self.rawtext, msg)
231
+ return [prb], [msg]
232
+
233
+ return [index, target, reference], []
234
+
235
+ def build_uri(self) -> str:
236
+ base_url = self.inliner.document.settings.cve_base_url
237
+ ret = self.target.split('#', 1)
238
+ if len(ret) == 2:
239
+ return f'{base_url}{ret[0]}#{ret[1]}'
240
+ return f'{base_url}{ret[0]}'
241
+
242
+
243
+ class CWE(ReferenceRole):
244
+ def run(self) -> tuple[list[Node], list[system_message]]:
245
+ target_id = f'index-{self.env.new_serialno("index")}'
246
+ entries = [
247
+ (
248
+ 'single',
249
+ _('Common Weakness Enumeration; CWE %s') % self.target,
250
+ target_id,
251
+ '',
252
+ None,
253
+ )
254
+ ]
255
+
256
+ index = addnodes.index(entries=entries)
257
+ target = nodes.target('', '', ids=[target_id])
258
+ self.inliner.document.note_explicit_target(target)
259
+
260
+ try:
261
+ refuri = self.build_uri()
262
+ reference = nodes.reference(
263
+ '', '', internal=False, refuri=refuri, classes=['cwe']
264
+ )
265
+ if self.has_explicit_title:
266
+ reference += nodes.strong(self.title, self.title)
267
+ else:
268
+ title = f'CWE {self.title}'
269
+ reference += nodes.strong(title, title)
270
+ except ValueError:
271
+ msg = self.inliner.reporter.error(
272
+ __('invalid CWE number %s') % self.target, line=self.lineno
273
+ )
274
+ prb = self.inliner.problematic(self.rawtext, self.rawtext, msg)
275
+ return [prb], [msg]
276
+
277
+ return [index, target, reference], []
278
+
279
+ def build_uri(self) -> str:
280
+ base_url = self.inliner.document.settings.cwe_base_url
281
+ ret = self.target.split('#', 1)
282
+ if len(ret) == 2:
283
+ return f'{base_url}{int(ret[0])}.html#{ret[1]}'
284
+ return f'{base_url}{int(ret[0])}.html'
285
+
286
+
195
287
  class PEP(ReferenceRole):
196
288
  def run(self) -> tuple[list[Node], list[system_message]]:
197
289
  target_id = 'index-%s' % self.env.new_serialno('index')
@@ -211,7 +303,9 @@ class PEP(ReferenceRole):
211
303
 
212
304
  try:
213
305
  refuri = self.build_uri()
214
- reference = nodes.reference('', '', internal=False, refuri=refuri, classes=['pep'])
306
+ reference = nodes.reference(
307
+ '', '', internal=False, refuri=refuri, classes=['pep']
308
+ )
215
309
  if self.has_explicit_title:
216
310
  reference += nodes.strong(self.title, self.title)
217
311
  else:
@@ -238,7 +332,8 @@ class PEP(ReferenceRole):
238
332
  class RFC(ReferenceRole):
239
333
  def run(self) -> tuple[list[Node], list[system_message]]:
240
334
  target_id = 'index-%s' % self.env.new_serialno('index')
241
- entries = [('single', 'RFC; RFC %s' % self.target, target_id, '', None)]
335
+ formatted_target = _format_rfc_target(self.target)
336
+ entries = [('single', f'RFC; {formatted_target}', target_id, '', None)]
242
337
 
243
338
  index = addnodes.index(entries=entries)
244
339
  target = nodes.target('', '', ids=[target_id])
@@ -246,11 +341,13 @@ class RFC(ReferenceRole):
246
341
 
247
342
  try:
248
343
  refuri = self.build_uri()
249
- reference = nodes.reference('', '', internal=False, refuri=refuri, classes=['rfc'])
344
+ reference = nodes.reference(
345
+ '', '', internal=False, refuri=refuri, classes=['rfc']
346
+ )
250
347
  if self.has_explicit_title:
251
348
  reference += nodes.strong(self.title, self.title)
252
349
  else:
253
- title = 'RFC ' + self.title
350
+ title = formatted_target
254
351
  reference += nodes.strong(title, title)
255
352
  except ValueError:
256
353
  msg = self.inliner.reporter.error(
@@ -270,6 +367,24 @@ class RFC(ReferenceRole):
270
367
  return base_url + self.inliner.rfc_url % int(ret[0])
271
368
 
272
369
 
370
+ def _format_rfc_target(target: str, /) -> str:
371
+ """
372
+ Takes an RFC number with an optional anchor (like ``123#section-2.5.3``)
373
+ and attempts to produce a human-friendly title for it.
374
+
375
+ We have a set of known anchors that we format nicely,
376
+ everything else we leave alone.
377
+ """
378
+ number, _, anchor = target.partition('#')
379
+ if anchor:
380
+ first, _, remaining = anchor.partition('-')
381
+ if first in {'appendix', 'page', 'section'}:
382
+ if remaining:
383
+ return f'RFC {number} {first.title()} {remaining}'
384
+ return f'RFC {number} {first.title()}'
385
+ return f'RFC {target}'
386
+
387
+
273
388
  class GUILabel(SphinxRole):
274
389
  amp_re = re.compile(r'(?<!&)&(?![&\s])')
275
390
 
@@ -446,12 +561,17 @@ specific_docroles: dict[str, RoleFunction] = {
446
561
  'download': XRefRole(nodeclass=addnodes.download_reference),
447
562
  # links to anything
448
563
  'any': AnyXRefRole(warn_dangling=True),
564
+ # external links
565
+ 'cve': CVE(),
566
+ 'cwe': CWE(),
449
567
  'pep': PEP(),
450
568
  'rfc': RFC(),
569
+ # emphasised things
451
570
  'guilabel': GUILabel(),
452
571
  'menuselection': MenuSelection(),
453
572
  'file': EmphasizedLiteral(),
454
573
  'samp': EmphasizedLiteral(),
574
+ # other
455
575
  'abbr': Abbreviation(),
456
576
  'manpage': Manpage(),
457
577
  }
sphinx/search/__init__.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Create a full-text search index for offline search."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import dataclasses
@@ -15,11 +16,12 @@ from docutils import nodes
15
16
  from docutils.nodes import Element, Node
16
17
 
17
18
  from sphinx import addnodes, package_dir
18
- from sphinx.environment import BuildEnvironment
19
19
  from sphinx.util.index_entries import split_index_msg
20
20
 
21
21
  if TYPE_CHECKING:
22
- from collections.abc import Iterable
22
+ from collections.abc import Callable, Iterable
23
+
24
+ from sphinx.environment import BuildEnvironment
23
25
 
24
26
 
25
27
  class SearchLanguage:
@@ -52,10 +54,11 @@ class SearchLanguage:
52
54
  This class is used to preprocess search word which Sphinx HTML readers
53
55
  type, before searching index. Default implementation does nothing.
54
56
  """
57
+
55
58
  lang: str = ''
56
59
  language_name: str = ''
57
60
  stopwords: set[str] = set()
58
- js_splitter_code: str = ""
61
+ js_splitter_code: str = ''
59
62
  js_stemmer_rawcode: str = ''
60
63
  js_stemmer_code = """
61
64
  /**
@@ -105,16 +108,14 @@ var Stemmer = function() {
105
108
  Return true if the target word should be registered in the search index.
106
109
  This method is called after stemming.
107
110
  """
108
- return (
109
- len(word) == 0 or not (
110
- ((len(word) < 3) and (12353 < ord(word[0]) < 12436)) or
111
- (ord(word[0]) < 256 and (
112
- word in self.stopwords
113
- ))))
111
+ return len(word) == 0 or not (
112
+ ((len(word) < 3) and (12353 < ord(word[0]) < 12436))
113
+ or (ord(word[0]) < 256 and (word in self.stopwords))
114
+ )
114
115
 
115
116
 
116
117
  # SearchEnglish imported after SearchLanguage is defined due to circular import
117
- from sphinx.search.en import SearchEnglish
118
+ from sphinx.search.en import SearchEnglish # NoQA: E402
118
119
 
119
120
 
120
121
  def parse_stop_word(source: str) -> set[str]:
@@ -165,10 +166,10 @@ class _JavaScriptIndex:
165
166
  return self.PREFIX + json.dumps(data, sort_keys=True) + self.SUFFIX
166
167
 
167
168
  def loads(self, s: str) -> Any:
168
- data = s[len(self.PREFIX):-len(self.SUFFIX)]
169
- if not data or not s.startswith(self.PREFIX) or not \
170
- s.endswith(self.SUFFIX):
171
- raise ValueError('invalid data')
169
+ data = s[len(self.PREFIX) : -len(self.SUFFIX)]
170
+ if not data or not s.startswith(self.PREFIX) or not s.endswith(self.SUFFIX):
171
+ msg = 'invalid data'
172
+ raise ValueError(msg)
172
173
  return json.loads(data)
173
174
 
174
175
  def dump(self, data: Any, f: IO[str]) -> None:
@@ -187,9 +188,8 @@ def _is_meta_keywords(
187
188
  ) -> bool:
188
189
  if node.get('name') == 'keywords':
189
190
  meta_lang = node.get('lang')
190
- if meta_lang is None: # lang not specified
191
- return True
192
- elif meta_lang == lang: # matched to html_search_language
191
+ if meta_lang is None or meta_lang == lang:
192
+ # lang not specified or matched to html_search_language
193
193
  return True
194
194
 
195
195
  return False
@@ -222,8 +222,18 @@ class WordCollector(nodes.NodeVisitor):
222
222
  # Some people might put content in raw HTML that should be searched,
223
223
  # so we just amateurishly strip HTML tags and index the remaining
224
224
  # content
225
- nodetext = re.sub(r'<style.*?</style>', '', node.astext(), flags=re.IGNORECASE|re.DOTALL)
226
- nodetext = re.sub(r'<script.*?</script>', '', nodetext, flags=re.IGNORECASE|re.DOTALL)
225
+ nodetext = re.sub(
226
+ r'<style.*?</style>',
227
+ '',
228
+ node.astext(),
229
+ flags=re.IGNORECASE | re.DOTALL,
230
+ )
231
+ nodetext = re.sub(
232
+ r'<script.*?</script>',
233
+ '',
234
+ nodetext,
235
+ flags=re.IGNORECASE | re.DOTALL,
236
+ )
227
237
  nodetext = re.sub(r'<[^<]+?>', '', nodetext)
228
238
  self.found_words.extend(self.lang.split(nodetext))
229
239
  raise nodes.SkipNode
@@ -245,12 +255,15 @@ class IndexBuilder:
245
255
  Helper class that creates a search index based on the doctrees
246
256
  passed to the `feed` method.
247
257
  """
258
+
248
259
  formats = {
249
- 'json': json,
250
- 'pickle': pickle
260
+ 'json': json,
261
+ 'pickle': pickle,
251
262
  }
252
263
 
253
- def __init__(self, env: BuildEnvironment, lang: str, options: dict[str, str], scoring: str) -> None:
264
+ def __init__(
265
+ self, env: BuildEnvironment, lang: str, options: dict[str, str], scoring: str
266
+ ) -> None:
254
267
  self.env = env
255
268
  # docname -> title
256
269
  self._titles: dict[str, str | None] = env._search_index_titles
@@ -261,9 +274,13 @@ class IndexBuilder:
261
274
  # stemmed words in titles -> set(docname)
262
275
  self._title_mapping: dict[str, set[str]] = env._search_index_title_mapping
263
276
  # docname -> all titles in document
264
- self._all_titles: dict[str, list[tuple[str, str | None]]] = env._search_index_all_titles
277
+ self._all_titles: dict[str, list[tuple[str, str | None]]] = (
278
+ env._search_index_all_titles
279
+ )
265
280
  # docname -> list(index entry)
266
- self._index_entries: dict[str, list[tuple[str, str, str]]] = env._search_index_index_entries
281
+ self._index_entries: dict[str, list[tuple[str, str, str]]] = (
282
+ env._search_index_index_entries
283
+ )
267
284
  # objtype -> index
268
285
  self._objtypes: dict[tuple[str, str], int] = env._search_index_objtypes
269
286
  # objtype index -> (domain, type, objname (localized))
@@ -290,7 +307,7 @@ class IndexBuilder:
290
307
  self.js_scorer_code = fp.read().decode()
291
308
  else:
292
309
  self.js_scorer_code = ''
293
- self.js_splitter_code = ""
310
+ self.js_splitter_code = ''
294
311
 
295
312
  def load(self, stream: IO, format: Any) -> None:
296
313
  """Reconstruct from frozen data."""
@@ -298,15 +315,15 @@ class IndexBuilder:
298
315
  format = self.formats[format]
299
316
  frozen = format.load(stream)
300
317
  # if an old index is present, we treat it as not existing.
301
- if not isinstance(frozen, dict) or \
302
- frozen.get('envversion') != self.env.version:
303
- raise ValueError('old format')
318
+ if not isinstance(frozen, dict) or frozen.get('envversion') != self.env.version:
319
+ msg = 'old format'
320
+ raise ValueError(msg)
304
321
  index2fn = frozen['docnames']
305
- self._filenames = dict(zip(index2fn, frozen['filenames']))
306
- self._titles = dict(zip(index2fn, frozen['titles']))
322
+ self._filenames = dict(zip(index2fn, frozen['filenames'], strict=True))
323
+ self._titles = dict(zip(index2fn, frozen['titles'], strict=True))
307
324
  self._all_titles = {}
308
325
 
309
- for docname in self._titles.keys():
326
+ for docname in self._titles:
310
327
  self._all_titles[docname] = []
311
328
  for title, doc_tuples in frozen['alltitles'].items():
312
329
  for doc, titleid in doc_tuples:
@@ -331,14 +348,15 @@ class IndexBuilder:
331
348
  format = self.formats[format]
332
349
  format.dump(self.freeze(), stream)
333
350
 
334
- def get_objects(self, fn2index: dict[str, int]
335
- ) -> dict[str, list[tuple[int, int, int, str, str]]]:
351
+ def get_objects(
352
+ self, fn2index: dict[str, int]
353
+ ) -> dict[str, list[tuple[int, int, int, str, str]]]:
336
354
  rv: dict[str, list[tuple[int, int, int, str, str]]] = {}
337
355
  otypes = self._objtypes
338
356
  onames = self._objnames
339
- for domainname, domain in sorted(self.env.domains.items()):
340
- for fullname, dispname, type, docname, anchor, prio in \
341
- sorted(domain.get_objects()):
357
+ for domain in self.env.domains.sorted():
358
+ sorted_objects = sorted(domain.get_objects())
359
+ for fullname, dispname, type, docname, anchor, prio in sorted_objects:
342
360
  if docname not in fn2index:
343
361
  continue
344
362
  if prio < 0:
@@ -348,17 +366,20 @@ class IndexBuilder:
348
366
  prefix, _, name = dispname.rpartition('.')
349
367
  plist = rv.setdefault(prefix, [])
350
368
  try:
351
- typeindex = otypes[domainname, type]
369
+ typeindex = otypes[domain.name, type]
352
370
  except KeyError:
353
371
  typeindex = len(otypes)
354
- otypes[domainname, type] = typeindex
372
+ otypes[domain.name, type] = typeindex
355
373
  otype = domain.object_types.get(type)
356
374
  if otype:
357
375
  # use str() to fire translation proxies
358
- onames[typeindex] = (domainname, type,
359
- str(domain.get_type_name(otype)))
376
+ onames[typeindex] = (
377
+ domain.name,
378
+ type,
379
+ str(domain.get_type_name(otype)),
380
+ )
360
381
  else:
361
- onames[typeindex] = (domainname, type, type)
382
+ onames[typeindex] = (domain.name, type, type)
362
383
  if anchor == fullname:
363
384
  shortanchor = ''
364
385
  elif anchor == type + '-' + fullname:
@@ -368,7 +389,9 @@ class IndexBuilder:
368
389
  plist.append((fn2index[docname], typeindex, prio, shortanchor, name))
369
390
  return rv
370
391
 
371
- def get_terms(self, fn2index: dict[str, int]) -> tuple[dict[str, list[int] | int], dict[str, list[int] | int]]:
392
+ def get_terms(
393
+ self, fn2index: dict[str, int]
394
+ ) -> tuple[dict[str, list[int] | int], dict[str, list[int] | int]]:
372
395
  """
373
396
  Return a mapping of document and title terms to their corresponding sorted document IDs.
374
397
 
@@ -377,10 +400,10 @@ class IndexBuilder:
377
400
  of integers.
378
401
  """
379
402
  rvs: tuple[dict[str, list[int] | int], dict[str, list[int] | int]] = ({}, {})
380
- for rv, mapping in zip(rvs, (self._mapping, self._title_mapping)):
403
+ for rv, mapping in zip(rvs, (self._mapping, self._title_mapping), strict=True):
381
404
  for k, v in mapping.items():
382
405
  if len(v) == 1:
383
- fn, = v
406
+ (fn,) = v
384
407
  if fn in fn2index:
385
408
  rv[k] = fn2index[fn]
386
409
  else:
@@ -389,7 +412,7 @@ class IndexBuilder:
389
412
 
390
413
  def freeze(self) -> dict[str, Any]:
391
414
  """Create a usable data structure for serializing."""
392
- docnames, titles = zip(*sorted(self._titles.items()))
415
+ docnames, titles = zip(*sorted(self._titles.items()), strict=True)
393
416
  filenames = [self._filenames.get(docname) for docname in docnames]
394
417
  fn2index = {f: i for (i, f) in enumerate(docnames)}
395
418
  terms, title_terms = self.get_terms(fn2index)
@@ -406,15 +429,28 @@ class IndexBuilder:
406
429
  index_entries: dict[str, list[tuple[int, str, bool]]] = {}
407
430
  for docname, entries in self._index_entries.items():
408
431
  for entry, entry_id, main_entry in entries:
409
- index_entries.setdefault(entry.lower(), []).append((fn2index[docname], entry_id, main_entry == "main"))
432
+ index_entries.setdefault(entry.lower(), []).append((
433
+ fn2index[docname],
434
+ entry_id,
435
+ main_entry == 'main',
436
+ ))
410
437
 
411
- return dict(docnames=docnames, filenames=filenames, titles=titles, terms=terms,
412
- objects=objects, objtypes=objtypes, objnames=objnames,
413
- titleterms=title_terms, envversion=self.env.version,
414
- alltitles=alltitles, indexentries=index_entries)
438
+ return {
439
+ 'docnames': docnames,
440
+ 'filenames': filenames,
441
+ 'titles': titles,
442
+ 'terms': terms,
443
+ 'objects': objects,
444
+ 'objtypes': objtypes,
445
+ 'objnames': objnames,
446
+ 'titleterms': title_terms,
447
+ 'envversion': self.env.version,
448
+ 'alltitles': alltitles,
449
+ 'indexentries': index_entries,
450
+ }
415
451
 
416
452
  def label(self) -> str:
417
- return f"{self.lang.language_name} (code: {self.lang.lang})"
453
+ return f'{self.lang.language_name} (code: {self.lang.lang})'
418
454
 
419
455
  def prune(self, docnames: Iterable[str]) -> None:
420
456
  """Remove data for all docnames not in the list."""
@@ -434,7 +470,9 @@ class IndexBuilder:
434
470
  for wordnames in self._title_mapping.values():
435
471
  wordnames.intersection_update(docnames)
436
472
 
437
- def feed(self, docname: str, filename: str, title: str, doctree: nodes.document) -> None:
473
+ def feed(
474
+ self, docname: str, filename: str, title: str, doctree: nodes.document
475
+ ) -> None:
438
476
  """Feed a doctree to the index."""
439
477
  self._titles[docname] = title
440
478
  self._filenames[docname] = filename
@@ -487,40 +525,12 @@ class IndexBuilder:
487
525
  self._index_entries[docname] = sorted(_index_entries)
488
526
 
489
527
  def _word_collector(self, doctree: nodes.document) -> WordStore:
490
- def _visit_nodes(node: nodes.Node) -> None:
491
- if isinstance(node, nodes.comment):
492
- return
493
- elif isinstance(node, nodes.raw):
494
- if 'html' in node.get('format', '').split():
495
- # Some people might put content in raw HTML that should be searched,
496
- # so we just amateurishly strip HTML tags and index the remaining
497
- # content
498
- nodetext = re.sub(r'<style.*?</style>', '', node.astext(),
499
- flags=re.IGNORECASE | re.DOTALL)
500
- nodetext = re.sub(r'<script.*?</script>', '', nodetext,
501
- flags=re.IGNORECASE | re.DOTALL)
502
- nodetext = re.sub(r'<[^<]+?>', '', nodetext)
503
- word_store.words.extend(split(nodetext))
504
- return
505
- elif (isinstance(node, nodes.meta)
506
- and _is_meta_keywords(node, language)):
507
- keywords = [keyword.strip() for keyword in node['content'].split(',')]
508
- word_store.words.extend(keywords)
509
- elif isinstance(node, nodes.Text):
510
- word_store.words.extend(split(node.astext()))
511
- elif isinstance(node, nodes.title):
512
- title, is_main_title = node.astext(), len(word_store.titles) == 0
513
- ids = node.parent['ids']
514
- title_node_id = None if is_main_title else ids[0] if ids else None
515
- word_store.titles.append((title, title_node_id))
516
- word_store.title_words.extend(split(title))
517
- for child in node.children:
518
- _visit_nodes(child)
519
-
520
528
  word_store = WordStore()
521
529
  split = self.lang.split
522
530
  language = self.lang.lang
523
- _visit_nodes(doctree)
531
+ _feed_visit_nodes(
532
+ doctree, word_store=word_store, split=split, language=language
533
+ )
524
534
  return word_store
525
535
 
526
536
  def context_for_searchtool(self) -> dict[str, Any]:
@@ -553,11 +563,60 @@ class IndexBuilder:
553
563
  """Returns JS code that will be inserted into language_data.js."""
554
564
  if self.lang.js_stemmer_rawcode:
555
565
  js_dir = path.join(package_dir, 'search', 'minified-js')
556
- with open(path.join(js_dir, 'base-stemmer.js'), encoding='utf-8') as js_file:
566
+ with open(
567
+ path.join(js_dir, 'base-stemmer.js'), encoding='utf-8'
568
+ ) as js_file:
557
569
  base_js = js_file.read()
558
- with open(path.join(js_dir, self.lang.js_stemmer_rawcode), encoding='utf-8') as js_file:
570
+ with open(
571
+ path.join(js_dir, self.lang.js_stemmer_rawcode), encoding='utf-8'
572
+ ) as js_file:
559
573
  language_js = js_file.read()
560
- return ('%s\n%s\nStemmer = %sStemmer;' %
561
- (base_js, language_js, self.lang.language_name))
574
+ return (
575
+ f'{base_js}\n{language_js}\nStemmer = {self.lang.language_name}Stemmer;'
576
+ )
562
577
  else:
563
578
  return self.lang.js_stemmer_code
579
+
580
+
581
+ def _feed_visit_nodes(
582
+ node: nodes.Node,
583
+ *,
584
+ word_store: WordStore,
585
+ split: Callable[[str], list[str]],
586
+ language: str,
587
+ ) -> None:
588
+ if isinstance(node, nodes.comment):
589
+ return
590
+ elif isinstance(node, nodes.raw):
591
+ if 'html' in node.get('format', '').split():
592
+ # Some people might put content in raw HTML that should be searched,
593
+ # so we just amateurishly strip HTML tags and index the remaining
594
+ # content
595
+ nodetext = re.sub(
596
+ r'<style.*?</style>',
597
+ '',
598
+ node.astext(),
599
+ flags=re.IGNORECASE | re.DOTALL,
600
+ )
601
+ nodetext = re.sub(
602
+ r'<script.*?</script>',
603
+ '',
604
+ nodetext,
605
+ flags=re.IGNORECASE | re.DOTALL,
606
+ )
607
+ nodetext = re.sub(r'<[^<]+?>', '', nodetext)
608
+ word_store.words.extend(split(nodetext))
609
+ return
610
+ elif isinstance(node, nodes.meta) and _is_meta_keywords(node, language):
611
+ keywords = [keyword.strip() for keyword in node['content'].split(',')]
612
+ word_store.words.extend(keywords)
613
+ elif isinstance(node, nodes.Text):
614
+ word_store.words.extend(split(node.astext()))
615
+ elif isinstance(node, nodes.title):
616
+ title, is_main_title = node.astext(), len(word_store.titles) == 0
617
+ ids = node.parent['ids']
618
+ title_node_id = None if is_main_title else ids[0] if ids else None
619
+ word_store.titles.append((title, title_node_id))
620
+ word_store.title_words.extend(split(title))
621
+ for child in node.children:
622
+ _feed_visit_nodes(child, word_store=word_store, split=split, language=language)
sphinx/search/da.py CHANGED
@@ -2,13 +2,11 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Dict
6
-
7
5
  import snowballstemmer
8
6
 
9
7
  from sphinx.search import SearchLanguage, parse_stop_word
10
8
 
11
- danish_stopwords = parse_stop_word('''
9
+ danish_stopwords = parse_stop_word("""
12
10
  | source: https://snowball.tartarus.org/algorithms/danish/stop.txt
13
11
  og | and
14
12
  i | in
@@ -104,7 +102,7 @@ været | be
104
102
  thi | for (conj)
105
103
  jer | you
106
104
  sådan | such, like this/like that
107
- ''')
105
+ """)
108
106
 
109
107
 
110
108
  class SearchDanish(SearchLanguage):
sphinx/search/de.py CHANGED
@@ -2,13 +2,11 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Dict
6
-
7
5
  import snowballstemmer
8
6
 
9
7
  from sphinx.search import SearchLanguage, parse_stop_word
10
8
 
11
- german_stopwords = parse_stop_word('''
9
+ german_stopwords = parse_stop_word("""
12
10
  |source: https://snowball.tartarus.org/algorithms/german/stop.txt
13
11
  aber | but
14
12
 
@@ -287,7 +285,7 @@ zum | zu + dem
287
285
  zur | zu + der
288
286
  zwar | indeed
289
287
  zwischen | between
290
- ''')
288
+ """)
291
289
 
292
290
 
293
291
  class SearchGerman(SearchLanguage):
sphinx/search/en.py CHANGED
@@ -2,13 +2,12 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Dict
6
-
7
5
  import snowballstemmer
8
6
 
9
7
  from sphinx.search import SearchLanguage
10
8
 
11
- english_stopwords = set("""
9
+ english_stopwords = set(
10
+ """
12
11
  a and are as at
13
12
  be but by
14
13
  for
@@ -18,7 +17,8 @@ of on or
18
17
  such
19
18
  that the their then there these they this to
20
19
  was will with
21
- """.split())
20
+ """.split()
21
+ )
22
22
 
23
23
  js_porter_stemmer = """
24
24
  /**