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
@@ -155,6 +155,9 @@ class Symbol:
155
155
  # Do symbol addition after self._children has been initialised.
156
156
  self._add_template_and_function_params()
157
157
 
158
+ def __repr__(self) -> str:
159
+ return f'<Symbol {self.to_string(indent=0)!r}>'
160
+
158
161
  def _fill_empty(self, declaration: ASTDeclaration, docname: str, line: int) -> None:
159
162
  self._assert_invariants()
160
163
  assert self.declaration is None
@@ -17,7 +17,7 @@ from sphinx.roles import XRefRole
17
17
  from sphinx.util import logging
18
18
  from sphinx.util.docfields import Field, GroupedField, TypedField
19
19
  from sphinx.util.docutils import SphinxDirective
20
- from sphinx.util.nodes import make_id, make_refnode, nested_parse_with_titles
20
+ from sphinx.util.nodes import make_id, make_refnode
21
21
 
22
22
  if TYPE_CHECKING:
23
23
  from collections.abc import Iterator
@@ -311,10 +311,7 @@ class JSModule(SphinxDirective):
311
311
  self.env.ref_context['js:module'] = mod_name
312
312
  no_index = 'no-index' in self.options or 'noindex' in self.options
313
313
 
314
- content_node: Element = nodes.section()
315
- # necessary so that the child nodes get the right source/line set
316
- content_node.document = self.state.document
317
- nested_parse_with_titles(self.state, self.content, content_node, self.content_offset)
314
+ content_nodes = self.parse_content_to_nodes(allow_section_headings=True)
318
315
 
319
316
  ret: list[Node] = []
320
317
  if not no_index:
@@ -334,7 +331,7 @@ class JSModule(SphinxDirective):
334
331
  target = nodes.target('', '', ids=[node_id], ismod=True)
335
332
  self.state.document.note_explicit_target(target)
336
333
  ret.append(target)
337
- ret.extend(content_node.children)
334
+ ret.extend(content_nodes)
338
335
  return ret
339
336
 
340
337
 
sphinx/domains/math.py CHANGED
@@ -60,8 +60,8 @@ class MathDomain(Domain):
60
60
  def note_equation(self, docname: str, labelid: str, location: Any = None) -> None:
61
61
  if labelid in self.equations:
62
62
  other = self.equations[labelid][0]
63
- logger.warning(__('duplicate label of equation %s, other instance in %s') %
64
- (labelid, other), location=location)
63
+ logger.warning(__('duplicate label of equation %s, other instance in %s'),
64
+ labelid, other, location=location)
65
65
 
66
66
  self.equations[labelid] = (docname, self.env.new_serialno('eqno') + 1)
67
67
 
@@ -106,6 +106,7 @@ class MathDomain(Domain):
106
106
  if docname in env.toc_fignumbers:
107
107
  numbers = env.toc_fignumbers[docname]['displaymath'].get(node_id, ())
108
108
  eqno = '.'.join(map(str, numbers))
109
+ eqno = env.config.math_numsep.join(eqno.rsplit('.', 1))
109
110
  else:
110
111
  eqno = ''
111
112
  else:
@@ -22,7 +22,6 @@ from sphinx.util.nodes import (
22
22
  find_pending_xref_condition,
23
23
  make_id,
24
24
  make_refnode,
25
- nested_parse_with_titles,
26
25
  )
27
26
 
28
27
  if TYPE_CHECKING:
@@ -47,6 +46,7 @@ from sphinx.domains.python._object import ( # NoQA: F401
47
46
  PyGroupedField,
48
47
  PyTypedField,
49
48
  PyXrefMixin,
49
+ py_sig_re,
50
50
  )
51
51
 
52
52
  logger = logging.getLogger(__name__)
@@ -389,6 +389,45 @@ class PyProperty(PyObject):
389
389
  return _('%s (%s property)') % (attrname, clsname)
390
390
 
391
391
 
392
+ class PyTypeAlias(PyObject):
393
+ """Description of a type alias."""
394
+
395
+ option_spec: ClassVar[OptionSpec] = PyObject.option_spec.copy()
396
+ option_spec.update({
397
+ 'canonical': directives.unchanged,
398
+ })
399
+
400
+ def get_signature_prefix(self, sig: str) -> list[nodes.Node]:
401
+ return [nodes.Text('type'), addnodes.desc_sig_space()]
402
+
403
+ def handle_signature(self, sig: str, signode: desc_signature) -> tuple[str, str]:
404
+ fullname, prefix = super().handle_signature(sig, signode)
405
+ if canonical := self.options.get('canonical'):
406
+ canonical_annotations = _parse_annotation(canonical, self.env)
407
+ signode += addnodes.desc_annotation(
408
+ canonical, '',
409
+ addnodes.desc_sig_space(),
410
+ addnodes.desc_sig_punctuation('', '='),
411
+ addnodes.desc_sig_space(),
412
+ *canonical_annotations,
413
+ )
414
+ return fullname, prefix
415
+
416
+ def get_index_text(self, modname: str, name_cls: tuple[str, str]) -> str:
417
+ name, cls = name_cls
418
+ try:
419
+ clsname, attrname = name.rsplit('.', 1)
420
+ if modname and self.env.config.add_module_names:
421
+ clsname = f'{modname}.{clsname}'
422
+ except ValueError:
423
+ if modname:
424
+ return _('%s (in module %s)') % (name, modname)
425
+ else:
426
+ return name
427
+
428
+ return _('%s (type alias in %s)') % (attrname, clsname)
429
+
430
+
392
431
  class PyModule(SphinxDirective):
393
432
  """
394
433
  Directive to mark description of a new module.
@@ -416,10 +455,7 @@ class PyModule(SphinxDirective):
416
455
  no_index = 'no-index' in self.options or 'noindex' in self.options
417
456
  self.env.ref_context['py:module'] = modname
418
457
 
419
- content_node: Element = nodes.section()
420
- # necessary so that the child nodes get the right source/line set
421
- content_node.document = self.state.document
422
- nested_parse_with_titles(self.state, self.content, content_node, self.content_offset)
458
+ content_nodes = self.parse_content_to_nodes(allow_section_headings=True)
423
459
 
424
460
  ret: list[Node] = []
425
461
  if not no_index:
@@ -443,7 +479,7 @@ class PyModule(SphinxDirective):
443
479
  # The node order is: index node first, then target node.
444
480
  ret.append(inode)
445
481
  ret.append(target)
446
- ret.extend(content_node.children)
482
+ ret.extend(content_nodes)
447
483
  return ret
448
484
 
449
485
 
@@ -593,6 +629,7 @@ class PythonDomain(Domain):
593
629
  'staticmethod': ObjType(_('static method'), 'meth', 'obj'),
594
630
  'attribute': ObjType(_('attribute'), 'attr', 'obj'),
595
631
  'property': ObjType(_('property'), 'attr', '_prop', 'obj'),
632
+ 'type': ObjType(_('type alias'), 'type', 'obj'),
596
633
  'module': ObjType(_('module'), 'mod', 'obj'),
597
634
  }
598
635
 
@@ -606,6 +643,7 @@ class PythonDomain(Domain):
606
643
  'staticmethod': PyStaticMethod,
607
644
  'attribute': PyAttribute,
608
645
  'property': PyProperty,
646
+ 'type': PyTypeAlias,
609
647
  'module': PyModule,
610
648
  'currentmodule': PyCurrentModule,
611
649
  'decorator': PyDecoratorFunction,
@@ -618,6 +656,7 @@ class PythonDomain(Domain):
618
656
  'class': PyXRefRole(),
619
657
  'const': PyXRefRole(),
620
658
  'attr': PyXRefRole(),
659
+ 'type': PyXRefRole(),
621
660
  'meth': PyXRefRole(fix_parens=True),
622
661
  'mod': PyXRefRole(),
623
662
  'obj': PyXRefRole(),
@@ -89,6 +89,10 @@ class PyXrefMixin:
89
89
 
90
90
  return result
91
91
 
92
+ _delimiters_re = re.compile(
93
+ r'(\s*[\[\]\(\),](?:\s*o[rf]\s)?\s*|\s+o[rf]\s+|\s*\|\s*|\.\.\.)'
94
+ )
95
+
92
96
  def make_xrefs(
93
97
  self,
94
98
  rolename: str,
@@ -100,9 +104,7 @@ class PyXrefMixin:
100
104
  inliner: Inliner | None = None,
101
105
  location: Node | None = None,
102
106
  ) -> list[Node]:
103
- delims = r'(\s*[\[\]\(\),](?:\s*o[rf]\s)?\s*|\s+o[rf]\s+|\s*\|\s*|\.\.\.)'
104
- delims_re = re.compile(delims)
105
- sub_targets = re.split(delims, target)
107
+ sub_targets = self._delimiters_re.split(target)
106
108
 
107
109
  split_contnode = bool(contnode and contnode.astext() == target)
108
110
 
@@ -112,13 +114,13 @@ class PyXrefMixin:
112
114
  if split_contnode:
113
115
  contnode = nodes.Text(sub_target)
114
116
 
115
- if in_literal or delims_re.match(sub_target):
117
+ if in_literal or self._delimiters_re.match(sub_target):
116
118
  results.append(contnode or innernode(sub_target, sub_target)) # type: ignore[call-arg]
117
119
  else:
118
120
  results.append(self.make_xref(rolename, domain, sub_target,
119
121
  innernode, contnode, env, inliner, location))
120
122
 
121
- if sub_target in ('Literal', 'typing.Literal', '~typing.Literal'):
123
+ if sub_target in {'Literal', 'typing.Literal', '~typing.Literal'}:
122
124
  in_literal = True
123
125
 
124
126
  return results
sphinx/domains/rst.py CHANGED
@@ -244,8 +244,8 @@ class ReSTDomain(Domain):
244
244
  def note_object(self, objtype: str, name: str, node_id: str, location: Any = None) -> None:
245
245
  if (objtype, name) in self.objects:
246
246
  docname, node_id = self.objects[objtype, name]
247
- logger.warning(__('duplicate description of %s %s, other instance in %s') %
248
- (objtype, name, docname), location=location)
247
+ logger.warning(__('duplicate description of %s %s, other instance in %s'),
248
+ objtype, name, docname, location=location)
249
249
 
250
250
  self.objects[objtype, name] = (self.env.docname, node_id)
251
251
 
@@ -20,6 +20,7 @@ from sphinx.roles import EmphasizedLiteral, XRefRole
20
20
  from sphinx.util import docname_join, logging, ws_re
21
21
  from sphinx.util.docutils import SphinxDirective
22
22
  from sphinx.util.nodes import clean_astext, make_id, make_refnode
23
+ from sphinx.util.parsing import nested_parse_to_nodes
23
24
 
24
25
  if TYPE_CHECKING:
25
26
  from collections.abc import Iterable, Iterator
@@ -101,6 +102,76 @@ class EnvVarXRefRole(XRefRole):
101
102
  return [indexnode, targetnode, node], []
102
103
 
103
104
 
105
+ class ConfigurationValue(ObjectDescription[str]):
106
+ index_template: str = _('%s; configuration value')
107
+ option_spec: ClassVar[OptionSpec] = {
108
+ 'no-index': directives.flag,
109
+ 'no-index-entry': directives.flag,
110
+ 'no-contents-entry': directives.flag,
111
+ 'no-typesetting': directives.flag,
112
+ 'type': directives.unchanged_required,
113
+ 'default': directives.unchanged_required,
114
+ }
115
+
116
+ def handle_signature(self, sig: str, sig_node: desc_signature) -> str:
117
+ sig_node.clear()
118
+ sig_node += addnodes.desc_name(sig, sig)
119
+ name = ws_re.sub(' ', sig)
120
+ sig_node['fullname'] = name
121
+ return name
122
+
123
+ def _object_hierarchy_parts(self, sig_node: desc_signature) -> tuple[str, ...]:
124
+ return (sig_node['fullname'],)
125
+
126
+ def _toc_entry_name(self, sig_node: desc_signature) -> str:
127
+ if not sig_node.get('_toc_parts'):
128
+ return ''
129
+ name, = sig_node['_toc_parts']
130
+ return name
131
+
132
+ def add_target_and_index(self, name: str, sig: str, signode: desc_signature) -> None:
133
+ node_id = make_id(self.env, self.state.document, self.objtype, name)
134
+ signode['ids'].append(node_id)
135
+ self.state.document.note_explicit_target(signode)
136
+ index_entry = self.index_template % name
137
+ self.indexnode['entries'].append(('pair', index_entry, node_id, '', None))
138
+ self.env.domains['std'].note_object(self.objtype, name, node_id, location=signode)
139
+
140
+ def transform_content(self, content_node: addnodes.desc_content) -> None:
141
+ """Insert *type* and *default* as a field list."""
142
+ field_list = nodes.field_list()
143
+ if 'type' in self.options:
144
+ field, msgs = self.format_type(self.options['type'])
145
+ field_list.append(field)
146
+ field_list += msgs
147
+ if 'default' in self.options:
148
+ field, msgs = self.format_default(self.options['default'])
149
+ field_list.append(field)
150
+ field_list += msgs
151
+ if len(field_list.children) > 0:
152
+ content_node.insert(0, field_list)
153
+
154
+ def format_type(self, type_: str) -> tuple[nodes.field, list[system_message]]:
155
+ """Formats the ``:type:`` option."""
156
+ parsed, msgs = self.parse_inline(type_, lineno=self.lineno)
157
+ field = nodes.field(
158
+ '',
159
+ nodes.field_name('', _('Type')),
160
+ nodes.field_body('', *parsed),
161
+ )
162
+ return field, msgs
163
+
164
+ def format_default(self, default: str) -> tuple[nodes.field, list[system_message]]:
165
+ """Formats the ``:default:`` option."""
166
+ parsed, msgs = self.parse_inline(default, lineno=self.lineno)
167
+ field = nodes.field(
168
+ '',
169
+ nodes.field_name('', _('Default')),
170
+ nodes.field_body('', *parsed),
171
+ )
172
+ return field, msgs
173
+
174
+
104
175
  class Target(SphinxDirective):
105
176
  """
106
177
  Generic target for user-defined cross-reference types.
@@ -260,13 +331,18 @@ class OptionXRefRole(XRefRole):
260
331
  return title, target
261
332
 
262
333
 
263
- def split_term_classifiers(line: str) -> list[str | None]:
334
+ _term_classifiers_re = re.compile(' +: +')
335
+
336
+
337
+ def split_term_classifiers(line: str) -> tuple[str, str | None]:
264
338
  # split line into a term and classifiers. if no classifier, None is used..
265
- parts: list[str | None] = [*re.split(' +: +', line), None]
266
- return parts
339
+ parts = _term_classifiers_re.split(line)
340
+ term = parts[0]
341
+ first_classifier = parts[1] if len(parts) >= 2 else None
342
+ return term, first_classifier
267
343
 
268
344
 
269
- def make_glossary_term(env: BuildEnvironment, textnodes: Iterable[Node], index_key: str,
345
+ def make_glossary_term(env: BuildEnvironment, textnodes: Iterable[Node], index_key: str | None,
270
346
  source: str, lineno: int, node_id: str | None, document: nodes.document,
271
347
  ) -> nodes.term:
272
348
  # get a text-only representation of the term and register it
@@ -382,15 +458,14 @@ class Glossary(SphinxDirective):
382
458
  termnodes: list[Node] = []
383
459
  system_messages: list[Node] = []
384
460
  for line, source, lineno in terms:
385
- parts = split_term_classifiers(line)
461
+ term_, first_classifier = split_term_classifiers(line)
386
462
  # parse the term with inline markup
387
463
  # classifiers (parts[1:]) will not be shown on doctree
388
- textnodes, sysmsg = self.state.inline_text(parts[0],
389
- lineno)
464
+ textnodes, sysmsg = self.parse_inline(term_, lineno=lineno)
390
465
 
391
466
  # use first classifier as a index key
392
467
  term = make_glossary_term(self.env, textnodes,
393
- parts[1], source, lineno, # type: ignore[arg-type]
468
+ first_classifier, source, lineno,
394
469
  node_id=None, document=self.state.document)
395
470
  term.rawsource = line
396
471
  system_messages.extend(sysmsg)
@@ -398,11 +473,14 @@ class Glossary(SphinxDirective):
398
473
 
399
474
  termnodes.extend(system_messages)
400
475
 
401
- defnode = nodes.definition()
402
476
  if definition:
403
- self.state.nested_parse(definition, definition.items[0][1],
404
- defnode)
405
- termnodes.append(defnode)
477
+ offset = definition.items[0][1]
478
+ definition_nodes = nested_parse_to_nodes(
479
+ self.state, definition, offset=offset, allow_section_headings=False,
480
+ )
481
+ else:
482
+ definition_nodes = []
483
+ termnodes.append(nodes.definition('', *definition_nodes))
406
484
  items.append(nodes.definition_list_item('', *termnodes))
407
485
 
408
486
  dlist = nodes.definition_list('', *items)
@@ -519,6 +597,7 @@ class StandardDomain(Domain):
519
597
  'token': ObjType(_('grammar token'), 'token', searchprio=-1),
520
598
  'label': ObjType(_('reference label'), 'ref', 'keyword',
521
599
  searchprio=-1),
600
+ 'confval': ObjType('configuration value', 'confval'),
522
601
  'envvar': ObjType(_('environment variable'), 'envvar'),
523
602
  'cmdoption': ObjType(_('program option'), 'option'),
524
603
  'doc': ObjType(_('document'), 'doc', searchprio=-1),
@@ -528,12 +607,14 @@ class StandardDomain(Domain):
528
607
  'program': Program,
529
608
  'cmdoption': Cmdoption, # old name for backwards compatibility
530
609
  'option': Cmdoption,
610
+ 'confval': ConfigurationValue,
531
611
  'envvar': EnvVar,
532
612
  'glossary': Glossary,
533
613
  'productionlist': ProductionList,
534
614
  }
535
615
  roles: dict[str, RoleFunction | XRefRole] = {
536
616
  'option': OptionXRefRole(warn_dangling=True),
617
+ 'confval': XRefRole(warn_dangling=True),
537
618
  'envvar': EnvVarXRefRole(),
538
619
  # links to tokens in grammar productions
539
620
  'token': TokenXRefRole(),
@@ -921,7 +1002,7 @@ class StandardDomain(Domain):
921
1002
  # * :option:`-foo=bar`
922
1003
  # * :option:`-foo[=bar]`
923
1004
  # * :option:`-foo bar`
924
- for needle in {'=', '[=', ' '}:
1005
+ for needle in ('=', '[=', ' '):
925
1006
  if needle in target:
926
1007
  stem, _, _ = target.partition(needle)
927
1008
  docname, labelid = self.progoptions.get((progname, stem), ('', ''))
@@ -1110,7 +1191,7 @@ def warn_missing_reference(app: Sphinx, domain: Domain, node: pending_xref,
1110
1191
  else:
1111
1192
  msg = __('Failed to create a cross reference. A title or caption not found: %r')
1112
1193
 
1113
- logger.warning(msg % target, location=node, type='ref', subtype=node['reftype'])
1194
+ logger.warning(msg, target, location=node, type='ref', subtype=node['reftype'])
1114
1195
  return True
1115
1196
 
1116
1197
 
@@ -28,6 +28,7 @@ if TYPE_CHECKING:
28
28
 
29
29
  from docutils import nodes
30
30
  from docutils.nodes import Node
31
+ from docutils.parsers import Parser
31
32
 
32
33
  from sphinx.application import Sphinx
33
34
  from sphinx.builders import Builder
@@ -74,7 +75,7 @@ CONFIG_CHANGED_REASON = {
74
75
  }
75
76
 
76
77
 
77
- versioning_conditions: dict[str, bool | Callable] = {
78
+ versioning_conditions: dict[str, Literal[False] | Callable[[Node], bool]] = {
78
79
  'none': False,
79
80
  'text': is_translatable,
80
81
  }
@@ -158,7 +159,7 @@ class BuildEnvironment:
158
159
  self.version: dict[str, int] = app.registry.get_envversion(app)
159
160
 
160
161
  # the method of doctree versioning; see set_versioning_method
161
- self.versioning_condition: bool | Callable | None = None
162
+ self.versioning_condition: Literal[False] | Callable[[Node], bool] | None = None
162
163
  self.versioning_compare: bool | None = None
163
164
 
164
165
  # all the registered domains, set by the application
@@ -183,11 +184,21 @@ class BuildEnvironment:
183
184
  # docnames to re-read unconditionally on next build
184
185
  self.reread_always: set[str] = set()
185
186
 
186
- # docname -> pickled doctree
187
187
  self._pickled_doctree_cache: dict[str, bytes] = {}
188
+ """In-memory cache for reading pickled doctrees from disk.
189
+ docname -> pickled doctree
190
+
191
+ This cache is used in the ``get_doctree`` method to avoid reading the
192
+ doctree from disk multiple times.
193
+ """
188
194
 
189
- # docname -> doctree
190
195
  self._write_doc_doctree_cache: dict[str, nodes.document] = {}
196
+ """In-memory cache for unpickling doctrees from disk.
197
+ docname -> doctree
198
+
199
+ Items are added in ``Builder.write_doctree``, during the read phase,
200
+ then used only in the ``get_and_resolve_doctree`` method.
201
+ """
191
202
 
192
203
  # File metadata
193
204
  # docname -> dict of metadata items
@@ -222,7 +233,7 @@ class BuildEnvironment:
222
233
 
223
234
  # domain-specific inventories, here to be pickled
224
235
  # domainname -> domain-specific dict
225
- self.domaindata: dict[str, dict] = {}
236
+ self.domaindata: dict[str, dict[str, Any]] = {}
226
237
 
227
238
  # these map absolute path -> (docnames, unique filename)
228
239
  self.images: FilenameUniqDict = FilenameUniqDict()
@@ -242,7 +253,7 @@ class BuildEnvironment:
242
253
  # search index data
243
254
 
244
255
  # docname -> title
245
- self._search_index_titles: dict[str, str] = {}
256
+ self._search_index_titles: dict[str, str | None] = {}
246
257
  # docname -> filename
247
258
  self._search_index_filenames: dict[str, str] = {}
248
259
  # stemmed words -> set(docname)
@@ -250,7 +261,7 @@ class BuildEnvironment:
250
261
  # stemmed words in titles -> set(docname)
251
262
  self._search_index_title_mapping: dict[str, set[str]] = {}
252
263
  # docname -> all titles in document
253
- self._search_index_all_titles: dict[str, list[tuple[str, str]]] = {}
264
+ self._search_index_all_titles: dict[str, list[tuple[str, str | None]]] = {}
254
265
  # docname -> list(index entry)
255
266
  self._search_index_index_entries: dict[str, list[tuple[str, str, str]]] = {}
256
267
  # objtype -> index
@@ -261,16 +272,18 @@ class BuildEnvironment:
261
272
  # set up environment
262
273
  self.setup(app)
263
274
 
264
- def __getstate__(self) -> dict:
275
+ def __getstate__(self) -> dict[str, Any]:
265
276
  """Obtains serializable data for pickling."""
266
277
  __dict__ = self.__dict__.copy()
267
- __dict__.update(app=None, domains={}, events=None) # clear unpickable attributes
268
- # ensure that upon restoring the state, the most recent pickled files
278
+ # clear unpickable attributes
279
+ __dict__.update(app=None, domains={}, events=None)
280
+ # clear in-memory doctree caches, to reduce memory consumption and
281
+ # ensure that, upon restoring the state, the most recent pickled files
269
282
  # on the disk are used instead of those from a possibly outdated state
270
- __dict__.update(_pickled_doctree_cache={})
283
+ __dict__.update(_pickled_doctree_cache={}, _write_doc_doctree_cache={})
271
284
  return __dict__
272
285
 
273
- def __setstate__(self, state: dict) -> None:
286
+ def __setstate__(self, state: dict[str, Any]) -> None:
274
287
  self.__dict__.update(state)
275
288
 
276
289
  def setup(self, app: Sphinx) -> None:
@@ -340,7 +353,9 @@ class BuildEnvironment:
340
353
  # Allow to disable by 3rd party extension (workaround)
341
354
  self.settings.setdefault('smart_quotes', True)
342
355
 
343
- def set_versioning_method(self, method: str | Callable, compare: bool) -> None:
356
+ def set_versioning_method(
357
+ self, method: str | Callable[[Node], bool], compare: bool
358
+ ) -> None:
344
359
  """Set the doctree versioning method for this environment.
345
360
 
346
361
  Versioning methods are a builder property; only builders with the same
@@ -348,7 +363,7 @@ class BuildEnvironment:
348
363
  raise an exception if the user tries to use an environment with an
349
364
  incompatible versioning method.
350
365
  """
351
- condition: bool | Callable
366
+ condition: Literal[False] | Callable[[Node], bool]
352
367
  if callable(method):
353
368
  condition = method
354
369
  else:
@@ -356,7 +371,7 @@ class BuildEnvironment:
356
371
  raise ValueError('invalid versioning method: %r' % method)
357
372
  condition = versioning_conditions[method]
358
373
 
359
- if self.versioning_condition not in (None, condition):
374
+ if self.versioning_condition not in {None, condition}:
360
375
  raise SphinxError(__('This environment is incompatible with the '
361
376
  'selected builder, please choose another '
362
377
  'doctree directory.'))
@@ -549,6 +564,11 @@ class BuildEnvironment:
549
564
  """Returns the docname of the document currently being parsed."""
550
565
  return self.temp_data['docname']
551
566
 
567
+ @property
568
+ def parser(self) -> Parser:
569
+ """Returns the parser being used for to parse the current document."""
570
+ return self.temp_data['_parser']
571
+
552
572
  def new_serialno(self, category: str = '') -> int:
553
573
  """Return a serial number, e.g. for index entry targets.
554
574