Sphinx 7.2.5__py3-none-any.whl → 7.3.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 (388) hide show
  1. sphinx/__init__.py +8 -9
  2. sphinx/addnodes.py +31 -28
  3. sphinx/application.py +9 -15
  4. sphinx/builders/__init__.py +5 -6
  5. sphinx/builders/_epub_base.py +17 -9
  6. sphinx/builders/changes.py +10 -5
  7. sphinx/builders/dirhtml.py +4 -2
  8. sphinx/builders/dummy.py +3 -2
  9. sphinx/builders/epub3.py +5 -3
  10. sphinx/builders/gettext.py +24 -7
  11. sphinx/builders/html/__init__.py +88 -96
  12. sphinx/builders/html/_assets.py +16 -16
  13. sphinx/builders/html/transforms.py +4 -2
  14. sphinx/builders/latex/__init__.py +40 -33
  15. sphinx/builders/latex/nodes.py +6 -2
  16. sphinx/builders/latex/transforms.py +17 -8
  17. sphinx/builders/latex/util.py +1 -1
  18. sphinx/builders/linkcheck.py +86 -27
  19. sphinx/builders/manpage.py +8 -6
  20. sphinx/builders/singlehtml.py +5 -4
  21. sphinx/builders/texinfo.py +18 -14
  22. sphinx/builders/text.py +3 -2
  23. sphinx/builders/xml.py +5 -2
  24. sphinx/cmd/build.py +119 -76
  25. sphinx/cmd/make_mode.py +21 -20
  26. sphinx/cmd/quickstart.py +13 -16
  27. sphinx/config.py +432 -250
  28. sphinx/deprecation.py +23 -13
  29. sphinx/directives/__init__.py +8 -8
  30. sphinx/directives/code.py +7 -7
  31. sphinx/directives/other.py +23 -13
  32. sphinx/directives/patches.py +7 -6
  33. sphinx/domains/__init__.py +2 -2
  34. sphinx/domains/c/__init__.py +796 -0
  35. sphinx/domains/c/_ast.py +1421 -0
  36. sphinx/domains/c/_ids.py +65 -0
  37. sphinx/domains/c/_parser.py +1048 -0
  38. sphinx/domains/c/_symbol.py +700 -0
  39. sphinx/domains/changeset.py +11 -7
  40. sphinx/domains/citation.py +5 -2
  41. sphinx/domains/cpp/__init__.py +1089 -0
  42. sphinx/domains/cpp/_ast.py +3635 -0
  43. sphinx/domains/cpp/_ids.py +537 -0
  44. sphinx/domains/cpp/_parser.py +2117 -0
  45. sphinx/domains/cpp/_symbol.py +1092 -0
  46. sphinx/domains/index.py +6 -4
  47. sphinx/domains/javascript.py +16 -13
  48. sphinx/domains/math.py +9 -4
  49. sphinx/domains/python/__init__.py +890 -0
  50. sphinx/domains/python/_annotations.py +507 -0
  51. sphinx/domains/python/_object.py +426 -0
  52. sphinx/domains/rst.py +12 -7
  53. sphinx/domains/{std.py → std/__init__.py} +19 -16
  54. sphinx/environment/__init__.py +21 -19
  55. sphinx/environment/adapters/indexentries.py +2 -2
  56. sphinx/environment/adapters/toctree.py +10 -9
  57. sphinx/environment/collectors/__init__.py +6 -3
  58. sphinx/environment/collectors/asset.py +4 -3
  59. sphinx/environment/collectors/dependencies.py +3 -2
  60. sphinx/environment/collectors/metadata.py +6 -5
  61. sphinx/environment/collectors/title.py +3 -2
  62. sphinx/environment/collectors/toctree.py +5 -4
  63. sphinx/errors.py +13 -2
  64. sphinx/events.py +14 -9
  65. sphinx/ext/apidoc.py +9 -11
  66. sphinx/ext/autodoc/__init__.py +105 -71
  67. sphinx/ext/autodoc/directive.py +7 -6
  68. sphinx/ext/autodoc/importer.py +132 -52
  69. sphinx/ext/autodoc/mock.py +7 -5
  70. sphinx/ext/autodoc/preserve_defaults.py +4 -3
  71. sphinx/ext/autodoc/type_comment.py +2 -1
  72. sphinx/ext/autodoc/typehints.py +5 -4
  73. sphinx/ext/autosectionlabel.py +3 -2
  74. sphinx/ext/autosummary/__init__.py +21 -17
  75. sphinx/ext/autosummary/generate.py +9 -9
  76. sphinx/ext/coverage.py +26 -20
  77. sphinx/ext/doctest.py +38 -33
  78. sphinx/ext/duration.py +1 -0
  79. sphinx/ext/extlinks.py +4 -3
  80. sphinx/ext/githubpages.py +3 -2
  81. sphinx/ext/graphviz.py +10 -7
  82. sphinx/ext/ifconfig.py +5 -5
  83. sphinx/ext/imgconverter.py +6 -5
  84. sphinx/ext/imgmath.py +9 -8
  85. sphinx/ext/inheritance_diagram.py +31 -31
  86. sphinx/ext/intersphinx.py +140 -23
  87. sphinx/ext/linkcode.py +3 -2
  88. sphinx/ext/mathjax.py +2 -1
  89. sphinx/ext/napoleon/__init__.py +12 -7
  90. sphinx/ext/napoleon/docstring.py +34 -32
  91. sphinx/ext/todo.py +10 -7
  92. sphinx/ext/viewcode.py +12 -11
  93. sphinx/extension.py +18 -8
  94. sphinx/highlighting.py +39 -20
  95. sphinx/io.py +17 -8
  96. sphinx/jinja2glue.py +16 -15
  97. sphinx/locale/__init__.py +30 -23
  98. sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
  99. sphinx/locale/ar/LC_MESSAGES/sphinx.po +818 -761
  100. sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
  101. sphinx/locale/bg/LC_MESSAGES/sphinx.po +811 -754
  102. sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
  103. sphinx/locale/bn/LC_MESSAGES/sphinx.po +835 -778
  104. sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
  105. sphinx/locale/ca/LC_MESSAGES/sphinx.po +864 -807
  106. sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
  107. sphinx/locale/cak/LC_MESSAGES/sphinx.po +816 -759
  108. sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
  109. sphinx/locale/cs/LC_MESSAGES/sphinx.po +837 -780
  110. sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
  111. sphinx/locale/cy/LC_MESSAGES/sphinx.po +819 -762
  112. sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
  113. sphinx/locale/da/LC_MESSAGES/sphinx.po +838 -781
  114. sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
  115. sphinx/locale/de/LC_MESSAGES/sphinx.po +838 -781
  116. sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
  117. sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +811 -754
  118. sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
  119. sphinx/locale/el/LC_MESSAGES/sphinx.po +853 -796
  120. sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
  121. sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +811 -754
  122. sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
  123. sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +811 -754
  124. sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
  125. sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +856 -799
  126. sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
  127. sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +811 -754
  128. sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
  129. sphinx/locale/eo/LC_MESSAGES/sphinx.po +820 -763
  130. sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
  131. sphinx/locale/es/LC_MESSAGES/sphinx.po +856 -799
  132. sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
  133. sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +811 -754
  134. sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
  135. sphinx/locale/et/LC_MESSAGES/sphinx.po +845 -788
  136. sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
  137. sphinx/locale/eu/LC_MESSAGES/sphinx.po +837 -780
  138. sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
  139. sphinx/locale/fa/LC_MESSAGES/sphinx.po +854 -797
  140. sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
  141. sphinx/locale/fi/LC_MESSAGES/sphinx.po +816 -759
  142. sphinx/locale/fr/LC_MESSAGES/sphinx.js +1 -1
  143. sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
  144. sphinx/locale/fr/LC_MESSAGES/sphinx.po +904 -847
  145. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
  146. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +811 -754
  147. sphinx/locale/gl/LC_MESSAGES/sphinx.js +54 -54
  148. sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
  149. sphinx/locale/gl/LC_MESSAGES/sphinx.po +1506 -1449
  150. sphinx/locale/he/LC_MESSAGES/sphinx.js +1 -1
  151. sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
  152. sphinx/locale/he/LC_MESSAGES/sphinx.po +823 -766
  153. sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
  154. sphinx/locale/hi/LC_MESSAGES/sphinx.po +853 -796
  155. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
  156. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +811 -754
  157. sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
  158. sphinx/locale/hr/LC_MESSAGES/sphinx.po +844 -787
  159. sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
  160. sphinx/locale/hu/LC_MESSAGES/sphinx.po +837 -780
  161. sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
  162. sphinx/locale/id/LC_MESSAGES/sphinx.po +854 -797
  163. sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
  164. sphinx/locale/is/LC_MESSAGES/sphinx.po +811 -754
  165. sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
  166. sphinx/locale/it/LC_MESSAGES/sphinx.po +837 -780
  167. sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
  168. sphinx/locale/ja/LC_MESSAGES/sphinx.po +853 -796
  169. sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
  170. sphinx/locale/ka/LC_MESSAGES/sphinx.po +848 -791
  171. sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
  172. sphinx/locale/ko/LC_MESSAGES/sphinx.po +855 -798
  173. sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
  174. sphinx/locale/lt/LC_MESSAGES/sphinx.po +837 -780
  175. sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
  176. sphinx/locale/lv/LC_MESSAGES/sphinx.po +837 -780
  177. sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
  178. sphinx/locale/mk/LC_MESSAGES/sphinx.po +825 -768
  179. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js +27 -27
  180. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
  181. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +876 -818
  182. sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
  183. sphinx/locale/ne/LC_MESSAGES/sphinx.po +837 -780
  184. sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
  185. sphinx/locale/nl/LC_MESSAGES/sphinx.po +844 -787
  186. sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
  187. sphinx/locale/pl/LC_MESSAGES/sphinx.po +845 -788
  188. sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
  189. sphinx/locale/pt/LC_MESSAGES/sphinx.po +811 -754
  190. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
  191. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +908 -851
  192. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
  193. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +837 -780
  194. sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
  195. sphinx/locale/ro/LC_MESSAGES/sphinx.po +837 -780
  196. sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
  197. sphinx/locale/ru/LC_MESSAGES/sphinx.po +838 -781
  198. sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
  199. sphinx/locale/si/LC_MESSAGES/sphinx.po +823 -766
  200. sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
  201. sphinx/locale/sk/LC_MESSAGES/sphinx.po +854 -797
  202. sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
  203. sphinx/locale/sl/LC_MESSAGES/sphinx.po +832 -775
  204. sphinx/locale/sphinx.pot +813 -755
  205. sphinx/locale/sq/LC_MESSAGES/sphinx.js +1 -1
  206. sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
  207. sphinx/locale/sq/LC_MESSAGES/sphinx.po +865 -808
  208. sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
  209. sphinx/locale/sr/LC_MESSAGES/sphinx.po +835 -778
  210. sphinx/locale/sr@latin/LC_MESSAGES/sphinx.mo +0 -0
  211. sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo +0 -0
  212. sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
  213. sphinx/locale/sv/LC_MESSAGES/sphinx.po +837 -780
  214. sphinx/locale/ta/LC_MESSAGES/sphinx.js +54 -54
  215. sphinx/locale/ta/LC_MESSAGES/sphinx.mo +0 -0
  216. sphinx/locale/ta/LC_MESSAGES/sphinx.po +1530 -1473
  217. sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
  218. sphinx/locale/te/LC_MESSAGES/sphinx.po +811 -754
  219. sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
  220. sphinx/locale/tr/LC_MESSAGES/sphinx.po +853 -796
  221. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
  222. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +833 -776
  223. sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
  224. sphinx/locale/ur/LC_MESSAGES/sphinx.po +811 -754
  225. sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
  226. sphinx/locale/vi/LC_MESSAGES/sphinx.po +837 -780
  227. sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
  228. sphinx/locale/yue/LC_MESSAGES/sphinx.po +811 -754
  229. sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo +0 -0
  230. sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +855 -798
  231. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
  232. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +811 -754
  233. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js +1 -1
  234. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
  235. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +879 -822
  236. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
  237. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +811 -754
  238. sphinx/parsers.py +7 -5
  239. sphinx/project.py +18 -11
  240. sphinx/pycode/__init__.py +6 -5
  241. sphinx/pycode/ast.py +23 -8
  242. sphinx/pycode/parser.py +6 -5
  243. sphinx/registry.py +12 -6
  244. sphinx/roles.py +103 -57
  245. sphinx/search/__init__.py +17 -18
  246. sphinx/search/da.py +2 -2
  247. sphinx/search/de.py +2 -2
  248. sphinx/search/en.py +1 -1
  249. sphinx/search/es.py +2 -2
  250. sphinx/search/fi.py +2 -2
  251. sphinx/search/fr.py +2 -2
  252. sphinx/search/hu.py +2 -2
  253. sphinx/search/it.py +2 -2
  254. sphinx/search/ja.py +13 -22
  255. sphinx/search/nl.py +2 -2
  256. sphinx/search/no.py +2 -2
  257. sphinx/search/pt.py +2 -2
  258. sphinx/search/ro.py +1 -1
  259. sphinx/search/ru.py +2 -2
  260. sphinx/search/sv.py +2 -2
  261. sphinx/search/tr.py +1 -1
  262. sphinx/search/zh.py +2 -3
  263. sphinx/templates/graphviz/graphviz.css +1 -1
  264. sphinx/testing/fixtures.py +41 -24
  265. sphinx/testing/path.py +1 -1
  266. sphinx/testing/util.py +142 -53
  267. sphinx/texinputs/sphinx.xdy +1 -1
  268. sphinx/texinputs/sphinxlatextables.sty +1 -1
  269. sphinx/texinputs/sphinxpackagesubstitutefont.sty +21 -0
  270. sphinx/themes/agogo/layout.html +4 -4
  271. sphinx/themes/agogo/static/agogo.css_t +1 -1
  272. sphinx/themes/agogo/theme.toml +22 -0
  273. sphinx/themes/basic/defindex.html +1 -1
  274. sphinx/themes/basic/domainindex.html +1 -1
  275. sphinx/themes/basic/genindex-single.html +1 -1
  276. sphinx/themes/basic/genindex-split.html +1 -1
  277. sphinx/themes/basic/genindex.html +1 -1
  278. sphinx/themes/basic/globaltoc.html +1 -1
  279. sphinx/themes/basic/layout.html +1 -1
  280. sphinx/themes/basic/localtoc.html +1 -1
  281. sphinx/themes/basic/page.html +1 -1
  282. sphinx/themes/basic/relations.html +1 -1
  283. sphinx/themes/basic/search.html +5 -20
  284. sphinx/themes/basic/searchbox.html +3 -3
  285. sphinx/themes/basic/searchfield.html +3 -3
  286. sphinx/themes/basic/sourcelink.html +1 -1
  287. sphinx/themes/basic/static/basic.css_t +1 -1
  288. sphinx/themes/basic/static/doctools.js +1 -1
  289. sphinx/themes/basic/static/language_data.js_t +2 -2
  290. sphinx/themes/basic/static/searchtools.js +105 -60
  291. sphinx/themes/basic/theme.toml +23 -0
  292. sphinx/themes/bizstyle/layout.html +1 -6
  293. sphinx/themes/bizstyle/static/bizstyle.css_t +1 -1
  294. sphinx/themes/bizstyle/static/bizstyle.js_t +1 -1
  295. sphinx/themes/bizstyle/static/css3-mediaqueries_src.js +3 -3
  296. sphinx/themes/bizstyle/theme.toml +12 -0
  297. sphinx/themes/classic/layout.html +1 -1
  298. sphinx/themes/classic/static/classic.css_t +1 -1
  299. sphinx/themes/classic/static/sidebar.js_t +1 -1
  300. sphinx/themes/classic/theme.toml +34 -0
  301. sphinx/themes/default/theme.toml +2 -0
  302. sphinx/themes/epub/epub-cover.html +1 -1
  303. sphinx/themes/epub/layout.html +1 -1
  304. sphinx/themes/epub/static/epub.css_t +1 -1
  305. sphinx/themes/epub/theme.toml +10 -0
  306. sphinx/themes/haiku/layout.html +3 -3
  307. sphinx/themes/haiku/static/haiku.css_t +2 -2
  308. sphinx/themes/haiku/theme.toml +16 -0
  309. sphinx/themes/nature/static/nature.css_t +1 -1
  310. sphinx/themes/nature/theme.toml +6 -0
  311. sphinx/themes/nonav/layout.html +1 -1
  312. sphinx/themes/nonav/static/nonav.css_t +1 -1
  313. sphinx/themes/nonav/theme.toml +10 -0
  314. sphinx/themes/pyramid/static/epub.css_t +1 -1
  315. sphinx/themes/pyramid/static/pyramid.css_t +1 -1
  316. sphinx/themes/pyramid/theme.toml +6 -0
  317. sphinx/themes/scrolls/artwork/logo.svg +1 -1
  318. sphinx/themes/scrolls/layout.html +2 -2
  319. sphinx/themes/scrolls/static/scrolls.css_t +1 -1
  320. sphinx/themes/scrolls/theme.toml +15 -0
  321. sphinx/themes/sphinxdoc/static/sphinxdoc.css_t +1 -1
  322. sphinx/themes/sphinxdoc/theme.toml +6 -0
  323. sphinx/themes/traditional/static/traditional.css_t +1 -1
  324. sphinx/themes/traditional/theme.toml +9 -0
  325. sphinx/theming.py +427 -131
  326. sphinx/transforms/__init__.py +21 -24
  327. sphinx/transforms/compact_bullet_list.py +5 -5
  328. sphinx/transforms/i18n.py +30 -28
  329. sphinx/transforms/post_transforms/__init__.py +9 -7
  330. sphinx/transforms/post_transforms/code.py +4 -1
  331. sphinx/transforms/post_transforms/images.py +17 -13
  332. sphinx/transforms/references.py +3 -1
  333. sphinx/util/__init__.py +15 -11
  334. sphinx/util/_io.py +34 -0
  335. sphinx/util/_pathlib.py +23 -18
  336. sphinx/util/build_phase.py +1 -0
  337. sphinx/util/cfamily.py +19 -11
  338. sphinx/util/console.py +101 -21
  339. sphinx/util/display.py +3 -2
  340. sphinx/util/docfields.py +12 -8
  341. sphinx/util/docutils.py +21 -35
  342. sphinx/util/exceptions.py +3 -2
  343. sphinx/util/fileutil.py +5 -5
  344. sphinx/util/http_date.py +9 -2
  345. sphinx/util/i18n.py +40 -9
  346. sphinx/util/inspect.py +317 -245
  347. sphinx/util/inventory.py +22 -5
  348. sphinx/util/logging.py +81 -7
  349. sphinx/util/matching.py +2 -1
  350. sphinx/util/math.py +1 -2
  351. sphinx/util/nodes.py +39 -29
  352. sphinx/util/osutil.py +25 -6
  353. sphinx/util/parallel.py +6 -1
  354. sphinx/util/requests.py +8 -5
  355. sphinx/util/rst.py +8 -6
  356. sphinx/util/tags.py +3 -3
  357. sphinx/util/template.py +8 -3
  358. sphinx/util/typing.py +76 -42
  359. sphinx/versioning.py +6 -2
  360. sphinx/writers/html.py +1 -1
  361. sphinx/writers/html5.py +17 -13
  362. sphinx/writers/latex.py +12 -12
  363. sphinx/writers/manpage.py +13 -7
  364. sphinx/writers/texinfo.py +13 -10
  365. sphinx/writers/text.py +13 -23
  366. sphinx/writers/xml.py +1 -1
  367. sphinx-7.2.5.dist-info/LICENSE → sphinx-7.3.0.dist-info/LICENSE.rst +1 -1
  368. {sphinx-7.2.5.dist-info → sphinx-7.3.0.dist-info}/METADATA +13 -12
  369. sphinx-7.3.0.dist-info/RECORD +581 -0
  370. sphinx/domains/c.py +0 -3906
  371. sphinx/domains/cpp.py +0 -8233
  372. sphinx/domains/python.py +0 -1769
  373. sphinx/themes/agogo/theme.conf +0 -20
  374. sphinx/themes/basic/theme.conf +0 -16
  375. sphinx/themes/bizstyle/theme.conf +0 -10
  376. sphinx/themes/classic/theme.conf +0 -32
  377. sphinx/themes/default/theme.conf +0 -2
  378. sphinx/themes/epub/theme.conf +0 -8
  379. sphinx/themes/haiku/theme.conf +0 -14
  380. sphinx/themes/nature/theme.conf +0 -4
  381. sphinx/themes/nonav/theme.conf +0 -8
  382. sphinx/themes/pyramid/theme.conf +0 -4
  383. sphinx/themes/scrolls/theme.conf +0 -13
  384. sphinx/themes/sphinxdoc/theme.conf +0 -4
  385. sphinx/themes/traditional/theme.conf +0 -7
  386. sphinx-7.2.5.dist-info/RECORD +0 -569
  387. {sphinx-7.2.5.dist-info → sphinx-7.3.0.dist-info}/WHEEL +0 -0
  388. {sphinx-7.2.5.dist-info → sphinx-7.3.0.dist-info}/entry_points.txt +0 -0
@@ -21,7 +21,7 @@ from sphinx.util.i18n import format_date
21
21
  from sphinx.util.nodes import apply_source_workaround, is_smartquotable
22
22
 
23
23
  if TYPE_CHECKING:
24
- from collections.abc import Generator
24
+ from collections.abc import Iterator
25
25
 
26
26
  from docutils.nodes import Node, Text
27
27
 
@@ -29,6 +29,7 @@ if TYPE_CHECKING:
29
29
  from sphinx.config import Config
30
30
  from sphinx.domains.std import StandardDomain
31
31
  from sphinx.environment import BuildEnvironment
32
+ from sphinx.util.typing import ExtensionMetadata
32
33
 
33
34
 
34
35
  logger = logging.getLogger(__name__)
@@ -80,7 +81,7 @@ class SphinxTransformer(Transformer):
80
81
  if not hasattr(self.document.settings, 'env') and self.env:
81
82
  self.document.settings.env = self.env
82
83
 
83
- super().apply_transforms()
84
+ super().apply_transforms() # type: ignore[misc]
84
85
  else:
85
86
  # wrap the target node by document node during transforming
86
87
  try:
@@ -98,6 +99,7 @@ class DefaultSubstitutions(SphinxTransform):
98
99
  """
99
100
  Replace some substitutions if they aren't defined in the document.
100
101
  """
102
+
101
103
  # run before the default Substitutions
102
104
  default_priority = 210
103
105
 
@@ -139,6 +141,7 @@ class MoveModuleTargets(SphinxTransform):
139
141
 
140
142
  XXX Python specific
141
143
  """
144
+
142
145
  default_priority = 210
143
146
 
144
147
  def apply(self, **kwargs: Any) -> None:
@@ -161,6 +164,7 @@ class HandleCodeBlocks(SphinxTransform):
161
164
  """
162
165
  Several code block related transformations.
163
166
  """
167
+
164
168
  default_priority = 210
165
169
 
166
170
  def apply(self, **kwargs: Any) -> None:
@@ -185,6 +189,7 @@ class AutoNumbering(SphinxTransform):
185
189
  """
186
190
  Register IDs of tables, figures and literal_blocks to assign numbers.
187
191
  """
192
+
188
193
  default_priority = 210
189
194
 
190
195
  def apply(self, **kwargs: Any) -> None:
@@ -201,6 +206,7 @@ class SortIds(SphinxTransform):
201
206
  """
202
207
  Sort section IDs so that the "id[0-9]+" one comes last.
203
208
  """
209
+
204
210
  default_priority = 261
205
211
 
206
212
  def apply(self, **kwargs: Any) -> None:
@@ -222,6 +228,7 @@ class ApplySourceWorkaround(SphinxTransform):
222
228
  """
223
229
  Update source and rawsource attributes
224
230
  """
231
+
225
232
  default_priority = 10
226
233
 
227
234
  def apply(self, **kwargs: Any) -> None:
@@ -234,6 +241,7 @@ class AutoIndexUpgrader(SphinxTransform):
234
241
  """
235
242
  Detect old style (4 column based indices) and automatically upgrade to new style.
236
243
  """
244
+
237
245
  default_priority = 210
238
246
 
239
247
  def apply(self, **kwargs: Any) -> None:
@@ -244,13 +252,14 @@ class AutoIndexUpgrader(SphinxTransform):
244
252
  logger.warning(msg, location=node)
245
253
  for i, entry in enumerate(node['entries']):
246
254
  if len(entry) == 4:
247
- node['entries'][i] = entry + (None,)
255
+ node['entries'][i] = (*entry, None)
248
256
 
249
257
 
250
258
  class ExtraTranslatableNodes(SphinxTransform):
251
259
  """
252
260
  Make nodes translatable
253
261
  """
262
+
254
263
  default_priority = 10
255
264
 
256
265
  def apply(self, **kwargs: Any) -> None:
@@ -270,6 +279,7 @@ class UnreferencedFootnotesDetector(SphinxTransform):
270
279
  """
271
280
  Detect unreferenced footnotes and emit warnings
272
281
  """
282
+
273
283
  default_priority = 200
274
284
 
275
285
  def apply(self, **kwargs: Any) -> None:
@@ -291,6 +301,7 @@ class UnreferencedFootnotesDetector(SphinxTransform):
291
301
 
292
302
  class DoctestTransform(SphinxTransform):
293
303
  """Set "doctest" style to each doctest_block node"""
304
+
294
305
  default_priority = 500
295
306
 
296
307
  def apply(self, **kwargs: Any) -> None:
@@ -300,6 +311,7 @@ class DoctestTransform(SphinxTransform):
300
311
 
301
312
  class FilterSystemMessages(SphinxTransform):
302
313
  """Filter system messages from a doctree."""
314
+
303
315
  default_priority = 999
304
316
 
305
317
  def apply(self, **kwargs: Any) -> None:
@@ -315,6 +327,7 @@ class SphinxContentsFilter(ContentsFilter):
315
327
  Used with BuildEnvironment.add_toc_from() to discard cross-file links
316
328
  within table-of-contents link nodes.
317
329
  """
330
+
318
331
  visit_pending_xref = ContentsFilter.ignore_node_but_process_children
319
332
 
320
333
  def visit_image(self, node: nodes.image) -> None:
@@ -327,6 +340,7 @@ class SphinxSmartQuotes(SmartQuotes, SphinxTransform):
327
340
 
328
341
  refs: sphinx.parsers.RSTParser
329
342
  """
343
+
330
344
  default_priority = 750
331
345
 
332
346
  def apply(self, **kwargs: Any) -> None:
@@ -362,7 +376,7 @@ class SphinxSmartQuotes(SmartQuotes, SphinxTransform):
362
376
  for tag in normalize_language_tag(language)
363
377
  )
364
378
 
365
- def get_tokens(self, txtnodes: list[Text]) -> Generator[tuple[str, str], None, None]:
379
+ def get_tokens(self, txtnodes: list[Text]) -> Iterator[tuple[str, str]]:
366
380
  # A generator that yields ``(texttype, nodetext)`` tuples for a list
367
381
  # of "Text" nodes (interface to ``smartquotes.educate_tokens()``).
368
382
  for txtnode in txtnodes:
@@ -377,32 +391,16 @@ class SphinxSmartQuotes(SmartQuotes, SphinxTransform):
377
391
 
378
392
  class DoctreeReadEvent(SphinxTransform):
379
393
  """Emit :event:`doctree-read` event."""
394
+
380
395
  default_priority = 880
381
396
 
382
397
  def apply(self, **kwargs: Any) -> None:
383
398
  self.app.emit('doctree-read', self.document)
384
399
 
385
400
 
386
- class ManpageLink(SphinxTransform):
387
- """Find manpage section numbers and names"""
388
- default_priority = 999
389
-
390
- def apply(self, **kwargs: Any) -> None:
391
- for node in self.document.findall(addnodes.manpage):
392
- manpage = ' '.join([str(x) for x in node.children
393
- if isinstance(x, nodes.Text)])
394
- pattern = r'^(?P<path>(?P<page>.+)[\(\.](?P<section>[1-9]\w*)?\)?)$'
395
- info = {'path': manpage,
396
- 'page': manpage,
397
- 'section': ''}
398
- r = re.match(pattern, manpage)
399
- if r:
400
- info = r.groupdict()
401
- node.attributes.update(info)
402
-
403
-
404
401
  class GlossarySorter(SphinxTransform):
405
402
  """Sort glossaries that have the ``sorted`` flag."""
403
+
406
404
  # This must be done after i18n, therefore not right
407
405
  # away in the glossary directive.
408
406
  default_priority = 500
@@ -491,7 +489,7 @@ def _sort_key(node: nodes.Node) -> int:
491
489
  raise ValueError(msg)
492
490
 
493
491
 
494
- def setup(app: Sphinx) -> dict[str, Any]:
492
+ def setup(app: Sphinx) -> ExtensionMetadata:
495
493
  app.add_transform(ApplySourceWorkaround)
496
494
  app.add_transform(ExtraTranslatableNodes)
497
495
  app.add_transform(DefaultSubstitutions)
@@ -505,7 +503,6 @@ def setup(app: Sphinx) -> dict[str, Any]:
505
503
  app.add_transform(UnreferencedFootnotesDetector)
506
504
  app.add_transform(SphinxSmartQuotes)
507
505
  app.add_transform(DoctreeReadEvent)
508
- app.add_transform(ManpageLink)
509
506
  app.add_transform(GlossarySorter)
510
507
  app.add_transform(ReorderConsecutiveTargetAndIndexNodes)
511
508
 
@@ -13,6 +13,7 @@ if TYPE_CHECKING:
13
13
  from docutils.nodes import Node
14
14
 
15
15
  from sphinx.application import Sphinx
16
+ from sphinx.util.typing import ExtensionMetadata
16
17
 
17
18
 
18
19
  class RefOnlyListChecker(nodes.GenericNodeVisitor):
@@ -29,10 +30,8 @@ class RefOnlyListChecker(nodes.GenericNodeVisitor):
29
30
  pass
30
31
 
31
32
  def visit_list_item(self, node: nodes.list_item) -> None:
32
- children: list[Node] = []
33
- for child in node.children:
34
- if not isinstance(child, nodes.Invisible):
35
- children.append(child)
33
+ children: list[Node] = [child for child in node.children
34
+ if not isinstance(child, nodes.Invisible)]
36
35
  if len(children) != 1:
37
36
  raise nodes.NodeFound
38
37
  if not isinstance(children[0], nodes.paragraph):
@@ -55,6 +54,7 @@ class RefOnlyBulletListTransform(SphinxTransform):
55
54
  Specifically implemented for 'Indices and Tables' section, which looks
56
55
  odd when html_compact_lists is false.
57
56
  """
57
+
58
58
  default_priority = 100
59
59
 
60
60
  def apply(self, **kwargs: Any) -> None:
@@ -81,7 +81,7 @@ class RefOnlyBulletListTransform(SphinxTransform):
81
81
  item.replace(para, compact_para)
82
82
 
83
83
 
84
- def setup(app: Sphinx) -> dict[str, Any]:
84
+ def setup(app: Sphinx) -> ExtensionMetadata:
85
85
  app.add_transform(RefOnlyBulletListTransform)
86
86
 
87
87
  return {
sphinx/transforms/i18n.py CHANGED
@@ -33,6 +33,7 @@ if TYPE_CHECKING:
33
33
 
34
34
  from sphinx.application import Sphinx
35
35
  from sphinx.config import Config
36
+ from sphinx.util.typing import ExtensionMetadata
36
37
 
37
38
 
38
39
  logger = logging.getLogger(__name__)
@@ -77,7 +78,7 @@ def publish_msgstr(app: Sphinx, source: str, source_path: str, source_line: int,
77
78
  settings=settings,
78
79
  )
79
80
  with contextlib.suppress(IndexError): # empty node
80
- return doc[0] # type: ignore[return-value]
81
+ return doc[0]
81
82
  return doc
82
83
  finally:
83
84
  config.rst_prolog = rst_prolog # type: ignore[attr-defined]
@@ -95,6 +96,7 @@ class PreserveTranslatableMessages(SphinxTransform):
95
96
  """
96
97
  Preserve original translatable messages before translation
97
98
  """
99
+
98
100
  default_priority = 10 # this MUST be invoked before Locale transform
99
101
 
100
102
  def apply(self, **kwargs: Any) -> None:
@@ -136,7 +138,7 @@ class _NodeUpdater:
136
138
  if old_name != new_name:
137
139
  # if name would be changed, replace node names and
138
140
  # document nameids mapping with new name.
139
- names = section_node.setdefault('names', [])
141
+ names: list[str] = section_node.setdefault('names', [])
140
142
  names.append(new_name)
141
143
  # Original section name (reference target name) should be kept to refer
142
144
  # from other nodes which is still not translated or uses explicit target
@@ -181,7 +183,7 @@ class _NodeUpdater:
181
183
 
182
184
  # replace target's refname to new target name
183
185
  matcher = NodeMatcher(nodes.target, refname=old_name)
184
- for old_target in self.document.findall(matcher): # type: nodes.target
186
+ for old_target in matcher.findall(self.document):
185
187
  old_target['refname'] = new_name
186
188
 
187
189
  processed = True
@@ -197,10 +199,8 @@ class _NodeUpdater:
197
199
  lst.append(new)
198
200
 
199
201
  is_autofootnote_ref = NodeMatcher(nodes.footnote_reference, auto=Any)
200
- old_foot_refs: list[nodes.footnote_reference] = [
201
- *self.node.findall(is_autofootnote_ref)]
202
- new_foot_refs: list[nodes.footnote_reference] = [
203
- *self.patch.findall(is_autofootnote_ref)]
202
+ old_foot_refs = list(is_autofootnote_ref.findall(self.node))
203
+ new_foot_refs = list(is_autofootnote_ref.findall(self.patch))
204
204
  self.compare_references(old_foot_refs, new_foot_refs,
205
205
  __('inconsistent footnote references in translated message.' +
206
206
  ' original: {0}, translated: {1}'))
@@ -239,8 +239,8 @@ class _NodeUpdater:
239
239
  # * use translated refname for section refname.
240
240
  # * inline reference "`Python <...>`_" has no 'refname'.
241
241
  is_refnamed_ref = NodeMatcher(nodes.reference, refname=Any)
242
- old_refs: list[nodes.reference] = [*self.node.findall(is_refnamed_ref)]
243
- new_refs: list[nodes.reference] = [*self.patch.findall(is_refnamed_ref)]
242
+ old_refs = list(is_refnamed_ref.findall(self.node))
243
+ new_refs = list(is_refnamed_ref.findall(self.patch))
244
244
  self.compare_references(old_refs, new_refs,
245
245
  __('inconsistent references in translated message.' +
246
246
  ' original: {0}, translated: {1}'))
@@ -263,10 +263,8 @@ class _NodeUpdater:
263
263
  def update_refnamed_footnote_references(self) -> None:
264
264
  # refnamed footnote should use original 'ids'.
265
265
  is_refnamed_footnote_ref = NodeMatcher(nodes.footnote_reference, refname=Any)
266
- old_foot_refs: list[nodes.footnote_reference] = [*self.node.findall(
267
- is_refnamed_footnote_ref)]
268
- new_foot_refs: list[nodes.footnote_reference] = [*self.patch.findall(
269
- is_refnamed_footnote_ref)]
266
+ old_foot_refs = list(is_refnamed_footnote_ref.findall(self.node))
267
+ new_foot_refs = list(is_refnamed_footnote_ref.findall(self.patch))
270
268
  refname_ids_map: dict[str, list[str]] = {}
271
269
  self.compare_references(old_foot_refs, new_foot_refs,
272
270
  __('inconsistent footnote references in translated message.' +
@@ -281,8 +279,8 @@ class _NodeUpdater:
281
279
  def update_citation_references(self) -> None:
282
280
  # citation should use original 'ids'.
283
281
  is_citation_ref = NodeMatcher(nodes.citation_reference, refname=Any)
284
- old_cite_refs: list[nodes.citation_reference] = [*self.node.findall(is_citation_ref)]
285
- new_cite_refs: list[nodes.citation_reference] = [*self.patch.findall(is_citation_ref)]
282
+ old_cite_refs = list(is_citation_ref.findall(self.node))
283
+ new_cite_refs = list(is_citation_ref.findall(self.patch))
286
284
  self.compare_references(old_cite_refs, new_cite_refs,
287
285
  __('inconsistent citation references in translated message.' +
288
286
  ' original: {0}, translated: {1}'))
@@ -339,6 +337,7 @@ class Locale(SphinxTransform):
339
337
  """
340
338
  Replace translatable nodes with their translated doctree.
341
339
  """
340
+
342
341
  default_priority = 20
343
342
 
344
343
  def apply(self, **kwargs: Any) -> None:
@@ -395,7 +394,7 @@ class Locale(SphinxTransform):
395
394
  msgstr = '::\n\n' + indent(msgstr, ' ' * 3)
396
395
 
397
396
  patch = publish_msgstr(self.app, msgstr, source,
398
- node.line, self.config, settings)
397
+ node.line, self.config, settings) # type: ignore[arg-type]
399
398
  # FIXME: no warnings about inconsistent references in this part
400
399
  # XXX doctest and other block markup
401
400
  if not isinstance(patch, nodes.paragraph):
@@ -409,10 +408,10 @@ class Locale(SphinxTransform):
409
408
  for _id in node['ids']:
410
409
  parts = split_term_classifiers(msgstr)
411
410
  patch = publish_msgstr(
412
- self.app, parts[0] or '', source, node.line, self.config, settings,
411
+ self.app, parts[0] or '', source, node.line, self.config, settings, # type: ignore[arg-type]
413
412
  )
414
413
  updater.patch = make_glossary_term(
415
- self.env, patch, parts[1] or '', source, node.line, _id, self.document,
414
+ self.env, patch, parts[1] or '', source, node.line, _id, self.document, # type: ignore[arg-type]
416
415
  )
417
416
  processed = True
418
417
 
@@ -441,11 +440,11 @@ class Locale(SphinxTransform):
441
440
 
442
441
  # update translatable nodes
443
442
  if isinstance(node, addnodes.translatable):
444
- node.apply_translated_message(msg, msgstr) # type: ignore[attr-defined]
443
+ node.apply_translated_message(msg, msgstr)
445
444
  continue
446
445
 
447
446
  # update meta nodes
448
- if isinstance(node, nodes.meta): # type: ignore[attr-defined]
447
+ if isinstance(node, nodes.meta):
449
448
  node['content'] = msgstr
450
449
  node['translated'] = True
451
450
  continue
@@ -475,11 +474,11 @@ class Locale(SphinxTransform):
475
474
  msgstr = msgstr + '\n' + '=' * len(msgstr) * 2
476
475
 
477
476
  patch = publish_msgstr(self.app, msgstr, source,
478
- node.line, self.config, settings)
477
+ node.line, self.config, settings) # type: ignore[arg-type]
479
478
  # Structural Subelements phase2
480
479
  if isinstance(node, nodes.title):
481
480
  # get <title> node that placed as a first child
482
- patch = patch.next_node()
481
+ patch = patch.next_node() # type: ignore[assignment]
483
482
 
484
483
  # ignore unexpected markups in translation message
485
484
  unexpected: tuple[type[nodes.Element], ...] = (
@@ -538,6 +537,7 @@ class TranslationProgressTotaliser(SphinxTransform):
538
537
  """
539
538
  Calculate the number of translated and untranslated nodes.
540
539
  """
540
+
541
541
  default_priority = 25 # MUST happen after Locale
542
542
 
543
543
  def apply(self, **kwargs: Any) -> None:
@@ -546,7 +546,7 @@ class TranslationProgressTotaliser(SphinxTransform):
546
546
  return
547
547
 
548
548
  total = translated = 0
549
- for node in self.document.findall(NodeMatcher(translated=Any)): # type: nodes.Element
549
+ for node in NodeMatcher(nodes.Element, translated=Any).findall(self.document):
550
550
  total += 1
551
551
  if node['translated']:
552
552
  translated += 1
@@ -561,6 +561,7 @@ class AddTranslationClasses(SphinxTransform):
561
561
  """
562
562
  Add ``translated`` or ``untranslated`` classes to indicate translation status.
563
563
  """
564
+
564
565
  default_priority = 950
565
566
 
566
567
  def apply(self, **kwargs: Any) -> None:
@@ -584,19 +585,20 @@ class AddTranslationClasses(SphinxTransform):
584
585
  'True, False, "translated" or "untranslated"')
585
586
  raise ConfigError(msg)
586
587
 
587
- for node in self.document.findall(NodeMatcher(translated=Any)): # type: nodes.Element
588
+ for node in NodeMatcher(nodes.Element, translated=Any).findall(self.document):
588
589
  if node['translated']:
589
590
  if add_translated:
590
- node.setdefault('classes', []).append('translated')
591
+ node.setdefault('classes', []).append('translated') # type: ignore[arg-type]
591
592
  else:
592
593
  if add_untranslated:
593
- node.setdefault('classes', []).append('untranslated')
594
+ node.setdefault('classes', []).append('untranslated') # type: ignore[arg-type]
594
595
 
595
596
 
596
597
  class RemoveTranslatableInline(SphinxTransform):
597
598
  """
598
599
  Remove inline nodes used for translation as placeholders.
599
600
  """
601
+
600
602
  default_priority = 999
601
603
 
602
604
  def apply(self, **kwargs: Any) -> None:
@@ -605,12 +607,12 @@ class RemoveTranslatableInline(SphinxTransform):
605
607
  return
606
608
 
607
609
  matcher = NodeMatcher(nodes.inline, translatable=Any)
608
- for inline in list(self.document.findall(matcher)): # type: nodes.inline
610
+ for inline in matcher.findall(self.document):
609
611
  inline.parent.remove(inline)
610
612
  inline.parent += inline.children
611
613
 
612
614
 
613
- def setup(app: Sphinx) -> dict[str, Any]:
615
+ def setup(app: Sphinx) -> ExtensionMetadata:
614
616
  app.add_transform(PreserveTranslatableMessages)
615
617
  app.add_transform(Locale)
616
618
  app.add_transform(TranslationProgressTotaliser)
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import re
6
+ from itertools import starmap
6
7
  from typing import TYPE_CHECKING, Any, cast
7
8
 
8
9
  from docutils import nodes
@@ -22,6 +23,7 @@ if TYPE_CHECKING:
22
23
  from sphinx.addnodes import pending_xref
23
24
  from sphinx.application import Sphinx
24
25
  from sphinx.domains import Domain
26
+ from sphinx.util.typing import ExtensionMetadata
25
27
 
26
28
  logger = logging.getLogger(__name__)
27
29
 
@@ -33,6 +35,7 @@ class SphinxPostTransform(SphinxTransform):
33
35
  They resolve references, convert images, do special transformation for each output
34
36
  formats and so on. This class helps to implement these post transforms.
35
37
  """
38
+
36
39
  builders: tuple[str, ...] = ()
37
40
  formats: tuple[str, ...] = ()
38
41
 
@@ -44,10 +47,7 @@ class SphinxPostTransform(SphinxTransform):
44
47
  """Check this transform working for current builder."""
45
48
  if self.builders and self.app.builder.name not in self.builders:
46
49
  return False
47
- if self.formats and self.app.builder.format not in self.formats:
48
- return False
49
-
50
- return True
50
+ return not self.formats or self.app.builder.format in self.formats
51
51
 
52
52
  def run(self, **kwargs: Any) -> None:
53
53
  """Main method of post transforms.
@@ -81,7 +81,7 @@ class ReferencesResolver(SphinxPostTransform):
81
81
  domain = None
82
82
 
83
83
  try:
84
- if 'refdomain' in node and node['refdomain']:
84
+ if node.get('refdomain', False):
85
85
  # let the domain try to resolve the reference
86
86
  try:
87
87
  domain = self.env.domains[node['refdomain']]
@@ -154,7 +154,7 @@ class ReferencesResolver(SphinxPostTransform):
154
154
  def stringify(name: str, node: Element) -> str:
155
155
  reftitle = node.get('reftitle', node.astext())
156
156
  return f':{name}:`{reftitle}`'
157
- candidates = ' or '.join(stringify(name, role) for name, role in results)
157
+ candidates = ' or '.join(starmap(stringify, results))
158
158
  logger.warning(__("more than one target found for 'any' cross-"
159
159
  'reference %r: could be %s'), target, candidates,
160
160
  location=node)
@@ -234,6 +234,7 @@ class OnlyNodeTransform(SphinxPostTransform):
234
234
 
235
235
  class SigElementFallbackTransform(SphinxPostTransform):
236
236
  """Fallback various desc_* nodes to inline if translator does not support them."""
237
+
237
238
  default_priority = 200
238
239
 
239
240
  def run(self, **kwargs: Any) -> None:
@@ -276,6 +277,7 @@ class SigElementFallbackTransform(SphinxPostTransform):
276
277
 
277
278
  class PropagateDescDomain(SphinxPostTransform):
278
279
  """Add the domain name of the parent node as a class in each desc_signature node."""
280
+
279
281
  default_priority = 200
280
282
 
281
283
  def run(self, **kwargs: Any) -> None:
@@ -284,7 +286,7 @@ class PropagateDescDomain(SphinxPostTransform):
284
286
  node['classes'].append(node.parent['domain'])
285
287
 
286
288
 
287
- def setup(app: Sphinx) -> dict[str, Any]:
289
+ def setup(app: Sphinx) -> ExtensionMetadata:
288
290
  app.add_post_transform(ReferencesResolver)
289
291
  app.add_post_transform(OnlyNodeTransform)
290
292
  app.add_post_transform(SigElementFallbackTransform)
@@ -16,6 +16,7 @@ if TYPE_CHECKING:
16
16
  from docutils.nodes import Node, TextElement
17
17
 
18
18
  from sphinx.application import Sphinx
19
+ from sphinx.util.typing import ExtensionMetadata
19
20
 
20
21
 
21
22
  class HighlightSetting(NamedTuple):
@@ -32,6 +33,7 @@ class HighlightLanguageTransform(SphinxTransform):
32
33
  :rst:dir:`highlight` directive. After processing, this transform
33
34
  removes ``highlightlang`` node from doctree.
34
35
  """
36
+
35
37
  default_priority = 400
36
38
 
37
39
  def apply(self, **kwargs: Any) -> None:
@@ -88,6 +90,7 @@ class TrimDoctestFlagsTransform(SphinxTransform):
88
90
 
89
91
  see :confval:`trim_doctest_flags` for more information.
90
92
  """
93
+
91
94
  default_priority = HighlightLanguageTransform.default_priority + 1
92
95
 
93
96
  def apply(self, **kwargs: Any) -> None:
@@ -128,7 +131,7 @@ class TrimDoctestFlagsTransform(SphinxTransform):
128
131
  return False
129
132
 
130
133
 
131
- def setup(app: Sphinx) -> dict[str, Any]:
134
+ def setup(app: Sphinx) -> ExtensionMetadata:
132
135
  app.add_post_transform(HighlightLanguageTransform)
133
136
  app.add_post_transform(TrimDoctestFlagsTransform)
134
137
 
@@ -19,6 +19,7 @@ from sphinx.util.osutil import ensuredir
19
19
 
20
20
  if TYPE_CHECKING:
21
21
  from sphinx.application import Sphinx
22
+ from sphinx.util.typing import ExtensionMetadata
22
23
 
23
24
  logger = logging.getLogger(__name__)
24
25
 
@@ -47,7 +48,7 @@ class ImageDownloader(BaseImageConverter):
47
48
  default_priority = 100
48
49
 
49
50
  def match(self, node: nodes.image) -> bool:
50
- if self.app.builder.supported_image_types == []:
51
+ if not self.app.builder.supported_image_types:
51
52
  return False
52
53
  if self.app.builder.supported_remote_images:
53
54
  return False
@@ -61,21 +62,23 @@ class ImageDownloader(BaseImageConverter):
61
62
  if basename == '' or len(basename) > MAX_FILENAME_LEN:
62
63
  filename, ext = os.path.splitext(node['uri'])
63
64
  basename = sha1(filename.encode(), usedforsecurity=False).hexdigest() + ext
64
- basename = re.sub(CRITICAL_PATH_CHAR_RE, "_", basename)
65
+ basename = CRITICAL_PATH_CHAR_RE.sub("_", basename)
65
66
 
66
- dirname = node['uri'].replace('://', '/').translate({ord("?"): "/",
67
- ord("&"): "/"})
68
- if len(dirname) > MAX_FILENAME_LEN:
69
- dirname = sha1(dirname.encode(), usedforsecurity=False).hexdigest()
70
- ensuredir(os.path.join(self.imagedir, dirname))
71
- path = os.path.join(self.imagedir, dirname, basename)
67
+ uri_hash = sha1(node['uri'].encode(), usedforsecurity=False).hexdigest()
68
+ ensuredir(os.path.join(self.imagedir, uri_hash))
69
+ path = os.path.join(self.imagedir, uri_hash, basename)
72
70
 
73
71
  headers = {}
74
72
  if os.path.exists(path):
75
73
  timestamp: float = ceil(os.stat(path).st_mtime)
76
74
  headers['If-Modified-Since'] = epoch_to_rfc1123(timestamp)
77
75
 
78
- r = requests.get(node['uri'], headers=headers)
76
+ config = self.app.config
77
+ r = requests.get(
78
+ node['uri'], headers=headers,
79
+ _user_agent=config.user_agent,
80
+ _tls_info=(config.tls_verify, config.tls_cacerts),
81
+ )
79
82
  if r.status_code >= 400:
80
83
  logger.warning(__('Could not fetch remote image: %s [%d]') %
81
84
  (node['uri'], r.status_code))
@@ -95,7 +98,7 @@ class ImageDownloader(BaseImageConverter):
95
98
  if mimetype != '*' and os.path.splitext(basename)[1] == '':
96
99
  # append a suffix if URI does not contain suffix
97
100
  ext = get_image_extension(mimetype)
98
- newpath = os.path.join(self.imagedir, dirname, basename + ext)
101
+ newpath = os.path.join(self.imagedir, uri_hash, basename + ext)
99
102
  os.replace(path, newpath)
100
103
  self.app.env.original_image_uri.pop(path)
101
104
  self.app.env.original_image_uri[newpath] = node['uri']
@@ -112,7 +115,7 @@ class DataURIExtractor(BaseImageConverter):
112
115
  default_priority = 150
113
116
 
114
117
  def match(self, node: nodes.image) -> bool:
115
- if self.app.builder.supported_remote_images == []:
118
+ if not self.app.builder.supported_remote_images:
116
119
  return False
117
120
  if self.app.builder.supported_data_uri_images is True:
118
121
  return False
@@ -143,7 +146,7 @@ class DataURIExtractor(BaseImageConverter):
143
146
 
144
147
  def get_filename_for(filename: str, mimetype: str) -> str:
145
148
  basename = os.path.basename(filename)
146
- basename = re.sub(CRITICAL_PATH_CHAR_RE, "_", basename)
149
+ basename = CRITICAL_PATH_CHAR_RE.sub("_", basename)
147
150
  return os.path.splitext(basename)[0] + (get_image_extension(mimetype) or '')
148
151
 
149
152
 
@@ -168,6 +171,7 @@ class ImageConverter(BaseImageConverter):
168
171
  3. Register your image converter to Sphinx using
169
172
  :py:meth:`.Sphinx.add_post_transform`
170
173
  """
174
+
171
175
  default_priority = 200
172
176
 
173
177
  #: The converter is available or not. Will be filled at the first call of
@@ -269,7 +273,7 @@ class ImageConverter(BaseImageConverter):
269
273
  raise NotImplementedError
270
274
 
271
275
 
272
- def setup(app: Sphinx) -> dict[str, Any]:
276
+ def setup(app: Sphinx) -> ExtensionMetadata:
273
277
  app.add_post_transform(ImageDownloader)
274
278
  app.add_post_transform(DataURIExtractor)
275
279
 
@@ -10,6 +10,7 @@ from sphinx.transforms import SphinxTransform
10
10
 
11
11
  if TYPE_CHECKING:
12
12
  from sphinx.application import Sphinx
13
+ from sphinx.util.typing import ExtensionMetadata
13
14
 
14
15
 
15
16
  class SphinxDanglingReferences(DanglingReferences):
@@ -29,6 +30,7 @@ class SphinxDanglingReferences(DanglingReferences):
29
30
 
30
31
  class SphinxDomains(SphinxTransform):
31
32
  """Collect objects to Sphinx domains for cross references."""
33
+
32
34
  default_priority = 850
33
35
 
34
36
  def apply(self, **kwargs: Any) -> None:
@@ -36,7 +38,7 @@ class SphinxDomains(SphinxTransform):
36
38
  domain.process_doc(self.env, self.env.docname, self.document)
37
39
 
38
40
 
39
- def setup(app: Sphinx) -> dict[str, Any]:
41
+ def setup(app: Sphinx) -> ExtensionMetadata:
40
42
  app.add_transform(SphinxDanglingReferences)
41
43
  app.add_transform(SphinxDomains)
42
44