Sphinx 7.2.6__py3-none-any.whl → 7.3.1__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 +4 -9
  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 +102 -36
  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.6.dist-info/LICENSE → sphinx-7.3.1.dist-info/LICENSE.rst +1 -1
  368. {sphinx-7.2.6.dist-info → sphinx-7.3.1.dist-info}/METADATA +14 -12
  369. sphinx-7.3.1.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.6.dist-info/RECORD +0 -569
  387. {sphinx-7.2.6.dist-info → sphinx-7.3.1.dist-info}/WHEEL +0 -0
  388. {sphinx-7.2.6.dist-info → sphinx-7.3.1.dist-info}/entry_points.txt +0 -0
sphinx/ext/doctest.py CHANGED
@@ -11,7 +11,7 @@ import sys
11
11
  import time
12
12
  from io import StringIO
13
13
  from os import path
14
- from typing import TYPE_CHECKING, Any, Callable
14
+ from typing import TYPE_CHECKING, Any, Callable, ClassVar
15
15
 
16
16
  from docutils import nodes
17
17
  from docutils.parsers.rst import directives
@@ -22,7 +22,7 @@ import sphinx
22
22
  from sphinx.builders import Builder
23
23
  from sphinx.locale import __
24
24
  from sphinx.util import logging
25
- from sphinx.util.console import bold # type: ignore[attr-defined]
25
+ from sphinx.util.console import bold
26
26
  from sphinx.util.docutils import SphinxDirective
27
27
  from sphinx.util.osutil import relpath
28
28
 
@@ -32,7 +32,7 @@ if TYPE_CHECKING:
32
32
  from docutils.nodes import Element, Node, TextElement
33
33
 
34
34
  from sphinx.application import Sphinx
35
- from sphinx.util.typing import OptionSpec
35
+ from sphinx.util.typing import ExtensionMetadata, OptionSpec
36
36
 
37
37
 
38
38
  logger = logging.getLogger(__name__)
@@ -125,7 +125,7 @@ class TestDirective(SphinxDirective):
125
125
  if self.name == 'doctest' and 'pyversion' in self.options:
126
126
  try:
127
127
  spec = self.options['pyversion']
128
- python_version = '.'.join([str(v) for v in sys.version_info[:3]])
128
+ python_version = '.'.join(map(str, sys.version_info[:3]))
129
129
  if not is_allowed_version(spec, python_version):
130
130
  flag = doctest.OPTIONFLAGS_BY_NAME['SKIP']
131
131
  node['options'][flag] = True # Skip the test
@@ -143,19 +143,19 @@ class TestDirective(SphinxDirective):
143
143
 
144
144
 
145
145
  class TestsetupDirective(TestDirective):
146
- option_spec: OptionSpec = {
146
+ option_spec: ClassVar[OptionSpec] = {
147
147
  'skipif': directives.unchanged_required,
148
148
  }
149
149
 
150
150
 
151
151
  class TestcleanupDirective(TestDirective):
152
- option_spec: OptionSpec = {
152
+ option_spec: ClassVar[OptionSpec] = {
153
153
  'skipif': directives.unchanged_required,
154
154
  }
155
155
 
156
156
 
157
157
  class DoctestDirective(TestDirective):
158
- option_spec: OptionSpec = {
158
+ option_spec: ClassVar[OptionSpec] = {
159
159
  'hide': directives.flag,
160
160
  'no-trim-doctest-flags': directives.flag,
161
161
  'options': directives.unchanged,
@@ -166,7 +166,7 @@ class DoctestDirective(TestDirective):
166
166
 
167
167
 
168
168
  class TestcodeDirective(TestDirective):
169
- option_spec: OptionSpec = {
169
+ option_spec: ClassVar[OptionSpec] = {
170
170
  'hide': directives.flag,
171
171
  'no-trim-doctest-flags': directives.flag,
172
172
  'pyversion': directives.unchanged_required,
@@ -176,7 +176,7 @@ class TestcodeDirective(TestDirective):
176
176
 
177
177
 
178
178
  class TestoutputDirective(TestDirective):
179
- option_spec: OptionSpec = {
179
+ option_spec: ClassVar[OptionSpec] = {
180
180
  'hide': directives.flag,
181
181
  'no-trim-doctest-flags': directives.flag,
182
182
  'options': directives.unchanged,
@@ -276,6 +276,7 @@ class DocTestBuilder(Builder):
276
276
  """
277
277
  Runs test snippets in the documentation.
278
278
  """
279
+
279
280
  name = 'doctest'
280
281
  epilog = __('Testing of doctests in the sources finished, look at the '
281
282
  'results in %(outdir)s/output.txt.')
@@ -310,6 +311,12 @@ class DocTestBuilder(Builder):
310
311
  '==================================%s\n') %
311
312
  (date, '=' * len(date)))
312
313
 
314
+ def __del__(self) -> None:
315
+ # free resources upon destruction (the file handler might not be
316
+ # closed if the builder is never used)
317
+ if hasattr(self, 'outfile'):
318
+ self.outfile.close()
319
+
313
320
  def _out(self, text: str) -> None:
314
321
  logger.info(text, nonl=True)
315
322
  self.outfile.write(text)
@@ -361,16 +368,16 @@ Doctest summary
361
368
 
362
369
  def get_filename_for_node(self, node: Node, docname: str) -> str:
363
370
  """Try to get the file which actually contains the doctest, not the
364
- filename of the document it's included in."""
371
+ filename of the document it's included in.
372
+ """
365
373
  try:
366
- filename = relpath(node.source, self.env.srcdir)\
367
- .rsplit(':docstring of ', maxsplit=1)[0]
374
+ filename = relpath(node.source, self.env.srcdir).rsplit(':docstring of ', maxsplit=1)[0] # type: ignore[arg-type] # noqa: E501
368
375
  except Exception:
369
376
  filename = self.env.doc2path(docname, False)
370
377
  return filename
371
378
 
372
379
  @staticmethod
373
- def get_line_number(node: Node) -> int:
380
+ def get_line_number(node: Node) -> int | None:
374
381
  """Get the real line number or admit we don't know."""
375
382
  # TODO: Work out how to store or calculate real (file-relative)
376
383
  # line numbers for doctest blocks in docstrings.
@@ -379,7 +386,7 @@ Doctest summary
379
386
  # not the file. This is correct where it is set, in
380
387
  # `docutils.nodes.Node.setup_child`, but Sphinx should report
381
388
  # relative to the file, not the docstring.
382
- return None # type: ignore[return-value]
389
+ return None
383
390
  if node.line is not None:
384
391
  # TODO: find the root cause of this off by one error.
385
392
  return node.line - 1
@@ -393,7 +400,7 @@ Doctest summary
393
400
  context: dict[str, Any] = {}
394
401
  if self.config.doctest_global_setup:
395
402
  exec(self.config.doctest_global_setup, context) # NoQA: S102
396
- should_skip = eval(condition, context) # NoQA: PGH001
403
+ should_skip = eval(condition, context) # NoQA: S307
397
404
  if self.config.doctest_global_cleanup:
398
405
  exec(self.config.doctest_global_cleanup, context) # NoQA: S102
399
406
  return should_skip
@@ -420,21 +427,21 @@ Doctest summary
420
427
  def condition(node: Node) -> bool:
421
428
  return isinstance(node, (nodes.literal_block, nodes.comment)) \
422
429
  and 'testnodetype' in node
423
- for node in doctree.findall(condition): # type: Element
424
- if self.skipped(node):
430
+ for node in doctree.findall(condition):
431
+ if self.skipped(node): # type: ignore[arg-type]
425
432
  continue
426
433
 
427
- source = node['test'] if 'test' in node else node.astext()
434
+ source = node['test'] if 'test' in node else node.astext() # type: ignore[index, operator]
428
435
  filename = self.get_filename_for_node(node, docname)
429
436
  line_number = self.get_line_number(node)
430
437
  if not source:
431
438
  logger.warning(__('no code/output in %s block at %s:%s'),
432
- node.get('testnodetype', 'doctest'),
439
+ node.get('testnodetype', 'doctest'), # type: ignore[attr-defined]
433
440
  filename, line_number)
434
- code = TestCode(source, type=node.get('testnodetype', 'doctest'),
435
- filename=filename, lineno=line_number,
436
- options=node.get('options'))
437
- node_groups = node.get('groups', ['default'])
441
+ code = TestCode(source, type=node.get('testnodetype', 'doctest'), # type: ignore[attr-defined]
442
+ filename=filename, lineno=line_number, # type: ignore[arg-type]
443
+ options=node.get('options')) # type: ignore[attr-defined]
444
+ node_groups = node.get('groups', ['default']) # type: ignore[attr-defined]
438
445
  if '*' in node_groups:
439
446
  add_to_all_groups.append(code)
440
447
  continue
@@ -501,9 +508,7 @@ Doctest summary
501
508
  old_f = runner.failures
502
509
  self.type = 'exec' # the snippet may contain multiple statements
503
510
  runner.run(sim_doctest, out=self._warn_out, clear_globs=False)
504
- if runner.failures > old_f:
505
- return False
506
- return True
511
+ return runner.failures <= old_f
507
512
 
508
513
  # run the setup code
509
514
  if not run_setup_cleanup(self.setup_runner, group.setup, 'setup'):
@@ -555,7 +560,7 @@ Doctest summary
555
560
  run_setup_cleanup(self.cleanup_runner, group.cleanup, 'cleanup')
556
561
 
557
562
 
558
- def setup(app: Sphinx) -> dict[str, Any]:
563
+ def setup(app: Sphinx) -> ExtensionMetadata:
559
564
  app.add_directive('testsetup', TestsetupDirective)
560
565
  app.add_directive('testcleanup', TestcleanupDirective)
561
566
  app.add_directive('doctest', DoctestDirective)
@@ -563,13 +568,13 @@ def setup(app: Sphinx) -> dict[str, Any]:
563
568
  app.add_directive('testoutput', TestoutputDirective)
564
569
  app.add_builder(DocTestBuilder)
565
570
  # this config value adds to sys.path
566
- app.add_config_value('doctest_show_successes', True, False, (bool,))
567
- app.add_config_value('doctest_path', [], False)
568
- app.add_config_value('doctest_test_doctest_blocks', 'default', False)
569
- app.add_config_value('doctest_global_setup', '', False)
570
- app.add_config_value('doctest_global_cleanup', '', False)
571
+ app.add_config_value('doctest_show_successes', True, '', bool)
572
+ app.add_config_value('doctest_path', [], '')
573
+ app.add_config_value('doctest_test_doctest_blocks', 'default', '')
574
+ app.add_config_value('doctest_global_setup', '', '')
575
+ app.add_config_value('doctest_global_cleanup', '', '')
571
576
  app.add_config_value(
572
577
  'doctest_default_flags',
573
578
  doctest.DONT_ACCEPT_TRUE_FOR_1 | doctest.ELLIPSIS | doctest.IGNORE_EXCEPTION_DETAIL,
574
- False)
579
+ '')
575
580
  return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
sphinx/ext/duration.py CHANGED
@@ -22,6 +22,7 @@ logger = logging.getLogger(__name__)
22
22
 
23
23
  class DurationDomain(Domain):
24
24
  """A domain for durations of Sphinx processing."""
25
+
25
26
  name = 'duration'
26
27
 
27
28
  @property
sphinx/ext/extlinks.py CHANGED
@@ -37,7 +37,7 @@ if TYPE_CHECKING:
37
37
  from docutils.parsers.rst.states import Inliner
38
38
 
39
39
  from sphinx.application import Sphinx
40
- from sphinx.util.typing import RoleFunction
40
+ from sphinx.util.typing import ExtensionMetadata, RoleFunction
41
41
 
42
42
  logger = logging.getLogger(__name__)
43
43
 
@@ -96,7 +96,8 @@ def make_link_role(name: str, base_url: str, caption: str) -> RoleFunction:
96
96
  # Remark: It is an implementation detail that we use Pythons %-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
- inliner: Inliner, options: dict | None = None, content: Sequence[str] = (),
99
+ inliner: Inliner, options: dict[str, Any] | None = None,
100
+ content: Sequence[str] = (),
100
101
  ) -> tuple[list[Node], list[system_message]]:
101
102
  text = utils.unescape(text)
102
103
  has_explicit_title, title, part = split_explicit_title(text)
@@ -116,7 +117,7 @@ def setup_link_roles(app: Sphinx) -> None:
116
117
  app.add_role(name, make_link_role(name, base_url, caption))
117
118
 
118
119
 
119
- def setup(app: Sphinx) -> dict[str, Any]:
120
+ def setup(app: Sphinx) -> ExtensionMetadata:
120
121
  app.add_config_value('extlinks', {}, 'env')
121
122
  app.add_config_value('extlinks_detect_hardcoded_links', False, 'env')
122
123
 
sphinx/ext/githubpages.py CHANGED
@@ -5,13 +5,14 @@ from __future__ import annotations
5
5
  import contextlib
6
6
  import os
7
7
  import urllib.parse
8
- from typing import TYPE_CHECKING, Any
8
+ from typing import TYPE_CHECKING
9
9
 
10
10
  import sphinx
11
11
 
12
12
  if TYPE_CHECKING:
13
13
  from sphinx.application import Sphinx
14
14
  from sphinx.environment import BuildEnvironment
15
+ from sphinx.util.typing import ExtensionMetadata
15
16
 
16
17
 
17
18
  def _get_domain_from_url(url: str) -> str:
@@ -52,6 +53,6 @@ def create_nojekyll_and_cname(app: Sphinx, env: BuildEnvironment) -> None:
52
53
  os.unlink(cname_path)
53
54
 
54
55
 
55
- def setup(app: Sphinx) -> dict[str, Any]:
56
+ def setup(app: Sphinx) -> ExtensionMetadata:
56
57
  app.connect('env-updated', create_nojekyll_and_cname)
57
58
  return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
sphinx/ext/graphviz.py CHANGED
@@ -11,7 +11,7 @@ from hashlib import sha1
11
11
  from itertools import chain
12
12
  from os import path
13
13
  from subprocess import CalledProcessError
14
- from typing import TYPE_CHECKING, Any
14
+ from typing import TYPE_CHECKING, Any, ClassVar
15
15
  from urllib.parse import urlsplit, urlunsplit
16
16
 
17
17
  from docutils import nodes
@@ -31,7 +31,7 @@ if TYPE_CHECKING:
31
31
 
32
32
  from sphinx.application import Sphinx
33
33
  from sphinx.config import Config
34
- from sphinx.util.typing import OptionSpec
34
+ from sphinx.util.typing import ExtensionMetadata, OptionSpec
35
35
  from sphinx.writers.html import HTML5Translator
36
36
  from sphinx.writers.latex import LaTeXTranslator
37
37
  from sphinx.writers.manpage import ManualPageTranslator
@@ -47,6 +47,7 @@ class GraphvizError(SphinxError):
47
47
 
48
48
  class ClickableMapDefinition:
49
49
  """A manipulator for clickable map file of graphviz."""
50
+
50
51
  maptag_re = re.compile('<map id="(.*?)"')
51
52
  href_re = re.compile('href=".*?"')
52
53
 
@@ -81,7 +82,7 @@ class ClickableMapDefinition:
81
82
  If not exists, this only returns empty string.
82
83
  """
83
84
  if self.clickable:
84
- return '\n'.join([self.content[0]] + self.clickable + [self.content[-1]])
85
+ return '\n'.join((self.content[0], *self.clickable, self.content[-1]))
85
86
  else:
86
87
  return ''
87
88
 
@@ -111,11 +112,12 @@ class Graphviz(SphinxDirective):
111
112
  """
112
113
  Directive to insert arbitrary dot markup.
113
114
  """
115
+
114
116
  has_content = True
115
117
  required_arguments = 0
116
118
  optional_arguments = 1
117
119
  final_argument_whitespace = False
118
- option_spec: OptionSpec = {
120
+ option_spec: ClassVar[OptionSpec] = {
119
121
  'alt': directives.unchanged,
120
122
  'align': align_spec,
121
123
  'caption': directives.unchanged,
@@ -179,11 +181,12 @@ class GraphvizSimple(SphinxDirective):
179
181
  """
180
182
  Directive to insert arbitrary dot markup.
181
183
  """
184
+
182
185
  has_content = True
183
186
  required_arguments = 1
184
187
  optional_arguments = 0
185
188
  final_argument_whitespace = False
186
- option_spec: OptionSpec = {
189
+ option_spec: ClassVar[OptionSpec] = {
187
190
  'alt': directives.unchanged,
188
191
  'align': align_spec,
189
192
  'caption': directives.unchanged,
@@ -330,7 +333,7 @@ def render_dot_html(self: HTML5Translator, node: graphviz, code: str, options: d
330
333
  logger.warning(__('dot code %r: %s'), code, exc)
331
334
  raise nodes.SkipNode from exc
332
335
 
333
- classes = [imgcls, 'graphviz'] + node.get('classes', [])
336
+ classes = [imgcls, 'graphviz', *node.get('classes', [])]
334
337
  imgcls = ' '.join(filter(None, classes))
335
338
 
336
339
  if fname is None:
@@ -449,7 +452,7 @@ def on_config_inited(_app: Sphinx, config: Config) -> None:
449
452
  config.html_static_path.append(css_path)
450
453
 
451
454
 
452
- def setup(app: Sphinx) -> dict[str, Any]:
455
+ def setup(app: Sphinx) -> ExtensionMetadata:
453
456
  app.add_node(graphviz,
454
457
  html=(html_visit_graphviz, None),
455
458
  latex=(latex_visit_graphviz, None),
sphinx/ext/ifconfig.py CHANGED
@@ -16,7 +16,7 @@ namespace of the project configuration (that is, all variables from
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- from typing import TYPE_CHECKING, Any
19
+ from typing import TYPE_CHECKING, ClassVar
20
20
 
21
21
  from docutils import nodes
22
22
 
@@ -28,7 +28,7 @@ if TYPE_CHECKING:
28
28
  from docutils.nodes import Node
29
29
 
30
30
  from sphinx.application import Sphinx
31
- from sphinx.util.typing import OptionSpec
31
+ from sphinx.util.typing import ExtensionMetadata, OptionSpec
32
32
 
33
33
 
34
34
  class ifconfig(nodes.Element):
@@ -41,7 +41,7 @@ class IfConfig(SphinxDirective):
41
41
  required_arguments = 1
42
42
  optional_arguments = 0
43
43
  final_argument_whitespace = True
44
- option_spec: OptionSpec = {}
44
+ option_spec: ClassVar[OptionSpec] = {}
45
45
 
46
46
  def run(self) -> list[Node]:
47
47
  node = ifconfig()
@@ -58,7 +58,7 @@ def process_ifconfig_nodes(app: Sphinx, doctree: nodes.document, docname: str) -
58
58
  ns['builder'] = app.builder.name
59
59
  for node in list(doctree.findall(ifconfig)):
60
60
  try:
61
- res = eval(node['expr'], ns) # NoQA: PGH001
61
+ res = eval(node['expr'], ns) # NoQA: S307
62
62
  except Exception as err:
63
63
  # handle exceptions in a clean fashion
64
64
  from traceback import format_exception_only
@@ -74,7 +74,7 @@ def process_ifconfig_nodes(app: Sphinx, doctree: nodes.document, docname: str) -
74
74
  node.replace_self(node.children)
75
75
 
76
76
 
77
- def setup(app: Sphinx) -> dict[str, Any]:
77
+ def setup(app: Sphinx) -> ExtensionMetadata:
78
78
  app.add_node(ifconfig)
79
79
  app.add_directive('ifconfig', IfConfig)
80
80
  app.connect('doctree-resolved', process_ifconfig_nodes)
@@ -5,7 +5,7 @@ from __future__ import annotations
5
5
  import subprocess
6
6
  import sys
7
7
  from subprocess import CalledProcessError
8
- from typing import TYPE_CHECKING, Any
8
+ from typing import TYPE_CHECKING
9
9
 
10
10
  import sphinx
11
11
  from sphinx.errors import ExtensionError
@@ -15,6 +15,7 @@ from sphinx.util import logging
15
15
 
16
16
  if TYPE_CHECKING:
17
17
  from sphinx.application import Sphinx
18
+ from sphinx.util.typing import ExtensionMetadata
18
19
 
19
20
  logger = logging.getLogger(__name__)
20
21
 
@@ -56,9 +57,9 @@ class ImagemagickConverter(ImageConverter):
56
57
  # (or first page) of image (ex. Animation GIF, PDF)
57
58
  _from += '[0]'
58
59
 
59
- args = ([self.config.image_converter] +
60
- self.config.image_converter_args +
61
- [_from, _to])
60
+ args = ([
61
+ self.config.image_converter, *self.config.image_converter_args, _from, _to,
62
+ ])
62
63
  logger.debug('Invoking %r ...', args)
63
64
  subprocess.run(args, capture_output=True, check=True)
64
65
  return True
@@ -73,7 +74,7 @@ class ImagemagickConverter(ImageConverter):
73
74
  (exc.stderr, exc.stdout)) from exc
74
75
 
75
76
 
76
- def setup(app: Sphinx) -> dict[str, Any]:
77
+ def setup(app: Sphinx) -> ExtensionMetadata:
77
78
  app.add_post_transform(ImagemagickConverter)
78
79
  if sys.platform == 'win32':
79
80
  # On Windows, we use Imagemagik v7 by default to avoid the trouble for
sphinx/ext/imgmath.py CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ __all__ = ()
6
+
5
7
  import base64
6
8
  import contextlib
7
9
  import re
@@ -11,7 +13,7 @@ import tempfile
11
13
  from hashlib import sha1
12
14
  from os import path
13
15
  from subprocess import CalledProcessError
14
- from typing import TYPE_CHECKING, Any
16
+ from typing import TYPE_CHECKING
15
17
 
16
18
  from docutils import nodes
17
19
 
@@ -33,14 +35,13 @@ if TYPE_CHECKING:
33
35
  from sphinx.application import Sphinx
34
36
  from sphinx.builders import Builder
35
37
  from sphinx.config import Config
38
+ from sphinx.util.typing import ExtensionMetadata
36
39
  from sphinx.writers.html import HTML5Translator
37
40
 
38
41
  logger = logging.getLogger(__name__)
39
42
 
40
43
  templates_path = path.join(package_dir, 'templates', 'imgmath')
41
44
 
42
- __all__ = ()
43
-
44
45
 
45
46
  class MathExtError(SphinxError):
46
47
  category = 'Math extension error'
@@ -70,7 +71,7 @@ def read_svg_depth(filename: str) -> int | None:
70
71
  """Read the depth from comment at last line of SVG file
71
72
  """
72
73
  with open(filename, encoding="utf-8") as f:
73
- for line in f: # noqa: B007
74
+ for line in f: # NoQA: B007
74
75
  pass
75
76
  # Only last line is checked
76
77
  matched = depthsvgcomment_re.match(line)
@@ -140,7 +141,7 @@ def compile_math(latex: str, builder: Builder) -> str:
140
141
  # --output-directory option, so we have to manually chdir to the
141
142
  # temp dir to run it.
142
143
  command = [builder.config.imgmath_latex]
143
- if imgmath_latex_name not in ['tectonic']:
144
+ if imgmath_latex_name != 'tectonic':
144
145
  command.append('--interaction=nonstopmode')
145
146
  # add custom args from the config file
146
147
  command.extend(builder.config.imgmath_latex_args)
@@ -149,7 +150,7 @@ def compile_math(latex: str, builder: Builder) -> str:
149
150
  try:
150
151
  subprocess.run(command, capture_output=True, cwd=tempdir, check=True,
151
152
  encoding='ascii')
152
- if imgmath_latex_name in ['xelatex', 'tectonic']:
153
+ if imgmath_latex_name in {'xelatex', 'tectonic'}:
153
154
  return path.join(tempdir, 'math.xdv')
154
155
  else:
155
156
  return path.join(tempdir, 'math.dvi')
@@ -384,7 +385,7 @@ def html_visit_displaymath(self: HTML5Translator, node: nodes.math_block) -> Non
384
385
  raise nodes.SkipNode
385
386
 
386
387
 
387
- def setup(app: Sphinx) -> dict[str, Any]:
388
+ def setup(app: Sphinx) -> ExtensionMetadata:
388
389
  app.add_html_math_renderer('imgmath',
389
390
  (html_visit_math, None),
390
391
  (html_visit_displaymath, None))
@@ -402,6 +403,6 @@ def setup(app: Sphinx) -> dict[str, Any]:
402
403
  app.add_config_value('imgmath_latex_preamble', '', 'html')
403
404
  app.add_config_value('imgmath_add_tooltips', True, 'html')
404
405
  app.add_config_value('imgmath_font_size', 12, 'html')
405
- app.add_config_value('imgmath_embed', False, 'html', [bool])
406
+ app.add_config_value('imgmath_embed', False, 'html', bool)
406
407
  app.connect('build-finished', clean_up_files)
407
408
  return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
@@ -37,7 +37,7 @@ import re
37
37
  from collections.abc import Iterable, Sequence
38
38
  from importlib import import_module
39
39
  from os import path
40
- from typing import TYPE_CHECKING, Any, cast
40
+ from typing import TYPE_CHECKING, Any, ClassVar, cast
41
41
 
42
42
  from docutils import nodes
43
43
  from docutils.parsers.rst import directives
@@ -58,7 +58,7 @@ if TYPE_CHECKING:
58
58
 
59
59
  from sphinx.application import Sphinx
60
60
  from sphinx.environment import BuildEnvironment
61
- from sphinx.util.typing import OptionSpec
61
+ from sphinx.util.typing import ExtensionMetadata, OptionSpec
62
62
  from sphinx.writers.html import HTML5Translator
63
63
  from sphinx.writers.latex import LaTeXTranslator
64
64
  from sphinx.writers.texinfo import TexinfoTranslator
@@ -123,11 +123,8 @@ def import_classes(name: str, currmodule: str) -> Any:
123
123
  return [target]
124
124
  elif inspect.ismodule(target):
125
125
  # If imported object is a module, return classes defined on it
126
- classes = []
127
- for cls in target.__dict__.values():
128
- if inspect.isclass(cls) and cls.__module__ == target.__name__:
129
- classes.append(cls)
130
- return classes
126
+ return [cls for cls in target.__dict__.values()
127
+ if inspect.isclass(cls) and cls.__module__ == target.__name__]
131
128
  raise InheritanceException('%r specified for inheritance diagram is '
132
129
  'not a class or module' % name)
133
130
 
@@ -142,6 +139,7 @@ class InheritanceGraph:
142
139
  from all the way to the root "object", and then is able to generate a
143
140
  graphviz dot graph from them.
144
141
  """
142
+
145
143
  def __init__(self, class_names: list[str], currmodule: str, show_builtins: bool = False,
146
144
  private_bases: bool = False, parts: int = 0,
147
145
  aliases: dict[str, str] | None = None, top_classes: Sequence[Any] = (),
@@ -272,10 +270,10 @@ class InheritanceGraph:
272
270
  }
273
271
 
274
272
  def _format_node_attrs(self, attrs: dict[str, Any]) -> str:
275
- return ','.join(['%s=%s' % x for x in sorted(attrs.items())])
273
+ return ','.join(f'{k}={v}' for k, v in sorted(attrs.items()))
276
274
 
277
275
  def _format_graph_attrs(self, attrs: dict[str, Any]) -> str:
278
- return ''.join(['%s=%s;\n' % x for x in sorted(attrs.items())])
276
+ return ''.join(f'{k}={v};\n' for k, v in sorted(attrs.items()))
279
277
 
280
278
  def generate_dot(self, name: str, urls: dict[str, str] | None = None,
281
279
  env: BuildEnvironment | None = None,
@@ -309,34 +307,35 @@ class InheritanceGraph:
309
307
  n_attrs.update(env.config.inheritance_node_attrs)
310
308
  e_attrs.update(env.config.inheritance_edge_attrs)
311
309
 
312
- res: list[str] = []
313
- res.append('digraph %s {\n' % name)
314
- res.append(self._format_graph_attrs(g_attrs))
310
+ res: list[str] = [
311
+ f'digraph {name} {{\n',
312
+ self._format_graph_attrs(g_attrs),
313
+ ]
315
314
 
316
315
  for name, fullname, bases, tooltip in sorted(self.class_info):
317
316
  # Write the node
318
317
  this_node_attrs = n_attrs.copy()
319
318
  if fullname in urls:
320
- this_node_attrs['URL'] = '"%s"' % urls[fullname]
321
- this_node_attrs['target'] = '"_top"'
319
+ this_node_attrs["URL"] = '"%s"' % urls[fullname]
320
+ this_node_attrs["target"] = '"_top"'
322
321
  if tooltip:
323
- this_node_attrs['tooltip'] = tooltip
324
- res.append(' "%s" [%s];\n' %
325
- (name, self._format_node_attrs(this_node_attrs)))
322
+ this_node_attrs["tooltip"] = tooltip
323
+ res.append(' "%s" [%s];\n' % (name, self._format_node_attrs(this_node_attrs)))
326
324
 
327
325
  # Write the edges
328
- for base_name in bases:
329
- res.append(' "%s" -> "%s" [%s];\n' %
330
- (base_name, name,
331
- self._format_node_attrs(e_attrs)))
332
- res.append('}\n')
333
- return ''.join(res)
326
+ res.extend(
327
+ ' "%s" -> "%s" [%s];\n' % (base_name, name, self._format_node_attrs(e_attrs))
328
+ for base_name in bases
329
+ )
330
+ res.append("}\n")
331
+ return "".join(res)
334
332
 
335
333
 
336
334
  class inheritance_diagram(graphviz):
337
335
  """
338
336
  A docutils node to use as a placeholder for the inheritance diagram.
339
337
  """
338
+
340
339
  pass
341
340
 
342
341
 
@@ -344,11 +343,12 @@ class InheritanceDiagram(SphinxDirective):
344
343
  """
345
344
  Run when the inheritance_diagram directive is first encountered.
346
345
  """
346
+
347
347
  has_content = False
348
348
  required_arguments = 1
349
349
  optional_arguments = 0
350
350
  final_argument_whitespace = True
351
- option_spec: OptionSpec = {
351
+ option_spec: ClassVar[OptionSpec] = {
352
352
  'parts': int,
353
353
  'private-bases': directives.flag,
354
354
  'caption': directives.unchanged,
@@ -378,7 +378,7 @@ 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)]
381
+ return [node.document.reporter.warning(err, line=self.lineno)] # type: ignore[union-attr]
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
@@ -386,7 +386,7 @@ class InheritanceDiagram(SphinxDirective):
386
386
  # removed from the doctree after we're done with them.
387
387
  for name in graph.get_all_class_names():
388
388
  refnodes, x = class_role( # type: ignore[call-arg,misc]
389
- 'class', ':class:`%s`' % name, name, 0, self.state) # type: ignore[arg-type]
389
+ 'class', ':class:`%s`' % name, name, 0, self.state)
390
390
  node.extend(refnodes)
391
391
  # Store the graph object so we can use it to generate the
392
392
  # dot file later
@@ -477,7 +477,7 @@ def skip(self: nodes.NodeVisitor, node: inheritance_diagram) -> None:
477
477
  raise nodes.SkipNode
478
478
 
479
479
 
480
- def setup(app: Sphinx) -> dict[str, Any]:
480
+ def setup(app: Sphinx) -> ExtensionMetadata:
481
481
  app.setup_extension('sphinx.ext.graphviz')
482
482
  app.add_node(
483
483
  inheritance_diagram,
@@ -487,8 +487,8 @@ def setup(app: Sphinx) -> dict[str, Any]:
487
487
  man=(skip, None),
488
488
  texinfo=(texinfo_visit_inheritance_diagram, None))
489
489
  app.add_directive('inheritance-diagram', InheritanceDiagram)
490
- app.add_config_value('inheritance_graph_attrs', {}, False)
491
- app.add_config_value('inheritance_node_attrs', {}, False)
492
- app.add_config_value('inheritance_edge_attrs', {}, False)
493
- app.add_config_value('inheritance_alias', {}, False)
490
+ app.add_config_value('inheritance_graph_attrs', {}, '')
491
+ app.add_config_value('inheritance_node_attrs', {}, '')
492
+ app.add_config_value('inheritance_edge_attrs', {}, '')
493
+ app.add_config_value('inheritance_alias', {}, '')
494
494
  return {'version': sphinx.__display_version__, 'parallel_read_safe': True}