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/config.py CHANGED
@@ -23,7 +23,7 @@ else:
23
23
 
24
24
  if TYPE_CHECKING:
25
25
  import os
26
- from collections.abc import Collection, Iterator, Sequence, Set
26
+ from collections.abc import Collection, Iterable, Iterator, Sequence, Set
27
27
  from typing import TypeAlias
28
28
 
29
29
  from sphinx.application import Sphinx
@@ -271,7 +271,7 @@ class Config:
271
271
  'smartquotes': _Opt(True, 'env', ()),
272
272
  'smartquotes_action': _Opt('qDe', 'env', ()),
273
273
  'smartquotes_excludes': _Opt(
274
- {'languages': ['ja'], 'builders': ['man', 'text']}, 'env', ()),
274
+ {'languages': ['ja', 'zh_CN', 'zh_TW'], 'builders': ['man', 'text']}, 'env', ()),
275
275
  'option_emphasise_placeholders': _Opt(False, 'env', ()),
276
276
  }
277
277
 
@@ -619,28 +619,55 @@ def init_numfig_format(app: Sphinx, config: Config) -> None:
619
619
  config.numfig_format = numfig_format
620
620
 
621
621
 
622
+ def evaluate_copyright_placeholders(_app: Sphinx, config: Config) -> None:
623
+ """Replace copyright year placeholders (%Y) with the current year."""
624
+ replace_yr = str(time.localtime().tm_year)
625
+ for k in ('copyright', 'epub_copyright'):
626
+ if k in config:
627
+ value: str | Sequence[str] = config[k]
628
+ if isinstance(value, str):
629
+ if '%Y' in value:
630
+ config[k] = value.replace('%Y', replace_yr)
631
+ else:
632
+ if any('%Y' in line for line in value):
633
+ items = (line.replace('%Y', replace_yr) for line in value)
634
+ config[k] = type(value)(items) # type: ignore[call-arg]
635
+
636
+
622
637
  def correct_copyright_year(_app: Sphinx, config: Config) -> None:
623
638
  """Correct values of copyright year that are not coherent with
624
639
  the SOURCE_DATE_EPOCH environment variable (if set)
625
640
 
626
641
  See https://reproducible-builds.org/specs/source-date-epoch/
627
642
  """
628
- if (source_date_epoch := getenv('SOURCE_DATE_EPOCH')) is None:
643
+ if source_date_epoch := int(getenv('SOURCE_DATE_EPOCH', '0')):
644
+ source_date_epoch_year = time.gmtime(source_date_epoch).tm_year
645
+ else:
629
646
  return
630
647
 
631
- source_date_epoch_year = str(time.gmtime(int(source_date_epoch)).tm_year)
648
+ # If the current year is the replacement year, there's no work to do.
649
+ # We also skip replacement years that are in the future.
650
+ current_year = time.localtime().tm_year
651
+ if current_year <= source_date_epoch_year:
652
+ return
632
653
 
654
+ current_yr = str(current_year)
655
+ replace_yr = str(source_date_epoch_year)
633
656
  for k in ('copyright', 'epub_copyright'):
634
657
  if k in config:
635
658
  value: str | Sequence[str] = config[k]
636
659
  if isinstance(value, str):
637
- config[k] = _substitute_copyright_year(value, source_date_epoch_year)
660
+ config[k] = _substitute_copyright_year(value, current_yr, replace_yr)
638
661
  else:
639
- items = (_substitute_copyright_year(x, source_date_epoch_year) for x in value)
662
+ items = (
663
+ _substitute_copyright_year(x, current_yr, replace_yr) for x in value
664
+ )
640
665
  config[k] = type(value)(items) # type: ignore[call-arg]
641
666
 
642
667
 
643
- def _substitute_copyright_year(copyright_line: str, replace_year: str) -> str:
668
+ def _substitute_copyright_year(
669
+ copyright_line: str, current_year: str, replace_year: str
670
+ ) -> str:
644
671
  """Replace the year in a single copyright line.
645
672
 
646
673
  Legal formats are:
@@ -648,6 +675,7 @@ def _substitute_copyright_year(copyright_line: str, replace_year: str) -> str:
648
675
  * ``YYYY``
649
676
  * ``YYYY,``
650
677
  * ``YYYY ``
678
+ * ``YYYY-YYYY``
651
679
  * ``YYYY-YYYY,``
652
680
  * ``YYYY-YYYY ``
653
681
 
@@ -656,13 +684,17 @@ def _substitute_copyright_year(copyright_line: str, replace_year: str) -> str:
656
684
  if len(copyright_line) < 4 or not copyright_line[:4].isdigit():
657
685
  return copyright_line
658
686
 
659
- if copyright_line[4:5] in {'', ' ', ','}:
687
+ if copyright_line[:4] == current_year and copyright_line[4:5] in {'', ' ', ','}:
660
688
  return replace_year + copyright_line[4:]
661
689
 
662
- if copyright_line[4] != '-':
690
+ if copyright_line[4:5] != '-':
663
691
  return copyright_line
664
692
 
665
- if copyright_line[5:9].isdigit() and copyright_line[9:10] in {'', ' ', ','}:
693
+ if (
694
+ copyright_line[5:9].isdigit()
695
+ and copyright_line[5:9] == current_year
696
+ and copyright_line[9:10] in {'', ' ', ','}
697
+ ):
666
698
  return copyright_line[:5] + replace_year + copyright_line[9:]
667
699
 
668
700
  return copyright_line
@@ -739,8 +771,8 @@ def check_primary_domain(app: Sphinx, config: Config) -> None:
739
771
  config.primary_domain = None
740
772
 
741
773
 
742
- def check_root_doc(app: Sphinx, env: BuildEnvironment, added: set[str],
743
- changed: set[str], removed: set[str]) -> set[str]:
774
+ def check_root_doc(app: Sphinx, env: BuildEnvironment, added: Set[str],
775
+ changed: Set[str], removed: Set[str]) -> Iterable[str]:
744
776
  """Adjust root_doc to 'contents' to support an old project which does not have
745
777
  any root_doc setting.
746
778
  """
@@ -758,6 +790,7 @@ def setup(app: Sphinx) -> ExtensionMetadata:
758
790
  app.connect('config-inited', convert_source_suffix, priority=800)
759
791
  app.connect('config-inited', convert_highlight_options, priority=800)
760
792
  app.connect('config-inited', init_numfig_format, priority=800)
793
+ app.connect('config-inited', evaluate_copyright_placeholders, priority=795)
761
794
  app.connect('config-inited', correct_copyright_year, priority=800)
762
795
  app.connect('config-inited', check_confval_types, priority=800)
763
796
  app.connect('config-inited', check_primary_domain, priority=800)
sphinx/deprecation.py CHANGED
@@ -40,7 +40,11 @@ def _deprecation_warning(
40
40
 
41
41
  # deprecated name -> (object to return, canonical path or empty string, removal version)
42
42
  _DEPRECATED_OBJECTS = {
43
- 'deprecated_name': (object_to_return, 'fully_qualified_replacement_name', (9, 0)),
43
+ 'deprecated_name': (
44
+ object_to_return,
45
+ 'fully_qualified_replacement_name',
46
+ (9, 0),
47
+ ),
44
48
  }
45
49
 
46
50
 
@@ -65,7 +69,9 @@ def _deprecation_warning(
65
69
 
66
70
  qualname = f'{module}.{attribute}'
67
71
  if canonical_name:
68
- message = f'The alias {qualname!r} is deprecated, use {canonical_name!r} instead.'
72
+ message = (
73
+ f'The alias {qualname!r} is deprecated, use {canonical_name!r} instead.'
74
+ )
69
75
  else:
70
76
  message = f'{qualname!r} is deprecated.'
71
77
 
@@ -111,7 +111,9 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
111
111
  """
112
112
  raise ValueError
113
113
 
114
- def add_target_and_index(self, name: ObjDescT, sig: str, signode: desc_signature) -> None:
114
+ def add_target_and_index(
115
+ self, name: ObjDescT, sig: str, signode: desc_signature
116
+ ) -> None:
115
117
  """
116
118
  Add cross-reference IDs and entries to self.indexnode, if applicable.
117
119
 
@@ -228,19 +230,18 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
228
230
  self.options['no-index'] = self.options['noindex']
229
231
  if 'no-index-entry' not in self.options and 'noindexentry' in self.options:
230
232
  self.options['no-index-entry'] = self.options['noindexentry']
231
- if 'no-contents-entry' not in self.options and 'nocontentsentry' in self.options:
233
+ if (
234
+ 'no-contents-entry' not in self.options
235
+ and 'nocontentsentry' in self.options
236
+ ):
232
237
  self.options['no-contents-entry'] = self.options['nocontentsentry']
233
238
 
234
- node['no-index'] = node['noindex'] = no_index = (
235
- 'no-index' in self.options
236
- )
237
- node['no-index-entry'] = node['noindexentry'] = (
238
- 'no-index-entry' in self.options
239
- )
239
+ node['no-index'] = node['noindex'] = no_index = 'no-index' in self.options
240
+ node['no-index-entry'] = node['noindexentry'] = 'no-index-entry' in self.options
240
241
  node['no-contents-entry'] = node['nocontentsentry'] = (
241
242
  'no-contents-entry' in self.options
242
243
  )
243
- node['no-typesetting'] = ('no-typesetting' in self.options)
244
+ node['no-typesetting'] = 'no-typesetting' in self.options
244
245
  if self.domain:
245
246
  node['classes'].append(self.domain)
246
247
  node['classes'].append(node['objtype'])
@@ -287,8 +288,9 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
287
288
  content_node = addnodes.desc_content('', *content_children)
288
289
  node.append(content_node)
289
290
  self.transform_content(content_node)
290
- self.env.app.emit('object-description-transform',
291
- self.domain, self.objtype, content_node)
291
+ self.env.app.emit(
292
+ 'object-description-transform', self.domain, self.objtype, content_node
293
+ )
292
294
  DocFieldTransformer(self).transform_all(content_node)
293
295
  self.env.temp_data['object'] = None
294
296
  self.after_content()
@@ -299,8 +301,11 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
299
301
  # If ``:no-index:`` is set, or there are no ids on the node
300
302
  # or any of its children, then just return the index node,
301
303
  # as Docutils expects a target node to have at least one id.
302
- if node_ids := [node_id for el in node.findall(nodes.Element) # type: ignore[var-annotated]
303
- for node_id in el.get('ids', ())]:
304
+ if node_ids := [ # type: ignore[var-annotated]
305
+ node_id
306
+ for el in node.findall(nodes.Element)
307
+ for node_id in el.get('ids', ())
308
+ ]:
304
309
  target_node = nodes.target(ids=node_ids)
305
310
  self.set_source_info(target_node)
306
311
  return [self.indexnode, target_node]
@@ -321,16 +326,20 @@ class DefaultRole(SphinxDirective):
321
326
  docutils.unregister_role('')
322
327
  return []
323
328
  role_name = self.arguments[0]
324
- role, messages = roles.role(role_name, self.state_machine.language,
325
- self.lineno, self.state.reporter)
329
+ role, messages = roles.role(
330
+ role_name, self.state_machine.language, self.lineno, self.state.reporter
331
+ )
326
332
  if role:
327
333
  docutils.register_role('', role) # type: ignore[arg-type]
328
334
  self.env.temp_data['default_role'] = role_name
329
335
  else:
330
336
  literal_block = nodes.literal_block(self.block_text, self.block_text)
331
337
  reporter = self.state.reporter
332
- error = reporter.error('Unknown interpreted text role "%s".' % role_name,
333
- literal_block, line=self.lineno)
338
+ error = reporter.error(
339
+ 'Unknown interpreted text role "%s".' % role_name,
340
+ literal_block,
341
+ line=self.lineno,
342
+ )
334
343
  messages += [error]
335
344
 
336
345
  return cast(list[nodes.Node], messages)
@@ -351,7 +360,7 @@ class DefaultDomain(SphinxDirective):
351
360
  domain_name = self.arguments[0].lower()
352
361
  # if domain_name not in env.domains:
353
362
  # # try searching by label
354
- # for domain in env.domains.values():
363
+ # for domain in env.domains.sorted():
355
364
  # if domain.label.lower() == domain_name:
356
365
  # domain_name = domain.name
357
366
  # break
@@ -360,7 +369,7 @@ class DefaultDomain(SphinxDirective):
360
369
 
361
370
 
362
371
  def setup(app: Sphinx) -> ExtensionMetadata:
363
- app.add_config_value("strip_signature_backslash", False, 'env')
372
+ app.add_config_value('strip_signature_backslash', False, 'env')
364
373
  directives.register_directive('default-role', DefaultRole)
365
374
  directives.register_directive('default-domain', DefaultDomain)
366
375
  directives.register_directive('describe', ObjectDescription)
sphinx/directives/code.py CHANGED
@@ -11,7 +11,8 @@ from docutils.parsers.rst import directives
11
11
  from sphinx import addnodes
12
12
  from sphinx.directives import optional_int
13
13
  from sphinx.locale import __
14
- from sphinx.util import logging, parselinenos
14
+ from sphinx.util import logging
15
+ from sphinx.util._lines import parse_line_num_spec
15
16
  from sphinx.util.docutils import SphinxDirective
16
17
 
17
18
  if TYPE_CHECKING:
@@ -45,13 +46,15 @@ class Highlight(SphinxDirective):
45
46
  force = 'force' in self.options
46
47
 
47
48
  self.env.temp_data['highlight_language'] = language
48
- return [addnodes.highlightlang(lang=language,
49
- force=force,
50
- linenothreshold=linenothreshold)]
49
+ return [
50
+ addnodes.highlightlang(
51
+ lang=language, force=force, linenothreshold=linenothreshold
52
+ )
53
+ ]
51
54
 
52
55
 
53
56
  def dedent_lines(
54
- lines: list[str], dedent: int | None, location: tuple[str, int] | None = None,
57
+ lines: list[str], dedent: int | None, location: tuple[str, int] | None = None
55
58
  ) -> list[str]:
56
59
  if dedent is None:
57
60
  return textwrap.dedent(''.join(lines)).splitlines(True)
@@ -70,10 +73,11 @@ def dedent_lines(
70
73
 
71
74
 
72
75
  def container_wrapper(
73
- directive: SphinxDirective, literal_node: Node, caption: str,
76
+ directive: SphinxDirective, literal_node: Node, caption: str
74
77
  ) -> nodes.container:
75
- container_node = nodes.container('', literal_block=True,
76
- classes=['literal-block-wrapper'])
78
+ container_node = nodes.container(
79
+ '', literal_block=True, classes=['literal-block-wrapper']
80
+ )
77
81
  parsed = directive.parse_text_to_nodes(caption, offset=directive.content_offset)
78
82
  node = parsed[0]
79
83
  if isinstance(node, nodes.system_message):
@@ -119,11 +123,14 @@ class CodeBlock(SphinxDirective):
119
123
  if linespec:
120
124
  try:
121
125
  nlines = len(self.content)
122
- hl_lines = parselinenos(linespec, nlines)
126
+ hl_lines = parse_line_num_spec(linespec, nlines)
123
127
  if any(i >= nlines for i in hl_lines):
124
- logger.warning(__('line number spec is out of range(1-%d): %r'),
125
- nlines, self.options['emphasize-lines'],
126
- location=location)
128
+ logger.warning(
129
+ __('line number spec is out of range(1-%d): %r'),
130
+ nlines,
131
+ self.options['emphasize-lines'],
132
+ location=location,
133
+ )
127
134
 
128
135
  hl_lines = [x + 1 for x in hl_lines if x < nlines]
129
136
  except ValueError as err:
@@ -149,8 +156,9 @@ class CodeBlock(SphinxDirective):
149
156
  # no highlight language specified. Then this directive refers the current
150
157
  # highlight setting via ``highlight`` directive or ``highlight_language``
151
158
  # configuration.
152
- literal['language'] = self.env.temp_data.get('highlight_language',
153
- self.config.highlight_language)
159
+ literal['language'] = self.env.temp_data.get(
160
+ 'highlight_language', self.config.highlight_language
161
+ )
154
162
  extra_args = literal['highlight_args'] = {}
155
163
  if hl_lines is not None:
156
164
  extra_args['hl_lines'] = hl_lines
@@ -200,11 +208,11 @@ class LiteralIncludeReader:
200
208
  def parse_options(self) -> None:
201
209
  for option1, option2 in self.INVALID_OPTIONS_PAIR:
202
210
  if option1 in self.options and option2 in self.options:
203
- raise ValueError(__('Cannot use both "%s" and "%s" options') %
204
- (option1, option2))
211
+ msg = __('Cannot use both "%s" and "%s" options') % (option1, option2)
212
+ raise ValueError(msg)
205
213
 
206
214
  def read_file(
207
- self, filename: str, location: tuple[str, int] | None = None,
215
+ self, filename: str, location: tuple[str, int] | None = None
208
216
  ) -> list[str]:
209
217
  try:
210
218
  with open(filename, encoding=self.encoding, errors='strict') as f:
@@ -214,24 +222,28 @@ class LiteralIncludeReader:
214
222
 
215
223
  return text.splitlines(True)
216
224
  except OSError as exc:
217
- raise OSError(__('Include file %r not found or reading it failed') %
218
- filename) from exc
225
+ msg = __('Include file %r not found or reading it failed') % filename
226
+ raise OSError(msg) from exc
219
227
  except UnicodeError as exc:
220
- raise UnicodeError(__('Encoding %r used for reading included file %r seems to '
221
- 'be wrong, try giving an :encoding: option') %
222
- (self.encoding, filename)) from exc
228
+ msg = __(
229
+ 'Encoding %r used for reading included file %r seems to '
230
+ 'be wrong, try giving an :encoding: option'
231
+ ) % (self.encoding, filename)
232
+ raise UnicodeError(msg) from exc
223
233
 
224
234
  def read(self, location: tuple[str, int] | None = None) -> tuple[str, int]:
225
235
  if 'diff' in self.options:
226
236
  lines = self.show_diff()
227
237
  else:
228
- filters = [self.pyobject_filter,
229
- self.start_filter,
230
- self.end_filter,
231
- self.lines_filter,
232
- self.dedent_filter,
233
- self.prepend_filter,
234
- self.append_filter]
238
+ filters = [
239
+ self.pyobject_filter,
240
+ self.start_filter,
241
+ self.end_filter,
242
+ self.lines_filter,
243
+ self.dedent_filter,
244
+ self.prepend_filter,
245
+ self.append_filter,
246
+ ]
235
247
  lines = self.read_file(self.filename, location=location)
236
248
  for func in filters:
237
249
  lines = func(lines, location=location)
@@ -246,33 +258,41 @@ class LiteralIncludeReader:
246
258
  return list(diff)
247
259
 
248
260
  def pyobject_filter(
249
- self, lines: list[str], location: tuple[str, int] | None = None,
261
+ self, lines: list[str], location: tuple[str, int] | None = None
250
262
  ) -> list[str]:
251
263
  pyobject = self.options.get('pyobject')
252
264
  if pyobject:
253
265
  from sphinx.pycode import ModuleAnalyzer
266
+
254
267
  analyzer = ModuleAnalyzer.for_file(self.filename, '')
255
268
  tags = analyzer.find_tags()
256
269
  if pyobject not in tags:
257
- raise ValueError(__('Object named %r not found in include file %r') %
258
- (pyobject, self.filename))
270
+ msg = __('Object named %r not found in include file %r') % (
271
+ pyobject,
272
+ self.filename,
273
+ )
274
+ raise ValueError(msg)
259
275
  start = tags[pyobject][1]
260
276
  end = tags[pyobject][2]
261
- lines = lines[start - 1:end]
277
+ lines = lines[start - 1 : end]
262
278
  if 'lineno-match' in self.options:
263
279
  self.lineno_start = start
264
280
 
265
281
  return lines
266
282
 
267
283
  def lines_filter(
268
- self, lines: list[str], location: tuple[str, int] | None = None,
284
+ self, lines: list[str], location: tuple[str, int] | None = None
269
285
  ) -> list[str]:
270
286
  linespec = self.options.get('lines')
271
287
  if linespec:
272
- linelist = parselinenos(linespec, len(lines))
288
+ linelist = parse_line_num_spec(linespec, len(lines))
273
289
  if any(i >= len(lines) for i in linelist):
274
- logger.warning(__('line number spec is out of range(1-%d): %r'),
275
- len(lines), linespec, location=location)
290
+ logger.warning(
291
+ __('line number spec is out of range(1-%d): %r'),
292
+ len(lines),
293
+ linespec,
294
+ location=location,
295
+ )
276
296
 
277
297
  if 'lineno-match' in self.options:
278
298
  # make sure the line list is not "disjoint".
@@ -280,18 +300,21 @@ class LiteralIncludeReader:
280
300
  if all(first + i == n for i, n in enumerate(linelist)):
281
301
  self.lineno_start += linelist[0]
282
302
  else:
283
- raise ValueError(__('Cannot use "lineno-match" with a disjoint '
284
- 'set of "lines"'))
303
+ msg = __('Cannot use "lineno-match" with a disjoint set of "lines"')
304
+ raise ValueError(msg)
285
305
 
286
306
  lines = [lines[n] for n in linelist if n < len(lines)]
287
307
  if not lines:
288
- raise ValueError(__('Line spec %r: no lines pulled from include file %r') %
289
- (linespec, self.filename))
308
+ msg = __('Line spec %r: no lines pulled from include file %r') % (
309
+ linespec,
310
+ self.filename,
311
+ )
312
+ raise ValueError(msg)
290
313
 
291
314
  return lines
292
315
 
293
316
  def start_filter(
294
- self, lines: list[str], location: tuple[str, int] | None = None,
317
+ self, lines: list[str], location: tuple[str, int] | None = None
295
318
  ) -> list[str]:
296
319
  if 'start-at' in self.options:
297
320
  start = self.options.get('start-at')
@@ -309,7 +332,7 @@ class LiteralIncludeReader:
309
332
  if 'lineno-match' in self.options:
310
333
  self.lineno_start += lineno + 1
311
334
 
312
- return lines[lineno + 1:]
335
+ return lines[lineno + 1 :]
313
336
  else:
314
337
  if 'lineno-match' in self.options:
315
338
  self.lineno_start += lineno
@@ -324,7 +347,7 @@ class LiteralIncludeReader:
324
347
  return lines
325
348
 
326
349
  def end_filter(
327
- self, lines: list[str], location: tuple[str, int] | None = None,
350
+ self, lines: list[str], location: tuple[str, int] | None = None
328
351
  ) -> list[str]:
329
352
  if 'end-at' in self.options:
330
353
  end = self.options.get('end-at')
@@ -339,7 +362,7 @@ class LiteralIncludeReader:
339
362
  for lineno, line in enumerate(lines):
340
363
  if end in line:
341
364
  if inclusive:
342
- return lines[:lineno + 1]
365
+ return lines[: lineno + 1]
343
366
  else:
344
367
  if lineno == 0:
345
368
  pass # end-before ignores first line
@@ -353,7 +376,7 @@ class LiteralIncludeReader:
353
376
  return lines
354
377
 
355
378
  def prepend_filter(
356
- self, lines: list[str], location: tuple[str, int] | None = None,
379
+ self, lines: list[str], location: tuple[str, int] | None = None
357
380
  ) -> list[str]:
358
381
  prepend = self.options.get('prepend')
359
382
  if prepend:
@@ -362,7 +385,7 @@ class LiteralIncludeReader:
362
385
  return lines
363
386
 
364
387
  def append_filter(
365
- self, lines: list[str], location: tuple[str, int] | None = None,
388
+ self, lines: list[str], location: tuple[str, int] | None = None
366
389
  ) -> list[str]:
367
390
  append = self.options.get('append')
368
391
  if append:
@@ -371,7 +394,7 @@ class LiteralIncludeReader:
371
394
  return lines
372
395
 
373
396
  def dedent_filter(
374
- self, lines: list[str], location: tuple[str, int] | None = None,
397
+ self, lines: list[str], location: tuple[str, int] | None = None
375
398
  ) -> list[str]:
376
399
  if 'dedent' in self.options:
377
400
  return dedent_lines(lines, self.options.get('dedent'), location=location)
@@ -417,8 +440,9 @@ class LiteralInclude(SphinxDirective):
417
440
  def run(self) -> list[Node]:
418
441
  document = self.state.document
419
442
  if not document.settings.file_insertion_enabled:
420
- return [document.reporter.warning('File insertion disabled',
421
- line=self.lineno)]
443
+ return [
444
+ document.reporter.warning('File insertion disabled', line=self.lineno)
445
+ ]
422
446
  # convert options['diff'] to absolute path
423
447
  if 'diff' in self.options:
424
448
  _, path = self.env.relfn2path(self.options['diff'])
@@ -439,17 +463,23 @@ class LiteralInclude(SphinxDirective):
439
463
  retnode['language'] = 'udiff'
440
464
  elif 'language' in self.options:
441
465
  retnode['language'] = self.options['language']
442
- if ('linenos' in self.options or 'lineno-start' in self.options or
443
- 'lineno-match' in self.options):
466
+ if (
467
+ 'linenos' in self.options
468
+ or 'lineno-start' in self.options
469
+ or 'lineno-match' in self.options
470
+ ):
444
471
  retnode['linenos'] = True
445
472
  retnode['classes'] += self.options.get('class', [])
446
473
  extra_args = retnode['highlight_args'] = {}
447
474
  if 'emphasize-lines' in self.options:
448
- hl_lines = parselinenos(self.options['emphasize-lines'], lines)
475
+ hl_lines = parse_line_num_spec(self.options['emphasize-lines'], lines)
449
476
  if any(i >= lines for i in hl_lines):
450
- logger.warning(__('line number spec is out of range(1-%d): %r'),
451
- lines, self.options['emphasize-lines'],
452
- location=location)
477
+ logger.warning(
478
+ __('line number spec is out of range(1-%d): %r'),
479
+ lines,
480
+ self.options['emphasize-lines'],
481
+ location=location,
482
+ )
453
483
  extra_args['hl_lines'] = [x + 1 for x in hl_lines if x < lines]
454
484
  extra_args['linenostart'] = reader.lineno_start
455
485