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
@@ -15,7 +15,8 @@ from docutils import nodes
15
15
  from docutils.utils import smartquotes
16
16
 
17
17
  from sphinx import addnodes
18
- from sphinx.builders.html import BuildInfo, StandaloneHTMLBuilder
18
+ from sphinx.builders.html import StandaloneHTMLBuilder
19
+ from sphinx.builders.html._build_info import BuildInfo
19
20
  from sphinx.locale import __
20
21
  from sphinx.util import logging
21
22
  from sphinx.util.display import status_iterator
@@ -27,6 +28,7 @@ if TYPE_CHECKING:
27
28
 
28
29
  try:
29
30
  from PIL import Image
31
+
30
32
  PILLOW_AVAILABLE = True
31
33
  except ImportError:
32
34
  PILLOW_AVAILABLE = False
@@ -78,7 +80,7 @@ VECTOR_GRAPHICS_EXTENSIONS = ('.svg',)
78
80
  # Regular expression to match colons only in local fragment identifiers.
79
81
  # If the URI contains a colon before the #,
80
82
  # it is an external link that should not change.
81
- REFURI_RE = re.compile("([^#:]*#)(.*)")
83
+ REFURI_RE = re.compile('([^#:]*#)(.*)')
82
84
 
83
85
 
84
86
  class ManifestItem(NamedTuple):
@@ -119,6 +121,7 @@ ssp = sphinx_smarty_pants
119
121
 
120
122
  # The epub publisher
121
123
 
124
+
122
125
  class EpubBuilder(StandaloneHTMLBuilder):
123
126
  """
124
127
  Builder that outputs epub files.
@@ -130,8 +133,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
130
133
 
131
134
  # don't copy the reST source
132
135
  copysource = False
133
- supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
134
- 'image/jpeg']
136
+ supported_image_types = ['image/svg+xml', 'image/png', 'image/gif', 'image/jpeg']
135
137
  supported_remote_images = False
136
138
 
137
139
  # don't add links
@@ -154,8 +156,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
154
156
  guide_titles = GUIDE_TITLES
155
157
  media_types = MEDIA_TYPES
156
158
  refuri_re = REFURI_RE
157
- template_dir = ""
158
- doctype = ""
159
+ template_dir = ''
160
+ doctype = ''
159
161
 
160
162
  def init(self) -> None:
161
163
  super().init()
@@ -185,7 +187,9 @@ class EpubBuilder(StandaloneHTMLBuilder):
185
187
  return id
186
188
 
187
189
  def get_refnodes(
188
- self, doctree: Node, result: list[dict[str, Any]],
190
+ self,
191
+ doctree: Node,
192
+ result: list[dict[str, Any]],
189
193
  ) -> list[dict[str, Any]]:
190
194
  """Collect section titles, their depth in the toc and the refuri."""
191
195
  # XXX: is there a better way than checking the attribute
@@ -215,8 +219,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
215
219
  logger.warning(
216
220
  __('duplicated ToC entry found: %s'),
217
221
  node['refuri'],
218
- type="epub",
219
- subtype="duplicated_toc_entry",
222
+ type='epub',
223
+ subtype='duplicated_toc_entry',
220
224
  )
221
225
  else:
222
226
  appeared.add(node['refuri'])
@@ -225,9 +229,9 @@ class EpubBuilder(StandaloneHTMLBuilder):
225
229
  """Get the total table of contents, containing the root_doc
226
230
  and pre and post files not managed by sphinx.
227
231
  """
228
- doctree = self.env.get_and_resolve_doctree(self.config.root_doc,
229
- self, prune_toctrees=False,
230
- includehidden=True)
232
+ doctree = self.env.get_and_resolve_doctree(
233
+ self.config.root_doc, self, prune_toctrees=False, includehidden=True
234
+ )
231
235
  self.refnodes = self.get_refnodes(doctree, [])
232
236
  master_dir = path.dirname(self.config.root_doc)
233
237
  if master_dir:
@@ -237,20 +241,26 @@ class EpubBuilder(StandaloneHTMLBuilder):
237
241
  self.toc_add_files(self.refnodes)
238
242
 
239
243
  def toc_add_files(self, refnodes: list[dict[str, Any]]) -> None:
240
- """Add the root_doc, pre and post files to a list of refnodes.
241
- """
242
- refnodes.insert(0, {
243
- 'level': 1,
244
- 'refuri': html.escape(self.config.root_doc + self.out_suffix),
245
- 'text': ssp(html.escape(
246
- self.env.titles[self.config.root_doc].astext())),
247
- })
248
- for file, text in reversed(self.config.epub_pre_files):
249
- refnodes.insert(0, {
244
+ """Add the root_doc, pre and post files to a list of refnodes."""
245
+ refnodes.insert(
246
+ 0,
247
+ {
250
248
  'level': 1,
251
- 'refuri': html.escape(file),
252
- 'text': ssp(html.escape(text)),
253
- })
249
+ 'refuri': html.escape(self.config.root_doc + self.out_suffix),
250
+ 'text': ssp(
251
+ html.escape(self.env.titles[self.config.root_doc].astext())
252
+ ),
253
+ },
254
+ )
255
+ for file, text in reversed(self.config.epub_pre_files):
256
+ refnodes.insert(
257
+ 0,
258
+ {
259
+ 'level': 1,
260
+ 'refuri': html.escape(file),
261
+ 'text': ssp(html.escape(text)),
262
+ },
263
+ )
254
264
  for file, text in self.config.epub_post_files:
255
265
  refnodes.append({
256
266
  'level': 1,
@@ -268,6 +278,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
268
278
  Some readers crash because they interpret the part as a
269
279
  transport protocol specification.
270
280
  """
281
+
271
282
  def update_node_id(node: Element) -> None:
272
283
  """Update IDs of given *node*."""
273
284
  new_ids: list[str] = []
@@ -295,10 +306,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
295
306
  for desc_signature in tree.findall(addnodes.desc_signature):
296
307
  update_node_id(desc_signature)
297
308
 
298
- def add_visible_links(self, tree: nodes.document, show_urls: str = 'inline') -> None:
309
+ def add_visible_links(
310
+ self, tree: nodes.document, show_urls: str = 'inline'
311
+ ) -> None:
299
312
  """Add visible link targets for external links"""
300
313
 
301
- def make_footnote_ref(doc: nodes.document, label: str) -> nodes.footnote_reference:
314
+ def make_footnote_ref(
315
+ doc: nodes.document, label: str
316
+ ) -> nodes.footnote_reference:
302
317
  """Create a footnote_reference node with children"""
303
318
  footnote_ref = nodes.footnote_reference('[#]_')
304
319
  footnote_ref.append(nodes.Text(label))
@@ -379,17 +394,16 @@ class EpubBuilder(StandaloneHTMLBuilder):
379
394
  # Logic modeled from themes/basic/genindex.html
380
395
  for _key, columns in tree:
381
396
  for _entryname, (links, subitems, _key) in columns:
382
- for (i, (ismain, link)) in enumerate(links):
383
- m = self.refuri_re.match(link)
384
- if m:
385
- links[i] = (ismain,
386
- self.fix_fragment(m.group(1), m.group(2)))
397
+ for i, (ismain, link) in enumerate(links):
398
+ if m := self.refuri_re.match(link):
399
+ links[i] = ismain, self.fix_fragment(m.group(1), m.group(2))
387
400
  for _subentryname, subentrylinks in subitems:
388
- for (i, (ismain, link)) in enumerate(subentrylinks):
389
- m = self.refuri_re.match(link)
390
- if m:
391
- subentrylinks[i] = (ismain,
392
- self.fix_fragment(m.group(1), m.group(2)))
401
+ for i, (ismain, link) in enumerate(subentrylinks):
402
+ if m := self.refuri_re.match(link):
403
+ subentrylinks[i] = (
404
+ ismain,
405
+ self.fix_fragment(m.group(1), m.group(2)),
406
+ )
393
407
 
394
408
  def is_vector_graphics(self, filename: str) -> bool:
395
409
  """Does the filename extension indicate a vector graphic format?"""
@@ -402,15 +416,22 @@ class EpubBuilder(StandaloneHTMLBuilder):
402
416
  the format and resizing the image if necessary/possible.
403
417
  """
404
418
  ensuredir(path.join(self.outdir, self.imagedir))
405
- for src in status_iterator(self.images, __('copying images... '), "brown",
406
- len(self.images), self.app.verbosity):
419
+ for src in status_iterator(
420
+ self.images,
421
+ __('copying images... '),
422
+ 'brown',
423
+ len(self.images),
424
+ self.app.verbosity,
425
+ ):
407
426
  dest = self.images[src]
408
427
  try:
409
428
  img = Image.open(path.join(self.srcdir, src))
410
429
  except OSError:
411
430
  if not self.is_vector_graphics(src):
412
- logger.warning(__('cannot read image file %r: copying it instead'),
413
- path.join(self.srcdir, src))
431
+ logger.warning(
432
+ __('cannot read image file %r: copying it instead'),
433
+ path.join(self.srcdir, src),
434
+ )
414
435
  try:
415
436
  copyfile(
416
437
  self.srcdir / src,
@@ -418,8 +439,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
418
439
  force=True,
419
440
  )
420
441
  except OSError as err:
421
- logger.warning(__('cannot copy image file %r: %s'),
422
- path.join(self.srcdir, src), err)
442
+ logger.warning(
443
+ __('cannot copy image file %r: %s'),
444
+ path.join(self.srcdir, src),
445
+ err,
446
+ )
423
447
  continue
424
448
  if self.config.epub_fix_images:
425
449
  if img.mode == 'P':
@@ -435,8 +459,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
435
459
  try:
436
460
  img.save(path.join(self.outdir, self.imagedir, dest))
437
461
  except OSError as err:
438
- logger.warning(__('cannot write image file %r: %s'),
439
- path.join(self.srcdir, src), err)
462
+ logger.warning(
463
+ __('cannot write image file %r: %s'),
464
+ path.join(self.srcdir, src),
465
+ err,
466
+ )
440
467
 
441
468
  def copy_image_files(self) -> None:
442
469
  """Copy image files to destination directory.
@@ -554,13 +581,19 @@ class EpubBuilder(StandaloneHTMLBuilder):
554
581
  # we always have JS and potentially OpenSearch files, don't
555
582
  # always warn about them
556
583
  if ext not in ('.js', '.xml'):
557
- logger.warning(__('unknown mimetype for %s, ignoring'), filename,
558
- type='epub', subtype='unknown_project_files')
584
+ logger.warning(
585
+ __('unknown mimetype for %s, ignoring'),
586
+ filename,
587
+ type='epub',
588
+ subtype='unknown_project_files',
589
+ )
559
590
  continue
560
591
  filename = filename.replace(os.sep, '/')
561
- item = ManifestItem(html.escape(quote(filename)),
562
- html.escape(self.make_id(filename)),
563
- html.escape(self.media_types[ext]))
592
+ item = ManifestItem(
593
+ html.escape(quote(filename)),
594
+ html.escape(self.make_id(filename)),
595
+ html.escape(self.media_types[ext]),
596
+ )
564
597
  metadata['manifest_items'].append(item)
565
598
  self.files.append(filename)
566
599
 
@@ -600,13 +633,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
600
633
  if self.coverpage_name not in self.files:
601
634
  ext = path.splitext(self.coverpage_name)[-1]
602
635
  self.files.append(self.coverpage_name)
603
- item = ManifestItem(html.escape(self.coverpage_name),
604
- html.escape(self.make_id(self.coverpage_name)),
605
- html.escape(self.media_types[ext]))
636
+ item = ManifestItem(
637
+ html.escape(self.coverpage_name),
638
+ html.escape(self.make_id(self.coverpage_name)),
639
+ html.escape(self.media_types[ext]),
640
+ )
606
641
  metadata['manifest_items'].append(item)
607
642
  ctx = {'image': html.escape(image), 'title': self.config.project}
608
- self.handle_page(
609
- path.splitext(self.coverpage_name)[0], ctx, html_tmpl)
643
+ self.handle_page(path.splitext(self.coverpage_name)[0], ctx, html_tmpl)
610
644
  spinefiles.add(self.coverpage_name)
611
645
 
612
646
  auto_add_cover = True
@@ -620,17 +654,25 @@ class EpubBuilder(StandaloneHTMLBuilder):
620
654
  auto_add_cover = False
621
655
  if type == 'toc':
622
656
  auto_add_toc = False
623
- metadata['guides'].append(Guide(html.escape(type),
624
- html.escape(title),
625
- html.escape(uri)))
657
+ metadata['guides'].append(
658
+ Guide(html.escape(type), html.escape(title), html.escape(uri))
659
+ )
626
660
  if auto_add_cover and html_tmpl:
627
- metadata['guides'].append(Guide('cover',
628
- self.guide_titles['cover'],
629
- html.escape(self.coverpage_name)))
661
+ metadata['guides'].append(
662
+ Guide(
663
+ 'cover',
664
+ self.guide_titles['cover'],
665
+ html.escape(self.coverpage_name),
666
+ )
667
+ )
630
668
  if auto_add_toc and self.refnodes:
631
- metadata['guides'].append(Guide('toc',
632
- self.guide_titles['toc'],
633
- html.escape(self.refnodes[0]['refuri'])))
669
+ metadata['guides'].append(
670
+ Guide(
671
+ 'toc',
672
+ self.guide_titles['toc'],
673
+ html.escape(self.refnodes[0]['refuri']),
674
+ )
675
+ )
634
676
 
635
677
  # write the project file
636
678
  copy_asset_file(
@@ -640,14 +682,17 @@ class EpubBuilder(StandaloneHTMLBuilder):
640
682
  force=True,
641
683
  )
642
684
 
643
- def new_navpoint(self, node: dict[str, Any], level: int, incr: bool = True) -> NavPoint:
685
+ def new_navpoint(
686
+ self, node: dict[str, Any], level: int, incr: bool = True
687
+ ) -> NavPoint:
644
688
  """Create a new entry in the toc from the node at given level."""
645
689
  # XXX Modifies the node
646
690
  if incr:
647
691
  self.playorder += 1
648
692
  self.tocid += 1
649
- return NavPoint('navPoint%d' % self.tocid, self.playorder,
650
- node['text'], node['refuri'], [])
693
+ return NavPoint(
694
+ f'navPoint{self.tocid}', self.playorder, node['text'], node['refuri'], []
695
+ )
651
696
 
652
697
  def build_navpoints(self, nodes: list[dict[str, Any]]) -> list[NavPoint]:
653
698
  """Create the toc navigation structure.
@@ -676,7 +721,9 @@ class EpubBuilder(StandaloneHTMLBuilder):
676
721
  level += 1
677
722
  if lastnode and self.config.epub_tocdup:
678
723
  # Insert starting point in subtoc with same playOrder
679
- navstack[-1].children.append(self.new_navpoint(lastnode, level, False))
724
+ navstack[-1].children.append(
725
+ self.new_navpoint(lastnode, level, False)
726
+ )
680
727
  navpoint = self.new_navpoint(node, level)
681
728
  navstack[-1].children.append(navpoint)
682
729
  navstack.append(navpoint)
@@ -709,9 +756,9 @@ class EpubBuilder(StandaloneHTMLBuilder):
709
756
  logger.info(__('writing toc.ncx file...'))
710
757
 
711
758
  if self.config.epub_tocscope == 'default':
712
- doctree = self.env.get_and_resolve_doctree(self.config.root_doc,
713
- self, prune_toctrees=False,
714
- includehidden=False)
759
+ doctree = self.env.get_and_resolve_doctree(
760
+ self.config.root_doc, self, prune_toctrees=False, includehidden=False
761
+ )
715
762
  refnodes = self.get_refnodes(doctree, [])
716
763
  self.toc_add_files(refnodes)
717
764
  else:
@@ -4,11 +4,10 @@ from __future__ import annotations
4
4
 
5
5
  import html
6
6
  from os import path
7
- from typing import TYPE_CHECKING, Any, cast
7
+ from typing import TYPE_CHECKING
8
8
 
9
9
  from sphinx import package_dir
10
10
  from sphinx.builders import Builder
11
- from sphinx.domains.changeset import ChangeSetDomain
12
11
  from sphinx.locale import _, __
13
12
  from sphinx.theming import HTMLThemeFactory
14
13
  from sphinx.util import logging
@@ -17,6 +16,8 @@ from sphinx.util.fileutil import copy_asset_file
17
16
  from sphinx.util.osutil import ensuredir, os_path
18
17
 
19
18
  if TYPE_CHECKING:
19
+ from collections.abc import Set
20
+
20
21
  from sphinx.application import Sphinx
21
22
  from sphinx.util.typing import ExtensionMetadata
22
23
 
@@ -47,9 +48,9 @@ class ChangesBuilder(Builder):
47
48
  'versionremoved': 'removed',
48
49
  }
49
50
 
50
- def write(self, *ignored: Any) -> None:
51
+ def write_documents(self, _docnames: Set[str]) -> None:
51
52
  version = self.config.version
52
- domain = cast(ChangeSetDomain, self.env.get_domain('changeset'))
53
+ domain = self.env.domains.changeset_domain
53
54
  libchanges: dict[str, list[tuple[str, str, int]]] = {}
54
55
  apichanges: list[tuple[str, str, int]] = []
55
56
  otherchanges: dict[tuple[str, str], list[tuple[str, str, int]]] = {}
@@ -80,15 +81,21 @@ class ChangesBuilder(Builder):
80
81
  entry = f'<b>{descname}</b>: <i>{ttext}:</i> {context}'
81
82
  else:
82
83
  entry = f'<b>{descname}</b>: <i>{ttext}</i>.'
83
- libchanges.setdefault(module, []).append((entry, changeset.docname,
84
- changeset.lineno))
84
+ libchanges.setdefault(module, []).append((
85
+ entry,
86
+ changeset.docname,
87
+ changeset.lineno,
88
+ ))
85
89
  else:
86
90
  if not context:
87
91
  continue
88
92
  entry = f'<i>{ttext.capitalize()}:</i> {context}'
89
93
  title = self.env.titles[changeset.docname].astext()
90
- otherchanges.setdefault((changeset.docname, title), []).append(
91
- (entry, changeset.docname, changeset.lineno))
94
+ otherchanges.setdefault((changeset.docname, title), []).append((
95
+ entry,
96
+ changeset.docname,
97
+ changeset.lineno,
98
+ ))
92
99
 
93
100
  ctx = {
94
101
  'project': self.config.project,
@@ -106,11 +113,12 @@ class ChangesBuilder(Builder):
106
113
  with open(path.join(self.outdir, 'changes.html'), 'w', encoding='utf8') as f:
107
114
  f.write(self.templates.render('changes/versionchanges.html', ctx))
108
115
 
109
- hltext = ['.. versionadded:: %s' % version,
110
- '.. versionchanged:: %s' % version,
111
- '.. deprecated:: %s' % version,
112
- '.. versionremoved:: %s' % version,
113
- ]
116
+ hltext = [
117
+ f'.. versionadded:: {version}',
118
+ f'.. versionchanged:: {version}',
119
+ f'.. deprecated:: {version}',
120
+ f'.. versionremoved:: {version}',
121
+ ]
114
122
 
115
123
  def hl(no: int, line: str) -> str:
116
124
  line = '<a name="L%s"> </a>' % no + html.escape(line)
@@ -122,12 +130,15 @@ class ChangesBuilder(Builder):
122
130
 
123
131
  logger.info(bold(__('copying source files...')))
124
132
  for docname in self.env.all_docs:
125
- with open(self.env.doc2path(docname),
126
- encoding=self.env.config.source_encoding) as f:
133
+ with open(
134
+ self.env.doc2path(docname), encoding=self.env.config.source_encoding
135
+ ) as f:
127
136
  try:
128
137
  lines = f.readlines()
129
138
  except UnicodeDecodeError:
130
- logger.warning(__('could not read %r for changelog creation'), docname)
139
+ logger.warning(
140
+ __('could not read %r for changelog creation'), docname
141
+ )
131
142
  continue
132
143
  targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html'
133
144
  ensuredir(path.dirname(targetfn))
@@ -138,8 +149,9 @@ class ChangesBuilder(Builder):
138
149
  'text': text,
139
150
  }
140
151
  f.write(self.templates.render('changes/rstsource.html', ctx))
141
- themectx = {'theme_' + key: val for (key, val) in
142
- self.theme.get_options({}).items()}
152
+ themectx = {
153
+ 'theme_' + key: val for (key, val) in self.theme.get_options({}).items()
154
+ }
143
155
  copy_asset_file(
144
156
  path.join(package_dir, 'themes', 'default', 'static', 'default.css.jinja'),
145
157
  self.outdir,
@@ -155,9 +167,15 @@ class ChangesBuilder(Builder):
155
167
 
156
168
  def hl(self, text: str, version: str) -> str:
157
169
  text = html.escape(text)
158
- for directive in ('versionchanged', 'versionadded', 'deprecated', 'versionremoved'):
159
- text = text.replace(f'.. {directive}:: {version}',
160
- f'<b>.. {directive}:: {version}</b>')
170
+ for directive in (
171
+ 'versionchanged',
172
+ 'versionadded',
173
+ 'deprecated',
174
+ 'versionremoved',
175
+ ):
176
+ text = text.replace(
177
+ f'.. {directive}:: {version}', f'<b>.. {directive}:: {version}</b>'
178
+ )
161
179
  return text
162
180
 
163
181
  def finish(self) -> None:
@@ -34,11 +34,11 @@ class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
34
34
 
35
35
  def get_outfilename(self, pagename: str) -> str:
36
36
  if pagename == 'index' or pagename.endswith(SEP + 'index'):
37
- outfilename = path.join(self.outdir, os_path(pagename) +
38
- self.out_suffix)
37
+ outfilename = path.join(self.outdir, os_path(pagename) + self.out_suffix)
39
38
  else:
40
- outfilename = path.join(self.outdir, os_path(pagename),
41
- 'index' + self.out_suffix)
39
+ outfilename = path.join(
40
+ self.outdir, os_path(pagename), 'index' + self.out_suffix
41
+ )
42
42
 
43
43
  return outfilename
44
44
 
sphinx/builders/dummy.py CHANGED
@@ -8,7 +8,7 @@ from sphinx.builders import Builder
8
8
  from sphinx.locale import __
9
9
 
10
10
  if TYPE_CHECKING:
11
- from docutils.nodes import Node
11
+ from docutils import nodes
12
12
 
13
13
  from sphinx.application import Sphinx
14
14
  from sphinx.util.typing import ExtensionMetadata
@@ -29,10 +29,7 @@ class DummyBuilder(Builder):
29
29
  def get_target_uri(self, docname: str, typ: str | None = None) -> str:
30
30
  return ''
31
31
 
32
- def prepare_writing(self, docnames: set[str]) -> None:
33
- pass
34
-
35
- def write_doc(self, docname: str, doctree: Node) -> None:
32
+ def write_doc(self, docname: str, doctree: nodes.document) -> None:
36
33
  pass
37
34
 
38
35
  def finish(self) -> None:
sphinx/builders/epub3.py CHANGED
@@ -21,6 +21,8 @@ from sphinx.util.fileutil import copy_asset_file
21
21
  from sphinx.util.osutil import make_filename
22
22
 
23
23
  if TYPE_CHECKING:
24
+ from collections.abc import Set
25
+
24
26
  from sphinx.application import Sphinx
25
27
  from sphinx.util.typing import ExtensionMetadata
26
28
 
@@ -47,7 +49,7 @@ THEME_WRITING_MODES = {
47
49
  'horizontal': 'horizontal-tb',
48
50
  }
49
51
 
50
- DOCTYPE = '''<!DOCTYPE html>'''
52
+ DOCTYPE = """<!DOCTYPE html>"""
51
53
 
52
54
  HTML_TAG = (
53
55
  '<html xmlns="http://www.w3.org/1999/xhtml" '
@@ -56,14 +58,14 @@ HTML_TAG = (
56
58
 
57
59
  # https://www.w3.org/TR/REC-xml/#NT-Name
58
60
  _xml_name_start_char = (
59
- ':|[A-Z]|_|[a-z]|[\u00C0-\u00D6]'
60
- '|[\u00D8-\u00F6]|[\u00F8-\u02FF]|[\u0370-\u037D]'
61
- '|[\u037F-\u1FFF]|[\u200C-\u200D]|[\u2070-\u218F]'
62
- '|[\u2C00-\u2FEF]|[\u3001-\uD7FF]|[\uF900-\uFDCF]'
63
- '|[\uFDF0-\uFFFD]|[\U00010000-\U000EFFFF]'
61
+ ':|[A-Z]|_|[a-z]|[\u00c0-\u00d6]'
62
+ '|[\u00d8-\u00f6]|[\u00f8-\u02ff]|[\u0370-\u037d]'
63
+ '|[\u037f-\u1fff]|[\u200c-\u200d]|[\u2070-\u218f]'
64
+ '|[\u2c00-\u2fef]|[\u3001-\ud7ff]|[\uf900-\ufdcf]'
65
+ '|[\ufdf0-\ufffd]|[\U00010000-\U000effff]'
64
66
  )
65
67
  _xml_name_char = (
66
- _xml_name_start_char + r'\-|\.' '|[0-9]|\u00B7|[\u0300-\u036F]|[\u203F-\u2040]'
68
+ _xml_name_start_char + r'\-|\.' '|[0-9]|\u00b7|[\u0300-\u036f]|[\u203f-\u2040]'
67
69
  )
68
70
  _XML_NAME_PATTERN = re.compile(f'({_xml_name_start_char})({_xml_name_char})*')
69
71
 
@@ -111,14 +113,16 @@ class Epub3Builder(_epub_base.EpubBuilder):
111
113
  metadata = super().content_metadata()
112
114
  metadata['description'] = html.escape(self.config.epub_description)
113
115
  metadata['contributor'] = html.escape(self.config.epub_contributor)
114
- metadata['page_progression_direction'] = PAGE_PROGRESSION_DIRECTIONS.get(writing_mode)
116
+ metadata['page_progression_direction'] = PAGE_PROGRESSION_DIRECTIONS.get(
117
+ writing_mode
118
+ )
115
119
  metadata['ibook_scroll_axis'] = IBOOK_SCROLL_AXIS.get(writing_mode)
116
- metadata['date'] = html.escape(time.strftime("%Y-%m-%dT%H:%M:%SZ", time_tuple))
120
+ metadata['date'] = html.escape(time.strftime('%Y-%m-%dT%H:%M:%SZ', time_tuple))
117
121
  metadata['version'] = html.escape(self.config.version)
118
122
  metadata['epub_version'] = self.config.epub_version
119
123
  return metadata
120
124
 
121
- def prepare_writing(self, docnames: set[str]) -> None:
125
+ def prepare_writing(self, docnames: Set[str]) -> None:
122
126
  super().prepare_writing(docnames)
123
127
 
124
128
  writing_mode = self.config.epub_writing_mode
@@ -186,8 +190,8 @@ class Epub3Builder(_epub_base.EpubBuilder):
186
190
 
187
191
  if self.config.epub_tocscope == 'default':
188
192
  doctree = self.env.get_and_resolve_doctree(
189
- self.config.root_doc, self,
190
- prune_toctrees=False, includehidden=False)
193
+ self.config.root_doc, self, prune_toctrees=False, includehidden=False
194
+ )
191
195
  refnodes = self.get_refnodes(doctree, [])
192
196
  self.toc_add_files(refnodes)
193
197
  else:
@@ -212,31 +216,47 @@ def validate_config_values(app: Sphinx) -> None:
212
216
 
213
217
  # <package> lang attribute, dc:language
214
218
  if not app.config.epub_language:
215
- logger.warning(__('conf value "epub_language" (or "language") '
216
- 'should not be empty for EPUB3'))
219
+ logger.warning(
220
+ __(
221
+ 'conf value "epub_language" (or "language") '
222
+ 'should not be empty for EPUB3'
223
+ )
224
+ )
217
225
  # <package> unique-identifier attribute
218
226
  if not _XML_NAME_PATTERN.match(app.config.epub_uid):
219
227
  logger.warning(__('conf value "epub_uid" should be XML NAME for EPUB3'))
220
228
  # dc:title
221
229
  if not app.config.epub_title:
222
- logger.warning(__('conf value "epub_title" (or "html_title") '
223
- 'should not be empty for EPUB3'))
230
+ logger.warning(
231
+ __(
232
+ 'conf value "epub_title" (or "html_title") '
233
+ 'should not be empty for EPUB3'
234
+ )
235
+ )
224
236
  # dc:creator
225
237
  if not app.config.epub_author:
226
238
  logger.warning(__('conf value "epub_author" should not be empty for EPUB3'))
227
239
  # dc:contributor
228
240
  if not app.config.epub_contributor:
229
- logger.warning(__('conf value "epub_contributor" should not be empty for EPUB3'))
241
+ logger.warning(
242
+ __('conf value "epub_contributor" should not be empty for EPUB3')
243
+ )
230
244
  # dc:description
231
245
  if not app.config.epub_description:
232
- logger.warning(__('conf value "epub_description" should not be empty for EPUB3'))
246
+ logger.warning(
247
+ __('conf value "epub_description" should not be empty for EPUB3')
248
+ )
233
249
  # dc:publisher
234
250
  if not app.config.epub_publisher:
235
251
  logger.warning(__('conf value "epub_publisher" should not be empty for EPUB3'))
236
252
  # dc:rights
237
253
  if not app.config.epub_copyright:
238
- logger.warning(__('conf value "epub_copyright" (or "copyright")'
239
- 'should not be empty for EPUB3'))
254
+ logger.warning(
255
+ __(
256
+ 'conf value "epub_copyright" (or "copyright")'
257
+ 'should not be empty for EPUB3'
258
+ )
259
+ )
240
260
  # dc:identifier
241
261
  if not app.config.epub_identifier:
242
262
  logger.warning(__('conf value "epub_identifier" should not be empty for EPUB3'))
@@ -293,8 +313,9 @@ def setup(app: Sphinx) -> ExtensionMetadata:
293
313
  app.add_config_value('epub_use_index', lambda self: self.html_use_index, 'epub')
294
314
  app.add_config_value('epub_description', 'unknown', 'epub')
295
315
  app.add_config_value('epub_contributor', 'unknown', 'epub')
296
- app.add_config_value('epub_writing_mode', 'horizontal', 'epub',
297
- ENUM('horizontal', 'vertical'))
316
+ app.add_config_value(
317
+ 'epub_writing_mode', 'horizontal', 'epub', ENUM('horizontal', 'vertical')
318
+ )
298
319
 
299
320
  # event handlers
300
321
  app.connect('config-inited', convert_epub_css_files, priority=800)