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/util/console.py CHANGED
@@ -93,7 +93,7 @@ def color_terminal() -> bool:
93
93
  if 'NO_COLOR' in os.environ:
94
94
  return False
95
95
  if sys.platform == 'win32' and colorama is not None:
96
- colorama.init()
96
+ colorama.just_fix_windows_console()
97
97
  return True
98
98
  if 'FORCE_COLOR' in os.environ:
99
99
  return True
sphinx/util/display.py CHANGED
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import functools
4
- from typing import Any, Callable, TypeVar
5
4
 
6
5
  from sphinx.locale import __
7
6
  from sphinx.util import logging
@@ -10,6 +9,13 @@ from sphinx.util.console import bold, color_terminal
10
9
  if False:
11
10
  from collections.abc import Iterable, Iterator
12
11
  from types import TracebackType
12
+ from typing import Any, Callable, TypeVar
13
+
14
+ from typing_extensions import ParamSpec
15
+
16
+ T = TypeVar('T')
17
+ P = ParamSpec('P')
18
+ R = TypeVar('R')
13
19
 
14
20
  logger = logging.getLogger(__name__)
15
21
 
@@ -22,9 +28,6 @@ def display_chunk(chunk: Any) -> str:
22
28
  return str(chunk)
23
29
 
24
30
 
25
- T = TypeVar('T')
26
-
27
-
28
31
  def status_iterator(
29
32
  iterable: Iterable[T],
30
33
  summary: str,
@@ -62,11 +65,12 @@ class SkipProgressMessage(Exception):
62
65
 
63
66
 
64
67
  class progress_message:
65
- def __init__(self, message: str) -> None:
68
+ def __init__(self, message: str, *, nonl: bool = True) -> None:
66
69
  self.message = message
70
+ self.nonl = nonl
67
71
 
68
72
  def __enter__(self) -> None:
69
- logger.info(bold(self.message + '... '), nonl=True)
73
+ logger.info(bold(self.message + '... '), nonl=self.nonl)
70
74
 
71
75
  def __exit__(
72
76
  self,
@@ -74,21 +78,22 @@ class progress_message:
74
78
  val: BaseException | None,
75
79
  tb: TracebackType | None,
76
80
  ) -> bool:
81
+ prefix = "" if self.nonl else bold(self.message + ': ')
77
82
  if isinstance(val, SkipProgressMessage):
78
- logger.info(__('skipped'))
83
+ logger.info(prefix + __('skipped'))
79
84
  if val.args:
80
85
  logger.info(*val.args)
81
86
  return True
82
87
  elif val:
83
- logger.info(__('failed'))
88
+ logger.info(prefix + __('failed'))
84
89
  else:
85
- logger.info(__('done'))
90
+ logger.info(prefix + __('done'))
86
91
 
87
92
  return False
88
93
 
89
- def __call__(self, f: Callable) -> Callable:
94
+ def __call__(self, f: Callable[P, R]) -> Callable[P, R]:
90
95
  @functools.wraps(f)
91
- def wrapper(*args: Any, **kwargs: Any) -> Any:
96
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: # type: ignore[return]
92
97
  with self:
93
98
  return f(*args, **kwargs)
94
99
 
sphinx/util/docutils.py CHANGED
@@ -17,11 +17,11 @@ from docutils.parsers.rst import Directive, directives, roles
17
17
  from docutils.parsers.rst.states import Inliner # NoQA: TCH002
18
18
  from docutils.statemachine import State, StateMachine, StringList
19
19
  from docutils.utils import Reporter, unescape
20
- from docutils.writers._html_base import HTMLTranslator
21
20
 
22
21
  from sphinx.errors import SphinxError
23
22
  from sphinx.locale import _, __
24
23
  from sphinx.util import logging
24
+ from sphinx.util.parsing import nested_parse_to_nodes
25
25
 
26
26
  logger = logging.getLogger(__name__)
27
27
  report_re = re.compile('^(.+?:(?:\\d+)?): \\((DEBUG|INFO|WARNING|ERROR|SEVERE)/(\\d+)?\\) ')
@@ -180,46 +180,12 @@ def using_user_docutils_conf(confdir: str | None) -> Iterator[None]:
180
180
  os.environ['DOCUTILSCONFIG'] = docutilsconfig
181
181
 
182
182
 
183
- @contextmanager
184
- def du19_footnotes() -> Iterator[None]:
185
- def visit_footnote(self: HTMLTranslator, node: Element) -> None:
186
- label_style = self.settings.footnote_references
187
- if not isinstance(node.previous_sibling(), type(node)):
188
- self.body.append(f'<aside class="footnote-list {label_style}">\n')
189
- self.body.append(self.starttag(node, 'aside',
190
- classes=[node.tagname, label_style],
191
- role="note"))
192
-
193
- def depart_footnote(self: HTMLTranslator, node: Element) -> None:
194
- self.body.append('</aside>\n')
195
- if not isinstance(node.next_node(descend=False, siblings=True),
196
- type(node)):
197
- self.body.append('</aside>\n')
198
-
199
- old_visit_footnote = HTMLTranslator.visit_footnote
200
- old_depart_footnote = HTMLTranslator.depart_footnote
201
-
202
- # Only apply on Docutils 0.18 or 0.18.1, as 0.17 and earlier used a <dl> based
203
- # approach, and 0.19 and later use the fixed approach by default.
204
- if docutils.__version_info__[:2] == (0, 18):
205
- HTMLTranslator.visit_footnote = visit_footnote # type: ignore[method-assign]
206
- HTMLTranslator.depart_footnote = depart_footnote # type: ignore[method-assign]
207
-
208
- try:
209
- yield
210
- finally:
211
- if docutils.__version_info__[:2] == (0, 18):
212
- HTMLTranslator.visit_footnote = old_visit_footnote # type: ignore[method-assign]
213
- HTMLTranslator.depart_footnote = old_depart_footnote # type: ignore[method-assign]
214
-
215
-
216
183
  @contextmanager
217
184
  def patch_docutils(confdir: str | None = None) -> Iterator[None]:
218
185
  """Patch to docutils temporarily."""
219
186
  with patched_get_language(), \
220
187
  patched_rst_get_language(), \
221
- using_user_docutils_conf(confdir), \
222
- du19_footnotes():
188
+ using_user_docutils_conf(confdir):
223
189
  yield
224
190
 
225
191
 
@@ -329,11 +295,11 @@ class WarningStream:
329
295
  def write(self, text: str) -> None:
330
296
  matched = report_re.search(text)
331
297
  if not matched:
332
- logger.warning(text.rstrip("\r\n"))
298
+ logger.warning(text.rstrip("\r\n"), type="docutils")
333
299
  else:
334
300
  location, type, level = matched.groups()
335
301
  message = report_re.sub('', text).rstrip()
336
- logger.log(type, message, location=location)
302
+ logger.log(type, message, location=location, type="docutils")
337
303
 
338
304
 
339
305
  class LoggingReporter(Reporter):
@@ -424,7 +390,82 @@ class SphinxDirective(Directive):
424
390
 
425
391
  def get_location(self) -> str:
426
392
  """Get current location info for logging."""
427
- return ':'.join(str(s) for s in self.get_source_info())
393
+ source, line = self.get_source_info()
394
+ if source and line:
395
+ return f'{source}:{line}'
396
+ if source:
397
+ return f'{source}:'
398
+ if line:
399
+ return f'<unknown>:{line}'
400
+ return ''
401
+
402
+ def parse_content_to_nodes(self, allow_section_headings: bool = False) -> list[Node]:
403
+ """Parse the directive's content into nodes.
404
+
405
+ :param allow_section_headings:
406
+ Are titles (sections) allowed in the directive's content?
407
+ Note that this option bypasses Docutils' usual checks on
408
+ doctree structure, and misuse of this option can lead to
409
+ an incoherent doctree. In Docutils, section nodes should
410
+ only be children of ``Structural`` nodes, which includes
411
+ ``document``, ``section``, and ``sidebar`` nodes.
412
+
413
+ .. versionadded:: 7.4
414
+ """
415
+ return nested_parse_to_nodes(
416
+ self.state,
417
+ self.content,
418
+ offset=self.content_offset,
419
+ allow_section_headings=allow_section_headings,
420
+ )
421
+
422
+ def parse_text_to_nodes(
423
+ self, text: str = '', /, *, offset: int = -1, allow_section_headings: bool = False,
424
+ ) -> list[Node]:
425
+ """Parse *text* into nodes.
426
+
427
+ :param text:
428
+ Text, in string form. ``StringList`` is also accepted.
429
+ :param allow_section_headings:
430
+ Are titles (sections) allowed in *text*?
431
+ Note that this option bypasses Docutils' usual checks on
432
+ doctree structure, and misuse of this option can lead to
433
+ an incoherent doctree. In Docutils, section nodes should
434
+ only be children of ``Structural`` nodes, which includes
435
+ ``document``, ``section``, and ``sidebar`` nodes.
436
+ :param offset:
437
+ The offset of the content.
438
+
439
+ .. versionadded:: 7.4
440
+ """
441
+ if offset == -1:
442
+ offset = self.content_offset
443
+ return nested_parse_to_nodes(
444
+ self.state,
445
+ text,
446
+ offset=offset,
447
+ allow_section_headings=allow_section_headings,
448
+ )
449
+
450
+ def parse_inline(
451
+ self, text: str, *, lineno: int = -1,
452
+ ) -> tuple[list[Node], list[system_message]]:
453
+ """Parse *text* as inline elements.
454
+
455
+ :param text:
456
+ The text to parse, which should be a single line or paragraph.
457
+ This cannot contain any structural elements (headings,
458
+ transitions, directives, etc).
459
+ :param lineno:
460
+ The line number where the interpreted text begins.
461
+ :returns:
462
+ A list of nodes (text and inline elements) and a list of system_messages.
463
+
464
+ .. versionadded:: 7.4
465
+ """
466
+ if lineno == -1:
467
+ lineno = self.lineno
468
+ return self.state.inline_text(text, lineno)
428
469
 
429
470
 
430
471
  class SphinxRole:
@@ -494,7 +535,14 @@ class SphinxRole:
494
535
 
495
536
  def get_location(self) -> str:
496
537
  """Get current location info for logging."""
497
- return ':'.join(str(s) for s in self.get_source_info())
538
+ source, line = self.get_source_info()
539
+ if source and line:
540
+ return f'{source}:{line}'
541
+ if source:
542
+ return f'{source}:'
543
+ if line:
544
+ return f'<unknown>:{line}'
545
+ return ''
498
546
 
499
547
 
500
548
  class ReferenceRole(SphinxRole):
sphinx/util/fileutil.py CHANGED
@@ -15,6 +15,19 @@ if TYPE_CHECKING:
15
15
  from sphinx.util.typing import PathMatcher
16
16
 
17
17
 
18
+ def _template_basename(filename: str | os.PathLike[str]) -> str | None:
19
+ """Given an input filename:
20
+ If the input looks like a template, then return the filename output should
21
+ be written to. Otherwise, return no result (None).
22
+ """
23
+ basename = os.path.basename(filename)
24
+ if basename.lower().endswith('_t'):
25
+ return str(filename)[:-2]
26
+ elif basename.lower().endswith('.jinja'):
27
+ return str(filename)[:-6]
28
+ return None
29
+
30
+
18
31
  def copy_asset_file(source: str | os.PathLike[str], destination: str | os.PathLike[str],
19
32
  context: dict[str, Any] | None = None,
20
33
  renderer: BaseRenderer | None = None) -> None:
@@ -37,14 +50,13 @@ def copy_asset_file(source: str | os.PathLike[str], destination: str | os.PathLi
37
50
  else:
38
51
  destination = str(destination)
39
52
 
40
- if os.path.basename(source).endswith(('_t', '_T')) and context is not None:
53
+ if _template_basename(source) and context is not None:
41
54
  if renderer is None:
42
55
  from sphinx.util.template import SphinxRenderer
43
56
  renderer = SphinxRenderer()
44
57
 
45
58
  with open(source, encoding='utf-8') as fsrc:
46
- if destination.endswith(('_t', '_T')):
47
- destination = destination[:-2]
59
+ destination = _template_basename(destination) or destination
48
60
  with open(destination, 'w', encoding='utf-8') as fdst:
49
61
  fdst.write(renderer.render_string(fsrc.read(), context))
50
62
  else:
sphinx/util/images.py CHANGED
@@ -24,6 +24,7 @@ mime_suffixes = {
24
24
  '.svg': 'image/svg+xml',
25
25
  '.svgz': 'image/svg+xml',
26
26
  '.ai': 'application/illustrator',
27
+ '.webp': 'image/webp',
27
28
  }
28
29
  _suffix_from_mime = {v: k for k, v in reversed(mime_suffixes.items())}
29
30
 
sphinx/util/inspect.py CHANGED
@@ -27,7 +27,36 @@ if TYPE_CHECKING:
27
27
  from collections.abc import Callable, Sequence
28
28
  from inspect import _ParameterKind
29
29
  from types import MethodType, ModuleType
30
- from typing import Final
30
+ from typing import Final, Protocol, Union
31
+
32
+ from typing_extensions import TypeAlias, TypeIs
33
+
34
+ class _SupportsGet(Protocol):
35
+ def __get__(self, __instance: Any, __owner: type | None = ...) -> Any: ... # NoQA: E704
36
+
37
+ class _SupportsSet(Protocol):
38
+ # instance and value are contravariants but we do not need that precision
39
+ def __set__(self, __instance: Any, __value: Any) -> None: ... # NoQA: E704
40
+
41
+ class _SupportsDelete(Protocol):
42
+ # instance is contravariant but we do not need that precision
43
+ def __delete__(self, __instance: Any) -> None: ... # NoQA: E704
44
+
45
+ _RoutineType: TypeAlias = Union[
46
+ types.FunctionType,
47
+ types.LambdaType,
48
+ types.MethodType,
49
+ types.BuiltinFunctionType,
50
+ types.BuiltinMethodType,
51
+ types.WrapperDescriptorType,
52
+ types.MethodDescriptorType,
53
+ types.ClassMethodDescriptorType,
54
+ ]
55
+ _SignatureType: TypeAlias = Union[
56
+ Callable[..., Any],
57
+ staticmethod,
58
+ classmethod,
59
+ ]
31
60
 
32
61
  logger = logging.getLogger(__name__)
33
62
 
@@ -90,7 +119,7 @@ def unwrap_all(obj: Any, *, stop: Callable[[Any], bool] | None = None) -> Any:
90
119
 
91
120
 
92
121
  def getall(obj: Any) -> Sequence[str] | None:
93
- """Get the ``__all__`` attribute of an object as sequence.
122
+ """Get the ``__all__`` attribute of an object as a sequence.
94
123
 
95
124
  This returns ``None`` if the given ``obj.__all__`` does not exist and
96
125
  raises :exc:`ValueError` if ``obj.__all__`` is not a list or tuple of
@@ -184,12 +213,12 @@ def isNewType(obj: Any) -> bool:
184
213
  return __module__ == 'typing' and __qualname__ == 'NewType.<locals>.new_type'
185
214
 
186
215
 
187
- def isenumclass(x: Any) -> bool:
216
+ def isenumclass(x: Any) -> TypeIs[type[enum.Enum]]:
188
217
  """Check if the object is an :class:`enumeration class <enum.Enum>`."""
189
218
  return isclass(x) and issubclass(x, enum.Enum)
190
219
 
191
220
 
192
- def isenumattribute(x: Any) -> bool:
221
+ def isenumattribute(x: Any) -> TypeIs[enum.Enum]:
193
222
  """Check if the object is an enumeration attribute."""
194
223
  return isinstance(x, enum.Enum)
195
224
 
@@ -206,12 +235,16 @@ def unpartial(obj: Any) -> Any:
206
235
  return obj
207
236
 
208
237
 
209
- def ispartial(obj: Any) -> bool:
238
+ def ispartial(obj: Any) -> TypeIs[partial | partialmethod]:
210
239
  """Check if the object is a partial function or method."""
211
240
  return isinstance(obj, (partial, partialmethod))
212
241
 
213
242
 
214
- def isclassmethod(obj: Any, cls: Any = None, name: str | None = None) -> bool:
243
+ def isclassmethod(
244
+ obj: Any,
245
+ cls: Any = None,
246
+ name: str | None = None,
247
+ ) -> TypeIs[classmethod]:
215
248
  """Check if the object is a :class:`classmethod`."""
216
249
  if isinstance(obj, classmethod):
217
250
  return True
@@ -227,7 +260,11 @@ def isclassmethod(obj: Any, cls: Any = None, name: str | None = None) -> bool:
227
260
  return False
228
261
 
229
262
 
230
- def isstaticmethod(obj: Any, cls: Any = None, name: str | None = None) -> bool:
263
+ def isstaticmethod(
264
+ obj: Any,
265
+ cls: Any = None,
266
+ name: str | None = None,
267
+ ) -> TypeIs[staticmethod]:
231
268
  """Check if the object is a :class:`staticmethod`."""
232
269
  if isinstance(obj, staticmethod):
233
270
  return True
@@ -241,7 +278,7 @@ def isstaticmethod(obj: Any, cls: Any = None, name: str | None = None) -> bool:
241
278
  return False
242
279
 
243
280
 
244
- def isdescriptor(x: Any) -> bool:
281
+ def isdescriptor(x: Any) -> TypeIs[_SupportsGet | _SupportsSet | _SupportsDelete]:
245
282
  """Check if the object is a :external+python:term:`descriptor`."""
246
283
  return any(
247
284
  callable(safe_getattr(x, item, None)) for item in ('__get__', '__set__', '__delete__')
@@ -308,12 +345,12 @@ def is_singledispatch_function(obj: Any) -> bool:
308
345
  )
309
346
 
310
347
 
311
- def is_singledispatch_method(obj: Any) -> bool:
348
+ def is_singledispatch_method(obj: Any) -> TypeIs[singledispatchmethod]:
312
349
  """Check if the object is a :class:`~functools.singledispatchmethod`."""
313
350
  return isinstance(obj, singledispatchmethod)
314
351
 
315
352
 
316
- def isfunction(obj: Any) -> bool:
353
+ def isfunction(obj: Any) -> TypeIs[types.FunctionType]:
317
354
  """Check if the object is a user-defined function.
318
355
 
319
356
  Partial objects are unwrapped before checking them.
@@ -323,7 +360,7 @@ def isfunction(obj: Any) -> bool:
323
360
  return inspect.isfunction(unpartial(obj))
324
361
 
325
362
 
326
- def isbuiltin(obj: Any) -> bool:
363
+ def isbuiltin(obj: Any) -> TypeIs[types.BuiltinFunctionType]:
327
364
  """Check if the object is a built-in function or method.
328
365
 
329
366
  Partial objects are unwrapped before checking them.
@@ -333,7 +370,7 @@ def isbuiltin(obj: Any) -> bool:
333
370
  return inspect.isbuiltin(unpartial(obj))
334
371
 
335
372
 
336
- def isroutine(obj: Any) -> bool:
373
+ def isroutine(obj: Any) -> TypeIs[_RoutineType]:
337
374
  """Check if the object is a kind of function or method.
338
375
 
339
376
  Partial objects are unwrapped before checking them.
@@ -343,7 +380,7 @@ def isroutine(obj: Any) -> bool:
343
380
  return inspect.isroutine(unpartial(obj))
344
381
 
345
382
 
346
- def iscoroutinefunction(obj: Any) -> bool:
383
+ def iscoroutinefunction(obj: Any) -> TypeIs[Callable[..., types.CoroutineType]]:
347
384
  """Check if the object is a :external+python:term:`coroutine` function."""
348
385
  obj = unwrap_all(obj, stop=_is_wrapped_coroutine)
349
386
  return inspect.iscoroutinefunction(obj)
@@ -358,12 +395,12 @@ def _is_wrapped_coroutine(obj: Any) -> bool:
358
395
  return hasattr(obj, '__wrapped__')
359
396
 
360
397
 
361
- def isproperty(obj: Any) -> bool:
398
+ def isproperty(obj: Any) -> TypeIs[property | cached_property]:
362
399
  """Check if the object is property (possibly cached)."""
363
400
  return isinstance(obj, (property, cached_property))
364
401
 
365
402
 
366
- def isgenericalias(obj: Any) -> bool:
403
+ def isgenericalias(obj: Any) -> TypeIs[types.GenericAlias]:
367
404
  """Check if the object is a generic alias."""
368
405
  return isinstance(obj, (types.GenericAlias, typing._BaseGenericAlias)) # type: ignore[attr-defined]
369
406
 
@@ -579,7 +616,7 @@ class TypeAliasNamespace(dict[str, Any]):
579
616
  raise KeyError
580
617
 
581
618
 
582
- def _should_unwrap(subject: Callable[..., Any]) -> bool:
619
+ def _should_unwrap(subject: _SignatureType) -> bool:
583
620
  """Check the function should be unwrapped on getting signature."""
584
621
  __globals__ = getglobals(subject)
585
622
  # contextmanger should be unwrapped
@@ -590,7 +627,7 @@ def _should_unwrap(subject: Callable[..., Any]) -> bool:
590
627
 
591
628
 
592
629
  def signature(
593
- subject: Callable[..., Any],
630
+ subject: _SignatureType,
594
631
  bound_method: bool = False,
595
632
  type_aliases: Mapping[str, str] | None = None,
596
633
  ) -> Signature:
@@ -603,12 +640,12 @@ def signature(
603
640
 
604
641
  try:
605
642
  if _should_unwrap(subject):
606
- signature = inspect.signature(subject)
643
+ signature = inspect.signature(subject) # type: ignore[arg-type]
607
644
  else:
608
- signature = inspect.signature(subject, follow_wrapped=True)
645
+ signature = inspect.signature(subject, follow_wrapped=True) # type: ignore[arg-type]
609
646
  except ValueError:
610
647
  # follow built-in wrappers up (ex. functools.lru_cache)
611
- signature = inspect.signature(subject)
648
+ signature = inspect.signature(subject) # type: ignore[arg-type]
612
649
  parameters = list(signature.parameters.values())
613
650
  return_annotation = signature.return_annotation
614
651
 
@@ -681,6 +718,13 @@ def _evaluate_forwardref(
681
718
  localns: dict[str, Any] | None,
682
719
  ) -> Any:
683
720
  """Evaluate a forward reference."""
721
+ if sys.version_info >= (3, 12, 4):
722
+ # ``type_params`` were added in 3.13 and the signature of _evaluate()
723
+ # is not backward-compatible (it was backported to 3.12.4, so anything
724
+ # before 3.12.4 still has the old signature).
725
+ #
726
+ # See: https://github.com/python/cpython/pull/118104.
727
+ return ref._evaluate(globalns, localns, {}, recursive_guard=frozenset()) # type: ignore[arg-type, misc]
684
728
  return ref._evaluate(globalns, localns, frozenset())
685
729
 
686
730
 
@@ -752,7 +796,7 @@ def stringify_signature(
752
796
 
753
797
  if show_annotation and param.annotation is not EMPTY:
754
798
  arg.write(': ')
755
- arg.write(stringify_annotation(param.annotation, mode))
799
+ arg.write(stringify_annotation(param.annotation, mode)) # type: ignore[arg-type]
756
800
  if param.default is not EMPTY:
757
801
  if show_annotation and param.annotation is not EMPTY:
758
802
  arg.write(' = ')
@@ -771,7 +815,7 @@ def stringify_signature(
771
815
  if sig.return_annotation is EMPTY or not show_annotation or not show_return_annotation:
772
816
  return f'({concatenated_args})'
773
817
  else:
774
- retann = stringify_annotation(sig.return_annotation, mode)
818
+ retann = stringify_annotation(sig.return_annotation, mode) # type: ignore[arg-type]
775
819
  return f'({concatenated_args}) -> {retann}'
776
820
 
777
821
 
sphinx/util/inventory.py CHANGED
@@ -6,6 +6,7 @@ import re
6
6
  import zlib
7
7
  from typing import IO, TYPE_CHECKING, Callable
8
8
 
9
+ from sphinx.locale import __
9
10
  from sphinx.util import logging
10
11
 
11
12
  BUFSIZE = 16 * 1024
@@ -125,6 +126,8 @@ class InventoryFile:
125
126
  invdata: Inventory = {}
126
127
  projname = stream.readline().rstrip()[11:]
127
128
  version = stream.readline().rstrip()[11:]
129
+ potential_ambiguities = set()
130
+ actual_ambiguities = set()
128
131
  line = stream.readline()
129
132
  if 'zlib' not in line:
130
133
  raise ValueError('invalid inventory header (not compressed): %s' % line)
@@ -147,11 +150,23 @@ class InventoryFile:
147
150
  # for Python modules, and the first
148
151
  # one is correct
149
152
  continue
153
+ if type in {'std:label', 'std:term'}:
154
+ # Some types require case insensitive matches:
155
+ # * 'term': https://github.com/sphinx-doc/sphinx/issues/9291
156
+ # * 'label': https://github.com/sphinx-doc/sphinx/issues/12008
157
+ definition = f"{type}:{name}"
158
+ if definition.lower() in potential_ambiguities:
159
+ actual_ambiguities.add(definition)
160
+ else:
161
+ potential_ambiguities.add(definition.lower())
150
162
  if location.endswith('$'):
151
163
  location = location[:-1] + name
152
164
  location = join(uri, location)
153
165
  inv_item: InventoryItem = projname, version, location, dispname
154
166
  invdata.setdefault(type, {})[name] = inv_item
167
+ for ambiguity in actual_ambiguities:
168
+ logger.warning(__("inventory <%s> contains multiple definitions for %s"),
169
+ uri, ambiguity, type='intersphinx', subtype='external')
155
170
  return invdata
156
171
 
157
172
  @classmethod
sphinx/util/logging.py CHANGED
@@ -16,7 +16,7 @@ from sphinx.util.console import colorize
16
16
  from sphinx.util.osutil import abspath
17
17
 
18
18
  if TYPE_CHECKING:
19
- from collections.abc import Iterator
19
+ from collections.abc import Iterator, Sequence, Set
20
20
 
21
21
  from docutils.nodes import Node
22
22
 
@@ -407,23 +407,18 @@ class InfoFilter(logging.Filter):
407
407
  return record.levelno < logging.WARNING
408
408
 
409
409
 
410
- def is_suppressed_warning(type: str, subtype: str, suppress_warnings: list[str]) -> bool:
410
+ def is_suppressed_warning(
411
+ warning_type: str, sub_type: str, suppress_warnings: Set[str] | Sequence[str],
412
+ ) -> bool:
411
413
  """Check whether the warning is suppressed or not."""
412
- if type is None:
414
+ if warning_type is None or len(suppress_warnings) == 0:
413
415
  return False
414
-
415
- subtarget: str | None
416
-
417
- for warning_type in suppress_warnings:
418
- if '.' in warning_type:
419
- target, subtarget = warning_type.split('.', 1)
420
- else:
421
- target, subtarget = warning_type, None
422
-
423
- if target == type and subtarget in (None, subtype, "*"):
424
- return True
425
-
426
- return False
416
+ suppressed_warnings = frozenset(suppress_warnings)
417
+ if warning_type in suppressed_warnings:
418
+ return True
419
+ if f'{warning_type}.*' in suppressed_warnings:
420
+ return True
421
+ return f'{warning_type}.{sub_type}' in suppressed_warnings
427
422
 
428
423
 
429
424
  class WarningSuppressor(logging.Filter):
@@ -441,7 +436,7 @@ class WarningSuppressor(logging.Filter):
441
436
  suppress_warnings = self.app.config.suppress_warnings
442
437
  except AttributeError:
443
438
  # config is not initialized yet (ex. in conf.py)
444
- suppress_warnings = []
439
+ suppress_warnings = ()
445
440
 
446
441
  if is_suppressed_warning(type, subtype, suppress_warnings):
447
442
  return False
@@ -589,12 +584,10 @@ class WarningLogRecordTranslator(SphinxLogRecordTranslator):
589
584
 
590
585
  def get_node_location(node: Node) -> str | None:
591
586
  source, line = get_source_line(node)
592
- if source:
593
- source = abspath(source)
594
587
  if source and line:
595
- return f"{source}:{line}"
588
+ return f"{abspath(source)}:{line}"
596
589
  if source:
597
- return f"{source}:"
590
+ return f"{abspath(source)}:"
598
591
  if line:
599
592
  return f"<unknown>:{line}"
600
593
  return None
sphinx/util/math.py CHANGED
@@ -20,7 +20,9 @@ def get_node_equation_number(writer: HTML5Translator, node: nodes.math_block) ->
20
20
 
21
21
  id = node['ids'][0]
22
22
  number = writer.builder.fignumbers.get(key, {}).get(id, ())
23
- return '.'.join(map(str, number))
23
+ eqno = '.'.join(map(str, number))
24
+ eqno = writer.builder.config.math_numsep.join(eqno.rsplit('.', 1))
25
+ return eqno
24
26
  else:
25
27
  return node['number']
26
28