Sphinx 7.3.6__py3-none-any.whl → 7.4.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 (357) hide show
  1. sphinx/__init__.py +5 -6
  2. sphinx/_cli/__init__.py +296 -0
  3. sphinx/_cli/util/__init__.py +0 -0
  4. sphinx/_cli/util/colour.py +103 -0
  5. sphinx/_cli/util/errors.py +165 -0
  6. sphinx/application.py +78 -43
  7. sphinx/builders/__init__.py +59 -15
  8. sphinx/builders/_epub_base.py +11 -5
  9. sphinx/builders/changes.py +2 -2
  10. sphinx/builders/epub3.py +2 -2
  11. sphinx/builders/gettext.py +10 -10
  12. sphinx/builders/html/__init__.py +56 -54
  13. sphinx/builders/latex/__init__.py +5 -5
  14. sphinx/builders/latex/constants.py +5 -0
  15. sphinx/builders/linkcheck.py +73 -38
  16. sphinx/builders/texinfo.py +1 -1
  17. sphinx/cmd/build.py +1 -1
  18. sphinx/cmd/quickstart.py +11 -11
  19. sphinx/config.py +57 -38
  20. sphinx/directives/__init__.py +7 -9
  21. sphinx/directives/code.py +12 -15
  22. sphinx/directives/other.py +12 -15
  23. sphinx/directives/patches.py +26 -0
  24. sphinx/domains/__init__.py +1 -1
  25. sphinx/domains/c/__init__.py +5 -5
  26. sphinx/domains/c/_ast.py +436 -12
  27. sphinx/domains/c/_symbol.py +89 -134
  28. sphinx/domains/changeset.py +3 -4
  29. sphinx/domains/cpp/__init__.py +5 -6
  30. sphinx/domains/cpp/_ast.py +822 -25
  31. sphinx/domains/cpp/_symbol.py +3 -0
  32. sphinx/domains/javascript.py +3 -6
  33. sphinx/domains/math.py +3 -2
  34. sphinx/domains/python/__init__.py +45 -6
  35. sphinx/domains/python/_object.py +7 -5
  36. sphinx/domains/rst.py +2 -2
  37. sphinx/domains/std/__init__.py +95 -14
  38. sphinx/environment/__init__.py +35 -15
  39. sphinx/environment/adapters/indexentries.py +71 -24
  40. sphinx/environment/adapters/toctree.py +1 -1
  41. sphinx/environment/collectors/__init__.py +18 -4
  42. sphinx/environment/collectors/asset.py +4 -4
  43. sphinx/environment/collectors/toctree.py +27 -14
  44. sphinx/events.py +7 -6
  45. sphinx/ext/apidoc.py +377 -170
  46. sphinx/ext/autodoc/__init__.py +13 -13
  47. sphinx/ext/autodoc/directive.py +10 -13
  48. sphinx/ext/autodoc/mock.py +10 -7
  49. sphinx/ext/autodoc/preserve_defaults.py +1 -1
  50. sphinx/ext/autodoc/typehints.py +2 -2
  51. sphinx/ext/autosummary/__init__.py +15 -9
  52. sphinx/ext/autosummary/generate.py +270 -154
  53. sphinx/ext/coverage.py +108 -18
  54. sphinx/ext/duration.py +10 -3
  55. sphinx/ext/extlinks.py +3 -2
  56. sphinx/ext/graphviz.py +3 -3
  57. sphinx/ext/ifconfig.py +1 -2
  58. sphinx/ext/imgconverter.py +1 -0
  59. sphinx/ext/imgmath.py +7 -6
  60. sphinx/ext/inheritance_diagram.py +3 -3
  61. sphinx/ext/intersphinx/__init__.py +81 -0
  62. sphinx/ext/intersphinx/__main__.py +10 -0
  63. sphinx/ext/intersphinx/_cli.py +44 -0
  64. sphinx/ext/intersphinx/_load.py +253 -0
  65. sphinx/ext/{intersphinx.py → intersphinx/_resolve.py} +17 -368
  66. sphinx/ext/intersphinx/_shared.py +53 -0
  67. sphinx/ext/mathjax.py +1 -1
  68. sphinx/ext/todo.py +2 -2
  69. sphinx/io.py +2 -6
  70. sphinx/locale/__init__.py +1 -5
  71. sphinx/locale/ar/LC_MESSAGES/sphinx.js +1 -1
  72. sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
  73. sphinx/locale/ar/LC_MESSAGES/sphinx.po +678 -471
  74. sphinx/locale/bg/LC_MESSAGES/sphinx.js +1 -1
  75. sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
  76. sphinx/locale/bg/LC_MESSAGES/sphinx.po +684 -476
  77. sphinx/locale/bn/LC_MESSAGES/sphinx.js +1 -1
  78. sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
  79. sphinx/locale/bn/LC_MESSAGES/sphinx.po +679 -472
  80. sphinx/locale/ca/LC_MESSAGES/sphinx.js +1 -1
  81. sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
  82. sphinx/locale/ca/LC_MESSAGES/sphinx.po +681 -474
  83. sphinx/locale/cak/LC_MESSAGES/sphinx.js +1 -1
  84. sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
  85. sphinx/locale/cak/LC_MESSAGES/sphinx.po +678 -471
  86. sphinx/locale/cs/LC_MESSAGES/sphinx.js +1 -1
  87. sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
  88. sphinx/locale/cs/LC_MESSAGES/sphinx.po +679 -472
  89. sphinx/locale/cy/LC_MESSAGES/sphinx.js +1 -1
  90. sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
  91. sphinx/locale/cy/LC_MESSAGES/sphinx.po +679 -472
  92. sphinx/locale/da/LC_MESSAGES/sphinx.js +1 -1
  93. sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
  94. sphinx/locale/da/LC_MESSAGES/sphinx.po +679 -472
  95. sphinx/locale/de/LC_MESSAGES/sphinx.js +1 -1
  96. sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
  97. sphinx/locale/de/LC_MESSAGES/sphinx.po +679 -472
  98. sphinx/locale/de_DE/LC_MESSAGES/sphinx.js +1 -1
  99. sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
  100. sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +678 -471
  101. sphinx/locale/el/LC_MESSAGES/sphinx.js +1 -1
  102. sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
  103. sphinx/locale/el/LC_MESSAGES/sphinx.po +701 -494
  104. sphinx/locale/en_DE/LC_MESSAGES/sphinx.js +1 -1
  105. sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
  106. sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +700 -493
  107. sphinx/locale/en_FR/LC_MESSAGES/sphinx.js +1 -1
  108. sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
  109. sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +700 -493
  110. sphinx/locale/en_GB/LC_MESSAGES/sphinx.js +1 -1
  111. sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
  112. sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +701 -494
  113. sphinx/locale/en_HK/LC_MESSAGES/sphinx.js +1 -1
  114. sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
  115. sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +700 -493
  116. sphinx/locale/eo/LC_MESSAGES/sphinx.js +1 -1
  117. sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
  118. sphinx/locale/eo/LC_MESSAGES/sphinx.po +701 -494
  119. sphinx/locale/es/LC_MESSAGES/sphinx.js +1 -1
  120. sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
  121. sphinx/locale/es/LC_MESSAGES/sphinx.po +701 -494
  122. sphinx/locale/es_CO/LC_MESSAGES/sphinx.js +1 -1
  123. sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
  124. sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +700 -493
  125. sphinx/locale/et/LC_MESSAGES/sphinx.js +1 -1
  126. sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
  127. sphinx/locale/et/LC_MESSAGES/sphinx.po +701 -494
  128. sphinx/locale/eu/LC_MESSAGES/sphinx.js +1 -1
  129. sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
  130. sphinx/locale/eu/LC_MESSAGES/sphinx.po +701 -494
  131. sphinx/locale/fa/LC_MESSAGES/sphinx.js +1 -1
  132. sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
  133. sphinx/locale/fa/LC_MESSAGES/sphinx.po +701 -494
  134. sphinx/locale/fi/LC_MESSAGES/sphinx.js +1 -1
  135. sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
  136. sphinx/locale/fi/LC_MESSAGES/sphinx.po +700 -493
  137. sphinx/locale/fr/LC_MESSAGES/sphinx.js +1 -1
  138. sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
  139. sphinx/locale/fr/LC_MESSAGES/sphinx.po +725 -518
  140. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.js +1 -1
  141. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
  142. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +700 -493
  143. sphinx/locale/gl/LC_MESSAGES/sphinx.js +1 -1
  144. sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
  145. sphinx/locale/gl/LC_MESSAGES/sphinx.po +701 -494
  146. sphinx/locale/he/LC_MESSAGES/sphinx.js +1 -1
  147. sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
  148. sphinx/locale/he/LC_MESSAGES/sphinx.po +700 -493
  149. sphinx/locale/hi/LC_MESSAGES/sphinx.js +1 -1
  150. sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
  151. sphinx/locale/hi/LC_MESSAGES/sphinx.po +701 -494
  152. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.js +1 -1
  153. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
  154. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +700 -493
  155. sphinx/locale/hr/LC_MESSAGES/sphinx.js +1 -1
  156. sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
  157. sphinx/locale/hr/LC_MESSAGES/sphinx.po +701 -494
  158. sphinx/locale/hu/LC_MESSAGES/sphinx.js +1 -1
  159. sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
  160. sphinx/locale/hu/LC_MESSAGES/sphinx.po +701 -494
  161. sphinx/locale/id/LC_MESSAGES/sphinx.js +1 -1
  162. sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
  163. sphinx/locale/id/LC_MESSAGES/sphinx.po +701 -494
  164. sphinx/locale/is/LC_MESSAGES/sphinx.js +1 -1
  165. sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
  166. sphinx/locale/is/LC_MESSAGES/sphinx.po +700 -493
  167. sphinx/locale/it/LC_MESSAGES/sphinx.js +1 -1
  168. sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
  169. sphinx/locale/it/LC_MESSAGES/sphinx.po +708 -500
  170. sphinx/locale/ja/LC_MESSAGES/sphinx.js +1 -1
  171. sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
  172. sphinx/locale/ja/LC_MESSAGES/sphinx.po +701 -494
  173. sphinx/locale/ka/LC_MESSAGES/sphinx.js +1 -1
  174. sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
  175. sphinx/locale/ka/LC_MESSAGES/sphinx.po +700 -493
  176. sphinx/locale/ko/LC_MESSAGES/sphinx.js +1 -1
  177. sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
  178. sphinx/locale/ko/LC_MESSAGES/sphinx.po +701 -494
  179. sphinx/locale/lt/LC_MESSAGES/sphinx.js +1 -1
  180. sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
  181. sphinx/locale/lt/LC_MESSAGES/sphinx.po +701 -494
  182. sphinx/locale/lv/LC_MESSAGES/sphinx.js +1 -1
  183. sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
  184. sphinx/locale/lv/LC_MESSAGES/sphinx.po +701 -494
  185. sphinx/locale/mk/LC_MESSAGES/sphinx.js +1 -1
  186. sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
  187. sphinx/locale/mk/LC_MESSAGES/sphinx.po +700 -493
  188. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js +1 -1
  189. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
  190. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +701 -494
  191. sphinx/locale/ne/LC_MESSAGES/sphinx.js +1 -1
  192. sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
  193. sphinx/locale/ne/LC_MESSAGES/sphinx.po +701 -494
  194. sphinx/locale/nl/LC_MESSAGES/sphinx.js +1 -1
  195. sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
  196. sphinx/locale/nl/LC_MESSAGES/sphinx.po +701 -494
  197. sphinx/locale/pl/LC_MESSAGES/sphinx.js +1 -1
  198. sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
  199. sphinx/locale/pl/LC_MESSAGES/sphinx.po +701 -494
  200. sphinx/locale/pt/LC_MESSAGES/sphinx.js +1 -1
  201. sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
  202. sphinx/locale/pt/LC_MESSAGES/sphinx.po +700 -493
  203. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js +1 -1
  204. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
  205. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +705 -498
  206. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.js +1 -1
  207. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
  208. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +701 -494
  209. sphinx/locale/ro/LC_MESSAGES/sphinx.js +1 -1
  210. sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
  211. sphinx/locale/ro/LC_MESSAGES/sphinx.po +701 -494
  212. sphinx/locale/ru/LC_MESSAGES/sphinx.js +1 -1
  213. sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
  214. sphinx/locale/ru/LC_MESSAGES/sphinx.po +890 -680
  215. sphinx/locale/si/LC_MESSAGES/sphinx.js +1 -1
  216. sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
  217. sphinx/locale/si/LC_MESSAGES/sphinx.po +700 -493
  218. sphinx/locale/sk/LC_MESSAGES/sphinx.js +1 -1
  219. sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
  220. sphinx/locale/sk/LC_MESSAGES/sphinx.po +701 -494
  221. sphinx/locale/sl/LC_MESSAGES/sphinx.js +1 -1
  222. sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
  223. sphinx/locale/sl/LC_MESSAGES/sphinx.po +701 -494
  224. sphinx/locale/sphinx.pot +702 -494
  225. sphinx/locale/sq/LC_MESSAGES/sphinx.js +1 -1
  226. sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
  227. sphinx/locale/sq/LC_MESSAGES/sphinx.po +704 -497
  228. sphinx/locale/sr/LC_MESSAGES/sphinx.js +1 -1
  229. sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
  230. sphinx/locale/sr/LC_MESSAGES/sphinx.po +700 -493
  231. sphinx/locale/sr@latin/LC_MESSAGES/sphinx.mo +0 -0
  232. sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo +0 -0
  233. sphinx/locale/sv/LC_MESSAGES/sphinx.js +1 -1
  234. sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
  235. sphinx/locale/sv/LC_MESSAGES/sphinx.po +701 -494
  236. sphinx/locale/ta/LC_MESSAGES/sphinx.po +1016 -808
  237. sphinx/locale/te/LC_MESSAGES/sphinx.js +1 -1
  238. sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
  239. sphinx/locale/te/LC_MESSAGES/sphinx.po +700 -493
  240. sphinx/locale/tr/LC_MESSAGES/sphinx.js +1 -1
  241. sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
  242. sphinx/locale/tr/LC_MESSAGES/sphinx.po +701 -494
  243. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.js +1 -1
  244. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
  245. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +701 -494
  246. sphinx/locale/ur/LC_MESSAGES/sphinx.js +1 -1
  247. sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
  248. sphinx/locale/ur/LC_MESSAGES/sphinx.po +700 -493
  249. sphinx/locale/vi/LC_MESSAGES/sphinx.js +1 -1
  250. sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
  251. sphinx/locale/vi/LC_MESSAGES/sphinx.po +701 -494
  252. sphinx/locale/yue/LC_MESSAGES/sphinx.js +1 -1
  253. sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
  254. sphinx/locale/yue/LC_MESSAGES/sphinx.po +700 -493
  255. sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +704 -496
  256. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.js +1 -1
  257. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
  258. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +700 -493
  259. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js +1 -1
  260. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
  261. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +729 -522
  262. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.js +1 -1
  263. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
  264. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +700 -493
  265. sphinx/roles.py +1 -1
  266. sphinx/search/__init__.py +17 -9
  267. sphinx/templates/quickstart/{root_doc.rst_t → root_doc.rst.jinja} +7 -10
  268. sphinx/testing/fixtures.py +22 -20
  269. sphinx/testing/path.py +6 -2
  270. sphinx/testing/util.py +8 -13
  271. sphinx/texinputs/sphinx.sty +449 -332
  272. sphinx/texinputs/sphinxlatexadmonitions.sty +209 -66
  273. sphinx/texinputs/sphinxlatexliterals.sty +9 -16
  274. sphinx/texinputs/sphinxlatexstyletext.sty +4 -38
  275. sphinx/texinputs/sphinxlatextables.sty +6 -14
  276. sphinx/texinputs/sphinxpackageboxes.sty +15 -42
  277. sphinx/texinputs/sphinxpackagefootnote.sty +4 -3
  278. sphinx/themes/agogo/layout.html +3 -3
  279. sphinx/themes/basic/genindex-single.html +2 -1
  280. sphinx/themes/basic/layout.html +3 -6
  281. sphinx/themes/basic/static/searchtools.js +4 -3
  282. sphinx/themes/haiku/layout.html +4 -4
  283. sphinx/themes/pyramid/layout.html +1 -1
  284. sphinx/themes/scrolls/layout.html +2 -2
  285. sphinx/theming.py +42 -7
  286. sphinx/transforms/__init__.py +34 -20
  287. sphinx/transforms/i18n.py +8 -7
  288. sphinx/transforms/post_transforms/__init__.py +1 -1
  289. sphinx/transforms/post_transforms/images.py +7 -10
  290. sphinx/util/_pathlib.py +2 -2
  291. sphinx/util/cfamily.py +52 -30
  292. sphinx/util/console.py +1 -1
  293. sphinx/util/display.py +16 -11
  294. sphinx/util/docutils.py +88 -40
  295. sphinx/util/fileutil.py +15 -3
  296. sphinx/util/images.py +1 -0
  297. sphinx/util/inspect.py +66 -22
  298. sphinx/util/inventory.py +15 -0
  299. sphinx/util/logging.py +14 -21
  300. sphinx/util/math.py +3 -1
  301. sphinx/util/nodes.py +9 -12
  302. sphinx/util/osutil.py +5 -5
  303. sphinx/util/parsing.py +93 -0
  304. sphinx/util/tags.py +71 -47
  305. sphinx/util/typing.py +261 -143
  306. sphinx/versioning.py +17 -17
  307. sphinx/writers/html5.py +26 -19
  308. sphinx/writers/latex.py +58 -28
  309. sphinx/writers/manpage.py +4 -3
  310. sphinx/writers/texinfo.py +19 -14
  311. {sphinx-7.3.6.dist-info → sphinx-7.4.0.dist-info}/METADATA +21 -20
  312. sphinx-7.4.0.dist-info/RECORD +591 -0
  313. sphinx-7.3.6.dist-info/RECORD +0 -581
  314. /sphinx/templates/apidoc/{module.rst_t → module.rst.jinja} +0 -0
  315. /sphinx/templates/apidoc/{package.rst_t → package.rst.jinja} +0 -0
  316. /sphinx/templates/apidoc/{toc.rst_t → toc.rst.jinja} +0 -0
  317. /sphinx/templates/epub3/{content.opf_t → content.opf.jinja} +0 -0
  318. /sphinx/templates/epub3/{nav.xhtml_t → nav.xhtml.jinja} +0 -0
  319. /sphinx/templates/epub3/{toc.ncx_t → toc.ncx.jinja} +0 -0
  320. /sphinx/templates/gettext/{message.pot_t → message.pot.jinja} +0 -0
  321. /sphinx/templates/imgmath/{preview.tex_t → preview.tex.jinja} +0 -0
  322. /sphinx/templates/imgmath/{template.tex_t → template.tex.jinja} +0 -0
  323. /sphinx/templates/latex/{latex.tex_t → latex.tex.jinja} +0 -0
  324. /sphinx/templates/latex/{longtable.tex_t → longtable.tex.jinja} +0 -0
  325. /sphinx/templates/latex/{sphinxmessages.sty_t → sphinxmessages.sty.jinja} +0 -0
  326. /sphinx/templates/latex/{tabular.tex_t → tabular.tex.jinja} +0 -0
  327. /sphinx/templates/latex/{tabulary.tex_t → tabulary.tex.jinja} +0 -0
  328. /sphinx/templates/quickstart/{Makefile_t → Makefile.jinja} +0 -0
  329. /sphinx/templates/quickstart/{Makefile.new_t → Makefile.new.jinja} +0 -0
  330. /sphinx/templates/quickstart/{conf.py_t → conf.py.jinja} +0 -0
  331. /sphinx/templates/quickstart/{make.bat_t → make.bat.jinja} +0 -0
  332. /sphinx/templates/quickstart/{make.bat.new_t → make.bat.new.jinja} +0 -0
  333. /sphinx/texinputs/{Makefile_t → Makefile.jinja} +0 -0
  334. /sphinx/texinputs/{latexmkjarc_t → latexmkjarc.jinja} +0 -0
  335. /sphinx/texinputs/{latexmkrc_t → latexmkrc.jinja} +0 -0
  336. /sphinx/texinputs/{make.bat_t → make.bat.jinja} +0 -0
  337. /sphinx/texinputs_win/{Makefile_t → Makefile.jinja} +0 -0
  338. /sphinx/themes/agogo/static/{agogo.css_t → agogo.css.jinja} +0 -0
  339. /sphinx/themes/basic/static/{basic.css_t → basic.css.jinja} +0 -0
  340. /sphinx/themes/basic/static/{documentation_options.js_t → documentation_options.js.jinja} +0 -0
  341. /sphinx/themes/basic/static/{language_data.js_t → language_data.js.jinja} +0 -0
  342. /sphinx/themes/bizstyle/static/{bizstyle.css_t → bizstyle.css.jinja} +0 -0
  343. /sphinx/themes/bizstyle/static/{bizstyle.js_t → bizstyle.js.jinja} +0 -0
  344. /sphinx/themes/classic/static/{classic.css_t → classic.css.jinja} +0 -0
  345. /sphinx/themes/classic/static/{sidebar.js_t → sidebar.js.jinja} +0 -0
  346. /sphinx/themes/epub/static/{epub.css_t → epub.css.jinja} +0 -0
  347. /sphinx/themes/haiku/static/{haiku.css_t → haiku.css.jinja} +0 -0
  348. /sphinx/themes/nature/static/{nature.css_t → nature.css.jinja} +0 -0
  349. /sphinx/themes/nonav/static/{nonav.css_t → nonav.css.jinja} +0 -0
  350. /sphinx/themes/pyramid/static/{epub.css_t → epub.css.jinja} +0 -0
  351. /sphinx/themes/pyramid/static/{pyramid.css_t → pyramid.css.jinja} +0 -0
  352. /sphinx/themes/scrolls/static/{scrolls.css_t → scrolls.css.jinja} +0 -0
  353. /sphinx/themes/sphinxdoc/static/{sphinxdoc.css_t → sphinxdoc.css.jinja} +0 -0
  354. /sphinx/themes/traditional/static/{traditional.css_t → traditional.css.jinja} +0 -0
  355. {sphinx-7.3.6.dist-info → sphinx-7.4.0.dist-info}/LICENSE.rst +0 -0
  356. {sphinx-7.3.6.dist-info → sphinx-7.4.0.dist-info}/WHEEL +0 -0
  357. {sphinx-7.3.6.dist-info → sphinx-7.4.0.dist-info}/entry_points.txt +0 -0
sphinx/application.py CHANGED
@@ -42,14 +42,16 @@ from sphinx.util.tags import Tags
42
42
 
43
43
  if TYPE_CHECKING:
44
44
  from docutils import nodes
45
- from docutils.nodes import Element
45
+ from docutils.nodes import Element, Node
46
46
  from docutils.parsers import Parser
47
47
 
48
48
  from sphinx.builders import Builder
49
49
  from sphinx.domains import Domain, Index
50
50
  from sphinx.environment.collectors import EnvironmentCollector
51
+ from sphinx.ext.autodoc import Documenter
51
52
  from sphinx.extension import Extension
52
53
  from sphinx.roles import XRefRole
54
+ from sphinx.search import SearchLanguage
53
55
  from sphinx.theming import Theme
54
56
  from sphinx.util.typing import RoleFunction, TitleGetter
55
57
 
@@ -138,13 +140,35 @@ class Sphinx:
138
140
  def __init__(self, srcdir: str | os.PathLike[str], confdir: str | os.PathLike[str] | None,
139
141
  outdir: str | os.PathLike[str], doctreedir: str | os.PathLike[str],
140
142
  buildername: str, confoverrides: dict | None = None,
141
- status: IO | None = sys.stdout, warning: IO | None = sys.stderr,
143
+ status: IO[str] | None = sys.stdout, warning: IO[str] | None = sys.stderr,
142
144
  freshenv: bool = False, warningiserror: bool = False,
143
- tags: list[str] | None = None,
145
+ tags: Sequence[str] = (),
144
146
  verbosity: int = 0, parallel: int = 0, keep_going: bool = False,
145
147
  pdb: bool = False) -> None:
148
+ """Initialize the Sphinx application.
149
+
150
+ :param srcdir: The path to the source directory.
151
+ :param confdir: The path to the configuration directory.
152
+ If not given, it is assumed to be the same as ``srcdir``.
153
+ :param outdir: Directory for storing build documents.
154
+ :param doctreedir: Directory for caching pickled doctrees.
155
+ :param buildername: The name of the builder to use.
156
+ :param confoverrides: A dictionary of configuration settings that override the
157
+ settings in the configuration file.
158
+ :param status: A file-like object to write status messages to.
159
+ :param warning: A file-like object to write warnings to.
160
+ :param freshenv: If true, clear the cached environment.
161
+ :param warningiserror: If true, warnings become errors.
162
+ :param tags: A list of tags to apply.
163
+ :param verbosity: The verbosity level.
164
+ :param parallel: The maximum number of parallel jobs to use
165
+ when reading/writing documents.
166
+ :param keep_going: If true, continue processing when an error occurs.
167
+ :param pdb: If true, enable the Python debugger on an exception.
168
+ """
146
169
  self.phase = BuildPhase.INITIALIZATION
147
170
  self.verbosity = verbosity
171
+ self._fresh_env_used: bool | None = None
148
172
  self.extensions: dict[str, Extension] = {}
149
173
  self.registry = SphinxComponentRegistry()
150
174
 
@@ -168,14 +192,14 @@ class Sphinx:
168
192
  self.parallel = parallel
169
193
 
170
194
  if status is None:
171
- self._status: IO = StringIO()
195
+ self._status: IO[str] = StringIO()
172
196
  self.quiet: bool = True
173
197
  else:
174
198
  self._status = status
175
199
  self.quiet = False
176
200
 
177
201
  if warning is None:
178
- self._warning: IO = StringIO()
202
+ self._warning: IO[str] = StringIO()
179
203
  else:
180
204
  self._warning = warning
181
205
  self._warncount = 0
@@ -194,7 +218,7 @@ class Sphinx:
194
218
  self.messagelog: deque = deque(maxlen=10)
195
219
 
196
220
  # say hello to the world
197
- logger.info(bold(__('Running Sphinx v%s') % sphinx.__display_version__))
221
+ logger.info(bold(__('Running Sphinx v%s')), sphinx.__display_version__)
198
222
 
199
223
  # status code for command-line application
200
224
  self.statuscode = 0
@@ -267,33 +291,37 @@ class Sphinx:
267
291
  # set up the builder
268
292
  self._init_builder()
269
293
 
294
+ @property
295
+ def fresh_env_used(self) -> bool | None:
296
+ """True/False as to whether a new environment was created for this build,
297
+ or None if the environment has not been initialised yet.
298
+ """
299
+ return self._fresh_env_used
300
+
270
301
  def _init_i18n(self) -> None:
271
302
  """Load translated strings from the configured localedirs if enabled in
272
303
  the configuration.
273
304
  """
274
- if self.config.language == 'en':
275
- self.translator, _ = locale.init([], None)
305
+ logger.info(bold(__('loading translations [%s]... ')), self.config.language,
306
+ nonl=True)
307
+
308
+ # compile mo files if sphinx.po file in user locale directories are updated
309
+ repo = CatalogRepository(self.srcdir, self.config.locale_dirs,
310
+ self.config.language, self.config.source_encoding)
311
+ for catalog in repo.catalogs:
312
+ if catalog.domain == 'sphinx' and catalog.is_outdated():
313
+ catalog.write_mo(self.config.language,
314
+ self.config.gettext_allow_fuzzy_translations)
315
+
316
+ locale_dirs: list[str | None] = list(repo.locale_dirs)
317
+ locale_dirs += [None]
318
+ locale_dirs += [path.join(package_dir, 'locale')]
319
+
320
+ self.translator, has_translation = locale.init(locale_dirs, self.config.language)
321
+ if has_translation or self.config.language == 'en':
322
+ logger.info(__('done'))
276
323
  else:
277
- logger.info(bold(__('loading translations [%s]... ') % self.config.language),
278
- nonl=True)
279
-
280
- # compile mo files if sphinx.po file in user locale directories are updated
281
- repo = CatalogRepository(self.srcdir, self.config.locale_dirs,
282
- self.config.language, self.config.source_encoding)
283
- for catalog in repo.catalogs:
284
- if catalog.domain == 'sphinx' and catalog.is_outdated():
285
- catalog.write_mo(self.config.language,
286
- self.config.gettext_allow_fuzzy_translations)
287
-
288
- locale_dirs: list[str | None] = list(repo.locale_dirs)
289
- locale_dirs += [None]
290
- locale_dirs += [path.join(package_dir, 'locale')]
291
-
292
- self.translator, has_translation = locale.init(locale_dirs, self.config.language)
293
- if has_translation:
294
- logger.info(__('done'))
295
- else:
296
- logger.info(__('not available for built-in messages'))
324
+ logger.info(__('not available for built-in messages'))
297
325
 
298
326
  def _init_env(self, freshenv: bool) -> BuildEnvironment:
299
327
  filename = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
@@ -322,7 +350,6 @@ class Sphinx:
322
350
  def _post_init_env(self) -> None:
323
351
  if self._fresh_env_used:
324
352
  self.env.find_files(self.config, self.builder)
325
- del self._fresh_env_used
326
353
 
327
354
  def preload_builder(self, name: str) -> None:
328
355
  self.registry.preload_builder(self, name)
@@ -376,13 +403,13 @@ class Sphinx:
376
403
  else:
377
404
  msg = __('build %s, %s warnings.')
378
405
 
379
- logger.info(bold(msg % (status, self._warncount)))
406
+ logger.info(bold(msg), status, self._warncount)
380
407
  else:
381
- logger.info(bold(__('build %s.') % status))
408
+ logger.info(bold(__('build %s.')), status)
382
409
 
383
410
  if self.statuscode == 0 and self.builder.epilog:
384
411
  logger.info('')
385
- logger.info(self.builder.epilog % {
412
+ logger.info(self.builder.epilog, {
386
413
  'outdir': relpath(self.outdir),
387
414
  'project': self.config.project,
388
415
  })
@@ -502,9 +529,11 @@ class Sphinx:
502
529
  """
503
530
  self.registry.add_builder(builder, override=override)
504
531
 
505
- # TODO(stephenfin): Describe 'types' parameter
506
- def add_config_value(self, name: str, default: Any, rebuild: _ConfigRebuild,
507
- types: type | Collection[type] | ENUM = ()) -> None:
532
+ def add_config_value(
533
+ self, name: str, default: Any, rebuild: _ConfigRebuild,
534
+ types: type | Collection[type] | ENUM = (),
535
+ description: str = '',
536
+ ) -> None:
508
537
  """Register a configuration value.
509
538
 
510
539
  This is necessary for Sphinx to recognize new values and set default
@@ -525,6 +554,7 @@ class Sphinx:
525
554
  :param types: The type of configuration value. A list of types can be specified. For
526
555
  example, ``[str]`` is used to describe a configuration that takes string
527
556
  value.
557
+ :param description: A short description of the configuration value.
528
558
 
529
559
  .. versionchanged:: 0.4
530
560
  If the *default* value is a callable, it will be called with the
@@ -536,9 +566,12 @@ class Sphinx:
536
566
  Changed *rebuild* from a simple boolean (equivalent to ``''`` or
537
567
  ``'env'``) to a string. However, booleans are still accepted and
538
568
  converted internally.
569
+
570
+ .. versionadded:: 7.4
571
+ The *description* parameter.
539
572
  """
540
573
  logger.debug('[app] adding config value: %r', (name, default, rebuild, types))
541
- self.config.add(name, default, rebuild, types)
574
+ self.config.add(name, default, rebuild, types, description)
542
575
 
543
576
  def add_event(self, name: str) -> None:
544
577
  """Register an event called *name*.
@@ -712,7 +745,10 @@ class Sphinx:
712
745
  name, type='app', subtype='add_role')
713
746
  docutils.register_role(name, role)
714
747
 
715
- def add_generic_role(self, name: str, nodeclass: Any, override: bool = False) -> None:
748
+ def add_generic_role(
749
+ self, name: str, nodeclass: type[Node], override: bool = False
750
+
751
+ ) -> None:
716
752
  """Register a generic Docutils role.
717
753
 
718
754
  Register a Docutils role that does nothing but wrap its contents in the
@@ -733,7 +769,7 @@ class Sphinx:
733
769
  logger.warning(__('role %r is already registered, it will be overridden'),
734
770
  name, type='app', subtype='add_generic_role')
735
771
  role = roles.GenericRole(name, nodeclass)
736
- docutils.register_role(name, role) # type: ignore[arg-type]
772
+ docutils.register_role(name, role)
737
773
 
738
774
  def add_domain(self, domain: type[Domain], override: bool = False) -> None:
739
775
  """Register a domain.
@@ -789,7 +825,7 @@ class Sphinx:
789
825
  """
790
826
  self.registry.add_role_to_domain(domain, name, role, override=override)
791
827
 
792
- def add_index_to_domain(self, domain: str, index: type[Index], override: bool = False,
828
+ def add_index_to_domain(self, domain: str, index: type[Index], _override: bool = False,
793
829
  ) -> None:
794
830
  """Register a custom index for a domain.
795
831
 
@@ -1134,7 +1170,7 @@ class Sphinx:
1134
1170
  logger.debug('[app] adding lexer: %r', (alias, lexer))
1135
1171
  lexer_classes[alias] = lexer
1136
1172
 
1137
- def add_autodocumenter(self, cls: Any, override: bool = False) -> None:
1173
+ def add_autodocumenter(self, cls: type[Documenter], override: bool = False) -> None:
1138
1174
  """Register a new documenter class for the autodoc extension.
1139
1175
 
1140
1176
  Add *cls* as a new documenter class for the :mod:`sphinx.ext.autodoc`
@@ -1172,7 +1208,7 @@ class Sphinx:
1172
1208
  logger.debug('[app] adding autodoc attrgetter: %r', (typ, getter))
1173
1209
  self.registry.add_autodoc_attrgetter(typ, getter)
1174
1210
 
1175
- def add_search_language(self, cls: Any) -> None:
1211
+ def add_search_language(self, cls: type[SearchLanguage]) -> None:
1176
1212
  """Register a new language for the HTML search index.
1177
1213
 
1178
1214
  Add *cls*, which must be a subclass of
@@ -1184,8 +1220,7 @@ class Sphinx:
1184
1220
  .. versionadded:: 1.1
1185
1221
  """
1186
1222
  logger.debug('[app] adding search language: %r', cls)
1187
- from sphinx.search import SearchLanguage, languages
1188
- assert issubclass(cls, SearchLanguage)
1223
+ from sphinx.search import languages
1189
1224
  languages[cls.lang] = cls
1190
1225
 
1191
1226
  def add_source_suffix(self, suffix: str, filetype: str, override: bool = False) -> None:
@@ -4,9 +4,10 @@ from __future__ import annotations
4
4
 
5
5
  import codecs
6
6
  import pickle
7
+ import re
7
8
  import time
8
9
  from os import path
9
- from typing import TYPE_CHECKING, Any
10
+ from typing import TYPE_CHECKING, Any, Literal, final
10
11
 
11
12
  from docutils import nodes
12
13
  from docutils.utils import DependencyList
@@ -21,7 +22,7 @@ from sphinx.util.console import bold
21
22
  from sphinx.util.display import progress_message, status_iterator
22
23
  from sphinx.util.docutils import sphinx_domains
23
24
  from sphinx.util.i18n import CatalogInfo, CatalogRepository, docname_to_domain
24
- from sphinx.util.osutil import SEP, ensuredir, relative_uri, relpath
25
+ from sphinx.util.osutil import SEP, canon_path, ensuredir, relative_uri, relpath
25
26
  from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, parallel_available
26
27
 
27
28
  # side effect: registers roles and directives
@@ -71,9 +72,9 @@ class Builder:
71
72
  #: The list of MIME types of image formats supported by the builder.
72
73
  #: Image files are searched in the order in which they appear here.
73
74
  supported_image_types: list[str] = []
74
- #: The builder supports remote images or not.
75
+ #: The builder can produce output documents that may fetch external images when opened.
75
76
  supported_remote_images = False
76
- #: The builder supports data URIs or not.
77
+ #: The file format produced by the builder allows images to be embedded using data-URIs.
77
78
  supported_data_uri_images = False
78
79
 
79
80
  def __init__(self, app: Sphinx, env: BuildEnvironment) -> None:
@@ -92,8 +93,8 @@ class Builder:
92
93
  self.tags: Tags = app.tags
93
94
  self.tags.add(self.format)
94
95
  self.tags.add(self.name)
95
- self.tags.add("format_%s" % self.format)
96
- self.tags.add("builder_%s" % self.name)
96
+ self.tags.add(f'format_{self.format}')
97
+ self.tags.add(f'builder_{self.name}')
97
98
 
98
99
  # images that need to be copied over (source -> dest)
99
100
  self.images: dict[str, str] = {}
@@ -245,12 +246,14 @@ class Builder:
245
246
 
246
247
  # build methods
247
248
 
249
+ @final
248
250
  def build_all(self) -> None:
249
251
  """Build all source files."""
250
252
  self.compile_all_catalogs()
251
253
 
252
254
  self.build(None, summary=__('all source files'), method='all')
253
255
 
256
+ @final
254
257
  def build_specific(self, filenames: list[str]) -> None:
255
258
  """Only rebuild as much as needed for changes in the *filenames*."""
256
259
  docnames: list[str] = []
@@ -281,6 +284,7 @@ class Builder:
281
284
  self.build(docnames, method='specific',
282
285
  summary=__('%d source files given on command line') % len(docnames))
283
286
 
287
+ @final
284
288
  def build_update(self) -> None:
285
289
  """Only rebuild what was changed or added since last build."""
286
290
  self.compile_update_catalogs()
@@ -294,19 +298,20 @@ class Builder:
294
298
  summary=__('targets for %d source files that are out of date') %
295
299
  len(to_build))
296
300
 
301
+ @final
297
302
  def build(
298
303
  self,
299
304
  docnames: Iterable[str] | None,
300
305
  summary: str | None = None,
301
- method: str = 'update',
306
+ method: Literal['all', 'specific', 'update'] = 'update',
302
307
  ) -> None:
303
- """Main build method.
308
+ """Main build method, usually called by a specific ``build_*`` method.
304
309
 
305
310
  First updates the environment, and then calls
306
311
  :meth:`!write`.
307
312
  """
308
313
  if summary:
309
- logger.info(bold(__('building [%s]: ') % self.name) + summary)
314
+ logger.info(bold(__('building [%s]: ')) + summary, self.name)
310
315
 
311
316
  # while reading, collect all warnings from docutils
312
317
  with logging.pending_warnings():
@@ -367,6 +372,7 @@ class Builder:
367
372
  # wait for all tasks
368
373
  self.finish_tasks.join()
369
374
 
375
+ @final
370
376
  def read(self) -> list[str]:
371
377
  """(Re-)read all files new or changed since last update.
372
378
 
@@ -418,9 +424,40 @@ class Builder:
418
424
  else:
419
425
  self._read_serial(docnames)
420
426
 
421
- if self.config.root_doc not in self.env.all_docs:
422
- raise SphinxError('root file %s not found' %
423
- self.env.doc2path(self.config.root_doc))
427
+ if self.config.master_doc not in self.env.all_docs:
428
+ from sphinx.project import EXCLUDE_PATHS
429
+ from sphinx.util.matching import _translate_pattern
430
+
431
+ master_doc_path = self.env.doc2path(self.config.master_doc)
432
+ master_doc_canon = canon_path(master_doc_path)
433
+ for pat in EXCLUDE_PATHS:
434
+ if not re.match(_translate_pattern(pat), master_doc_canon):
435
+ continue
436
+ msg = __('Sphinx is unable to load the master document (%s) '
437
+ 'because it matches a built-in exclude pattern %r. '
438
+ 'Please move your master document to a different location.')
439
+ raise SphinxError(msg % (master_doc_path, pat))
440
+ for pat in self.config.exclude_patterns:
441
+ if not re.match(_translate_pattern(pat), master_doc_canon):
442
+ continue
443
+ msg = __('Sphinx is unable to load the master document (%s) '
444
+ 'because it matches an exclude pattern specified '
445
+ 'in conf.py, %r. '
446
+ 'Please remove this pattern from conf.py.')
447
+ raise SphinxError(msg % (master_doc_path, pat))
448
+ if set(self.config.include_patterns) != {'**'} and not any(
449
+ re.match(_translate_pattern(pat), master_doc_canon)
450
+ for pat in self.config.include_patterns
451
+ ):
452
+ msg = __('Sphinx is unable to load the master document (%s) '
453
+ 'because it is not included in the custom include_patterns = %r. '
454
+ 'Ensure that a pattern in include_patterns matches the '
455
+ 'master document.')
456
+ raise SphinxError(msg % (master_doc_path, self.config.include_patterns))
457
+ msg = __('Sphinx is unable to load the master document (%s). '
458
+ 'The master document must be within the source directory '
459
+ 'or a subdirectory of it.')
460
+ raise SphinxError(msg % master_doc_path)
424
461
 
425
462
  for retval in self.events.emit('env-updated', self.env):
426
463
  if retval is not None:
@@ -473,6 +510,7 @@ class Builder:
473
510
  tasks.join()
474
511
  logger.info('')
475
512
 
513
+ @final
476
514
  def read_doc(self, docname: str, *, _cache: bool = True) -> None:
477
515
  """Parse a file and add/update inventory entries for the doctree."""
478
516
  self.env.prepare_settings(docname)
@@ -485,6 +523,7 @@ class Builder:
485
523
  filename = self.env.doc2path(docname)
486
524
  filetype = get_filetype(self.app.config.source_suffix, filename)
487
525
  publisher = self.app.registry.get_publisher(self.app, filetype)
526
+ self.env.temp_data['_parser'] = publisher.parser
488
527
  # record_dependencies is mutable even though it is in settings,
489
528
  # explicitly re-initialise for each document
490
529
  publisher.settings.record_dependencies = DependencyList()
@@ -506,10 +545,11 @@ class Builder:
506
545
 
507
546
  self.write_doctree(docname, doctree, _cache=_cache)
508
547
 
548
+ @final
509
549
  def write_doctree(
510
550
  self, docname: str, doctree: nodes.document, *, _cache: bool = True,
511
551
  ) -> None:
512
- """Write the doctree to a file."""
552
+ """Write the doctree to a file, to be used as a cache by re-builds."""
513
553
  # make it picklable
514
554
  doctree.reporter = None # type: ignore[assignment]
515
555
  doctree.transformer = None # type: ignore[assignment]
@@ -536,8 +576,12 @@ class Builder:
536
576
  self,
537
577
  build_docnames: Iterable[str] | None,
538
578
  updated_docnames: Sequence[str],
539
- method: str = 'update',
579
+ method: Literal['all', 'specific', 'update'] = 'update',
540
580
  ) -> None:
581
+ """Write builder specific output files."""
582
+ # Allow any extensions to perform setup for writing
583
+ self.events.emit('write-started', self)
584
+
541
585
  if build_docnames is None or build_docnames == ['__all__']:
542
586
  # build_all
543
587
  build_docnames = self.env.found_docs
@@ -558,7 +602,7 @@ class Builder:
558
602
  with progress_message(__('preparing documents')):
559
603
  self.prepare_writing(docnames)
560
604
 
561
- with progress_message(__('copying assets')):
605
+ with progress_message(__('copying assets'), nonl=False):
562
606
  self.copy_assets()
563
607
 
564
608
  if self.parallel_ok:
@@ -170,7 +170,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
170
170
  def create_build_info(self) -> BuildInfo:
171
171
  return BuildInfo(self.config, self.tags, frozenset({'html', 'epub'}))
172
172
 
173
- def get_theme_config(self) -> tuple[str, dict]:
173
+ def get_theme_config(self) -> tuple[str, dict[str, str | int | bool]]:
174
174
  return self.config.epub_theme, self.config.epub_theme_options
175
175
 
176
176
  # generic support functions
@@ -451,8 +451,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
451
451
  def copy_download_files(self) -> None:
452
452
  pass
453
453
 
454
- def handle_page(self, pagename: str, addctx: dict, templatename: str = 'page.html',
455
- outfilename: str | None = None, event_arg: Any = None) -> None:
454
+ def handle_page(
455
+ self,
456
+ pagename: str,
457
+ addctx: dict[str, Any],
458
+ templatename: str = 'page.html',
459
+ outfilename: str | None = None,
460
+ event_arg: Any = None,
461
+ ) -> None:
456
462
  """Create a rendered page.
457
463
 
458
464
  This method is overwritten for genindex pages in order to fix href link
@@ -615,7 +621,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
615
621
  html.escape(self.refnodes[0]['refuri'])))
616
622
 
617
623
  # write the project file
618
- copy_asset_file(path.join(self.template_dir, 'content.opf_t'), self.outdir, metadata)
624
+ copy_asset_file(path.join(self.template_dir, 'content.opf.jinja'), self.outdir, metadata) # NoQA: E501
619
625
 
620
626
  def new_navpoint(self, node: dict[str, Any], level: int, incr: bool = True) -> NavPoint:
621
627
  """Create a new entry in the toc from the node at given level."""
@@ -698,7 +704,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
698
704
  navpoints = self.build_navpoints(refnodes)
699
705
  level = max(item['level'] for item in self.refnodes)
700
706
  level = min(level, self.config.epub_tocdepth)
701
- copy_asset_file(path.join(self.template_dir, 'toc.ncx_t'), self.outdir,
707
+ copy_asset_file(path.join(self.template_dir, 'toc.ncx.jinja'), self.outdir,
702
708
  self.toc_metadata(level, navpoints))
703
709
 
704
710
  def build_epub(self) -> None:
@@ -56,7 +56,7 @@ class ChangesBuilder(Builder):
56
56
 
57
57
  changesets = domain.get_changesets_for(version)
58
58
  if not changesets:
59
- logger.info(bold(__('no changes in version %s.') % version))
59
+ logger.info(bold(__('no changes in version %s.')), version)
60
60
  return
61
61
  logger.info(bold(__('writing summary file...')))
62
62
  for changeset in changesets:
@@ -140,7 +140,7 @@ class ChangesBuilder(Builder):
140
140
  f.write(self.templates.render('changes/rstsource.html', ctx))
141
141
  themectx = {'theme_' + key: val for (key, val) in
142
142
  self.theme.get_options({}).items()}
143
- copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css_t'),
143
+ copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css.jinja'), # NoQA: E501
144
144
  self.outdir, context=themectx, renderer=self.templates)
145
145
  copy_asset_file(path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'),
146
146
  self.outdir)
sphinx/builders/epub3.py CHANGED
@@ -194,7 +194,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
194
194
  # 'includehidden'
195
195
  refnodes = self.refnodes
196
196
  navlist = self.build_navlist(refnodes)
197
- copy_asset_file(path.join(self.template_dir, 'nav.xhtml_t'), self.outdir,
197
+ copy_asset_file(path.join(self.template_dir, 'nav.xhtml.jinja'), self.outdir,
198
198
  self.navigation_doc_metadata(navlist))
199
199
 
200
200
  # Add nav.xhtml to epub file
@@ -255,7 +255,7 @@ def convert_epub_css_files(app: Sphinx, config: Config) -> None:
255
255
  logger.warning(__('invalid css_file: %r, ignored'), entry)
256
256
  continue
257
257
 
258
- config.epub_css_files = epub_css_files # type: ignore[attr-defined]
258
+ config.epub_css_files = epub_css_files
259
259
 
260
260
 
261
261
  def setup(app: Sphinx) -> ExtensionMetadata:
@@ -7,7 +7,7 @@ import time
7
7
  from codecs import open
8
8
  from collections import defaultdict
9
9
  from os import getenv, path, walk
10
- from typing import TYPE_CHECKING, Any
10
+ from typing import TYPE_CHECKING, Any, Literal
11
11
  from uuid import uuid4
12
12
 
13
13
  from docutils import nodes
@@ -119,8 +119,8 @@ class GettextRenderer(SphinxRenderer):
119
119
  class I18nTags(Tags):
120
120
  """Dummy tags module for I18nBuilder.
121
121
 
122
- To translate all text inside of only nodes, this class
123
- always returns True value even if no tags are defined.
122
+ To ensure that all text inside ``only`` nodes is translated,
123
+ this class always returns ``True`` regardless the defined tags.
124
124
  """
125
125
 
126
126
  def eval_condition(self, condition: Any) -> bool:
@@ -240,7 +240,7 @@ class MessageCatalogBuilder(I18nBuilder):
240
240
  def _extract_from_template(self) -> None:
241
241
  files = list(self._collect_templates())
242
242
  files.sort()
243
- logger.info(bold(__('building [%s]: ') % self.name), nonl=True)
243
+ logger.info(bold(__('building [%s]: ')), self.name, nonl=True)
244
244
  logger.info(__('targets for %d template files'), len(files))
245
245
 
246
246
  extract_translations = self.templates.environment.extract_translations
@@ -257,11 +257,11 @@ class MessageCatalogBuilder(I18nBuilder):
257
257
  msg = f'{template}: {exc!r}'
258
258
  raise ThemeError(msg) from exc
259
259
 
260
- def build(
260
+ def build( # type: ignore[misc]
261
261
  self,
262
262
  docnames: Iterable[str] | None,
263
263
  summary: str | None = None,
264
- method: str = 'update',
264
+ method: Literal['all', 'specific', 'update'] = 'update',
265
265
  ) -> None:
266
266
  self._extract_from_template()
267
267
  super().build(docnames, summary, method)
@@ -287,7 +287,7 @@ class MessageCatalogBuilder(I18nBuilder):
287
287
  ensuredir(path.join(self.outdir, path.dirname(textdomain)))
288
288
 
289
289
  context['messages'] = list(catalog)
290
- content = GettextRenderer(outdir=self.outdir).render('message.pot_t', context)
290
+ content = GettextRenderer(outdir=self.outdir).render('message.pot.jinja', context)
291
291
 
292
292
  pofn = path.join(self.outdir, textdomain + '.pot')
293
293
  if should_write(pofn, content):
@@ -299,9 +299,9 @@ def _gettext_compact_validator(app: Sphinx, config: Config) -> None:
299
299
  gettext_compact = config.gettext_compact
300
300
  # Convert 0/1 from the command line to ``bool`` types
301
301
  if gettext_compact == '0':
302
- config.gettext_compact = False # type: ignore[attr-defined]
302
+ config.gettext_compact = False
303
303
  elif gettext_compact == '1':
304
- config.gettext_compact = True # type: ignore[attr-defined]
304
+ config.gettext_compact = True
305
305
 
306
306
 
307
307
  def setup(app: Sphinx) -> ExtensionMetadata:
@@ -311,7 +311,7 @@ def setup(app: Sphinx) -> ExtensionMetadata:
311
311
  app.add_config_value('gettext_location', True, 'gettext')
312
312
  app.add_config_value('gettext_uuid', False, 'gettext')
313
313
  app.add_config_value('gettext_auto_build', True, 'env')
314
- app.add_config_value('gettext_additional_targets', [], 'env')
314
+ app.add_config_value('gettext_additional_targets', [], 'env', types={set, list})
315
315
  app.add_config_value('gettext_last_translator', 'FULL NAME <EMAIL@ADDRESS>', 'gettext')
316
316
  app.add_config_value('gettext_language_team', 'LANGUAGE <LL@li.org>', 'gettext')
317
317
  app.connect('config-inited', _gettext_compact_validator, priority=800)