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
@@ -21,7 +21,8 @@ from requests.exceptions import Timeout as RequestTimeout
21
21
  from sphinx.builders.dummy import DummyBuilder
22
22
  from sphinx.locale import __
23
23
  from sphinx.transforms.post_transforms import SphinxPostTransform
24
- from sphinx.util import encode_uri, logging, requests
24
+ from sphinx.util import logging, requests
25
+ from sphinx.util._uri import encode_uri
25
26
  from sphinx.util.console import darkgray, darkgreen, purple, red, turquoise
26
27
  from sphinx.util.http_date import rfc1123_to_epoch
27
28
  from sphinx.util.nodes import get_node_line
@@ -39,7 +40,8 @@ if TYPE_CHECKING:
39
40
 
40
41
  logger = logging.getLogger(__name__)
41
42
 
42
- uri_re = re.compile('([a-z]+:)?//') # matches to foo:// and // (a protocol relative URL)
43
+ # matches to foo:// and // (a protocol relative URL)
44
+ uri_re = re.compile('([a-z]+:)?//')
43
45
 
44
46
  DEFAULT_REQUEST_HEADERS = {
45
47
  'Accept': 'text/html,application/xhtml+xml;q=0.9,*/*;q=0.8',
@@ -55,8 +57,7 @@ class CheckExternalLinksBuilder(DummyBuilder):
55
57
  """
56
58
 
57
59
  name = 'linkcheck'
58
- epilog = __('Look for any errors in the above output or in '
59
- '%(outdir)s/output.txt')
60
+ epilog = __('Look for any errors in the above output or in %(outdir)s/output.txt')
60
61
 
61
62
  def init(self) -> None:
62
63
  self.broken_hyperlinks = 0
@@ -71,8 +72,10 @@ class CheckExternalLinksBuilder(DummyBuilder):
71
72
 
72
73
  output_text = path.join(self.outdir, 'output.txt')
73
74
  output_json = path.join(self.outdir, 'output.json')
74
- with open(output_text, 'w', encoding='utf-8') as self.txt_outfile, \
75
- open(output_json, 'w', encoding='utf-8') as self.json_outfile:
75
+ with (
76
+ open(output_text, 'w', encoding='utf-8') as self.txt_outfile,
77
+ open(output_json, 'w', encoding='utf-8') as self.json_outfile,
78
+ ):
76
79
  for result in checker.check(self.hyperlinks):
77
80
  self.process_result(result)
78
81
 
@@ -83,9 +86,12 @@ class CheckExternalLinksBuilder(DummyBuilder):
83
86
  filename = self.env.doc2path(result.docname, False)
84
87
 
85
88
  linkstat: dict[str, str | int] = {
86
- 'filename': str(filename), 'lineno': result.lineno,
87
- 'status': result.status, 'code': result.code,
88
- 'uri': result.uri, 'info': result.message,
89
+ 'filename': str(filename),
90
+ 'lineno': result.lineno,
91
+ 'status': result.status,
92
+ 'code': result.code,
93
+ 'uri': result.uri,
94
+ 'info': result.message,
89
95
  }
90
96
  self.write_linkstat(linkstat)
91
97
 
@@ -102,26 +108,48 @@ class CheckExternalLinksBuilder(DummyBuilder):
102
108
  logger.info(darkgray('-ignored- ') + result.uri)
103
109
  elif result.status == 'local':
104
110
  logger.info(darkgray('-local- ') + result.uri)
105
- self.write_entry('local', result.docname, filename, result.lineno, result.uri)
111
+ self.write_entry(
112
+ 'local', result.docname, filename, result.lineno, result.uri
113
+ )
106
114
  elif result.status == 'working':
107
115
  logger.info(darkgreen('ok ') + result.uri + result.message)
108
116
  elif result.status == 'timeout':
109
- if self.app.quiet or self.app.warningiserror:
110
- logger.warning('timeout ' + result.uri + result.message,
111
- location=(result.docname, result.lineno))
117
+ if self.app.quiet:
118
+ logger.warning(
119
+ 'timeout ' + result.uri + result.message,
120
+ location=(result.docname, result.lineno),
121
+ )
112
122
  else:
113
- logger.info(red('timeout ') + result.uri + red(' - ' + result.message))
114
- self.write_entry('timeout', result.docname, filename, result.lineno,
115
- result.uri + ': ' + result.message)
123
+ logger.info(
124
+ red('timeout ') + result.uri + red(' - ' + result.message)
125
+ )
126
+ self.write_entry(
127
+ 'timeout',
128
+ result.docname,
129
+ filename,
130
+ result.lineno,
131
+ result.uri + ': ' + result.message,
132
+ )
116
133
  self.timed_out_hyperlinks += 1
117
134
  elif result.status == 'broken':
118
- if self.app.quiet or self.app.warningiserror:
119
- logger.warning(__('broken link: %s (%s)'), result.uri, result.message,
120
- location=(result.docname, result.lineno))
135
+ if self.app.quiet:
136
+ logger.warning(
137
+ __('broken link: %s (%s)'),
138
+ result.uri,
139
+ result.message,
140
+ location=(result.docname, result.lineno),
141
+ )
121
142
  else:
122
- logger.info(red('broken ') + result.uri + red(' - ' + result.message))
123
- self.write_entry('broken', result.docname, filename, result.lineno,
124
- result.uri + ': ' + result.message)
143
+ logger.info(
144
+ red('broken ') + result.uri + red(' - ' + result.message)
145
+ )
146
+ self.write_entry(
147
+ 'broken',
148
+ result.docname,
149
+ filename,
150
+ result.lineno,
151
+ result.uri + ': ' + result.message,
152
+ )
125
153
  self.broken_hyperlinks += 1
126
154
  elif result.status == 'redirected':
127
155
  try:
@@ -136,13 +164,23 @@ class CheckExternalLinksBuilder(DummyBuilder):
136
164
  text, color = ('with unknown code', purple)
137
165
  linkstat['text'] = text
138
166
  if self.config.linkcheck_allowed_redirects:
139
- logger.warning('redirect ' + result.uri + ' - ' + text + ' to ' +
140
- result.message, location=(result.docname, result.lineno))
167
+ logger.warning(
168
+ 'redirect ' + result.uri + ' - ' + text + ' to ' + result.message,
169
+ location=(result.docname, result.lineno),
170
+ )
141
171
  else:
142
- logger.info(color('redirect ') + result.uri +
143
- color(' - ' + text + ' to ' + result.message))
144
- self.write_entry('redirected ' + text, result.docname, filename,
145
- result.lineno, result.uri + ' to ' + result.message)
172
+ logger.info(
173
+ color('redirect ')
174
+ + result.uri
175
+ + color(' - ' + text + ' to ' + result.message)
176
+ )
177
+ self.write_entry(
178
+ 'redirected ' + text,
179
+ result.docname,
180
+ filename,
181
+ result.lineno,
182
+ result.uri + ' to ' + result.message,
183
+ )
146
184
  else:
147
185
  raise ValueError('Unknown status %s.' % result.status)
148
186
 
@@ -150,8 +188,9 @@ class CheckExternalLinksBuilder(DummyBuilder):
150
188
  self.json_outfile.write(json.dumps(data))
151
189
  self.json_outfile.write('\n')
152
190
 
153
- def write_entry(self, what: str, docname: str, filename: _StrPath, line: int,
154
- uri: str) -> None:
191
+ def write_entry(
192
+ self, what: str, docname: str, filename: _StrPath, line: int, uri: str
193
+ ) -> None:
155
194
  self.txt_outfile.write(f'{filename}:{line}: [{what}] {uri}\n')
156
195
 
157
196
 
@@ -220,7 +259,9 @@ class HyperlinkCollector(SphinxPostTransform):
220
259
  lineno = -1
221
260
 
222
261
  if uri not in hyperlinks:
223
- hyperlinks[uri] = Hyperlink(uri, docname, self.env.doc2path(docname), lineno)
262
+ hyperlinks[uri] = Hyperlink(
263
+ uri, docname, self.env.doc2path(docname), lineno
264
+ )
224
265
 
225
266
 
226
267
  class Hyperlink(NamedTuple):
@@ -239,8 +280,9 @@ class HyperlinkAvailabilityChecker:
239
280
  self.wqueue: PriorityQueue[CheckRequest] = PriorityQueue()
240
281
  self.num_workers: int = config.linkcheck_workers
241
282
 
242
- self.to_ignore: list[re.Pattern[str]] = list(map(re.compile,
243
- self.config.linkcheck_ignore))
283
+ self.to_ignore: list[re.Pattern[str]] = list(
284
+ map(re.compile, self.config.linkcheck_ignore)
285
+ )
244
286
 
245
287
  def check(self, hyperlinks: dict[str, Hyperlink]) -> Iterator[CheckResult]:
246
288
  self.invoke_threads()
@@ -248,8 +290,9 @@ class HyperlinkAvailabilityChecker:
248
290
  total_links = 0
249
291
  for hyperlink in hyperlinks.values():
250
292
  if self.is_ignored_uri(hyperlink.uri):
251
- yield CheckResult(hyperlink.uri, hyperlink.docname, hyperlink.lineno,
252
- 'ignored', '', 0)
293
+ yield CheckResult(
294
+ hyperlink.uri, hyperlink.docname, hyperlink.lineno, 'ignored', '', 0
295
+ )
253
296
  else:
254
297
  self.wqueue.put(CheckRequest(CHECK_IMMEDIATELY, hyperlink), False)
255
298
  total_links += 1
@@ -263,9 +306,9 @@ class HyperlinkAvailabilityChecker:
263
306
 
264
307
  def invoke_threads(self) -> None:
265
308
  for _i in range(self.num_workers):
266
- thread = HyperlinkAvailabilityCheckWorker(self.config,
267
- self.rqueue, self.wqueue,
268
- self.rate_limits)
309
+ thread = HyperlinkAvailabilityCheckWorker(
310
+ self.config, self.rqueue, self.wqueue, self.rate_limits
311
+ )
269
312
  thread.start()
270
313
  self.workers.append(thread)
271
314
 
@@ -295,25 +338,35 @@ class CheckResult(NamedTuple):
295
338
  class HyperlinkAvailabilityCheckWorker(Thread):
296
339
  """A worker class for checking the availability of hyperlinks."""
297
340
 
298
- def __init__(self, config: Config,
299
- rqueue: Queue[CheckResult],
300
- wqueue: Queue[CheckRequest],
301
- rate_limits: dict[str, RateLimit]) -> None:
341
+ def __init__(
342
+ self,
343
+ config: Config,
344
+ rqueue: Queue[CheckResult],
345
+ wqueue: Queue[CheckRequest],
346
+ rate_limits: dict[str, RateLimit],
347
+ ) -> None:
302
348
  self.rate_limits = rate_limits
303
349
  self.rqueue = rqueue
304
350
  self.wqueue = wqueue
305
351
 
306
352
  self.anchors_ignore: list[re.Pattern[str]] = list(
307
- map(re.compile, config.linkcheck_anchors_ignore))
353
+ map(re.compile, config.linkcheck_anchors_ignore)
354
+ )
308
355
  self.anchors_ignore_for_url: list[re.Pattern[str]] = list(
309
- map(re.compile, config.linkcheck_anchors_ignore_for_url))
356
+ map(re.compile, config.linkcheck_anchors_ignore_for_url)
357
+ )
310
358
  self.documents_exclude: list[re.Pattern[str]] = list(
311
- map(re.compile, config.linkcheck_exclude_documents))
312
- self.auth = [(re.compile(pattern), auth_info) for pattern, auth_info
313
- in config.linkcheck_auth]
359
+ map(re.compile, config.linkcheck_exclude_documents)
360
+ )
361
+ self.auth = [
362
+ (re.compile(pattern), auth_info)
363
+ for pattern, auth_info in config.linkcheck_auth
364
+ ]
314
365
 
315
366
  self.timeout: int | float | None = config.linkcheck_timeout
316
- self.request_headers: dict[str, dict[str, str]] = config.linkcheck_request_headers
367
+ self.request_headers: dict[str, dict[str, str]] = (
368
+ config.linkcheck_request_headers
369
+ )
317
370
  self.check_anchors: bool = config.linkcheck_anchors
318
371
  self.allowed_redirects: dict[re.Pattern[str], re.Pattern[str]]
319
372
  self.allowed_redirects = config.linkcheck_allowed_redirects
@@ -361,12 +414,16 @@ class HyperlinkAvailabilityCheckWorker(Thread):
361
414
  continue
362
415
  status, info, code = self._check(docname, uri, hyperlink)
363
416
  if status == 'rate-limited':
364
- logger.info(darkgray('-rate limited- ') + uri + darkgray(' | sleeping...'))
417
+ logger.info(
418
+ darkgray('-rate limited- ') + uri + darkgray(' | sleeping...')
419
+ )
365
420
  else:
366
421
  self.rqueue.put(CheckResult(uri, docname, lineno, status, info, code))
367
422
  self.wqueue.task_done()
368
423
 
369
- def _check(self, docname: str, uri: str, hyperlink: Hyperlink) -> tuple[str, str, int]:
424
+ def _check(
425
+ self, docname: str, uri: str, hyperlink: Hyperlink
426
+ ) -> tuple[str, str, int]:
370
427
  # check for various conditions without bothering the network
371
428
 
372
429
  for doc_matcher in self.documents_exclude:
@@ -445,10 +502,13 @@ class HyperlinkAvailabilityCheckWorker(Thread):
445
502
  error_message = ''
446
503
  status_code = -1
447
504
  response_url = retry_after = ''
448
- for retrieval_method, kwargs in self._retrieval_methods(self.check_anchors, anchor):
505
+ for retrieval_method, kwargs in self._retrieval_methods(
506
+ self.check_anchors, anchor
507
+ ):
449
508
  try:
450
509
  with retrieval_method(
451
- url=req_url, auth=auth_info,
510
+ url=req_url,
511
+ auth=auth_info,
452
512
  headers=headers,
453
513
  timeout=self.timeout,
454
514
  **kwargs,
@@ -461,11 +521,17 @@ class HyperlinkAvailabilityCheckWorker(Thread):
461
521
  except UnicodeDecodeError:
462
522
  return 'ignored', 'unable to decode response content', 0
463
523
  if not found:
464
- return 'broken', __("Anchor '%s' not found") % quote(anchor), 0
524
+ return (
525
+ 'broken',
526
+ __("Anchor '%s' not found") % quote(anchor),
527
+ 0,
528
+ )
465
529
 
466
530
  # Copy data we need from the (closed) response
467
531
  status_code = response.status_code
468
- redirect_status_code = response.history[-1].status_code if response.history else None # NoQA: E501
532
+ redirect_status_code = (
533
+ response.history[-1].status_code if response.history else None
534
+ ) # NoQA: E501
469
535
  retry_after = response.headers.get('Retry-After', '')
470
536
  response_url = f'{response.url}'
471
537
  response.raise_for_status()
@@ -521,9 +587,10 @@ class HyperlinkAvailabilityCheckWorker(Thread):
521
587
  netloc = urlsplit(req_url).netloc
522
588
  self.rate_limits.pop(netloc, None)
523
589
 
524
- if ((response_url.rstrip('/') == req_url.rstrip('/'))
525
- or _allowed_redirect(req_url, response_url,
526
- self.allowed_redirects)):
590
+ if (
591
+ (response_url.rstrip('/') == req_url.rstrip('/'))
592
+ or _allowed_redirect(req_url, response_url, self.allowed_redirects)
593
+ ): # fmt: skip
527
594
  return 'working', '', 0
528
595
  elif redirect_status_code is not None:
529
596
  return 'redirected', response_url, redirect_status_code
@@ -573,10 +640,12 @@ def _get_request_headers(
573
640
  request_headers: dict[str, dict[str, str]],
574
641
  ) -> dict[str, str]:
575
642
  url = urlsplit(uri)
576
- candidates = (f'{url.scheme}://{url.netloc}',
577
- f'{url.scheme}://{url.netloc}/',
578
- uri,
579
- '*')
643
+ candidates = (
644
+ f'{url.scheme}://{url.netloc}',
645
+ f'{url.scheme}://{url.netloc}/',
646
+ uri,
647
+ '*',
648
+ )
580
649
 
581
650
  for u in candidates:
582
651
  if u in request_headers:
@@ -590,8 +659,9 @@ def contains_anchor(response: Response, anchor: str) -> bool:
590
659
  # Read file in chunks. If we find a matching anchor, we break
591
660
  # the loop early in hopes not to have to download the whole thing.
592
661
  for chunk in response.iter_content(chunk_size=4096, decode_unicode=True):
593
- if isinstance(chunk, bytes): # requests failed to decode
594
- chunk = chunk.decode() # manually try to decode it
662
+ if isinstance(chunk, bytes):
663
+ # requests failed to decode, manually try to decode it
664
+ chunk = chunk.decode()
595
665
 
596
666
  parser.feed(chunk)
597
667
  if parser.found:
@@ -616,12 +686,12 @@ class AnchorCheckParser(HTMLParser):
616
686
  break
617
687
 
618
688
 
619
- def _allowed_redirect(url: str, new_url: str,
620
- allowed_redirects: dict[re.Pattern[str], re.Pattern[str]]) -> bool:
689
+ def _allowed_redirect(
690
+ url: str, new_url: str, allowed_redirects: dict[re.Pattern[str], re.Pattern[str]]
691
+ ) -> bool:
621
692
  return any(
622
693
  from_url.match(url) and to_url.match(new_url)
623
- for from_url, to_url
624
- in allowed_redirects.items()
694
+ for from_url, to_url in allowed_redirects.items()
625
695
  )
626
696
 
627
697
 
@@ -647,15 +717,19 @@ def rewrite_github_anchor(app: Sphinx, uri: str) -> str | None:
647
717
 
648
718
  def compile_linkcheck_allowed_redirects(app: Sphinx, config: Config) -> None:
649
719
  """Compile patterns in linkcheck_allowed_redirects to the regexp objects."""
650
- for url, pattern in list(app.config.linkcheck_allowed_redirects.items()):
720
+ linkcheck_allowed_redirects = app.config.linkcheck_allowed_redirects
721
+ for url, pattern in list(linkcheck_allowed_redirects.items()):
651
722
  try:
652
- app.config.linkcheck_allowed_redirects[re.compile(url)] = re.compile(pattern)
723
+ linkcheck_allowed_redirects[re.compile(url)] = re.compile(pattern)
653
724
  except re.error as exc:
654
- logger.warning(__('Failed to compile regex in linkcheck_allowed_redirects: %r %s'),
655
- exc.pattern, exc.msg)
725
+ logger.warning(
726
+ __('Failed to compile regex in linkcheck_allowed_redirects: %r %s'),
727
+ exc.pattern,
728
+ exc.msg,
729
+ )
656
730
  finally:
657
731
  # Remove the original regexp-string
658
- app.config.linkcheck_allowed_redirects.pop(url)
732
+ linkcheck_allowed_redirects.pop(url)
659
733
 
660
734
 
661
735
  def setup(app: Sphinx) -> ExtensionMetadata:
@@ -20,6 +20,8 @@ from sphinx.util.osutil import ensuredir, make_filename_from_project
20
20
  from sphinx.writers.manpage import ManualPageTranslator, ManualPageWriter
21
21
 
22
22
  if TYPE_CHECKING:
23
+ from collections.abc import Set
24
+
23
25
  from sphinx.application import Sphinx
24
26
  from sphinx.config import Config
25
27
  from sphinx.util.typing import ExtensionMetadata
@@ -41,8 +43,12 @@ class ManualPageBuilder(Builder):
41
43
 
42
44
  def init(self) -> None:
43
45
  if not self.config.man_pages:
44
- logger.warning(__('no "man_pages" config value found; no manual pages '
45
- 'will be written'))
46
+ logger.warning(
47
+ __(
48
+ 'no "man_pages" config value found; no manual pages '
49
+ 'will be written'
50
+ )
51
+ )
46
52
 
47
53
  def get_outdated_docs(self) -> str | list[str]:
48
54
  return 'all manpages' # for now
@@ -51,7 +57,7 @@ class ManualPageBuilder(Builder):
51
57
  return ''
52
58
 
53
59
  @progress_message(__('writing'))
54
- def write(self, *ignored: Any) -> None:
60
+ def write_documents(self, _docnames: Set[str]) -> None:
55
61
  docwriter = ManualPageWriter(self)
56
62
  with warnings.catch_warnings():
57
63
  warnings.filterwarnings('ignore', category=DeprecationWarning)
@@ -60,13 +66,16 @@ class ManualPageBuilder(Builder):
60
66
  docsettings: Any = OptionParser(
61
67
  defaults=self.env.settings,
62
68
  components=(docwriter,),
63
- read_config_files=True).get_default_values()
69
+ read_config_files=True,
70
+ ).get_default_values()
64
71
 
65
72
  for info in self.config.man_pages:
66
73
  docname, name, description, authors, section = info
67
74
  if docname not in self.env.all_docs:
68
- logger.warning(__('"man_pages" config value references unknown '
69
- 'document %s'), docname)
75
+ logger.warning(
76
+ __('"man_pages" config value references unknown ' 'document %s'),
77
+ docname,
78
+ )
70
79
  continue
71
80
  if isinstance(authors, str):
72
81
  if authors:
@@ -86,15 +95,16 @@ class ManualPageBuilder(Builder):
86
95
  else:
87
96
  targetname = f'{name}.{section}'
88
97
 
89
- logger.info(darkgreen(targetname) + ' { ', nonl=True)
98
+ logger.info(darkgreen(targetname) + ' { ')
90
99
  destination = FileOutput(
91
- destination_path=path.join(self.outdir, targetname),
92
- encoding='utf-8')
100
+ destination_path=path.join(self.outdir, targetname), encoding='utf-8'
101
+ )
93
102
 
94
103
  tree = self.env.get_doctree(docname)
95
104
  docnames: set[str] = set()
96
- largetree = inline_all_toctrees(self, docnames, docname, tree,
97
- darkgreen, [docname])
105
+ largetree = inline_all_toctrees(
106
+ self, docnames, docname, tree, darkgreen, [docname]
107
+ )
98
108
  largetree.settings = docsettings
99
109
  logger.info('} ', nonl=True)
100
110
  self.env.resolve_references(largetree, docname, self)
@@ -111,8 +121,15 @@ class ManualPageBuilder(Builder):
111
121
  def default_man_pages(config: Config) -> list[tuple[str, str, str, list[str], int]]:
112
122
  """Better default man_pages settings."""
113
123
  filename = make_filename_from_project(config.project)
114
- return [(config.root_doc, filename, f'{config.project} {config.release}',
115
- [config.author], 1)]
124
+ return [
125
+ (
126
+ config.root_doc,
127
+ filename,
128
+ f'{config.project} {config.release}',
129
+ [config.author],
130
+ 1,
131
+ )
132
+ ]
116
133
 
117
134
 
118
135
  def setup(app: Sphinx) -> ExtensionMetadata:
@@ -16,6 +16,8 @@ from sphinx.util.display import progress_message
16
16
  from sphinx.util.nodes import inline_all_toctrees
17
17
 
18
18
  if TYPE_CHECKING:
19
+ from collections.abc import Set
20
+
19
21
  from docutils.nodes import Node
20
22
 
21
23
  from sphinx.application import Sphinx
@@ -52,7 +54,6 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
52
54
 
53
55
  def fix_refuris(self, tree: Node) -> None:
54
56
  # fix refuris with double anchor
55
- fname = self.config.root_doc + self.out_suffix
56
57
  for refnode in tree.findall(nodes.reference):
57
58
  if 'refuri' not in refnode:
58
59
  continue
@@ -62,9 +63,12 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
62
63
  continue
63
64
  hashindex = refuri.find('#', hashindex + 1)
64
65
  if hashindex >= 0:
65
- refnode['refuri'] = fname + refuri[hashindex:]
66
+ # all references are on the same page...
67
+ refnode['refuri'] = refuri[hashindex:]
66
68
 
67
- def _get_local_toctree(self, docname: str, collapse: bool = True, **kwargs: Any) -> str:
69
+ def _get_local_toctree(
70
+ self, docname: str, collapse: bool = True, **kwargs: Any
71
+ ) -> str:
68
72
  if isinstance(includehidden := kwargs.get('includehidden'), str):
69
73
  if includehidden.lower() == 'false':
70
74
  kwargs['includehidden'] = False
@@ -72,7 +76,9 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
72
76
  kwargs['includehidden'] = True
73
77
  if kwargs.get('maxdepth') == '':
74
78
  kwargs.pop('maxdepth')
75
- toctree = global_toctree_for_doc(self.env, docname, self, collapse=collapse, **kwargs)
79
+ toctree = global_toctree_for_doc(
80
+ self.env, docname, self, collapse=collapse, **kwargs
81
+ )
76
82
  if toctree is not None:
77
83
  self.fix_refuris(toctree)
78
84
  return self.render_partial(toctree)['fragment']
@@ -80,6 +86,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
80
86
  def assemble_doctree(self) -> nodes.document:
81
87
  master = self.config.root_doc
82
88
  tree = self.env.get_doctree(master)
89
+ logger.info(darkgreen(master))
83
90
  tree = inline_all_toctrees(self, set(), master, tree, darkgreen, [master])
84
91
  tree['docname'] = master
85
92
  self.env.resolve_references(tree, master, self)
@@ -99,12 +106,14 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
99
106
  new_secnumbers: dict[str, tuple[int, ...]] = {}
100
107
  for docname, secnums in self.env.toc_secnumbers.items():
101
108
  for id, secnum in secnums.items():
102
- alias = f"{docname}/{id}"
109
+ alias = f'{docname}/{id}'
103
110
  new_secnumbers[alias] = secnum
104
111
 
105
112
  return {self.config.root_doc: new_secnumbers}
106
113
 
107
- def assemble_toc_fignumbers(self) -> dict[str, dict[str, dict[str, tuple[int, ...]]]]:
114
+ def assemble_toc_fignumbers(
115
+ self,
116
+ ) -> dict[str, dict[str, dict[str, tuple[int, ...]]]]:
108
117
  # Assemble toc_fignumbers to resolve figure numbers on SingleHTML.
109
118
  # Merge all fignumbers to single fignumber.
110
119
  #
@@ -118,7 +127,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
118
127
  # {'foo': {'figure': {'id2': (2,), 'id1': (1,)}}, 'bar': {'figure': {'id1': (3,)}}}
119
128
  for docname, fignumlist in self.env.toc_fignumbers.items():
120
129
  for figtype, fignums in fignumlist.items():
121
- alias = f"{docname}/{figtype}"
130
+ alias = f'{docname}/{figtype}'
122
131
  new_fignumbers.setdefault(alias, {})
123
132
  for id, fignum in fignums.items():
124
133
  new_fignumbers[alias][id] = fignum
@@ -127,7 +136,9 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
127
136
 
128
137
  def get_doc_context(self, docname: str, body: str, metatags: str) -> dict[str, Any]:
129
138
  # no relation links...
130
- toctree = global_toctree_for_doc(self.env, self.config.root_doc, self, collapse=False)
139
+ toctree = global_toctree_for_doc(
140
+ self.env, self.config.root_doc, self, collapse=False
141
+ )
131
142
  # if there is no toctree, toc is None
132
143
  if toctree:
133
144
  self.fix_refuris(toctree)
@@ -151,13 +162,10 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
151
162
  'display_toc': display_toc,
152
163
  }
153
164
 
154
- def write(self, *ignored: Any) -> None:
155
- docnames = self.env.all_docs
156
-
157
- with progress_message(__('preparing documents')):
158
- self.prepare_writing(docnames) # type: ignore[arg-type]
165
+ def write_documents(self, _docnames: Set[str]) -> None:
166
+ self.prepare_writing(self.env.all_docs.keys())
159
167
 
160
- with progress_message(__('assembling single document')):
168
+ with progress_message(__('assembling single document'), nonl=False):
161
169
  doctree = self.assemble_doctree()
162
170
  self.env.toc_secnumbers = self.assemble_toc_secnumbers()
163
171
  self.env.toc_fignumbers = self.assemble_toc_fignumbers()