Sphinx 8.0.2__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 +9 -2
  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.2.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.2.dist-info/LICENSE.rst +0 -67
  422. sphinx-8.0.2.dist-info/RECORD +0 -590
  423. {sphinx-8.0.2.dist-info → sphinx-8.1.0.dist-info}/WHEEL +0 -0
  424. {sphinx-8.0.2.dist-info → sphinx-8.1.0.dist-info}/entry_points.txt +0 -0
sphinx/util/nodes.py CHANGED
@@ -35,7 +35,7 @@ explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<([^<]*?)>$', re.DOTALL)
35
35
  caption_ref_re = explicit_title_re # b/w compat alias
36
36
 
37
37
 
38
- N = TypeVar("N", bound=Node)
38
+ N = TypeVar('N', bound=Node)
39
39
 
40
40
 
41
41
  class NodeMatcher(Generic[N]):
@@ -135,8 +135,11 @@ def apply_source_workaround(node: Element) -> None:
135
135
  # * rawsource of term node will have: ``term text : classifier1 : classifier2``
136
136
  # * rawsource of classifier node will be None
137
137
  if isinstance(node, nodes.classifier) and not node.rawsource:
138
- logger.debug('[i18n] PATCH: %r to have source, line and rawsource: %s',
139
- get_full_module_name(node), repr_domxml(node))
138
+ logger.debug(
139
+ '[i18n] PATCH: %r to have source, line and rawsource: %s',
140
+ get_full_module_name(node),
141
+ repr_domxml(node),
142
+ )
140
143
  definition_list_item = node.parent
141
144
  node.source = definition_list_item.source
142
145
  node.line = definition_list_item.line - 1 # type: ignore[operator]
@@ -145,24 +148,37 @@ def apply_source_workaround(node: Element) -> None:
145
148
  # docutils-0.15 fills in rawsource attribute, but not in source.
146
149
  node.source = node.parent.source
147
150
  if isinstance(node, nodes.image) and node.source is None:
148
- logger.debug('[i18n] PATCH: %r to have source, line: %s',
149
- get_full_module_name(node), repr_domxml(node))
151
+ logger.debug(
152
+ '[i18n] PATCH: %r to have source, line: %s',
153
+ get_full_module_name(node),
154
+ repr_domxml(node),
155
+ )
150
156
  node.source, node.line = node.parent.source, node.parent.line
151
157
  if isinstance(node, nodes.title) and node.source is None:
152
- logger.debug('[i18n] PATCH: %r to have source: %s',
153
- get_full_module_name(node), repr_domxml(node))
158
+ logger.debug(
159
+ '[i18n] PATCH: %r to have source: %s',
160
+ get_full_module_name(node),
161
+ repr_domxml(node),
162
+ )
154
163
  node.source, node.line = node.parent.source, node.parent.line
155
164
  if isinstance(node, nodes.term):
156
- logger.debug('[i18n] PATCH: %r to have rawsource: %s',
157
- get_full_module_name(node), repr_domxml(node))
165
+ logger.debug(
166
+ '[i18n] PATCH: %r to have rawsource: %s',
167
+ get_full_module_name(node),
168
+ repr_domxml(node),
169
+ )
158
170
  # strip classifier from rawsource of term
159
171
  for classifier in reversed(list(node.parent.findall(nodes.classifier))):
160
- node.rawsource = re.sub(r'\s*:\s*%s' % re.escape(classifier.astext()),
161
- '', node.rawsource)
172
+ node.rawsource = re.sub(
173
+ r'\s*:\s*%s' % re.escape(classifier.astext()), '', node.rawsource
174
+ )
162
175
  if isinstance(node, nodes.topic) and node.source is None:
163
176
  # docutils-0.18 does not fill the source attribute of topic
164
- logger.debug('[i18n] PATCH: %r to have source, line: %s',
165
- get_full_module_name(node), repr_domxml(node))
177
+ logger.debug(
178
+ '[i18n] PATCH: %r to have source, line: %s',
179
+ get_full_module_name(node),
180
+ repr_domxml(node),
181
+ )
166
182
  node.source, node.line = node.parent.source, node.parent.line
167
183
 
168
184
  # workaround: literal_block under bullet list (#4913)
@@ -178,14 +194,20 @@ def apply_source_workaround(node: Element) -> None:
178
194
  return
179
195
 
180
196
  # workaround: some docutils nodes doesn't have source, line.
181
- if isinstance(node, (
182
- nodes.rubric # #1305 rubric directive
183
- | nodes.line # #1477 line node
184
- | nodes.image # #3093 image directive in substitution
185
- | nodes.field_name # #3335 field list syntax
186
- )):
187
- logger.debug('[i18n] PATCH: %r to have source and line: %s',
188
- get_full_module_name(node), repr_domxml(node))
197
+ if isinstance(
198
+ node,
199
+ (
200
+ nodes.rubric # #1305 rubric directive
201
+ | nodes.line # #1477 line node
202
+ | nodes.image # #3093 image directive in substitution
203
+ | nodes.field_name # #3335 field list syntax
204
+ ),
205
+ ):
206
+ logger.debug(
207
+ '[i18n] PATCH: %r to have source and line: %s',
208
+ get_full_module_name(node),
209
+ repr_domxml(node),
210
+ )
189
211
  try:
190
212
  node.source = get_node_source(node)
191
213
  except ValueError:
@@ -217,24 +239,36 @@ def is_translatable(node: Node) -> bool:
217
239
 
218
240
  if isinstance(node, nodes.TextElement):
219
241
  if not node.source:
220
- logger.debug('[i18n] SKIP %r because no node.source: %s',
221
- get_full_module_name(node), repr_domxml(node))
242
+ logger.debug(
243
+ '[i18n] SKIP %r because no node.source: %s',
244
+ get_full_module_name(node),
245
+ repr_domxml(node),
246
+ )
222
247
  return False # built-in message
223
248
  if isinstance(node, IGNORED_NODES) and 'translatable' not in node:
224
- logger.debug("[i18n] SKIP %r because node is in IGNORED_NODES "
225
- "and no node['translatable']: %s",
226
- get_full_module_name(node), repr_domxml(node))
249
+ logger.debug(
250
+ '[i18n] SKIP %r because node is in IGNORED_NODES '
251
+ "and no node['translatable']: %s",
252
+ get_full_module_name(node),
253
+ repr_domxml(node),
254
+ )
227
255
  return False
228
256
  if not node.get('translatable', True):
229
257
  # not(node['translatable'] == True or node['translatable'] is None)
230
- logger.debug("[i18n] SKIP %r because not node['translatable']: %s",
231
- get_full_module_name(node), repr_domxml(node))
258
+ logger.debug(
259
+ "[i18n] SKIP %r because not node['translatable']: %s",
260
+ get_full_module_name(node),
261
+ repr_domxml(node),
262
+ )
232
263
  return False
233
264
  # <field_name>orphan</field_name>
234
265
  # XXX ignore all metadata (== docinfo)
235
266
  if isinstance(node, nodes.field_name) and (node.children[0] == 'orphan'):
236
- logger.debug('[i18n] SKIP %r because orphan node: %s',
237
- get_full_module_name(node), repr_domxml(node))
267
+ logger.debug(
268
+ '[i18n] SKIP %r because orphan node: %s',
269
+ get_full_module_name(node),
270
+ repr_domxml(node),
271
+ )
238
272
  return False
239
273
  return True
240
274
 
@@ -249,7 +283,7 @@ LITERAL_TYPE_NODES = (
249
283
  )
250
284
  IMAGE_TYPE_NODES = (
251
285
  nodes.image,
252
- )
286
+ ) # fmt: skip
253
287
 
254
288
 
255
289
  def extract_messages(doctree: Element) -> Iterable[tuple[Element, str]]:
@@ -272,7 +306,7 @@ def extract_messages(doctree: Element) -> Iterable[tuple[Element, str]]:
272
306
  else:
273
307
  msg = ''
274
308
  elif isinstance(node, nodes.meta):
275
- msg = node["content"]
309
+ msg = node['content']
276
310
  else:
277
311
  msg = node.rawsource.replace('\n', ' ').strip() # type: ignore[attr-defined]
278
312
 
@@ -325,8 +359,9 @@ def traverse_translatable_index(
325
359
  yield node, entries
326
360
 
327
361
 
328
- def nested_parse_with_titles(state: RSTState, content: StringList, node: Node,
329
- content_offset: int = 0) -> str:
362
+ def nested_parse_with_titles(
363
+ state: RSTState, content: StringList, node: Node, content_offset: int = 0
364
+ ) -> str:
330
365
  """Version of state.nested_parse() that allows titles and does not require
331
366
  titles to have the same decoration as the calling document.
332
367
 
@@ -359,13 +394,13 @@ def split_explicit_title(text: str) -> tuple[bool, str, str]:
359
394
  return False, text, text
360
395
 
361
396
 
362
- indextypes = [
363
- 'single', 'pair', 'double', 'triple', 'see', 'seealso',
364
- ]
397
+ indextypes = ['single', 'pair', 'double', 'triple', 'see', 'seealso']
365
398
 
366
399
 
367
- def process_index_entry(entry: str, targetid: str,
368
- ) -> list[tuple[str, str, str, str, str | None]]:
400
+ def process_index_entry(
401
+ entry: str,
402
+ targetid: str,
403
+ ) -> list[tuple[str, str, str, str, str | None]]:
369
404
  from sphinx.domains.python import pairindextypes
370
405
 
371
406
  indexentries: list[tuple[str, str, str, str, str | None]] = []
@@ -377,18 +412,25 @@ def process_index_entry(entry: str, targetid: str,
377
412
  entry = entry[1:].lstrip()
378
413
  for index_type in pairindextypes:
379
414
  if entry.startswith(f'{index_type}:'):
380
- value = entry[len(index_type) + 1:].strip()
415
+ value = entry[len(index_type) + 1 :].strip()
381
416
  value = f'{pairindextypes[index_type]}; {value}'
382
417
  # xref RemovedInSphinx90Warning
383
- logger.warning(__('%r is deprecated for index entries (from entry %r). '
384
- "Use 'pair: %s' instead."),
385
- index_type, entry, value, type='index')
418
+ logger.warning(
419
+ __(
420
+ '%r is deprecated for index entries (from entry %r). '
421
+ "Use 'pair: %s' instead."
422
+ ),
423
+ index_type,
424
+ entry,
425
+ value,
426
+ type='index',
427
+ )
386
428
  indexentries.append(('pair', value, targetid, main, None))
387
429
  break
388
430
  else:
389
431
  for index_type in indextypes:
390
432
  if entry.startswith(f'{index_type}:'):
391
- value = entry[len(index_type) + 1:].strip()
433
+ value = entry[len(index_type) + 1 :].strip()
392
434
  if index_type == 'double':
393
435
  index_type = 'pair'
394
436
  indexentries.append((index_type, value, targetid, main, None))
@@ -414,6 +456,7 @@ def inline_all_toctrees(
414
456
  tree: nodes.document,
415
457
  colorfunc: Callable[[str], str],
416
458
  traversed: list[str],
459
+ indent: str = '',
417
460
  ) -> nodes.document:
418
461
  """Inline all toctrees in the *tree*.
419
462
 
@@ -423,18 +466,28 @@ def inline_all_toctrees(
423
466
  for toctreenode in list(tree.findall(addnodes.toctree)):
424
467
  newnodes = []
425
468
  includefiles = map(str, toctreenode['includefiles'])
469
+ indent += ' '
426
470
  for includefile in includefiles:
427
471
  if includefile not in traversed:
428
472
  try:
429
473
  traversed.append(includefile)
430
- logger.info(colorfunc(includefile) + " ", nonl=True)
431
- subtree = inline_all_toctrees(builder, docnameset, includefile,
432
- builder.env.get_doctree(includefile),
433
- colorfunc, traversed)
474
+ logger.info(indent + colorfunc(includefile))
475
+ subtree = inline_all_toctrees(
476
+ builder,
477
+ docnameset,
478
+ includefile,
479
+ builder.env.get_doctree(includefile),
480
+ colorfunc,
481
+ traversed,
482
+ indent,
483
+ )
434
484
  docnameset.add(includefile)
435
485
  except Exception:
436
- logger.warning(__('toctree contains ref to nonexisting file %r'),
437
- includefile, location=docname)
486
+ logger.warning(
487
+ __('toctree contains ref to nonexisting file %r'),
488
+ includefile,
489
+ location=docname,
490
+ )
438
491
  else:
439
492
  sof = addnodes.start_of_file(docname=includefile)
440
493
  sof.children = subtree.children
@@ -476,57 +529,61 @@ def _make_id(string: str) -> str:
476
529
  _non_id_chars = re.compile('[^a-zA-Z0-9._]+')
477
530
  _non_id_at_ends = re.compile('^[-0-9._]+|-+$')
478
531
  _non_id_translate = {
479
- 0x00f8: 'o', # o with stroke
480
- 0x0111: 'd', # d with stroke
481
- 0x0127: 'h', # h with stroke
482
- 0x0131: 'i', # dotless i
483
- 0x0142: 'l', # l with stroke
484
- 0x0167: 't', # t with stroke
485
- 0x0180: 'b', # b with stroke
486
- 0x0183: 'b', # b with topbar
487
- 0x0188: 'c', # c with hook
488
- 0x018c: 'd', # d with topbar
489
- 0x0192: 'f', # f with hook
490
- 0x0199: 'k', # k with hook
491
- 0x019a: 'l', # l with bar
492
- 0x019e: 'n', # n with long right leg
493
- 0x01a5: 'p', # p with hook
494
- 0x01ab: 't', # t with palatal hook
495
- 0x01ad: 't', # t with hook
496
- 0x01b4: 'y', # y with hook
497
- 0x01b6: 'z', # z with stroke
498
- 0x01e5: 'g', # g with stroke
499
- 0x0225: 'z', # z with hook
500
- 0x0234: 'l', # l with curl
501
- 0x0235: 'n', # n with curl
502
- 0x0236: 't', # t with curl
503
- 0x0237: 'j', # dotless j
504
- 0x023c: 'c', # c with stroke
505
- 0x023f: 's', # s with swash tail
506
- 0x0240: 'z', # z with swash tail
507
- 0x0247: 'e', # e with stroke
508
- 0x0249: 'j', # j with stroke
509
- 0x024b: 'q', # q with hook tail
510
- 0x024d: 'r', # r with stroke
511
- 0x024f: 'y', # y with stroke
532
+ 0x00F8: 'o', # o with stroke
533
+ 0x0111: 'd', # d with stroke
534
+ 0x0127: 'h', # h with stroke
535
+ 0x0131: 'i', # dotless i
536
+ 0x0142: 'l', # l with stroke
537
+ 0x0167: 't', # t with stroke
538
+ 0x0180: 'b', # b with stroke
539
+ 0x0183: 'b', # b with topbar
540
+ 0x0188: 'c', # c with hook
541
+ 0x018C: 'd', # d with topbar
542
+ 0x0192: 'f', # f with hook
543
+ 0x0199: 'k', # k with hook
544
+ 0x019A: 'l', # l with bar
545
+ 0x019E: 'n', # n with long right leg
546
+ 0x01A5: 'p', # p with hook
547
+ 0x01AB: 't', # t with palatal hook
548
+ 0x01AD: 't', # t with hook
549
+ 0x01B4: 'y', # y with hook
550
+ 0x01B6: 'z', # z with stroke
551
+ 0x01E5: 'g', # g with stroke
552
+ 0x0225: 'z', # z with hook
553
+ 0x0234: 'l', # l with curl
554
+ 0x0235: 'n', # n with curl
555
+ 0x0236: 't', # t with curl
556
+ 0x0237: 'j', # dotless j
557
+ 0x023C: 'c', # c with stroke
558
+ 0x023F: 's', # s with swash tail
559
+ 0x0240: 'z', # z with swash tail
560
+ 0x0247: 'e', # e with stroke
561
+ 0x0249: 'j', # j with stroke
562
+ 0x024B: 'q', # q with hook tail
563
+ 0x024D: 'r', # r with stroke
564
+ 0x024F: 'y', # y with stroke
512
565
  }
513
566
  _non_id_translate_digraphs = {
514
- 0x00df: 'sz', # ligature sz
515
- 0x00e6: 'ae', # ae
516
- 0x0153: 'oe', # ligature oe
517
- 0x0238: 'db', # db digraph
518
- 0x0239: 'qp', # qp digraph
567
+ 0x00DF: 'sz', # ligature sz
568
+ 0x00E6: 'ae', # ae
569
+ 0x0153: 'oe', # ligature oe
570
+ 0x0238: 'db', # db digraph
571
+ 0x0239: 'qp', # qp digraph
519
572
  }
520
573
 
521
574
 
522
- def make_id(env: BuildEnvironment, document: nodes.document,
523
- prefix: str = '', term: str | None = None) -> str:
575
+ def make_id(
576
+ env: BuildEnvironment,
577
+ document: nodes.document,
578
+ prefix: str = '',
579
+ term: str | None = None,
580
+ ) -> str:
524
581
  """Generate an appropriate node_id for given *prefix* and *term*."""
525
582
  node_id = None
526
583
  if prefix:
527
- idformat = prefix + "-%s"
584
+ idformat = prefix + '-%s'
528
585
  else:
529
- idformat = (document.settings.id_prefix or "id") + "%s"
586
+ idformat = (document.settings.id_prefix or 'id') + '%s'
530
587
 
531
588
  # try to generate node_id by *term*
532
589
  if prefix and term:
@@ -545,27 +602,36 @@ def make_id(env: BuildEnvironment, document: nodes.document,
545
602
  return node_id
546
603
 
547
604
 
548
- def find_pending_xref_condition(node: addnodes.pending_xref, condition: str,
549
- ) -> Element | None:
605
+ def find_pending_xref_condition(
606
+ node: addnodes.pending_xref, condition: str
607
+ ) -> Element | None:
550
608
  """Pick matched pending_xref_condition node up from the pending_xref."""
551
609
  for subnode in node:
552
- if (isinstance(subnode, addnodes.pending_xref_condition) and
553
- subnode.get('condition') == condition):
610
+ if (
611
+ isinstance(subnode, addnodes.pending_xref_condition)
612
+ and subnode.get('condition') == condition
613
+ ):
554
614
  return subnode
555
615
  return None
556
616
 
557
617
 
558
- def make_refnode(builder: Builder, fromdocname: str, todocname: str, targetid: str | None,
559
- child: Node | list[Node], title: str | None = None,
560
- ) -> nodes.reference:
618
+ def make_refnode(
619
+ builder: Builder,
620
+ fromdocname: str,
621
+ todocname: str,
622
+ targetid: str | None,
623
+ child: Node | list[Node],
624
+ title: str | None = None,
625
+ ) -> nodes.reference:
561
626
  """Shortcut to create a reference node."""
562
627
  node = nodes.reference('', '', internal=True)
563
628
  if fromdocname == todocname and targetid:
564
629
  node['refid'] = targetid
565
630
  else:
566
631
  if targetid:
567
- node['refuri'] = (builder.get_relative_uri(fromdocname, todocname) +
568
- '#' + targetid)
632
+ node['refuri'] = (
633
+ builder.get_relative_uri(fromdocname, todocname) + '#' + targetid
634
+ )
569
635
  else:
570
636
  node['refuri'] = builder.get_relative_uri(fromdocname, todocname)
571
637
  if title:
@@ -575,8 +641,9 @@ def make_refnode(builder: Builder, fromdocname: str, todocname: str, targetid: s
575
641
 
576
642
 
577
643
  def set_source_info(directive: Directive, node: Node) -> None:
578
- node.source, node.line = \
579
- directive.state_machine.get_source_and_line(directive.lineno)
644
+ node.source, node.line = directive.state_machine.get_source_and_line(
645
+ directive.lineno
646
+ )
580
647
 
581
648
 
582
649
  def set_role_source_info(inliner: Inliner, lineno: int, node: Node) -> None:
@@ -633,7 +700,8 @@ def _only_node_keep_children(node: addnodes.only, tags: Tags) -> bool:
633
700
  logger.warning(
634
701
  __('exception while evaluating only directive expression: %s'),
635
702
  err,
636
- location=node)
703
+ location=node,
704
+ )
637
705
  return True
638
706
 
639
707
 
@@ -649,10 +717,10 @@ def _copy_except__document(el: Element) -> Element:
649
717
  newnode.rawsource = el.rawsource
650
718
  newnode.tagname = el.tagname
651
719
  # copied in Element.copy()
652
- newnode.attributes = {k: (v
653
- if k not in {'ids', 'classes', 'names', 'dupnames', 'backrefs'}
654
- else v[:])
655
- for k, v in el.attributes.items()}
720
+ newnode.attributes = {
721
+ k: (v if k not in {'ids', 'classes', 'names', 'dupnames', 'backrefs'} else v[:])
722
+ for k, v in el.attributes.items()
723
+ }
656
724
  newnode.line = el.line
657
725
  newnode.source = el.source
658
726
  return newnode
sphinx/util/osutil.py CHANGED
@@ -25,7 +25,7 @@ if TYPE_CHECKING:
25
25
  # Define SEP as a manifest constant, not so much because we expect it to change
26
26
  # in the future as to avoid the suspicion that a stray "/" in the code is a
27
27
  # hangover from more *nix-oriented origins.
28
- SEP = "/"
28
+ SEP = '/'
29
29
 
30
30
 
31
31
  def os_path(canonical_path: str, /) -> str:
@@ -115,21 +115,23 @@ def copyfile(
115
115
  raise FileNotFoundError(msg)
116
116
 
117
117
  if (
118
- not (dest_exists := dest.exists()) or
118
+ not (dest_exists := dest.exists())
119
119
  # comparison must be done using shallow=False since
120
120
  # two different files might have the same size
121
- not filecmp.cmp(source, dest, shallow=False)
121
+ or not filecmp.cmp(source, dest, shallow=False)
122
122
  ):
123
123
  if not force and dest_exists:
124
124
  # sphinx.util.logging imports sphinx.util.osutil,
125
125
  # so use a local import to avoid circular imports
126
126
  from sphinx.util import logging
127
+
127
128
  logger = logging.getLogger(__name__)
128
129
 
129
- msg = __('Aborted attempted copy from %s to %s '
130
- '(the destination path has existing data).')
131
- logger.warning(msg, source, dest,
132
- type='misc', subtype='copy_overwrite')
130
+ msg = __(
131
+ 'Aborted attempted copy from %s to %s '
132
+ '(the destination path has existing data).'
133
+ )
134
+ logger.warning(msg, source, dest, type='misc', subtype='copy_overwrite')
133
135
  return
134
136
 
135
137
  shutil.copyfile(source, dest)
@@ -149,8 +151,9 @@ def make_filename_from_project(project: str) -> str:
149
151
  return make_filename(project.removesuffix(' Documentation')).lower()
150
152
 
151
153
 
152
- def relpath(path: str | os.PathLike[str],
153
- start: str | os.PathLike[str] | None = os.curdir) -> str:
154
+ def relpath(
155
+ path: str | os.PathLike[str], start: str | os.PathLike[str] | None = os.curdir
156
+ ) -> str:
154
157
  """Return a relative filepath to *path* either from the current directory or
155
158
  from an optional *start* directory.
156
159
 
@@ -241,7 +244,7 @@ class FileAvoidWrite:
241
244
  return self
242
245
 
243
246
  def __exit__(
244
- self, exc_type: type[Exception], exc_value: Exception, traceback: Any,
247
+ self, exc_type: type[Exception], exc_value: Exception, traceback: Any
245
248
  ) -> bool:
246
249
  self.close()
247
250
  return True
sphinx/util/parallel.py CHANGED
@@ -10,6 +10,7 @@ from typing import TYPE_CHECKING, Any
10
10
 
11
11
  try:
12
12
  import multiprocessing
13
+
13
14
  HAS_MULTIPROCESSING = True
14
15
  except ImportError:
15
16
  HAS_MULTIPROCESSING = False
@@ -23,7 +24,7 @@ if TYPE_CHECKING:
23
24
  logger = logging.getLogger(__name__)
24
25
 
25
26
  # our parallel functionality only works for the forking Process
26
- parallel_available = multiprocessing and os.name == 'posix'
27
+ parallel_available = HAS_MULTIPROCESSING and os.name == 'posix'
27
28
 
28
29
 
29
30
  class SerialTasks:
@@ -33,7 +34,7 @@ class SerialTasks:
33
34
  pass
34
35
 
35
36
  def add_task(
36
- self, task_func: Callable, arg: Any = None, result_func: Callable | None = None,
37
+ self, task_func: Callable, arg: Any = None, result_func: Callable | None = None
37
38
  ) -> None:
38
39
  if arg is not None:
39
40
  res = task_func(arg)
@@ -83,7 +84,7 @@ class ParallelTasks:
83
84
  pipe.send((failed, collector.logs, ret))
84
85
 
85
86
  def add_task(
86
- self, task_func: Callable, arg: Any = None, result_func: Callable | None = None,
87
+ self, task_func: Callable, arg: Any = None, result_func: Callable | None = None
87
88
  ) -> None:
88
89
  tid = self._taskid
89
90
  self._taskid += 1
@@ -156,4 +157,4 @@ def make_chunks(arguments: Sequence[str], nproc: int, maxbatch: int = 10) -> lis
156
157
  if rest:
157
158
  nchunks += 1
158
159
  # partition documents in "chunks" that will be written by one Process
159
- return [arguments[i * chunksize:(i + 1) * chunksize] for i in range(nchunks)]
160
+ return [arguments[i * chunksize : (i + 1) * chunksize] for i in range(nchunks)]
sphinx/util/parsing.py CHANGED
@@ -53,7 +53,7 @@ def nested_parse_to_nodes(
53
53
  """
54
54
  document = state.document
55
55
  content = _text_to_string_list(
56
- text, source=source, tab_width=document.settings.tab_width,
56
+ text, source=source, tab_width=document.settings.tab_width
57
57
  )
58
58
  node = Element() # Anonymous container for parsing
59
59
  node.document = document
@@ -62,7 +62,9 @@ def nested_parse_to_nodes(
62
62
  state.nested_parse(content, offset, node, match_titles=allow_section_headings)
63
63
  else:
64
64
  with _fresh_title_style_context(state):
65
- state.nested_parse(content, offset, node, match_titles=allow_section_headings)
65
+ state.nested_parse(
66
+ content, offset, node, match_titles=allow_section_headings
67
+ )
66
68
  return node.children
67
69
 
68
70
 
@@ -84,7 +86,7 @@ def _fresh_title_style_context(state: RSTState) -> Iterator[None]:
84
86
 
85
87
 
86
88
  def _text_to_string_list(
87
- text: str | StringList, /, *, source: str, tab_width: int,
89
+ text: str | StringList, /, *, source: str, tab_width: int
88
90
  ) -> StringList:
89
91
  # Doesn't really belong in this module, but avoids circular imports.
90
92
  if isinstance(text, StringList):
sphinx/util/png.py CHANGED
@@ -10,13 +10,13 @@ LEN_DEPTH = 22
10
10
 
11
11
  DEPTH_CHUNK_LEN = struct.pack('!i', 10)
12
12
  DEPTH_CHUNK_START = b'tEXtDepth\x00'
13
- IEND_CHUNK = b'\x00\x00\x00\x00IEND\xAE\x42\x60\x82'
13
+ IEND_CHUNK = b'\x00\x00\x00\x00IEND\xae\x42\x60\x82'
14
14
 
15
15
 
16
16
  def read_png_depth(filename: str) -> int | None:
17
17
  """Read the special tEXt chunk indicating the depth from a PNG file."""
18
18
  with open(filename, 'rb') as f:
19
- f.seek(- (LEN_IEND + LEN_DEPTH), 2)
19
+ f.seek(-(LEN_IEND + LEN_DEPTH), 2)
20
20
  depthchunk = f.read(LEN_DEPTH)
21
21
  if not depthchunk.startswith(DEPTH_CHUNK_LEN + DEPTH_CHUNK_START):
22
22
  # either not a PNG file or not containing the depth chunk
@@ -37,7 +37,7 @@ def write_png_depth(filename: str, depth: int) -> None:
37
37
  # overwrite it with the depth chunk
38
38
  f.write(DEPTH_CHUNK_LEN + DEPTH_CHUNK_START + data)
39
39
  # calculate the checksum over chunk name and data
40
- crc = binascii.crc32(DEPTH_CHUNK_START + data) & 0xffffffff
40
+ crc = binascii.crc32(DEPTH_CHUNK_START + data) & 0xFFFFFFFF
41
41
  f.write(struct.pack('!I', crc))
42
42
  # replace the IEND chunk
43
43
  f.write(IEND_CHUNK)
sphinx/util/requests.py CHANGED
@@ -11,8 +11,10 @@ from urllib3.exceptions import InsecureRequestWarning
11
11
 
12
12
  import sphinx
13
13
 
14
- _USER_AGENT = (f'Mozilla/5.0 (X11; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/100.0 '
15
- f'Sphinx/{sphinx.__version__}')
14
+ _USER_AGENT = (
15
+ f'Mozilla/5.0 (X11; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/100.0 '
16
+ f'Sphinx/{sphinx.__version__}'
17
+ )
16
18
 
17
19
 
18
20
  def _get_tls_cacert(url: str, certs: str | dict[str, str] | None) -> str | bool:
@@ -49,7 +51,9 @@ def head(url: str, **kwargs: Any) -> requests.Response:
49
51
 
50
52
  class _Session(requests.Session):
51
53
  def request( # type: ignore[override]
52
- self, method: str, url: str,
54
+ self,
55
+ method: str,
56
+ url: str,
53
57
  _user_agent: str = '',
54
58
  _tls_info: tuple[bool, str | dict[str, str] | None] = (), # type: ignore[assignment]
55
59
  **kwargs: Any,
@@ -72,5 +76,5 @@ class _Session(requests.Session):
72
76
 
73
77
  with warnings.catch_warnings():
74
78
  # ignore InsecureRequestWarning if verify=False
75
- warnings.filterwarnings("ignore", category=InsecureRequestWarning)
79
+ warnings.filterwarnings('ignore', category=InsecureRequestWarning)
76
80
  return super().request(method, url, **kwargs)
sphinx/util/rst.py CHANGED
@@ -29,8 +29,8 @@ symbols_re = re.compile(r'([!-\-/:-@\[-`{-~])') # symbols without dot(0x2e)
29
29
  SECTIONING_CHARS = ['=', '-', '~']
30
30
 
31
31
  # width of characters
32
- WIDECHARS: dict[str, str] = defaultdict(lambda: "WF") # WF: Wide + Full-width
33
- WIDECHARS["ja"] = "WFA" # In Japanese, Ambiguous characters also have double width
32
+ WIDECHARS: dict[str, str] = defaultdict(lambda: 'WF') # WF: Wide + Full-width
33
+ WIDECHARS['ja'] = 'WFA' # In Japanese, Ambiguous characters also have double width
34
34
 
35
35
 
36
36
  def escape(text: str) -> str:
@@ -41,6 +41,7 @@ def escape(text: str) -> str:
41
41
 
42
42
  def textwidth(text: str, widechars: str = 'WF') -> int:
43
43
  """Get width of text."""
44
+
44
45
  def charwidth(char: str, widechars: str) -> int:
45
46
  if east_asian_width(char) in widechars:
46
47
  return 2
@@ -103,7 +104,8 @@ def append_epilog(content: StringList, epilog: str) -> None:
103
104
  if epilog:
104
105
  if len(content) > 0:
105
106
  source, lineno = content.info(-1)
106
- lineno = cast(int, lineno) # lineno will never be None, since len(content) > 0
107
+ # lineno will never be None, since len(content) > 0
108
+ lineno = cast(int, lineno)
107
109
  else:
108
110
  source = '<generated>'
109
111
  lineno = 0