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
@@ -6,25 +6,29 @@ import operator
6
6
  import token
7
7
  from collections import deque
8
8
  from inspect import Parameter
9
- from typing import TYPE_CHECKING, Any
9
+ from typing import TYPE_CHECKING
10
10
 
11
11
  from docutils import nodes
12
12
 
13
13
  from sphinx import addnodes
14
- from sphinx.addnodes import desc_signature, pending_xref, pending_xref_condition
14
+ from sphinx.addnodes import pending_xref, pending_xref_condition
15
+ from sphinx.locale import _
15
16
  from sphinx.pycode.parser import Token, TokenProcessor
16
17
  from sphinx.util.inspect import signature_from_str
17
18
 
18
19
  if TYPE_CHECKING:
19
20
  from collections.abc import Iterable, Iterator
21
+ from typing import Any
20
22
 
21
23
  from docutils.nodes import Element, Node
22
24
 
25
+ from sphinx.addnodes import desc_signature
23
26
  from sphinx.environment import BuildEnvironment
24
27
 
25
28
 
26
- def parse_reftarget(reftarget: str, suppress_prefix: bool = False,
27
- ) -> tuple[str, str, str, bool]:
29
+ def parse_reftarget(
30
+ reftarget: str, suppress_prefix: bool = False
31
+ ) -> tuple[str, str, str, bool]:
28
32
  """Parse a type string and return (reftype, reftarget, title, refspecific flag)"""
29
33
  refspecific = False
30
34
  if reftarget.startswith('.'):
@@ -50,12 +54,15 @@ def parse_reftarget(reftarget: str, suppress_prefix: bool = False,
50
54
  return reftype, reftarget, title, refspecific
51
55
 
52
56
 
53
- def type_to_xref(target: str, env: BuildEnvironment, *,
54
- suppress_prefix: bool = False) -> addnodes.pending_xref:
57
+ def type_to_xref(
58
+ target: str, env: BuildEnvironment, *, suppress_prefix: bool = False
59
+ ) -> addnodes.pending_xref:
55
60
  """Convert a type string to a cross reference node."""
56
61
  if env:
57
- kwargs = {'py:module': env.ref_context.get('py:module'),
58
- 'py:class': env.ref_context.get('py:class')}
62
+ kwargs = {
63
+ 'py:module': env.ref_context.get('py:module'),
64
+ 'py:class': env.ref_context.get('py:class'),
65
+ }
59
66
  else:
60
67
  kwargs = {}
61
68
 
@@ -66,14 +73,22 @@ def type_to_xref(target: str, env: BuildEnvironment, *,
66
73
  # nested classes. But python domain can't access the real python object because this
67
74
  # module should work not-dynamically.
68
75
  shortname = title.split('.')[-1]
69
- contnodes: list[Node] = [pending_xref_condition('', shortname, condition='resolved'),
70
- pending_xref_condition('', title, condition='*')]
76
+ contnodes: list[Node] = [
77
+ pending_xref_condition('', shortname, condition='resolved'),
78
+ pending_xref_condition('', title, condition='*'),
79
+ ]
71
80
  else:
72
81
  contnodes = [nodes.Text(title)]
73
82
 
74
- return pending_xref('', *contnodes,
75
- refdomain='py', reftype=reftype, reftarget=target,
76
- refspecific=refspecific, **kwargs)
83
+ return pending_xref(
84
+ '',
85
+ *contnodes,
86
+ refdomain='py',
87
+ reftype=reftype,
88
+ reftarget=target,
89
+ refspecific=refspecific,
90
+ **kwargs,
91
+ )
77
92
 
78
93
 
79
94
  def _parse_annotation(annotation: str, env: BuildEnvironment) -> list[Node]:
@@ -82,19 +97,21 @@ def _parse_annotation(annotation: str, env: BuildEnvironment) -> list[Node]:
82
97
 
83
98
  def unparse(node: ast.AST) -> list[Node]:
84
99
  if isinstance(node, ast.Attribute):
85
- return [nodes.Text(f"{unparse(node.value)[0]}.{node.attr}")]
100
+ return [nodes.Text(f'{unparse(node.value)[0]}.{node.attr}')]
86
101
  if isinstance(node, ast.BinOp):
87
102
  result: list[Node] = unparse(node.left)
88
103
  result.extend(unparse(node.op))
89
104
  result.extend(unparse(node.right))
90
105
  return result
91
106
  if isinstance(node, ast.BitOr):
92
- return [addnodes.desc_sig_space(),
93
- addnodes.desc_sig_punctuation('', '|'),
94
- addnodes.desc_sig_space()]
107
+ return [
108
+ addnodes.desc_sig_space(),
109
+ addnodes.desc_sig_punctuation('', '|'),
110
+ addnodes.desc_sig_space(),
111
+ ]
95
112
  if isinstance(node, ast.Constant):
96
113
  if node.value is Ellipsis:
97
- return [addnodes.desc_sig_punctuation('', "...")]
114
+ return [addnodes.desc_sig_punctuation('', '...')]
98
115
  if isinstance(node.value, bool):
99
116
  return [addnodes.desc_sig_keyword('', repr(node.value))]
100
117
  if isinstance(node.value, int):
@@ -140,7 +157,7 @@ def _parse_annotation(annotation: str, env: BuildEnvironment) -> list[Node]:
140
157
  result.append(addnodes.desc_sig_punctuation('', ']'))
141
158
 
142
159
  # Wrap the Text nodes inside brackets by literal node if the subscript is a Literal
143
- if result[0] in ('Literal', 'typing.Literal'):
160
+ if result[0] in {'Literal', 'typing.Literal'}:
144
161
  for i, subnode in enumerate(result[1:], start=1):
145
162
  if isinstance(subnode, nodes.Text):
146
163
  result[i] = nodes.literal('', '', subnode)
@@ -157,8 +174,10 @@ def _parse_annotation(annotation: str, env: BuildEnvironment) -> list[Node]:
157
174
  result.pop()
158
175
  result.pop()
159
176
  else:
160
- result = [addnodes.desc_sig_punctuation('', '('),
161
- addnodes.desc_sig_punctuation('', ')')]
177
+ result = [
178
+ addnodes.desc_sig_punctuation('', '('),
179
+ addnodes.desc_sig_punctuation('', ')'),
180
+ ]
162
181
 
163
182
  return result
164
183
  if isinstance(node, ast.Call):
@@ -211,8 +230,11 @@ def _parse_annotation(annotation: str, env: BuildEnvironment) -> list[Node]:
211
230
  if isinstance(node, nodes.literal):
212
231
  result.append(node[0])
213
232
  elif isinstance(node, nodes.Text) and node.strip():
214
- if (result and isinstance(result[-1], addnodes.desc_sig_punctuation) and
215
- result[-1].astext() == '~'):
233
+ if (
234
+ result
235
+ and isinstance(result[-1], addnodes.desc_sig_punctuation)
236
+ and result[-1].astext() == '~'
237
+ ):
216
238
  result.pop()
217
239
  result.append(type_to_xref(str(node), env, suppress_prefix=True))
218
240
  else:
@@ -244,8 +266,7 @@ class _TypeParameterListParser(TokenProcessor):
244
266
  else:
245
267
  if current == token.INDENT:
246
268
  tokens += self.fetch_until(token.DEDENT)
247
- elif current.match(
248
- [token.OP, ':'], [token.OP, '='], [token.OP, ',']):
269
+ elif current.match([token.OP, ':'], [token.OP, '='], [token.OP, ',']):
249
270
  tokens.pop()
250
271
  break
251
272
  return tokens
@@ -254,7 +275,9 @@ class _TypeParameterListParser(TokenProcessor):
254
275
  while current := self.fetch_token():
255
276
  if current == token.NAME:
256
277
  tp_name = current.value.strip()
257
- if self.previous and self.previous.match([token.OP, '*'], [token.OP, '**']):
278
+ if self.previous and self.previous.match(
279
+ [token.OP, '*'], [token.OP, '**']
280
+ ):
258
281
  if self.previous == [token.OP, '*']:
259
282
  tp_kind = Parameter.VAR_POSITIONAL
260
283
  else:
@@ -275,9 +298,14 @@ class _TypeParameterListParser(TokenProcessor):
275
298
  tokens = self.fetch_type_param_spec()
276
299
  tp_default = self._build_identifier(tokens)
277
300
 
278
- if tp_kind != Parameter.POSITIONAL_OR_KEYWORD and tp_ann != Parameter.empty:
279
- msg = ('type parameter bound or constraint is not allowed '
280
- f'for {tp_kind.description} parameters')
301
+ if (
302
+ tp_kind != Parameter.POSITIONAL_OR_KEYWORD
303
+ and tp_ann != Parameter.empty
304
+ ):
305
+ msg = (
306
+ 'type parameter bound or constraint is not allowed '
307
+ f'for {tp_kind.description} parameters'
308
+ )
281
309
  raise SyntaxError(msg)
282
310
 
283
311
  type_param = (tp_name, tp_kind, tp_default, tp_ann)
@@ -315,12 +343,22 @@ class _TypeParameterListParser(TokenProcessor):
315
343
  idents.append(ident)
316
344
  # determine if the next token is an unpack operator depending
317
345
  # on the left and right hand side of the operator symbol
318
- is_unpack_operator = (
319
- op.match([token.OP, '*'], [token.OP, '**']) and not (
320
- tok.match(token.NAME, token.NUMBER, token.STRING,
321
- [token.OP, ')'], [token.OP, ']'], [token.OP, '}'])
322
- and after.match(token.NAME, token.NUMBER, token.STRING,
323
- [token.OP, '('], [token.OP, '['], [token.OP, '{'])
346
+ is_unpack_operator = op.match([token.OP, '*'], [token.OP, '**']) and not (
347
+ tok.match(
348
+ token.NAME,
349
+ token.NUMBER,
350
+ token.STRING,
351
+ [token.OP, ')'],
352
+ [token.OP, ']'],
353
+ [token.OP, '}'],
354
+ )
355
+ and after.match(
356
+ token.NAME,
357
+ token.NUMBER,
358
+ token.STRING,
359
+ [token.OP, '('],
360
+ [token.OP, '['],
361
+ [token.OP, '{'],
324
362
  )
325
363
  )
326
364
 
@@ -356,28 +394,33 @@ class _TypeParameterListParser(TokenProcessor):
356
394
  [token.OP, '@'], [token.OP, '/'], [token.OP, '//'], [token.OP, '%'],
357
395
  [token.OP, '<<'], [token.OP, '>>'], [token.OP, '>>>'],
358
396
  [token.OP, '<='], [token.OP, '>='], [token.OP, '=='], [token.OP, '!='],
359
- ):
397
+ ): # fmt: skip
360
398
  return f' {tok.value} '
361
399
 
362
400
  return tok.value
363
401
 
364
402
 
365
403
  def _parse_type_list(
366
- tp_list: str, env: BuildEnvironment,
404
+ tp_list: str,
405
+ env: BuildEnvironment,
367
406
  multi_line_parameter_list: bool = False,
407
+ trailing_comma: bool = True,
368
408
  ) -> addnodes.desc_type_parameter_list:
369
409
  """Parse a list of type parameters according to PEP 695."""
370
410
  type_params = addnodes.desc_type_parameter_list(tp_list)
371
411
  type_params['multi_line_parameter_list'] = multi_line_parameter_list
412
+ type_params['multi_line_trailing_comma'] = trailing_comma
372
413
  # formal parameter names are interpreted as type parameter names and
373
414
  # type annotations are interpreted as type parameter bound or constraints
374
415
  parser = _TypeParameterListParser(tp_list)
375
416
  parser.parse()
376
- for (tp_name, tp_kind, tp_default, tp_ann) in parser.type_params:
417
+ for tp_name, tp_kind, tp_default, tp_ann in parser.type_params:
377
418
  # no positional-only or keyword-only allowed in a type parameters list
378
419
  if tp_kind in {Parameter.POSITIONAL_ONLY, Parameter.KEYWORD_ONLY}:
379
- msg = ('positional-only or keyword-only parameters '
380
- 'are prohibited in type parameter lists')
420
+ msg = (
421
+ 'positional-only or keyword-only parameters '
422
+ 'are prohibited in type parameter lists'
423
+ )
381
424
  raise SyntaxError(msg)
382
425
 
383
426
  node = addnodes.desc_type_parameter()
@@ -395,8 +438,7 @@ def _parse_type_list(
395
438
  node += addnodes.desc_sig_punctuation('', ':')
396
439
  node += addnodes.desc_sig_space()
397
440
 
398
- type_ann_expr = addnodes.desc_sig_name('', '',
399
- *annotation) # type: ignore[arg-type]
441
+ type_ann_expr = addnodes.desc_sig_name('', '', *annotation) # type: ignore[arg-type]
400
442
  # a type bound is ``T: U`` whereas type constraints
401
443
  # must be enclosed with parentheses. ``T: (U, V)``
402
444
  if tp_ann.startswith('(') and tp_ann.endswith(')'):
@@ -416,31 +458,35 @@ def _parse_type_list(
416
458
  node += addnodes.desc_sig_space()
417
459
  node += addnodes.desc_sig_operator('', '=')
418
460
  node += addnodes.desc_sig_space()
419
- node += nodes.inline('', tp_default,
420
- classes=['default_value'],
421
- support_smartquotes=False)
461
+ node += nodes.inline(
462
+ '', tp_default, classes=['default_value'], support_smartquotes=False
463
+ )
422
464
 
423
465
  type_params += node
424
466
  return type_params
425
467
 
426
468
 
427
469
  def _parse_arglist(
428
- arglist: str, env: BuildEnvironment, multi_line_parameter_list: bool = False,
470
+ arglist: str,
471
+ env: BuildEnvironment,
472
+ multi_line_parameter_list: bool = False,
473
+ trailing_comma: bool = True,
429
474
  ) -> addnodes.desc_parameterlist:
430
475
  """Parse a list of arguments using AST parser"""
431
476
  params = addnodes.desc_parameterlist(arglist)
432
477
  params['multi_line_parameter_list'] = multi_line_parameter_list
478
+ params['multi_line_trailing_comma'] = trailing_comma
433
479
  sig = signature_from_str('(%s)' % arglist)
434
480
  last_kind = None
435
481
  for param in sig.parameters.values():
436
482
  if param.kind != param.POSITIONAL_ONLY and last_kind == param.POSITIONAL_ONLY:
437
- # PEP-570: Separator for Positional Only Parameter: /
438
- params += addnodes.desc_parameter('', '', addnodes.desc_sig_operator('', '/'))
439
- if param.kind == param.KEYWORD_ONLY and last_kind in (param.POSITIONAL_OR_KEYWORD,
440
- param.POSITIONAL_ONLY,
441
- None):
442
- # PEP-3102: Separator for Keyword Only Parameter: *
443
- params += addnodes.desc_parameter('', '', addnodes.desc_sig_operator('', '*'))
483
+ params += _positional_only_separator()
484
+ if param.kind == param.KEYWORD_ONLY and last_kind in {
485
+ param.POSITIONAL_OR_KEYWORD,
486
+ param.POSITIONAL_ONLY,
487
+ None,
488
+ }:
489
+ params += _keyword_only_separator()
444
490
 
445
491
  node = addnodes.desc_parameter()
446
492
  if param.kind == param.VAR_POSITIONAL:
@@ -464,23 +510,48 @@ def _parse_arglist(
464
510
  node += addnodes.desc_sig_space()
465
511
  else:
466
512
  node += addnodes.desc_sig_operator('', '=')
467
- node += nodes.inline('', param.default, classes=['default_value'],
468
- support_smartquotes=False)
513
+ node += nodes.inline(
514
+ '', param.default, classes=['default_value'], support_smartquotes=False
515
+ )
469
516
 
470
517
  params += node
471
518
  last_kind = param.kind
472
519
 
473
520
  if last_kind == Parameter.POSITIONAL_ONLY:
474
- # PEP-570: Separator for Positional Only Parameter: /
475
- params += addnodes.desc_parameter('', '', addnodes.desc_sig_operator('', '/'))
521
+ params += _positional_only_separator()
476
522
 
477
523
  return params
478
524
 
479
525
 
526
+ def _positional_only_separator() -> addnodes.desc_parameter:
527
+ # PEP 570: Separator for positional only parameters: /
528
+ positional_only_abbr = nodes.abbreviation(
529
+ '/', '/', explanation=_('Positional-only parameter separator (PEP 570)')
530
+ )
531
+ positional_only_op = addnodes.desc_sig_operator(
532
+ '/', '', positional_only_abbr, classes=['positional-only-separator']
533
+ )
534
+ return addnodes.desc_parameter('/', '', positional_only_op)
535
+
536
+
537
+ def _keyword_only_separator() -> addnodes.desc_parameter:
538
+ # PEP 3102: Separator for keyword only parameters: *
539
+ keyword_only_abbr = nodes.abbreviation(
540
+ '*', '*', explanation=_('Keyword-only parameters separator (PEP 3102)')
541
+ )
542
+ keyword_only_op = addnodes.desc_sig_operator(
543
+ '*', '', keyword_only_abbr, classes=['keyword-only-separator']
544
+ )
545
+ return addnodes.desc_parameter('*', '', keyword_only_op)
546
+
547
+
480
548
  def _pseudo_parse_arglist(
481
- signode: desc_signature, arglist: str, multi_line_parameter_list: bool = False,
549
+ signode: desc_signature,
550
+ arglist: str,
551
+ multi_line_parameter_list: bool = False,
552
+ trailing_comma: bool = True,
482
553
  ) -> None:
483
- """"Parse" a list of arguments separated by commas.
554
+ """'Parse' a list of arguments separated by commas.
484
555
 
485
556
  Arguments can have "optional" annotations given by enclosing them in
486
557
  brackets. Currently, this will split at any comma, even if it's inside a
@@ -488,6 +559,7 @@ def _pseudo_parse_arglist(
488
559
  """
489
560
  paramlist = addnodes.desc_parameterlist()
490
561
  paramlist['multi_line_parameter_list'] = multi_line_parameter_list
562
+ paramlist['multi_line_trailing_comma'] = trailing_comma
491
563
  stack: list[Element] = [paramlist]
492
564
  try:
493
565
  for argument in arglist.split(','):
@@ -508,7 +580,8 @@ def _pseudo_parse_arglist(
508
580
  argument = argument[:-1].strip()
509
581
  if argument:
510
582
  stack[-1] += addnodes.desc_parameter(
511
- '', '', addnodes.desc_sig_name(argument, argument))
583
+ '', '', addnodes.desc_sig_name(argument, argument)
584
+ )
512
585
  while ends_open:
513
586
  stack.append(addnodes.desc_optional())
514
587
  stack[-2] += stack[-1]
@@ -517,7 +590,7 @@ def _pseudo_parse_arglist(
517
590
  stack.pop()
518
591
  ends_close -= 1
519
592
  if len(stack) != 1:
520
- raise IndexError
593
+ raise IndexError # NoQA: TRY301
521
594
  except IndexError:
522
595
  # if there are too few or too many elements on the stack, just give up
523
596
  # and treat the whole argument list as one argument, discarding the