Sphinx 7.3.7__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 +44 -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 +3 -3
  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.7.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.7.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.7.dist-info → sphinx-7.4.0.dist-info}/LICENSE.rst +0 -0
  356. {sphinx-7.3.7.dist-info → sphinx-7.4.0.dist-info}/WHEEL +0 -0
  357. {sphinx-7.3.7.dist-info → sphinx-7.4.0.dist-info}/entry_points.txt +0 -0
sphinx/ext/coverage.py CHANGED
@@ -9,6 +9,7 @@ from __future__ import annotations
9
9
  import glob
10
10
  import inspect
11
11
  import pickle
12
+ import pkgutil
12
13
  import re
13
14
  import sys
14
15
  from importlib import import_module
@@ -23,7 +24,7 @@ from sphinx.util.console import red
23
24
  from sphinx.util.inspect import safe_getattr
24
25
 
25
26
  if TYPE_CHECKING:
26
- from collections.abc import Iterator
27
+ from collections.abc import Iterable, Iterator, Sequence, Set
27
28
 
28
29
  from sphinx.application import Sphinx
29
30
  from sphinx.util.typing import ExtensionMetadata
@@ -66,6 +67,93 @@ def _add_row(col_widths: list[int], columns: list[str], separator: str) -> Itera
66
67
  yield _add_line(col_widths, separator)
67
68
 
68
69
 
70
+ def _load_modules(mod_name: str, ignored_module_exps: Iterable[re.Pattern[str]]) -> Set[str]:
71
+ """Recursively load all submodules.
72
+
73
+ :param mod_name: The name of a module to load submodules for.
74
+ :param ignored_module_exps: A list of regexes for modules to ignore.
75
+ :returns: A set of modules names including the provided module name,
76
+ ``mod_name``
77
+ :raises ImportError: If the module indicated by ``mod_name`` could not be
78
+ loaded.
79
+ """
80
+ if any(exp.match(mod_name) for exp in ignored_module_exps):
81
+ return set()
82
+
83
+ # This can raise an exception, which must be handled by the caller.
84
+ mod = import_module(mod_name)
85
+ modules = {mod_name}
86
+ if mod.__spec__ is None:
87
+ return modules
88
+
89
+ search_locations = mod.__spec__.submodule_search_locations
90
+ for (_, sub_mod_name, sub_mod_ispkg) in pkgutil.iter_modules(search_locations):
91
+ if sub_mod_name == '__main__':
92
+ continue
93
+
94
+ if sub_mod_ispkg:
95
+ modules |= _load_modules(f'{mod_name}.{sub_mod_name}', ignored_module_exps)
96
+ else:
97
+ if any(exp.match(sub_mod_name) for exp in ignored_module_exps):
98
+ continue
99
+ modules.add(f'{mod_name}.{sub_mod_name}')
100
+
101
+ return modules
102
+
103
+
104
+ def _determine_py_coverage_modules(
105
+ coverage_modules: Sequence[str],
106
+ seen_modules: Set[str],
107
+ ignored_module_exps: Iterable[re.Pattern[str]],
108
+ py_undoc: dict[str, dict[str, Any]],
109
+ ) -> list[str]:
110
+ """Return a sorted list of modules to check for coverage.
111
+
112
+ Figure out which of the two operating modes to use:
113
+
114
+ - If 'coverage_modules' is not specified, we check coverage for all modules
115
+ seen in the documentation tree. Any objects found in these modules that are
116
+ not documented will be noted. This will therefore only identify missing
117
+ objects, but it requires no additional configuration.
118
+
119
+ - If 'coverage_modules' is specified, we check coverage for all modules
120
+ specified in this configuration value. Any objects found in these modules
121
+ that are not documented will be noted. In addition, any objects from other
122
+ modules that are documented will be noted. This will therefore identify both
123
+ missing modules and missing objects, but it requires manual configuration.
124
+ """
125
+ if not coverage_modules:
126
+ return sorted(seen_modules)
127
+
128
+ modules: set[str] = set()
129
+ for mod_name in coverage_modules:
130
+ try:
131
+ modules |= _load_modules(mod_name, ignored_module_exps)
132
+ except ImportError as err:
133
+ # TODO(stephenfin): Define a subtype for all logs in this module
134
+ logger.warning(__('module %s could not be imported: %s'), mod_name, err)
135
+ py_undoc[mod_name] = {'error': err}
136
+ continue
137
+
138
+ # if there are additional modules then we warn but continue scanning
139
+ if additional_modules := seen_modules - modules:
140
+ logger.warning(
141
+ __('the following modules are documented but were not specified '
142
+ 'in coverage_modules: %s'),
143
+ ', '.join(additional_modules),
144
+ )
145
+
146
+ # likewise, if there are missing modules we warn but continue scanning
147
+ if missing_modules := modules - seen_modules:
148
+ logger.warning(
149
+ __('the following modules are specified in coverage_modules '
150
+ 'but were not documented'),
151
+ ', '.join(missing_modules),
152
+ )
153
+
154
+ return sorted(modules)
155
+
156
+
69
157
  class CoverageBuilder(Builder):
70
158
  """
71
159
  Evaluates coverage of code in the documentation.
@@ -106,12 +194,12 @@ class CoverageBuilder(Builder):
106
194
 
107
195
  def write(self, *ignored: Any) -> None:
108
196
  self.py_undoc: dict[str, dict[str, Any]] = {}
109
- self.py_undocumented: dict[str, set[str]] = {}
110
- self.py_documented: dict[str, set[str]] = {}
197
+ self.py_undocumented: dict[str, Set[str]] = {}
198
+ self.py_documented: dict[str, Set[str]] = {}
111
199
  self.build_py_coverage()
112
200
  self.write_py_coverage()
113
201
 
114
- self.c_undoc: dict[str, set[tuple[str, str]]] = {}
202
+ self.c_undoc: dict[str, Set[tuple[str, str]]] = {}
115
203
  self.build_c_coverage()
116
204
  self.write_c_coverage()
117
205
 
@@ -169,11 +257,14 @@ class CoverageBuilder(Builder):
169
257
  )
170
258
 
171
259
  def build_py_coverage(self) -> None:
172
- objects = self.env.domaindata['py']['objects']
173
- modules = self.env.domaindata['py']['modules']
260
+ seen_objects = frozenset(self.env.domaindata['py']['objects'])
261
+ seen_modules = frozenset(self.env.domaindata['py']['modules'])
174
262
 
175
263
  skip_undoc = self.config.coverage_skip_undoc_in_source
176
264
 
265
+ modules = _determine_py_coverage_modules(
266
+ self.config.coverage_modules, seen_modules, self.mod_ignorexps, self.py_undoc,
267
+ )
177
268
  for mod_name in modules:
178
269
  ignore = False
179
270
  for exp in self.mod_ignorexps:
@@ -213,7 +304,7 @@ class CoverageBuilder(Builder):
213
304
  continue
214
305
 
215
306
  if inspect.isfunction(obj):
216
- if full_name not in objects:
307
+ if full_name not in seen_objects:
217
308
  for exp in self.fun_ignorexps:
218
309
  if exp.match(name):
219
310
  break
@@ -229,7 +320,7 @@ class CoverageBuilder(Builder):
229
320
  if exp.match(name):
230
321
  break
231
322
  else:
232
- if full_name not in objects:
323
+ if full_name not in seen_objects:
233
324
  if skip_undoc and not obj.__doc__:
234
325
  continue
235
326
  # not documented at all
@@ -257,7 +348,7 @@ class CoverageBuilder(Builder):
257
348
  full_attr_name = f'{full_name}.{attr_name}'
258
349
  if self.ignore_pyobj(full_attr_name):
259
350
  continue
260
- if full_attr_name not in objects:
351
+ if full_attr_name not in seen_objects:
261
352
  attrs.append(attr_name)
262
353
  undocumented_objects.add(full_attr_name)
263
354
  else:
@@ -273,19 +364,17 @@ class CoverageBuilder(Builder):
273
364
 
274
365
  def _write_py_statistics(self, op: TextIO) -> None:
275
366
  """Outputs the table of ``op``."""
276
- all_modules = set(self.py_documented.keys()).union(
277
- set(self.py_undocumented.keys()))
278
- all_objects: set[str] = set()
279
- all_documented_objects: set[str] = set()
367
+ all_modules = frozenset(self.py_documented.keys() | self.py_undocumented.keys())
368
+ all_objects: Set[str] = set()
369
+ all_documented_objects: Set[str] = set()
280
370
  for module in all_modules:
281
- all_module_objects = self.py_documented[module].union(self.py_undocumented[module])
282
- all_objects = all_objects.union(all_module_objects)
283
- all_documented_objects = all_documented_objects.union(self.py_documented[module])
371
+ all_objects |= self.py_documented[module] | self.py_undocumented[module]
372
+ all_documented_objects |= self.py_documented[module]
284
373
 
285
374
  # prepare tabular
286
375
  table = [['Module', 'Coverage', 'Undocumented']]
287
- for module in all_modules:
288
- module_objects = self.py_documented[module].union(self.py_undocumented[module])
376
+ for module in sorted(all_modules):
377
+ module_objects = self.py_documented[module] | self.py_undocumented[module]
289
378
  if len(module_objects):
290
379
  value = 100.0 * len(self.py_documented[module]) / len(module_objects)
291
380
  else:
@@ -391,6 +480,7 @@ class CoverageBuilder(Builder):
391
480
 
392
481
  def setup(app: Sphinx) -> ExtensionMetadata:
393
482
  app.add_builder(CoverageBuilder)
483
+ app.add_config_value('coverage_modules', (), '', types={tuple, list})
394
484
  app.add_config_value('coverage_ignore_modules', [], '')
395
485
  app.add_config_value('coverage_ignore_functions', [], '')
396
486
  app.add_config_value('coverage_ignore_classes', [], '')
sphinx/ext/duration.py CHANGED
@@ -13,10 +13,15 @@ from sphinx.locale import __
13
13
  from sphinx.util import logging
14
14
 
15
15
  if TYPE_CHECKING:
16
+ from typing import TypedDict
17
+
16
18
  from docutils import nodes
17
19
 
18
20
  from sphinx.application import Sphinx
19
21
 
22
+ class _DurationDomainData(TypedDict):
23
+ reading_durations: dict[str, float]
24
+
20
25
  logger = logging.getLogger(__name__)
21
26
 
22
27
 
@@ -38,9 +43,11 @@ class DurationDomain(Domain):
38
43
  def clear_doc(self, docname: str) -> None:
39
44
  self.reading_durations.pop(docname, None)
40
45
 
41
- def merge_domaindata(self, docnames: list[str], otherdata: dict[str, float]) -> None:
42
- for docname, duration in otherdata.items():
43
- if docname in docnames:
46
+ def merge_domaindata(self, docnames: list[str], otherdata: _DurationDomainData) -> None: # type: ignore[override]
47
+ other_reading_durations = otherdata.get('reading_durations', {})
48
+ docnames_set = frozenset(docnames)
49
+ for docname, duration in other_reading_durations.items():
50
+ if docname in docnames_set:
44
51
  self.reading_durations[docname] = duration
45
52
 
46
53
 
sphinx/ext/extlinks.py CHANGED
@@ -91,9 +91,9 @@ class ExternalLinksChecker(SphinxPostTransform):
91
91
 
92
92
  def make_link_role(name: str, base_url: str, caption: str) -> RoleFunction:
93
93
  # Check whether we have base_url and caption strings have an '%s' for
94
- # expansion. If not, fall back the the old behaviour and use the string as
94
+ # expansion. If not, fall back to the old behaviour and use the string as
95
95
  # a prefix.
96
- # Remark: It is an implementation detail that we use Pythons %-formatting.
96
+ # Remark: It is an implementation detail that we use Python's %-formatting.
97
97
  # So far we only expose ``%s`` and require quoting of ``%`` using ``%%``.
98
98
  def role(typ: str, rawtext: str, text: str, lineno: int,
99
99
  inliner: Inliner, options: dict[str, Any] | None = None,
@@ -108,6 +108,7 @@ def make_link_role(name: str, base_url: str, caption: str) -> RoleFunction:
108
108
  else:
109
109
  title = caption % part
110
110
  pnode = nodes.reference(title, title, internal=False, refuri=full_url)
111
+ pnode["classes"].append(f"extlink-{name}")
111
112
  return [pnode], []
112
113
  return role
113
114
 
sphinx/ext/graphviz.py CHANGED
@@ -15,7 +15,7 @@ from typing import TYPE_CHECKING, Any, ClassVar
15
15
  from urllib.parse import urlsplit, urlunsplit
16
16
 
17
17
  from docutils import nodes
18
- from docutils.parsers.rst import Directive, directives
18
+ from docutils.parsers.rst import directives
19
19
 
20
20
  import sphinx
21
21
  from sphinx.errors import SphinxError
@@ -91,12 +91,12 @@ class graphviz(nodes.General, nodes.Inline, nodes.Element):
91
91
  pass
92
92
 
93
93
 
94
- def figure_wrapper(directive: Directive, node: graphviz, caption: str) -> nodes.figure:
94
+ def figure_wrapper(directive: SphinxDirective, node: graphviz, caption: str) -> nodes.figure:
95
95
  figure_node = nodes.figure('', node)
96
96
  if 'align' in node:
97
97
  figure_node['align'] = node.attributes.pop('align')
98
98
 
99
- inodes, messages = directive.state.inline_text(caption, directive.lineno)
99
+ inodes, messages = directive.parse_inline(caption)
100
100
  caption_node = nodes.caption(caption, '', *inodes)
101
101
  caption_node.extend(messages)
102
102
  set_source_info(directive, caption_node)
sphinx/ext/ifconfig.py CHANGED
@@ -22,7 +22,6 @@ from docutils import nodes
22
22
 
23
23
  import sphinx
24
24
  from sphinx.util.docutils import SphinxDirective
25
- from sphinx.util.nodes import nested_parse_with_titles
26
25
 
27
26
  if TYPE_CHECKING:
28
27
  from docutils.nodes import Node
@@ -48,7 +47,7 @@ class IfConfig(SphinxDirective):
48
47
  node.document = self.state.document
49
48
  self.set_source_info(node)
50
49
  node['expr'] = self.arguments[0]
51
- nested_parse_with_titles(self.state, self.content, node, self.content_offset)
50
+ node += self.parse_content_to_nodes(allow_section_headings=True)
52
51
  return [node]
53
52
 
54
53
 
@@ -26,6 +26,7 @@ class ImagemagickConverter(ImageConverter):
26
26
  ('image/gif', 'image/png'),
27
27
  ('application/pdf', 'image/png'),
28
28
  ('application/illustrator', 'image/png'),
29
+ ('image/webp', 'image/png'),
29
30
  ]
30
31
 
31
32
  def is_available(self) -> bool:
sphinx/ext/imgmath.py CHANGED
@@ -103,16 +103,17 @@ def generate_latex_macro(image_format: str,
103
103
  }
104
104
 
105
105
  if config.imgmath_use_preview:
106
- template_name = 'preview.tex_t'
106
+ template_name = 'preview.tex'
107
107
  else:
108
- template_name = 'template.tex_t'
108
+ template_name = 'template.tex'
109
109
 
110
110
  for template_dir in config.templates_path:
111
- template = path.join(confdir, template_dir, template_name)
112
- if path.exists(template):
113
- return LaTeXRenderer().render(template, variables)
111
+ for template_suffix in ('.jinja', '_t'):
112
+ template = path.join(confdir, template_dir, template_name + template_suffix)
113
+ if path.exists(template):
114
+ return LaTeXRenderer().render(template, variables)
114
115
 
115
- return LaTeXRenderer(templates_path).render(template_name, variables)
116
+ return LaTeXRenderer(templates_path).render(template_name + '.jinja', variables)
116
117
 
117
118
 
118
119
  def ensure_tempdir(builder: Builder) -> str:
@@ -378,15 +378,15 @@ class InheritanceDiagram(SphinxDirective):
378
378
  aliases=self.config.inheritance_alias,
379
379
  top_classes=node['top-classes'])
380
380
  except InheritanceException as err:
381
- return [node.document.reporter.warning(err, line=self.lineno)] # type: ignore[union-attr]
381
+ return [node.document.reporter.warning(err, line=self.lineno)]
382
382
 
383
383
  # Create xref nodes for each target of the graph's image map and
384
384
  # add them to the doc tree so that Sphinx can resolve the
385
385
  # references to real URLs later. These nodes will eventually be
386
386
  # removed from the doctree after we're done with them.
387
387
  for name in graph.get_all_class_names():
388
- refnodes, x = class_role( # type: ignore[call-arg,misc]
389
- 'class', ':class:`%s`' % name, name, 0, self.state)
388
+ refnodes, x = class_role( # type: ignore[misc]
389
+ 'class', ':class:`%s`' % name, name, 0, self.state.inliner)
390
390
  node.extend(refnodes)
391
391
  # Store the graph object so we can use it to generate the
392
392
  # dot file later
@@ -0,0 +1,81 @@
1
+ """Insert links to objects documented in remote Sphinx documentation.
2
+
3
+ This works as follows:
4
+
5
+ * Each Sphinx HTML build creates a file named "objects.inv" that contains a
6
+ mapping from object names to URIs relative to the HTML set's root.
7
+
8
+ * Projects using the Intersphinx extension can specify links to such mapping
9
+ files in the `intersphinx_mapping` config value. The mapping will then be
10
+ used to resolve otherwise missing references to objects into links to the
11
+ other documentation.
12
+
13
+ * By default, the mapping file is assumed to be at the same location as the
14
+ rest of the documentation; however, the location of the mapping file can
15
+ also be specified individually, e.g. if the docs should be buildable
16
+ without Internet access.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ __all__ = (
22
+ 'InventoryAdapter',
23
+ 'fetch_inventory',
24
+ 'fetch_inventory_group',
25
+ 'load_mappings',
26
+ 'normalize_intersphinx_mapping',
27
+ 'IntersphinxRoleResolver',
28
+ 'inventory_exists',
29
+ 'install_dispatcher',
30
+ 'resolve_reference_in_inventory',
31
+ 'resolve_reference_any_inventory',
32
+ 'resolve_reference_detect_inventory',
33
+ 'missing_reference',
34
+ 'IntersphinxDispatcher',
35
+ 'IntersphinxRole',
36
+ 'inspect_main',
37
+ )
38
+
39
+ from typing import TYPE_CHECKING
40
+
41
+ import sphinx
42
+ from sphinx.ext.intersphinx._cli import inspect_main
43
+ from sphinx.ext.intersphinx._load import (
44
+ fetch_inventory,
45
+ fetch_inventory_group,
46
+ load_mappings,
47
+ normalize_intersphinx_mapping,
48
+ )
49
+ from sphinx.ext.intersphinx._resolve import (
50
+ IntersphinxDispatcher,
51
+ IntersphinxRole,
52
+ IntersphinxRoleResolver,
53
+ install_dispatcher,
54
+ inventory_exists,
55
+ missing_reference,
56
+ resolve_reference_any_inventory,
57
+ resolve_reference_detect_inventory,
58
+ resolve_reference_in_inventory,
59
+ )
60
+ from sphinx.ext.intersphinx._shared import InventoryAdapter
61
+
62
+ if TYPE_CHECKING:
63
+ from sphinx.application import Sphinx
64
+ from sphinx.util.typing import ExtensionMetadata
65
+
66
+
67
+ def setup(app: Sphinx) -> ExtensionMetadata:
68
+ app.add_config_value('intersphinx_mapping', {}, 'env')
69
+ app.add_config_value('intersphinx_cache_limit', 5, '')
70
+ app.add_config_value('intersphinx_timeout', None, '')
71
+ app.add_config_value('intersphinx_disabled_reftypes', ['std:doc'], 'env')
72
+ app.connect('config-inited', normalize_intersphinx_mapping, priority=800)
73
+ app.connect('builder-inited', load_mappings)
74
+ app.connect('source-read', install_dispatcher)
75
+ app.connect('missing-reference', missing_reference)
76
+ app.add_post_transform(IntersphinxRoleResolver)
77
+ return {
78
+ 'version': sphinx.__display_version__,
79
+ 'env_version': 1,
80
+ 'parallel_read_safe': True,
81
+ }
@@ -0,0 +1,10 @@
1
+ """Command line interface for the intersphinx extension."""
2
+
3
+ import logging as _logging
4
+ import sys
5
+
6
+ from sphinx.ext.intersphinx import inspect_main
7
+
8
+ _logging.basicConfig()
9
+
10
+ raise SystemExit(inspect_main(sys.argv[1:]))
@@ -0,0 +1,44 @@
1
+ """This module provides contains the code for intersphinx command-line utilities."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import sys
6
+
7
+ from sphinx.ext.intersphinx._load import fetch_inventory
8
+
9
+
10
+ def inspect_main(argv: list[str], /) -> int:
11
+ """Debug functionality to print out an inventory"""
12
+ if len(argv) < 1:
13
+ print('Print out an inventory file.\n'
14
+ 'Error: must specify local path or URL to an inventory file.',
15
+ file=sys.stderr)
16
+ return 1
17
+
18
+ class MockConfig:
19
+ intersphinx_timeout: int | None = None
20
+ tls_verify = False
21
+ tls_cacerts: str | dict[str, str] | None = None
22
+ user_agent: str = ''
23
+
24
+ class MockApp:
25
+ srcdir = ''
26
+ config = MockConfig()
27
+
28
+ try:
29
+ filename = argv[0]
30
+ inv_data = fetch_inventory(MockApp(), '', filename) # type: ignore[arg-type]
31
+ for key in sorted(inv_data or {}):
32
+ print(key)
33
+ inv_entries = sorted(inv_data[key].items())
34
+ for entry, (_proj, _ver, url_path, display_name) in inv_entries:
35
+ display_name = display_name * (display_name != '-')
36
+ print(f' {entry:<40} {display_name:<40}: {url_path}')
37
+ except ValueError as exc:
38
+ print(exc.args[0] % exc.args[1:], file=sys.stderr)
39
+ return 1
40
+ except Exception as exc:
41
+ print(f'Unknown error: {exc!r}', file=sys.stderr)
42
+ return 1
43
+ else:
44
+ return 0