Sphinx 8.1.2__py3-none-any.whl → 8.2.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 (328) hide show
  1. sphinx/__init__.py +8 -4
  2. sphinx/__main__.py +2 -0
  3. sphinx/_cli/__init__.py +2 -5
  4. sphinx/_cli/util/colour.py +34 -11
  5. sphinx/_cli/util/errors.py +128 -61
  6. sphinx/addnodes.py +51 -35
  7. sphinx/application.py +362 -230
  8. sphinx/builders/__init__.py +87 -64
  9. sphinx/builders/_epub_base.py +65 -56
  10. sphinx/builders/changes.py +17 -23
  11. sphinx/builders/dirhtml.py +8 -13
  12. sphinx/builders/epub3.py +70 -38
  13. sphinx/builders/gettext.py +93 -73
  14. sphinx/builders/html/__init__.py +240 -186
  15. sphinx/builders/html/_assets.py +9 -2
  16. sphinx/builders/html/_build_info.py +3 -0
  17. sphinx/builders/latex/__init__.py +64 -54
  18. sphinx/builders/latex/constants.py +14 -11
  19. sphinx/builders/latex/nodes.py +2 -0
  20. sphinx/builders/latex/theming.py +8 -9
  21. sphinx/builders/latex/transforms.py +7 -5
  22. sphinx/builders/linkcheck.py +193 -149
  23. sphinx/builders/manpage.py +17 -17
  24. sphinx/builders/singlehtml.py +28 -16
  25. sphinx/builders/texinfo.py +28 -21
  26. sphinx/builders/text.py +10 -15
  27. sphinx/builders/xml.py +10 -19
  28. sphinx/cmd/build.py +49 -119
  29. sphinx/cmd/make_mode.py +35 -31
  30. sphinx/cmd/quickstart.py +78 -62
  31. sphinx/config.py +265 -163
  32. sphinx/directives/__init__.py +51 -54
  33. sphinx/directives/admonitions.py +107 -0
  34. sphinx/directives/code.py +24 -19
  35. sphinx/directives/other.py +21 -42
  36. sphinx/directives/patches.py +28 -16
  37. sphinx/domains/__init__.py +54 -31
  38. sphinx/domains/_domains_container.py +22 -17
  39. sphinx/domains/_index.py +5 -8
  40. sphinx/domains/c/__init__.py +366 -245
  41. sphinx/domains/c/_ast.py +378 -256
  42. sphinx/domains/c/_ids.py +89 -31
  43. sphinx/domains/c/_parser.py +283 -214
  44. sphinx/domains/c/_symbol.py +269 -198
  45. sphinx/domains/changeset.py +39 -24
  46. sphinx/domains/citation.py +54 -24
  47. sphinx/domains/cpp/__init__.py +517 -362
  48. sphinx/domains/cpp/_ast.py +999 -682
  49. sphinx/domains/cpp/_ids.py +133 -65
  50. sphinx/domains/cpp/_parser.py +746 -588
  51. sphinx/domains/cpp/_symbol.py +692 -489
  52. sphinx/domains/index.py +10 -8
  53. sphinx/domains/javascript.py +152 -74
  54. sphinx/domains/math.py +50 -40
  55. sphinx/domains/python/__init__.py +402 -211
  56. sphinx/domains/python/_annotations.py +134 -61
  57. sphinx/domains/python/_object.py +155 -68
  58. sphinx/domains/rst.py +94 -49
  59. sphinx/domains/std/__init__.py +510 -249
  60. sphinx/environment/__init__.py +345 -61
  61. sphinx/environment/adapters/asset.py +7 -1
  62. sphinx/environment/adapters/indexentries.py +15 -20
  63. sphinx/environment/adapters/toctree.py +19 -9
  64. sphinx/environment/collectors/__init__.py +3 -1
  65. sphinx/environment/collectors/asset.py +18 -15
  66. sphinx/environment/collectors/dependencies.py +8 -10
  67. sphinx/environment/collectors/metadata.py +6 -4
  68. sphinx/environment/collectors/title.py +3 -1
  69. sphinx/environment/collectors/toctree.py +4 -4
  70. sphinx/errors.py +1 -3
  71. sphinx/events.py +4 -4
  72. sphinx/ext/apidoc/__init__.py +66 -0
  73. sphinx/ext/apidoc/__main__.py +9 -0
  74. sphinx/ext/apidoc/_cli.py +356 -0
  75. sphinx/ext/apidoc/_extension.py +262 -0
  76. sphinx/ext/apidoc/_generate.py +356 -0
  77. sphinx/ext/apidoc/_shared.py +99 -0
  78. sphinx/ext/autodoc/__init__.py +837 -483
  79. sphinx/ext/autodoc/directive.py +57 -21
  80. sphinx/ext/autodoc/importer.py +184 -67
  81. sphinx/ext/autodoc/mock.py +25 -10
  82. sphinx/ext/autodoc/preserve_defaults.py +17 -9
  83. sphinx/ext/autodoc/type_comment.py +56 -29
  84. sphinx/ext/autodoc/typehints.py +49 -26
  85. sphinx/ext/autosectionlabel.py +28 -11
  86. sphinx/ext/autosummary/__init__.py +281 -142
  87. sphinx/ext/autosummary/generate.py +121 -51
  88. sphinx/ext/coverage.py +152 -91
  89. sphinx/ext/doctest.py +169 -101
  90. sphinx/ext/duration.py +12 -6
  91. sphinx/ext/extlinks.py +33 -21
  92. sphinx/ext/githubpages.py +8 -8
  93. sphinx/ext/graphviz.py +175 -109
  94. sphinx/ext/ifconfig.py +11 -6
  95. sphinx/ext/imgconverter.py +48 -25
  96. sphinx/ext/imgmath.py +127 -97
  97. sphinx/ext/inheritance_diagram.py +177 -103
  98. sphinx/ext/intersphinx/__init__.py +22 -13
  99. sphinx/ext/intersphinx/__main__.py +3 -1
  100. sphinx/ext/intersphinx/_cli.py +18 -14
  101. sphinx/ext/intersphinx/_load.py +91 -82
  102. sphinx/ext/intersphinx/_resolve.py +108 -74
  103. sphinx/ext/intersphinx/_shared.py +2 -2
  104. sphinx/ext/linkcode.py +28 -12
  105. sphinx/ext/mathjax.py +60 -29
  106. sphinx/ext/napoleon/__init__.py +19 -7
  107. sphinx/ext/napoleon/docstring.py +229 -231
  108. sphinx/ext/todo.py +44 -49
  109. sphinx/ext/viewcode.py +105 -57
  110. sphinx/extension.py +3 -1
  111. sphinx/highlighting.py +13 -7
  112. sphinx/io.py +9 -13
  113. sphinx/jinja2glue.py +29 -26
  114. sphinx/locale/__init__.py +8 -9
  115. sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
  116. sphinx/locale/ar/LC_MESSAGES/sphinx.po +2155 -2050
  117. sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
  118. sphinx/locale/bg/LC_MESSAGES/sphinx.po +2045 -1940
  119. sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
  120. sphinx/locale/bn/LC_MESSAGES/sphinx.po +2175 -2070
  121. sphinx/locale/ca/LC_MESSAGES/sphinx.js +3 -3
  122. sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
  123. sphinx/locale/ca/LC_MESSAGES/sphinx.po +2690 -2585
  124. sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.js +63 -0
  125. sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.mo +0 -0
  126. sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.po +4216 -0
  127. sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
  128. sphinx/locale/cak/LC_MESSAGES/sphinx.po +2096 -1991
  129. sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
  130. sphinx/locale/cs/LC_MESSAGES/sphinx.po +2248 -2143
  131. sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
  132. sphinx/locale/cy/LC_MESSAGES/sphinx.po +2201 -2096
  133. sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
  134. sphinx/locale/da/LC_MESSAGES/sphinx.po +2282 -2177
  135. sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
  136. sphinx/locale/de/LC_MESSAGES/sphinx.po +2261 -2156
  137. sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
  138. sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2045 -1940
  139. sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
  140. sphinx/locale/el/LC_MESSAGES/sphinx.po +2604 -2499
  141. sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
  142. sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2045 -1940
  143. sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
  144. sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2045 -1940
  145. sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
  146. sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2631 -2526
  147. sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
  148. sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2045 -1940
  149. sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
  150. sphinx/locale/eo/LC_MESSAGES/sphinx.po +2078 -1973
  151. sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
  152. sphinx/locale/es/LC_MESSAGES/sphinx.po +2633 -2528
  153. sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
  154. sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2045 -1940
  155. sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
  156. sphinx/locale/et/LC_MESSAGES/sphinx.po +2449 -2344
  157. sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
  158. sphinx/locale/eu/LC_MESSAGES/sphinx.po +2241 -2136
  159. sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
  160. sphinx/locale/fa/LC_MESSAGES/sphinx.po +504 -500
  161. sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
  162. sphinx/locale/fi/LC_MESSAGES/sphinx.po +499 -495
  163. sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
  164. sphinx/locale/fr/LC_MESSAGES/sphinx.po +513 -509
  165. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
  166. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +499 -495
  167. sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
  168. sphinx/locale/gl/LC_MESSAGES/sphinx.po +2644 -2539
  169. sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
  170. sphinx/locale/he/LC_MESSAGES/sphinx.po +499 -495
  171. sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
  172. sphinx/locale/hi/LC_MESSAGES/sphinx.po +504 -500
  173. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
  174. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +499 -495
  175. sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
  176. sphinx/locale/hr/LC_MESSAGES/sphinx.po +501 -497
  177. sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
  178. sphinx/locale/hu/LC_MESSAGES/sphinx.po +499 -495
  179. sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
  180. sphinx/locale/id/LC_MESSAGES/sphinx.po +2609 -2504
  181. sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
  182. sphinx/locale/is/LC_MESSAGES/sphinx.po +499 -495
  183. sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
  184. sphinx/locale/it/LC_MESSAGES/sphinx.po +2265 -2160
  185. sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
  186. sphinx/locale/ja/LC_MESSAGES/sphinx.po +2621 -2516
  187. sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
  188. sphinx/locale/ka/LC_MESSAGES/sphinx.po +2567 -2462
  189. sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
  190. sphinx/locale/ko/LC_MESSAGES/sphinx.po +2631 -2526
  191. sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
  192. sphinx/locale/lt/LC_MESSAGES/sphinx.po +2214 -2109
  193. sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
  194. sphinx/locale/lv/LC_MESSAGES/sphinx.po +2218 -2113
  195. sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
  196. sphinx/locale/mk/LC_MESSAGES/sphinx.po +2088 -1983
  197. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
  198. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2247 -2142
  199. sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
  200. sphinx/locale/ne/LC_MESSAGES/sphinx.po +2227 -2122
  201. sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
  202. sphinx/locale/nl/LC_MESSAGES/sphinx.po +2316 -2211
  203. sphinx/locale/pl/LC_MESSAGES/sphinx.js +2 -2
  204. sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
  205. sphinx/locale/pl/LC_MESSAGES/sphinx.po +2442 -2336
  206. sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
  207. sphinx/locale/pt/LC_MESSAGES/sphinx.po +2045 -1940
  208. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
  209. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2657 -2552
  210. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
  211. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2243 -2138
  212. sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
  213. sphinx/locale/ro/LC_MESSAGES/sphinx.po +2244 -2139
  214. sphinx/locale/ru/LC_MESSAGES/sphinx.js +1 -1
  215. sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
  216. sphinx/locale/ru/LC_MESSAGES/sphinx.po +2660 -2555
  217. sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
  218. sphinx/locale/si/LC_MESSAGES/sphinx.po +2134 -2029
  219. sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
  220. sphinx/locale/sk/LC_MESSAGES/sphinx.po +2614 -2509
  221. sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
  222. sphinx/locale/sl/LC_MESSAGES/sphinx.po +2167 -2062
  223. sphinx/locale/sphinx.pot +2069 -1964
  224. sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
  225. sphinx/locale/sq/LC_MESSAGES/sphinx.po +2661 -2556
  226. sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
  227. sphinx/locale/sr/LC_MESSAGES/sphinx.po +2213 -2108
  228. sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
  229. sphinx/locale/sv/LC_MESSAGES/sphinx.po +2229 -2124
  230. sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
  231. sphinx/locale/te/LC_MESSAGES/sphinx.po +2045 -1940
  232. sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
  233. sphinx/locale/tr/LC_MESSAGES/sphinx.po +2608 -2503
  234. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
  235. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2167 -2062
  236. sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
  237. sphinx/locale/ur/LC_MESSAGES/sphinx.po +2045 -1940
  238. sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
  239. sphinx/locale/vi/LC_MESSAGES/sphinx.po +2204 -2099
  240. sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
  241. sphinx/locale/yue/LC_MESSAGES/sphinx.po +2045 -1940
  242. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
  243. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2045 -1940
  244. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
  245. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +2659 -2554
  246. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
  247. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2045 -1940
  248. sphinx/parsers.py +8 -7
  249. sphinx/project.py +2 -2
  250. sphinx/pycode/__init__.py +31 -21
  251. sphinx/pycode/ast.py +6 -3
  252. sphinx/pycode/parser.py +14 -8
  253. sphinx/pygments_styles.py +4 -5
  254. sphinx/registry.py +192 -92
  255. sphinx/roles.py +58 -7
  256. sphinx/search/__init__.py +75 -54
  257. sphinx/search/en.py +11 -13
  258. sphinx/search/fi.py +1 -1
  259. sphinx/search/ja.py +8 -6
  260. sphinx/search/nl.py +1 -1
  261. sphinx/search/zh.py +19 -21
  262. sphinx/testing/fixtures.py +26 -29
  263. sphinx/testing/path.py +26 -62
  264. sphinx/testing/restructuredtext.py +14 -8
  265. sphinx/testing/util.py +21 -19
  266. sphinx/texinputs/make.bat.jinja +50 -50
  267. sphinx/texinputs/sphinx.sty +4 -3
  268. sphinx/texinputs/sphinxlatexadmonitions.sty +1 -1
  269. sphinx/texinputs/sphinxlatexobjects.sty +29 -10
  270. sphinx/themes/basic/static/searchtools.js +8 -5
  271. sphinx/theming.py +49 -61
  272. sphinx/transforms/__init__.py +17 -38
  273. sphinx/transforms/compact_bullet_list.py +5 -3
  274. sphinx/transforms/i18n.py +8 -21
  275. sphinx/transforms/post_transforms/__init__.py +142 -93
  276. sphinx/transforms/post_transforms/code.py +5 -5
  277. sphinx/transforms/post_transforms/images.py +28 -24
  278. sphinx/transforms/references.py +3 -1
  279. sphinx/util/__init__.py +109 -60
  280. sphinx/util/_files.py +39 -23
  281. sphinx/util/_importer.py +4 -1
  282. sphinx/util/_inventory_file_reader.py +76 -0
  283. sphinx/util/_io.py +2 -2
  284. sphinx/util/_lines.py +6 -3
  285. sphinx/util/_pathlib.py +40 -2
  286. sphinx/util/build_phase.py +2 -0
  287. sphinx/util/cfamily.py +19 -14
  288. sphinx/util/console.py +44 -179
  289. sphinx/util/display.py +9 -10
  290. sphinx/util/docfields.py +140 -122
  291. sphinx/util/docstrings.py +1 -1
  292. sphinx/util/docutils.py +118 -77
  293. sphinx/util/fileutil.py +25 -26
  294. sphinx/util/http_date.py +2 -0
  295. sphinx/util/i18n.py +77 -64
  296. sphinx/util/images.py +8 -6
  297. sphinx/util/inspect.py +147 -38
  298. sphinx/util/inventory.py +215 -116
  299. sphinx/util/logging.py +33 -33
  300. sphinx/util/matching.py +12 -4
  301. sphinx/util/nodes.py +18 -13
  302. sphinx/util/osutil.py +38 -39
  303. sphinx/util/parallel.py +22 -13
  304. sphinx/util/parsing.py +2 -1
  305. sphinx/util/png.py +6 -2
  306. sphinx/util/requests.py +33 -2
  307. sphinx/util/rst.py +3 -2
  308. sphinx/util/tags.py +1 -1
  309. sphinx/util/template.py +18 -10
  310. sphinx/util/texescape.py +8 -6
  311. sphinx/util/typing.py +148 -122
  312. sphinx/versioning.py +3 -3
  313. sphinx/writers/html.py +3 -1
  314. sphinx/writers/html5.py +63 -52
  315. sphinx/writers/latex.py +83 -67
  316. sphinx/writers/manpage.py +19 -38
  317. sphinx/writers/texinfo.py +47 -47
  318. sphinx/writers/text.py +50 -32
  319. sphinx/writers/xml.py +11 -8
  320. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/LICENSE.rst +1 -1
  321. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/METADATA +25 -15
  322. sphinx-8.2.0.dist-info/RECORD +606 -0
  323. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/WHEEL +1 -1
  324. sphinx/builders/html/transforms.py +0 -90
  325. sphinx/ext/apidoc.py +0 -721
  326. sphinx/util/exceptions.py +0 -74
  327. sphinx-8.1.2.dist-info/RECORD +0 -598
  328. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/entry_points.txt +0 -0
@@ -31,21 +31,18 @@ if TYPE_CHECKING:
31
31
  _IndexEntryCategoryKey,
32
32
  ]
33
33
  _IndexEntryMap: TypeAlias = dict[str, _IndexEntry]
34
- _Index: TypeAlias = list[
34
+
35
+ # Used by ``create_index()`` for 'the real index'
36
+ _RealIndexEntry: TypeAlias = tuple[
37
+ str,
35
38
  tuple[
36
- str,
37
- list[
38
- tuple[
39
- str,
40
- tuple[
41
- _IndexEntryTargets,
42
- list[tuple[str, _IndexEntryTargets]],
43
- _IndexEntryCategoryKey,
44
- ],
45
- ]
46
- ],
47
- ]
39
+ _IndexEntryTargets,
40
+ list[tuple[str, _IndexEntryTargets]],
41
+ _IndexEntryCategoryKey,
42
+ ],
48
43
  ]
44
+ _RealIndexEntries: TypeAlias = list[_RealIndexEntry]
45
+ _Index: TypeAlias = list[tuple[str, _RealIndexEntries]]
49
46
 
50
47
  logger = logging.getLogger(__name__)
51
48
 
@@ -144,9 +141,10 @@ class IndexEntries:
144
141
  __('unknown index entry type %r'),
145
142
  entry_type,
146
143
  location=docname,
144
+ type='index',
147
145
  )
148
146
  except ValueError as err:
149
- logger.warning(str(err), location=docname)
147
+ logger.warning(str(err), location=docname, type='index')
150
148
 
151
149
  for targets, sub_items, _category_key in new.values():
152
150
  targets.sort(key=_key_func_0)
@@ -231,8 +229,7 @@ def _key_func_1(entry: tuple[str, _IndexEntry]) -> tuple[tuple[int, str], str]:
231
229
  # using the specified category key to sort
232
230
  key = category_key
233
231
  lc_key = unicodedata.normalize('NFD', key.lower())
234
- if lc_key.startswith('\N{RIGHT-TO-LEFT MARK}'):
235
- lc_key = lc_key[1:]
232
+ lc_key = lc_key.removeprefix('\N{RIGHT-TO-LEFT MARK}')
236
233
 
237
234
  if not lc_key[0:1].isalpha() and not lc_key.startswith('_'):
238
235
  # put symbols at the front of the index (0)
@@ -248,8 +245,7 @@ def _key_func_1(entry: tuple[str, _IndexEntry]) -> tuple[tuple[int, str], str]:
248
245
  def _key_func_2(entry: tuple[str, _IndexEntryTargets]) -> str:
249
246
  """Sort the sub-index entries"""
250
247
  key = unicodedata.normalize('NFD', entry[0].lower())
251
- if key.startswith('\N{RIGHT-TO-LEFT MARK}'):
252
- key = key[1:]
248
+ key = key.removeprefix('\N{RIGHT-TO-LEFT MARK}')
253
249
  if key[0:1].isalpha() or key.startswith('_'):
254
250
  key = chr(127) + key
255
251
  return key
@@ -263,8 +259,7 @@ def _group_by_func(entry: tuple[str, _IndexEntry]) -> str:
263
259
  return category_key
264
260
 
265
261
  # now calculate the key
266
- if key.startswith('\N{RIGHT-TO-LEFT MARK}'):
267
- key = key[1:]
262
+ key = key.removeprefix('\N{RIGHT-TO-LEFT MARK}')
268
263
  letter = unicodedata.normalize('NFD', key[0])[0].upper()
269
264
  if letter.isalpha() or letter == '_':
270
265
  return letter
@@ -2,10 +2,10 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Any, TypeVar
5
+ from typing import TYPE_CHECKING, TypeVar
6
6
 
7
7
  from docutils import nodes
8
- from docutils.nodes import Element, Node
8
+ from docutils.nodes import Element
9
9
 
10
10
  from sphinx import addnodes
11
11
  from sphinx.locale import __
@@ -15,6 +15,9 @@ from sphinx.util.nodes import _only_node_keep_children, clean_astext
15
15
 
16
16
  if TYPE_CHECKING:
17
17
  from collections.abc import Iterable, Set
18
+ from typing import Any
19
+
20
+ from docutils.nodes import Node
18
21
 
19
22
  from sphinx.builders import Builder
20
23
  from sphinx.environment import BuildEnvironment
@@ -86,6 +89,7 @@ def global_toctree_for_doc(
86
89
  titles_only=titles_only,
87
90
  collapse=collapse,
88
91
  includehidden=includehidden,
92
+ tags=builder.tags,
89
93
  )
90
94
  for toctree_node in env.master_doctree.findall(addnodes.toctree)
91
95
  )
@@ -110,6 +114,7 @@ def _resolve_toctree(
110
114
  titles_only: bool = False,
111
115
  collapse: bool = False,
112
116
  includehidden: bool = False,
117
+ tags: Tags,
113
118
  ) -> Element | None:
114
119
  """Resolve a *toctree* node into individual bullet lists with titles
115
120
  as items, returning None (if no containing titles are found) or
@@ -141,7 +146,8 @@ def _resolve_toctree(
141
146
  # </ul>
142
147
  #
143
148
  # The transformation is made in two passes in order to avoid
144
- # interactions between marking and pruning the tree (see bug #1046).
149
+ # interactions between marking and pruning the tree.
150
+ # See: https://github.com/sphinx-doc/sphinx/issues/1046
145
151
 
146
152
  toctree_ancestors = _get_toctree_ancestors(env.toctree_includes, docname)
147
153
  included = Matcher(env.config.include_patterns)
@@ -159,7 +165,7 @@ def _resolve_toctree(
159
165
  titles_only,
160
166
  collapse,
161
167
  includehidden,
162
- builder.tags,
168
+ tags,
163
169
  toctree_ancestors,
164
170
  included,
165
171
  excluded,
@@ -315,7 +321,7 @@ def _toctree_entry(
315
321
  else:
316
322
  if ref in parents:
317
323
  logger.warning(
318
- __('circular toctree references ' 'detected, ignoring: %s <- %s'),
324
+ __('circular toctree references detected, ignoring: %s <- %s'),
319
325
  ref,
320
326
  ' <- '.join(parents),
321
327
  location=ref,
@@ -353,12 +359,15 @@ def _toctree_entry(
353
359
  ref_path = str(env.doc2path(ref, False))
354
360
  if excluded(ref_path):
355
361
  message = __('toctree contains reference to excluded document %r')
362
+ subtype = 'excluded'
356
363
  elif not included(ref_path):
357
364
  message = __('toctree contains reference to non-included document %r')
365
+ subtype = 'not_included'
358
366
  else:
359
- message = __('toctree contains reference to nonexisting document %r')
367
+ message = __('toctree contains reference to non-existing document %r')
368
+ subtype = 'not_readable'
360
369
 
361
- logger.warning(message, ref, location=toctreenode)
370
+ logger.warning(message, ref, location=toctreenode, type='toc', subtype=subtype)
362
371
  raise
363
372
  return toc, refdoc
364
373
 
@@ -510,7 +519,7 @@ def _toctree_copy(
510
519
  copy.append(sub_node_copy)
511
520
  else:
512
521
  msg = f'Unexpected node type {subnode.__class__.__name__!r}!'
513
- raise ValueError(msg)
522
+ raise ValueError(msg) # NoQA: TRY004
514
523
  return copy
515
524
 
516
525
 
@@ -558,13 +567,14 @@ class TocTree:
558
567
  titles_only=titles_only,
559
568
  collapse=collapse,
560
569
  includehidden=includehidden,
570
+ tags=builder.tags,
561
571
  )
562
572
 
563
573
  def get_toctree_ancestors(self, docname: str) -> list[str]:
564
574
  return [*_get_toctree_ancestors(self.env.toctree_includes, docname)]
565
575
 
566
576
  def get_toc_for(self, docname: str, builder: Builder) -> Node:
567
- return document_toc(self.env, docname, self.env.app.builder.tags)
577
+ return document_toc(self.env, docname, self.env._tags)
568
578
 
569
579
  def get_toctree_for(
570
580
  self,
@@ -5,6 +5,8 @@ from __future__ import annotations
5
5
  from typing import TYPE_CHECKING
6
6
 
7
7
  if TYPE_CHECKING:
8
+ from collections.abc import Set
9
+
8
10
  from docutils import nodes
9
11
 
10
12
  from sphinx.application import Sphinx
@@ -55,7 +57,7 @@ class EnvironmentCollector:
55
57
  self,
56
58
  app: Sphinx,
57
59
  env: BuildEnvironment,
58
- docnames: set[str],
60
+ docnames: Set[str],
59
61
  other: BuildEnvironment,
60
62
  ) -> None:
61
63
  """Merge in specified data regarding docnames from a different `BuildEnvironment`
@@ -3,12 +3,12 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import os
6
+ import os.path
6
7
  from glob import glob
7
- from os import path
8
+ from pathlib import Path
8
9
  from typing import TYPE_CHECKING
9
10
 
10
11
  from docutils import nodes
11
- from docutils.utils import relative_path
12
12
 
13
13
  from sphinx import addnodes
14
14
  from sphinx.environment.collectors import EnvironmentCollector
@@ -16,8 +16,11 @@ from sphinx.locale import __
16
16
  from sphinx.util import logging
17
17
  from sphinx.util.i18n import get_image_filename_for_language, search_image_for_language
18
18
  from sphinx.util.images import guess_mimetype
19
+ from sphinx.util.osutil import _relative_path
19
20
 
20
21
  if TYPE_CHECKING:
22
+ from collections.abc import Set
23
+
21
24
  from docutils.nodes import Node
22
25
 
23
26
  from sphinx.application import Sphinx
@@ -37,7 +40,7 @@ class ImageCollector(EnvironmentCollector):
37
40
  self,
38
41
  app: Sphinx,
39
42
  env: BuildEnvironment,
40
- docnames: set[str],
43
+ docnames: Set[str],
41
44
  other: BuildEnvironment,
42
45
  ) -> None:
43
46
  env.images.merge_other(docnames, other.images)
@@ -70,9 +73,9 @@ class ImageCollector(EnvironmentCollector):
70
73
  # Search language-specific figures at first
71
74
  i18n_imguri = get_image_filename_for_language(imguri, app.env)
72
75
  _, full_i18n_imgpath = app.env.relfn2path(i18n_imguri, docname)
73
- self.collect_candidates(app.env, full_i18n_imgpath, candidates, node)
76
+ self.collect_candidates(app.srcdir, full_i18n_imgpath, candidates, node)
74
77
 
75
- self.collect_candidates(app.env, full_imgpath, candidates, node)
78
+ self.collect_candidates(app.srcdir, full_imgpath, candidates, node)
76
79
  else:
77
80
  # substitute imguri by figure_language_filename
78
81
  # (ex. foo.png -> foo.en.png)
@@ -89,8 +92,8 @@ class ImageCollector(EnvironmentCollector):
89
92
  # map image paths to unique image names (so that they can be put
90
93
  # into a single directory)
91
94
  for imgpath in candidates.values():
92
- app.env.dependencies[docname].add(imgpath)
93
- if not os.access(path.join(app.srcdir, imgpath), os.R_OK):
95
+ app.env.note_dependency(imgpath)
96
+ if not os.access(app.srcdir / imgpath, os.R_OK):
94
97
  logger.warning(
95
98
  __('image file not readable: %s'),
96
99
  imgpath,
@@ -103,21 +106,21 @@ class ImageCollector(EnvironmentCollector):
103
106
 
104
107
  def collect_candidates(
105
108
  self,
106
- env: BuildEnvironment,
109
+ srcdir: Path,
107
110
  imgpath: str,
108
111
  candidates: dict[str, str],
109
112
  node: Node,
110
113
  ) -> None:
111
114
  globbed: dict[str, list[str]] = {}
112
- for filename in glob(imgpath):
113
- new_imgpath = relative_path(path.join(env.srcdir, 'dummy'), filename)
115
+ for filename in glob(imgpath): # NoQA: PTH207
116
+ new_imgpath = _relative_path(Path(filename), srcdir)
114
117
  try:
115
118
  mimetype = guess_mimetype(filename)
116
119
  if mimetype is None:
117
- basename, suffix = path.splitext(filename)
120
+ basename, suffix = os.path.splitext(filename)
118
121
  mimetype = 'image/x-' + suffix[1:]
119
122
  if mimetype not in candidates:
120
- globbed.setdefault(mimetype, []).append(new_imgpath)
123
+ globbed.setdefault(mimetype, []).append(new_imgpath.as_posix())
121
124
  except OSError as err:
122
125
  logger.warning(
123
126
  __('image file %s not readable: %s'),
@@ -141,7 +144,7 @@ class DownloadFileCollector(EnvironmentCollector):
141
144
  self,
142
145
  app: Sphinx,
143
146
  env: BuildEnvironment,
144
- docnames: set[str],
147
+ docnames: Set[str],
145
148
  other: BuildEnvironment,
146
149
  ) -> None:
147
150
  env.dlfiles.merge_other(docnames, other.dlfiles)
@@ -154,7 +157,7 @@ class DownloadFileCollector(EnvironmentCollector):
154
157
  node['refuri'] = targetname
155
158
  else:
156
159
  rel_filename, filename = app.env.relfn2path(targetname, app.env.docname)
157
- app.env.dependencies[app.env.docname].add(rel_filename)
160
+ app.env.note_dependency(rel_filename)
158
161
  if not os.access(filename, os.R_OK):
159
162
  logger.warning(
160
163
  __('download file not readable: %s'),
@@ -166,7 +169,7 @@ class DownloadFileCollector(EnvironmentCollector):
166
169
  continue
167
170
  node['filename'] = app.env.dlfiles.add_file(
168
171
  app.env.docname, rel_filename
169
- )
172
+ ).as_posix()
170
173
 
171
174
 
172
175
  def setup(app: Sphinx) -> ExtensionMetadata:
@@ -2,16 +2,15 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import os
6
- from os import path
5
+ from pathlib import Path
7
6
  from typing import TYPE_CHECKING
8
7
 
9
- from docutils.utils import relative_path
10
-
11
8
  from sphinx.environment.collectors import EnvironmentCollector
12
- from sphinx.util.osutil import fs_encoding
9
+ from sphinx.util.osutil import _relative_path, fs_encoding
13
10
 
14
11
  if TYPE_CHECKING:
12
+ from collections.abc import Set
13
+
15
14
  from docutils import nodes
16
15
 
17
16
  from sphinx.application import Sphinx
@@ -29,7 +28,7 @@ class DependenciesCollector(EnvironmentCollector):
29
28
  self,
30
29
  app: Sphinx,
31
30
  env: BuildEnvironment,
32
- docnames: set[str],
31
+ docnames: Set[str],
33
32
  other: BuildEnvironment,
34
33
  ) -> None:
35
34
  for docname in docnames:
@@ -38,8 +37,7 @@ class DependenciesCollector(EnvironmentCollector):
38
37
 
39
38
  def process_doc(self, app: Sphinx, doctree: nodes.document) -> None:
40
39
  """Process docutils-generated dependency info."""
41
- cwd = os.getcwd()
42
- frompath = path.join(path.normpath(app.srcdir), 'dummy')
40
+ cwd = Path.cwd()
43
41
  deps = doctree.settings.record_dependencies
44
42
  if not deps:
45
43
  return
@@ -48,8 +46,8 @@ class DependenciesCollector(EnvironmentCollector):
48
46
  # one relative to the srcdir
49
47
  if isinstance(dep, bytes):
50
48
  dep = dep.decode(fs_encoding)
51
- relpath = relative_path(frompath, path.normpath(path.join(cwd, dep)))
52
- app.env.dependencies[app.env.docname].add(relpath)
49
+ relpath = _relative_path(cwd / dep, app.srcdir)
50
+ app.env.note_dependency(relpath)
53
51
 
54
52
 
55
53
  def setup(app: Sphinx) -> ExtensionMetadata:
@@ -9,6 +9,8 @@ from docutils import nodes
9
9
  from sphinx.environment.collectors import EnvironmentCollector
10
10
 
11
11
  if TYPE_CHECKING:
12
+ from collections.abc import Set
13
+
12
14
  from sphinx.application import Sphinx
13
15
  from sphinx.environment import BuildEnvironment
14
16
  from sphinx.util.typing import ExtensionMetadata
@@ -24,7 +26,7 @@ class MetadataCollector(EnvironmentCollector):
24
26
  self,
25
27
  app: Sphinx,
26
28
  env: BuildEnvironment,
27
- docnames: set[str],
29
+ docnames: Set[str],
28
30
  other: BuildEnvironment,
29
31
  ) -> None:
30
32
  for docname in docnames:
@@ -43,12 +45,12 @@ class MetadataCollector(EnvironmentCollector):
43
45
  for node in doctree[index]: # type: ignore[attr-defined]
44
46
  # nodes are multiply inherited...
45
47
  if isinstance(node, nodes.authors):
46
- authors = cast(list[nodes.author], node)
48
+ authors = cast('list[nodes.author]', node)
47
49
  md['authors'] = [author.astext() for author in authors]
48
50
  elif isinstance(node, nodes.field):
49
51
  assert len(node) == 2
50
- field_name = cast(nodes.field_name, node[0])
51
- field_body = cast(nodes.field_body, node[1])
52
+ field_name = cast('nodes.field_name', node[0])
53
+ field_body = cast('nodes.field_body', node[1])
52
54
  md[field_name.astext()] = field_body.astext()
53
55
  elif isinstance(node, nodes.TextElement):
54
56
  # other children must be TextElement
@@ -10,6 +10,8 @@ from sphinx.environment.collectors import EnvironmentCollector
10
10
  from sphinx.transforms import SphinxContentsFilter
11
11
 
12
12
  if TYPE_CHECKING:
13
+ from collections.abc import Set
14
+
13
15
  from sphinx.application import Sphinx
14
16
  from sphinx.environment import BuildEnvironment
15
17
  from sphinx.util.typing import ExtensionMetadata
@@ -26,7 +28,7 @@ class TitleCollector(EnvironmentCollector):
26
28
  self,
27
29
  app: Sphinx,
28
30
  env: BuildEnvironment,
29
- docnames: set[str],
31
+ docnames: Set[str],
30
32
  other: BuildEnvironment,
31
33
  ) -> None:
32
34
  for docname in docnames:
@@ -15,7 +15,7 @@ from sphinx.transforms import SphinxContentsFilter
15
15
  from sphinx.util import logging, url_re
16
16
 
17
17
  if TYPE_CHECKING:
18
- from collections.abc import Sequence
18
+ from collections.abc import Sequence, Set
19
19
 
20
20
  from docutils.nodes import Element, Node
21
21
 
@@ -47,7 +47,7 @@ class TocTreeCollector(EnvironmentCollector):
47
47
  self,
48
48
  app: Sphinx,
49
49
  env: BuildEnvironment,
50
- docnames: set[str],
50
+ docnames: Set[str],
51
51
  other: BuildEnvironment,
52
52
  ) -> None:
53
53
  for docname in docnames:
@@ -219,7 +219,7 @@ class TocTreeCollector(EnvironmentCollector):
219
219
  _walk_toc(subnode, secnums, depth - 1, titlenode)
220
220
  numstack.pop()
221
221
  titlenode = None
222
- elif isinstance(subnode, nodes.list_item): # NoQA: SIM114
222
+ elif isinstance(subnode, nodes.list_item):
223
223
  _walk_toc(subnode, secnums, depth, titlenode)
224
224
  titlenode = None
225
225
  elif isinstance(subnode, addnodes.only):
@@ -232,7 +232,7 @@ class TocTreeCollector(EnvironmentCollector):
232
232
  if 'skip_section_number' in subnode:
233
233
  continue
234
234
  numstack[-1] += 1
235
- reference = cast(nodes.reference, subnode[0])
235
+ reference = cast('nodes.reference', subnode[0])
236
236
  if depth > 0:
237
237
  number = numstack.copy()
238
238
  secnums[reference['anchorname']] = tuple(numstack)
sphinx/errors.py CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Any
6
-
7
5
 
8
6
  class SphinxError(Exception):
9
7
  """Base class for Sphinx errors.
@@ -109,7 +107,7 @@ class SphinxParallelError(SphinxError):
109
107
 
110
108
  category = 'Sphinx parallel build error'
111
109
 
112
- def __init__(self, message: str, traceback: Any) -> None:
110
+ def __init__(self, message: str, traceback: str) -> None:
113
111
  self.message = message
114
112
  self.traceback = traceback
115
113
 
sphinx/events.py CHANGED
@@ -36,7 +36,7 @@ logger = logging.getLogger(__name__)
36
36
 
37
37
  class EventListener(NamedTuple):
38
38
  id: int
39
- handler: Callable
39
+ handler: Callable[..., Any]
40
40
  priority: int
41
41
 
42
42
 
@@ -150,7 +150,7 @@ class EventManager:
150
150
  self,
151
151
  name: Literal['env-merge-info'],
152
152
  callback: Callable[
153
- [Sphinx, BuildEnvironment, list[str], BuildEnvironment], None
153
+ [Sphinx, BuildEnvironment, Set[str], BuildEnvironment], None
154
154
  ],
155
155
  priority: int,
156
156
  ) -> int: ...
@@ -364,7 +364,7 @@ class EventManager:
364
364
  priority: int,
365
365
  ) -> int: ...
366
366
 
367
- def connect(self, name: str, callback: Callable, priority: int) -> int:
367
+ def connect(self, name: str, callback: Callable[..., Any], priority: int) -> int:
368
368
  """Connect a handler to specific event."""
369
369
  if name not in self.events:
370
370
  raise ExtensionError(__('Unknown event name: %s') % name)
@@ -386,7 +386,7 @@ class EventManager:
386
386
  name: str,
387
387
  *args: Any,
388
388
  allowed_exceptions: tuple[type[Exception], ...] = (),
389
- ) -> list:
389
+ ) -> list[Any]:
390
390
  """Emit a Sphinx event."""
391
391
  # not every object likes to be repr()'d (think
392
392
  # random stuff coming via autodoc)
@@ -0,0 +1,66 @@
1
+ """Creates reST files corresponding to Python modules for code documentation.
2
+
3
+ Parses a directory tree looking for Python modules and packages and creates
4
+ ReST files appropriately to create code documentation with Sphinx. It also
5
+ creates a modules index (named modules.<suffix>).
6
+
7
+ This is derived from the "sphinx-autopackage" script, which is:
8
+ Copyright 2008 Société des arts technologiques (SAT),
9
+ https://sat.qc.ca/
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from typing import TYPE_CHECKING
15
+
16
+ import sphinx
17
+ from sphinx.ext.apidoc._cli import main
18
+
19
+ if TYPE_CHECKING:
20
+ from collections.abc import Sequence
21
+
22
+ from sphinx.application import Sphinx
23
+ from sphinx.util.typing import ExtensionMetadata
24
+
25
+ __all__: Sequence[str] = 'main', 'setup'
26
+
27
+
28
+ def setup(app: Sphinx) -> ExtensionMetadata:
29
+ from sphinx.ext.apidoc._extension import run_apidoc
30
+
31
+ # Require autodoc
32
+ app.setup_extension('sphinx.ext.autodoc')
33
+
34
+ # Configuration values
35
+ app.add_config_value(
36
+ 'apidoc_exclude_patterns', (), 'env', types=frozenset({list, tuple})
37
+ )
38
+ app.add_config_value('apidoc_max_depth', 4, 'env', types=frozenset({int}))
39
+ app.add_config_value('apidoc_follow_links', False, 'env', types=frozenset({bool}))
40
+ app.add_config_value(
41
+ 'apidoc_separate_modules', False, 'env', types=frozenset({bool})
42
+ )
43
+ app.add_config_value(
44
+ 'apidoc_include_private', False, 'env', types=frozenset({bool})
45
+ )
46
+ app.add_config_value('apidoc_no_headings', False, 'env', types=frozenset({bool}))
47
+ app.add_config_value('apidoc_module_first', False, 'env', types=frozenset({bool}))
48
+ app.add_config_value(
49
+ 'apidoc_implicit_namespaces', False, 'env', types=frozenset({bool})
50
+ )
51
+ app.add_config_value(
52
+ 'apidoc_automodule_options',
53
+ frozenset(('members', 'undoc-members', 'show-inheritance')),
54
+ 'env',
55
+ types=frozenset({frozenset, list, set, tuple}),
56
+ )
57
+ app.add_config_value('apidoc_modules', (), 'env', types=frozenset({list, tuple}))
58
+
59
+ # Entry point to run apidoc
60
+ app.connect('builder-inited', run_apidoc)
61
+
62
+ return {
63
+ 'version': sphinx.__display_version__,
64
+ 'parallel_read_safe': True,
65
+ 'parallel_write_safe': True,
66
+ }
@@ -0,0 +1,9 @@
1
+ """Command-line interface for the apidoc extension."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import sys
6
+
7
+ from sphinx.ext.apidoc._cli import main
8
+
9
+ raise SystemExit(main(sys.argv[1:]))