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
@@ -10,13 +10,14 @@ from __future__ import annotations
10
10
  import functools
11
11
  import operator
12
12
  import re
13
+ import sys
13
14
  from inspect import Parameter, Signature
14
15
  from typing import TYPE_CHECKING, Any, NewType, TypeVar
15
16
 
16
17
  from docutils.statemachine import StringList
17
18
 
18
19
  import sphinx
19
- from sphinx.config import ENUM, Config
20
+ from sphinx.config import ENUM
20
21
  from sphinx.errors import PycodeError
21
22
  from sphinx.ext.autodoc.importer import get_class_members, import_module, import_object
22
23
  from sphinx.ext.autodoc.mock import ismock, mock, undecorate
@@ -31,13 +32,7 @@ from sphinx.util.inspect import (
31
32
  safe_getattr,
32
33
  stringify_signature,
33
34
  )
34
- from sphinx.util.typing import (
35
- ExtensionMetadata,
36
- OptionSpec,
37
- get_type_hints,
38
- restify,
39
- stringify_annotation,
40
- )
35
+ from sphinx.util.typing import get_type_hints, restify, stringify_annotation
41
36
 
42
37
  if TYPE_CHECKING:
43
38
  from collections.abc import Callable, Iterator, Sequence
@@ -45,8 +40,12 @@ if TYPE_CHECKING:
45
40
  from typing import ClassVar, Literal, TypeAlias
46
41
 
47
42
  from sphinx.application import Sphinx
48
- from sphinx.environment import BuildEnvironment
43
+ from sphinx.config import Config
44
+ from sphinx.environment import BuildEnvironment, _CurrentDocument
45
+ from sphinx.events import EventManager
49
46
  from sphinx.ext.autodoc.directive import DocumenterBridge
47
+ from sphinx.registry import SphinxComponentRegistry
48
+ from sphinx.util.typing import ExtensionMetadata, OptionSpec, _RestifyMode
50
49
 
51
50
  _AutodocObjType = Literal[
52
51
  'module', 'class', 'exception', 'function', 'method', 'attribute'
@@ -65,17 +64,27 @@ MethodDescriptorType = type(type.__subclasses__)
65
64
 
66
65
  #: extended signature RE: with explicit module name separated by ::
67
66
  py_ext_sig_re = re.compile(
68
- r'''^ ([\w.]+::)? # explicit module name
67
+ r"""^ ([\w.]+::)? # explicit module name
69
68
  ([\w.]+\.)? # module and/or class name(s)
70
69
  (\w+) \s* # thing name
71
- (?: \[\s*(.*)\s*])? # optional: type parameters list
70
+ (?: \[\s*(.*?)\s*])? # optional: type parameters list
72
71
  (?: \((.*)\) # optional: arguments
73
72
  (?:\s* -> \s* (.*))? # return annotation
74
73
  )? $ # and nothing more
75
- ''', re.VERBOSE)
74
+ """,
75
+ re.VERBOSE,
76
+ )
76
77
  special_member_re = re.compile(r'^__\S+__$')
77
78
 
78
79
 
80
+ def _get_render_mode(
81
+ typehints_format: Literal['fully-qualified', 'short'],
82
+ ) -> _RestifyMode:
83
+ if typehints_format == 'short':
84
+ return 'smart'
85
+ return 'fully-qualified-except-typing'
86
+
87
+
79
88
  def identity(x: Any) -> Any:
80
89
  return x
81
90
 
@@ -106,7 +115,7 @@ SLOTSATTR = object()
106
115
 
107
116
  def members_option(arg: Any) -> object | list[str]:
108
117
  """Used to convert the :members: option to auto directives."""
109
- if arg in (None, True):
118
+ if arg in {None, True}:
110
119
  return ALL
111
120
  elif arg is False:
112
121
  return None
@@ -116,14 +125,14 @@ def members_option(arg: Any) -> object | list[str]:
116
125
 
117
126
  def exclude_members_option(arg: Any) -> object | set[str]:
118
127
  """Used to convert the :exclude-members: option."""
119
- if arg in (None, True):
128
+ if arg in {None, True}:
120
129
  return EMPTY
121
130
  return {x.strip() for x in arg.split(',') if x.strip()}
122
131
 
123
132
 
124
133
  def inherited_members_option(arg: Any) -> set[str]:
125
134
  """Used to convert the :inherited-members: option to auto directives."""
126
- if arg in (None, True):
135
+ if arg in {None, True}:
127
136
  return {'object'}
128
137
  elif arg:
129
138
  return {x.strip() for x in arg.split(',')}
@@ -133,9 +142,9 @@ def inherited_members_option(arg: Any) -> set[str]:
133
142
 
134
143
  def member_order_option(arg: Any) -> str | None:
135
144
  """Used to convert the :member-order: option to auto directives."""
136
- if arg in (None, True):
145
+ if arg in {None, True}:
137
146
  return None
138
- elif arg in ('alphabetical', 'bysource', 'groupwise'):
147
+ elif arg in {'alphabetical', 'bysource', 'groupwise'}:
139
148
  return arg
140
149
  else:
141
150
  raise ValueError(__('invalid value for member-order option: %s') % arg)
@@ -143,7 +152,7 @@ def member_order_option(arg: Any) -> str | None:
143
152
 
144
153
  def class_doc_from_option(arg: Any) -> str | None:
145
154
  """Used to convert the :class-doc-from: option to autoclass directives."""
146
- if arg in ('both', 'class', 'init'):
155
+ if arg in {'both', 'class', 'init'}:
147
156
  return arg
148
157
  else:
149
158
  raise ValueError(__('invalid value for class-doc-from option: %s') % arg)
@@ -153,7 +162,7 @@ SUPPRESS = object()
153
162
 
154
163
 
155
164
  def annotation_option(arg: Any) -> Any:
156
- if arg in (None, True):
165
+ if arg in {None, True}:
157
166
  # suppress showing the representation of the object
158
167
  return SUPPRESS
159
168
  else:
@@ -167,7 +176,7 @@ def bool_option(arg: Any) -> bool:
167
176
  return True
168
177
 
169
178
 
170
- def merge_members_option(options: dict) -> None:
179
+ def merge_members_option(options: dict[str, Any]) -> None:
171
180
  """Merge :private-members: and :special-members: options to the
172
181
  :members: option.
173
182
  """
@@ -177,16 +186,18 @@ def merge_members_option(options: dict) -> None:
177
186
 
178
187
  members = options.setdefault('members', [])
179
188
  for key in ('private-members', 'special-members'):
180
- if key in options and options[key] not in (ALL, None):
181
- for member in options[key]:
189
+ other_members = options.get(key)
190
+ if other_members is not None and other_members is not ALL:
191
+ for member in other_members:
182
192
  if member not in members:
183
193
  members.append(member)
184
194
 
185
195
 
186
196
  # Some useful event listener factories for autodoc-process-docstring.
187
197
 
198
+
188
199
  def cut_lines(
189
- pre: int, post: int = 0, what: str | list[str] | None = None
200
+ pre: int, post: int = 0, what: Sequence[str] | None = None
190
201
  ) -> _AutodocProcessDocstringListener:
191
202
  """Return a listener that removes the first *pre* and last *post*
192
203
  lines of every docstring. If *what* is a sequence of strings,
@@ -195,11 +206,17 @@ def cut_lines(
195
206
  Use like this (e.g. in the ``setup()`` function of :file:`conf.py`)::
196
207
 
197
208
  from sphinx.ext.autodoc import cut_lines
209
+
198
210
  app.connect('autodoc-process-docstring', cut_lines(4, what={'module'}))
199
211
 
200
212
  This can (and should) be used in place of :confval:`automodule_skip_lines`.
201
213
  """
202
- what_unique = frozenset(what or ())
214
+ if not what:
215
+ what_unique: frozenset[str] = frozenset()
216
+ elif isinstance(what, str): # strongly discouraged
217
+ what_unique = frozenset({what})
218
+ else:
219
+ what_unique = frozenset(what)
203
220
 
204
221
  def process(
205
222
  app: Sphinx,
@@ -209,7 +226,7 @@ def cut_lines(
209
226
  options: dict[str, bool],
210
227
  lines: list[str],
211
228
  ) -> None:
212
- if what_ not in what_unique:
229
+ if what_unique and what_ not in what_unique:
213
230
  return
214
231
  del lines[:pre]
215
232
  if post:
@@ -220,6 +237,7 @@ def cut_lines(
220
237
  # make sure there is a blank line at the end
221
238
  if lines and lines[-1]:
222
239
  lines.append('')
240
+
223
241
  return process
224
242
 
225
243
 
@@ -266,11 +284,13 @@ def between(
266
284
  # make sure there is a blank line at the end
267
285
  if lines and lines[-1]:
268
286
  lines.append('')
287
+
269
288
  return process
270
289
 
271
290
 
272
291
  # This class is used only in ``sphinx.ext.autodoc.directive``,
273
- # But we define this class here to keep compatibility (see #4538)
292
+ # But we define this class here to keep compatibility
293
+ # See: https://github.com/sphinx-doc/sphinx/issues/4538
274
294
  class Options(dict[str, Any]):
275
295
  """A dict/attribute hybrid that returns None on nonexisting keys."""
276
296
 
@@ -291,18 +311,43 @@ class ObjectMember:
291
311
  represent each member of the object.
292
312
  """
293
313
 
294
- def __init__(self, name: str, obj: Any, *, docstring: str | None = None,
295
- class_: Any = None, skipped: bool = False) -> None:
314
+ __slots__ = '__name__', 'object', 'docstring', 'class_', 'skipped'
315
+
316
+ __name__: str
317
+ object: Any
318
+ docstring: str | None
319
+ class_: Any
320
+ skipped: bool
321
+
322
+ def __init__(
323
+ self,
324
+ name: str,
325
+ obj: Any,
326
+ *,
327
+ docstring: str | None = None,
328
+ class_: Any = None,
329
+ skipped: bool = False,
330
+ ) -> None:
296
331
  self.__name__ = name
297
332
  self.object = obj
298
333
  self.docstring = docstring
299
- self.skipped = skipped
300
334
  self.class_ = class_
335
+ self.skipped = skipped
336
+
337
+ def __repr__(self) -> str:
338
+ return (
339
+ f'ObjectMember('
340
+ f'name={self.__name__!r}, '
341
+ f'obj={self.object!r}, '
342
+ f'docstring={self.docstring!r}, '
343
+ f'class_={self.class_!r}, '
344
+ f'skipped={self.skipped!r}'
345
+ f')'
346
+ )
301
347
 
302
348
 
303
349
  class Documenter:
304
- """
305
- A Documenter knows how to autodocument a single object type. When
350
+ """A Documenter knows how to autodocument a single object type. When
306
351
  registered with the AutoDirective, it will be used to document objects
307
352
  of that type when needed by autodoc.
308
353
 
@@ -330,25 +375,30 @@ class Documenter:
330
375
 
331
376
  option_spec: ClassVar[OptionSpec] = {
332
377
  'no-index': bool_option,
378
+ 'no-index-entry': bool_option,
333
379
  'noindex': bool_option,
334
380
  }
335
381
 
336
382
  def get_attr(self, obj: Any, name: str, *defargs: Any) -> Any:
337
383
  """getattr() override for types such as Zope interfaces."""
338
- return autodoc_attrgetter(self.env.app, obj, name, *defargs)
384
+ return autodoc_attrgetter(obj, name, *defargs, registry=self.env._registry)
339
385
 
340
386
  @classmethod
341
387
  def can_document_member(
342
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
388
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
343
389
  ) -> bool:
344
390
  """Called to see if a member can be documented by this Documenter."""
345
391
  msg = 'must be implemented in subclasses'
346
392
  raise NotImplementedError(msg)
347
393
 
348
- def __init__(self, directive: DocumenterBridge, name: str, indent: str = '') -> None:
394
+ def __init__(
395
+ self, directive: DocumenterBridge, name: str, indent: str = ''
396
+ ) -> None:
349
397
  self.directive = directive
350
398
  self.config: Config = directive.env.config
351
399
  self.env: BuildEnvironment = directive.env
400
+ self._current_document: _CurrentDocument = directive.env.current_document
401
+ self._events: EventManager = directive.env.events
352
402
  self.options = directive.genopt
353
403
  self.name = name
354
404
  self.indent = indent
@@ -373,7 +423,7 @@ class Documenter:
373
423
  @property
374
424
  def documenters(self) -> dict[str, type[Documenter]]:
375
425
  """Returns registered Documenter classes"""
376
- return self.env.app.registry.documenters
426
+ return self.env._registry.documenters
377
427
 
378
428
  def add_line(self, line: str, source: str, *lineno: int) -> None:
379
429
  """Append one line of generated reST to the output."""
@@ -382,8 +432,9 @@ class Documenter:
382
432
  else:
383
433
  self.directive.result.append('', source, *lineno)
384
434
 
385
- def resolve_name(self, modname: str | None, parents: Any, path: str, base: str,
386
- ) -> tuple[str | None, list[str]]:
435
+ def resolve_name(
436
+ self, modname: str | None, parents: Any, path: str, base: str
437
+ ) -> tuple[str | None, list[str]]:
387
438
  """Resolve the module and name of the object to document given by the
388
439
  arguments and the current module/class.
389
440
 
@@ -405,8 +456,12 @@ class Documenter:
405
456
  # an autogenerated one
406
457
  matched = py_ext_sig_re.match(self.name)
407
458
  if matched is None:
408
- logger.warning(__('invalid signature for auto%s (%r)'), self.objtype, self.name,
409
- type='autodoc')
459
+ logger.warning(
460
+ __('invalid signature for auto%s (%r)'),
461
+ self.objtype,
462
+ self.name,
463
+ type='autodoc',
464
+ )
410
465
  return False
411
466
  explicit_modname, path, base, tp_list, args, retann = matched.groups()
412
467
 
@@ -427,8 +482,7 @@ class Documenter:
427
482
  self.modname = modname
428
483
  self.args = args
429
484
  self.retann = retann
430
- self.fullname = ((self.modname or '') +
431
- ('.' + '.'.join(self.objpath) if self.objpath else ''))
485
+ self.fullname = '.'.join((self.modname or '', *self.objpath))
432
486
  return True
433
487
 
434
488
  def import_object(self, raiseerror: bool = False) -> bool:
@@ -440,8 +494,7 @@ class Documenter:
440
494
  with mock(self.config.autodoc_mock_imports):
441
495
  try:
442
496
  ret = import_object(
443
- self.modname, self.objpath, self.objtype,
444
- attrgetter=self.get_attr,
497
+ self.modname, self.objpath, self.objtype, attrgetter=self.get_attr
445
498
  )
446
499
  self.module, self.parent, self.object_name, self.object = ret
447
500
  if ismock(self.object):
@@ -509,7 +562,7 @@ class Documenter:
509
562
  """
510
563
  if self.args is not None:
511
564
  # signature given explicitly
512
- args = "(%s)" % self.args
565
+ args = f'({self.args})'
513
566
  retann = self.retann
514
567
  else:
515
568
  # try to introspect the signature
@@ -522,13 +575,23 @@ class Documenter:
522
575
  args = matched.group(1)
523
576
  retann = matched.group(2)
524
577
  except Exception as exc:
525
- logger.warning(__('error while formatting arguments for %s: %s'),
526
- self.fullname, exc, type='autodoc')
578
+ logger.warning(
579
+ __('error while formatting arguments for %s: %s'),
580
+ self.fullname,
581
+ exc,
582
+ type='autodoc',
583
+ )
527
584
  args = None
528
585
 
529
- result = self.env.events.emit_firstresult('autodoc-process-signature',
530
- self.objtype, self.fullname,
531
- self.object, self.options, args, retann)
586
+ result = self._events.emit_firstresult(
587
+ 'autodoc-process-signature',
588
+ self.objtype,
589
+ self.fullname,
590
+ self.object,
591
+ self.options,
592
+ args,
593
+ retann,
594
+ )
532
595
  if result:
533
596
  args, retann = result
534
597
 
@@ -546,14 +609,15 @@ class Documenter:
546
609
 
547
610
  # one signature per line, indented by column
548
611
  prefix = f'.. {domain}:{directive}:: '
549
- for i, sig_line in enumerate(sig.split("\n")):
550
- self.add_line(f'{prefix}{name}{sig_line}',
551
- sourcename)
612
+ for i, sig_line in enumerate(sig.split('\n')):
613
+ self.add_line(f'{prefix}{name}{sig_line}', sourcename)
552
614
  if i == 0:
553
- prefix = " " * len(prefix)
615
+ prefix = ' ' * len(prefix)
554
616
 
555
617
  if self.options.no_index or self.options.noindex:
556
618
  self.add_line(' :no-index:', sourcename)
619
+ if self.options.no_index_entry:
620
+ self.add_line(' :no-index-entry:', sourcename)
557
621
  if self.objpath:
558
622
  # Be explicit about the module, this is necessary since .. class::
559
623
  # etc. don't support a prepended module name
@@ -565,8 +629,13 @@ class Documenter:
565
629
  When it returns None, autodoc-process-docstring will not be called for this
566
630
  object.
567
631
  """
568
- docstring = getdoc(self.object, self.get_attr, self.config.autodoc_inherit_docstrings,
569
- self.parent, self.object_name)
632
+ docstring = getdoc(
633
+ self.object,
634
+ self.get_attr,
635
+ self.config.autodoc_inherit_docstrings,
636
+ self.parent,
637
+ self.object_name,
638
+ )
570
639
  if docstring:
571
640
  tab_width = self.directive.state.document.settings.tab_width
572
641
  return [prepare_docstring(docstring, tab_width)]
@@ -575,21 +644,27 @@ class Documenter:
575
644
  def process_doc(self, docstrings: list[list[str]]) -> Iterator[str]:
576
645
  """Let the user process the docstrings before adding them."""
577
646
  for docstringlines in docstrings:
578
- if self.env.app:
647
+ if self._events is not None:
579
648
  # let extensions preprocess docstrings
580
- self.env.app.emit('autodoc-process-docstring',
581
- self.objtype, self.fullname, self.object,
582
- self.options, docstringlines)
649
+ self._events.emit(
650
+ 'autodoc-process-docstring',
651
+ self.objtype,
652
+ self.fullname,
653
+ self.object,
654
+ self.options,
655
+ docstringlines,
656
+ )
583
657
 
584
- if docstringlines and docstringlines[-1] != '':
658
+ if docstringlines and docstringlines[-1]:
585
659
  # append a blank line to the end of the docstring
586
660
  docstringlines.append('')
587
661
 
588
662
  yield from docstringlines
589
663
 
590
664
  def get_sourcename(self) -> str:
591
- if (inspect.safe_getattr(self.object, '__module__', None) and
592
- inspect.safe_getattr(self.object, '__qualname__', None)):
665
+ obj_module = inspect.safe_getattr(self.object, '__module__', None)
666
+ obj_qualname = inspect.safe_getattr(self.object, '__qualname__', None)
667
+ if obj_module and obj_qualname:
593
668
  # Get the correct location of docstring from self.object
594
669
  # to support inherited methods
595
670
  fullname = f'{self.object.__module__}.{self.object.__qualname__}'
@@ -650,8 +725,9 @@ class Documenter:
650
725
  msg = 'must be implemented in subclasses'
651
726
  raise NotImplementedError(msg)
652
727
 
653
- def filter_members(self, members: list[ObjectMember], want_all: bool,
654
- ) -> list[tuple[str, Any, bool]]:
728
+ def filter_members(
729
+ self, members: list[ObjectMember], want_all: bool
730
+ ) -> list[tuple[str, Any, bool]]:
655
731
  """Filter the given member list.
656
732
 
657
733
  Members are skipped if
@@ -665,12 +741,22 @@ class Documenter:
665
741
  The user can override the skipping decision by connecting to the
666
742
  ``autodoc-skip-member`` event.
667
743
  """
744
+
668
745
  def is_filtered_inherited_member(name: str, obj: Any) -> bool:
669
746
  inherited_members = self.options.inherited_members or set()
747
+ seen = set()
670
748
 
671
749
  if inspect.isclass(self.object):
672
750
  for cls in self.object.__mro__:
673
- if cls.__name__ in inherited_members and cls != self.object:
751
+ if name in cls.__dict__:
752
+ seen.add(cls)
753
+ if (
754
+ cls.__name__ in inherited_members
755
+ and cls != self.object
756
+ and any(
757
+ issubclass(potential_child, cls) for potential_child in seen
758
+ )
759
+ ):
674
760
  # given member is a member of specified *super class*
675
761
  return True
676
762
  if name in cls.__dict__:
@@ -701,8 +787,13 @@ class Documenter:
701
787
  isattr = member is INSTANCEATTR or (namespace, membername) in attr_docs
702
788
 
703
789
  try:
704
- doc = getdoc(member, self.get_attr, self.config.autodoc_inherit_docstrings,
705
- self.object, membername)
790
+ doc = getdoc(
791
+ member,
792
+ self.get_attr,
793
+ self.config.autodoc_inherit_docstrings,
794
+ self.object,
795
+ membername,
796
+ )
706
797
  if not isinstance(doc, str):
707
798
  # Ignore non-string __doc__
708
799
  doc = None
@@ -735,14 +826,18 @@ class Documenter:
735
826
  if ismock(member) and (namespace, membername) not in attr_docs:
736
827
  # mocked module or object
737
828
  pass
738
- elif (self.options.exclude_members and
739
- membername in self.options.exclude_members):
829
+ elif (
830
+ self.options.exclude_members
831
+ and membername in self.options.exclude_members
832
+ ):
740
833
  # remove members given by exclude-members
741
834
  keep = False
742
835
  elif want_all and special_member_re.match(membername):
743
836
  # special __methods__
744
- if (self.options.special_members and
745
- membername in self.options.special_members):
837
+ if (
838
+ self.options.special_members
839
+ and membername in self.options.special_members
840
+ ):
746
841
  if membername == '__doc__': # NoQA: SIM114
747
842
  keep = False
748
843
  elif is_filtered_inherited_member(membername, obj):
@@ -771,8 +866,9 @@ class Documenter:
771
866
  else:
772
867
  keep = False
773
868
  else:
774
- if (self.options.members is ALL and
775
- is_filtered_inherited_member(membername, obj)):
869
+ if self.options.members is ALL and is_filtered_inherited_member(
870
+ membername, obj
871
+ ):
776
872
  keep = False
777
873
  else:
778
874
  # ignore undocumented members if :undoc-members: is not given
@@ -784,17 +880,30 @@ class Documenter:
784
880
 
785
881
  # give the user a chance to decide whether this member
786
882
  # should be skipped
787
- if self.env.app:
883
+ if self._events is not None:
788
884
  # let extensions preprocess docstrings
789
- skip_user = self.env.app.emit_firstresult(
790
- 'autodoc-skip-member', self.objtype, membername, member,
791
- not keep, self.options)
885
+ skip_user = self._events.emit_firstresult(
886
+ 'autodoc-skip-member',
887
+ self.objtype,
888
+ membername,
889
+ member,
890
+ not keep,
891
+ self.options,
892
+ )
792
893
  if skip_user is not None:
793
894
  keep = not skip_user
794
895
  except Exception as exc:
795
- logger.warning(__('autodoc: failed to determine %s.%s (%r) to be documented, '
796
- 'the following exception was raised:\n%s'),
797
- self.name, membername, member, exc, type='autodoc')
896
+ logger.warning(
897
+ __(
898
+ 'autodoc: failed to determine %s.%s (%r) to be documented, '
899
+ 'the following exception was raised:\n%s'
900
+ ),
901
+ self.name,
902
+ membername,
903
+ member,
904
+ exc,
905
+ type='autodoc',
906
+ )
798
907
  keep = False
799
908
 
800
909
  if keep:
@@ -809,21 +918,24 @@ class Documenter:
809
918
  *self.options.members*.
810
919
  """
811
920
  # set current namespace for finding members
812
- self.env.temp_data['autodoc:module'] = self.modname
921
+ self._current_document.autodoc_module = self.modname
813
922
  if self.objpath:
814
- self.env.temp_data['autodoc:class'] = self.objpath[0]
923
+ self._current_document.autodoc_class = self.objpath[0]
815
924
 
816
- want_all = (all_members or
817
- self.options.inherited_members or
818
- self.options.members is ALL)
925
+ want_all = (
926
+ all_members or self.options.inherited_members or self.options.members is ALL
927
+ )
819
928
  # find out which members are documentable
820
929
  members_check_module, members = self.get_object_members(want_all)
821
930
 
822
931
  # document non-skipped members
823
- memberdocumenters: list[tuple[Documenter, bool]] = []
824
- for (mname, member, isattr) in self.filter_members(members, want_all):
825
- classes = [cls for cls in self.documenters.values()
826
- if cls.can_document_member(member, mname, isattr, self)]
932
+ member_documenters: list[tuple[Documenter, bool]] = []
933
+ for mname, member, isattr in self.filter_members(members, want_all):
934
+ classes = [
935
+ cls
936
+ for cls in self.documenters.values()
937
+ if cls.can_document_member(member, mname, isattr, self)
938
+ ]
827
939
  if not classes:
828
940
  # don't know how to document this member
829
941
  continue
@@ -833,22 +945,39 @@ class Documenter:
833
945
  # of inner classes can be documented
834
946
  full_mname = f'{self.modname}::' + '.'.join((*self.objpath, mname))
835
947
  documenter = classes[-1](self.directive, full_mname, self.indent)
836
- memberdocumenters.append((documenter, isattr))
948
+ member_documenters.append((documenter, isattr))
837
949
 
838
950
  member_order = self.options.member_order or self.config.autodoc_member_order
839
- memberdocumenters = self.sort_members(memberdocumenters, member_order)
840
-
841
- for documenter, isattr in memberdocumenters:
842
- documenter.generate(
843
- all_members=True, real_modname=self.real_modname,
844
- check_module=members_check_module and not isattr)
951
+ # We now try to import all objects before ordering them. This is to
952
+ # avoid possible circular imports if we were to import objects after
953
+ # their associated documenters have been sorted.
954
+ member_documenters = [
955
+ (documenter, isattr)
956
+ for documenter, isattr in member_documenters
957
+ if documenter.parse_name() and documenter.import_object()
958
+ ]
959
+ member_documenters = self.sort_members(member_documenters, member_order)
960
+
961
+ for documenter, isattr in member_documenters:
962
+ assert documenter.modname
963
+ # We can directly call ._generate() since the documenters
964
+ # already called parse_name() and import_object() before.
965
+ #
966
+ # Note that those two methods above do not emit events, so
967
+ # whatever objects we deduced should not have changed.
968
+ documenter._generate(
969
+ all_members=True,
970
+ real_modname=self.real_modname,
971
+ check_module=members_check_module and not isattr,
972
+ )
845
973
 
846
974
  # reset current objects
847
- self.env.temp_data['autodoc:module'] = None
848
- self.env.temp_data['autodoc:class'] = None
975
+ self._current_document.autodoc_module = ''
976
+ self._current_document.autodoc_class = ''
849
977
 
850
- def sort_members(self, documenters: list[tuple[Documenter, bool]],
851
- order: str) -> list[tuple[Documenter, bool]]:
978
+ def sort_members(
979
+ self, documenters: list[tuple[Documenter, bool]], order: str
980
+ ) -> list[tuple[Documenter, bool]]:
852
981
  """Sort the given member list."""
853
982
  if order == 'groupwise':
854
983
  # sort by group; alphabetically within groups
@@ -863,6 +992,7 @@ class Documenter:
863
992
  def keyfunc(entry: tuple[Documenter, bool]) -> int:
864
993
  fullname = entry[0].name.split('::')[1]
865
994
  return tagorder.get(fullname, len(tagorder))
995
+
866
996
  documenters.sort(key=keyfunc)
867
997
  else: # alphabetical
868
998
  documenters.sort(key=lambda e: e[0].name)
@@ -887,16 +1017,29 @@ class Documenter:
887
1017
  if not self.parse_name():
888
1018
  # need a module to import
889
1019
  logger.warning(
890
- __("don't know which module to import for autodocumenting "
891
- '%r (try placing a "module" or "currentmodule" directive '
892
- 'in the document, or giving an explicit module name)'),
893
- self.name, type='autodoc')
1020
+ __(
1021
+ "don't know which module to import for autodocumenting "
1022
+ '%r (try placing a "module" or "currentmodule" directive '
1023
+ 'in the document, or giving an explicit module name)'
1024
+ ),
1025
+ self.name,
1026
+ type='autodoc',
1027
+ )
894
1028
  return
895
1029
 
896
1030
  # now, import the module and get object to document
897
1031
  if not self.import_object():
898
1032
  return
899
1033
 
1034
+ self._generate(more_content, real_modname, check_module, all_members)
1035
+
1036
+ def _generate(
1037
+ self,
1038
+ more_content: StringList | None = None,
1039
+ real_modname: str | None = None,
1040
+ check_module: bool = False,
1041
+ all_members: bool = False,
1042
+ ) -> None:
900
1043
  # If there is no real module defined, figure out which to use.
901
1044
  # The real module is used in the module analyzer to look up the module
902
1045
  # where the attribute documentation would actually be found in.
@@ -929,10 +1072,16 @@ class Documenter:
929
1072
  except PycodeError:
930
1073
  pass
931
1074
 
932
- docstrings: list[str] = functools.reduce(operator.iadd, self.get_doc() or [], [])
1075
+ docstrings: list[str] = functools.reduce(
1076
+ operator.iadd, self.get_doc() or [], []
1077
+ )
933
1078
  if ismock(self.object) and not docstrings:
934
- logger.warning(__('A mocked object is detected: %r'),
935
- self.name, type='autodoc')
1079
+ logger.warning(
1080
+ __('A mocked object is detected: %r'),
1081
+ self.name,
1082
+ type='autodoc',
1083
+ subtype='mocked_object',
1084
+ )
936
1085
 
937
1086
  # check __module__ of object (for members not given explicitly)
938
1087
  if check_module:
@@ -950,8 +1099,12 @@ class Documenter:
950
1099
  try:
951
1100
  sig = self.format_signature()
952
1101
  except Exception as exc:
953
- logger.warning(__('error while formatting signature for %s: %s'),
954
- self.fullname, exc, type='autodoc')
1102
+ logger.warning(
1103
+ __('error while formatting signature for %s: %s'),
1104
+ self.fullname,
1105
+ exc,
1106
+ type='autodoc',
1107
+ )
955
1108
  return
956
1109
 
957
1110
  # generate the directive header and options, if applicable
@@ -969,22 +1122,28 @@ class Documenter:
969
1122
 
970
1123
 
971
1124
  class ModuleDocumenter(Documenter):
972
- """
973
- Specialized Documenter subclass for modules.
974
- """
1125
+ """Specialized Documenter subclass for modules."""
975
1126
 
976
1127
  objtype = 'module'
977
1128
  content_indent = ''
978
1129
  _extra_indent = ' '
979
1130
 
980
1131
  option_spec: ClassVar[OptionSpec] = {
981
- 'members': members_option, 'undoc-members': bool_option,
982
- 'no-index': bool_option, 'inherited-members': inherited_members_option,
983
- 'show-inheritance': bool_option, 'synopsis': identity,
984
- 'platform': identity, 'deprecated': bool_option,
985
- 'member-order': member_order_option, 'exclude-members': exclude_members_option,
986
- 'private-members': members_option, 'special-members': members_option,
987
- 'imported-members': bool_option, 'ignore-module-all': bool_option,
1132
+ 'members': members_option,
1133
+ 'undoc-members': bool_option,
1134
+ 'no-index': bool_option,
1135
+ 'no-index-entry': bool_option,
1136
+ 'inherited-members': inherited_members_option,
1137
+ 'show-inheritance': bool_option,
1138
+ 'synopsis': identity,
1139
+ 'platform': identity,
1140
+ 'deprecated': bool_option,
1141
+ 'member-order': member_order_option,
1142
+ 'exclude-members': exclude_members_option,
1143
+ 'private-members': members_option,
1144
+ 'special-members': members_option,
1145
+ 'imported-members': bool_option,
1146
+ 'ignore-module-all': bool_option,
988
1147
  'no-value': bool_option,
989
1148
  'noindex': bool_option,
990
1149
  }
@@ -1005,24 +1164,28 @@ class ModuleDocumenter(Documenter):
1005
1164
 
1006
1165
  @classmethod
1007
1166
  def can_document_member(
1008
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
1167
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
1009
1168
  ) -> bool:
1010
1169
  # don't document submodules automatically
1011
1170
  return False
1012
1171
 
1013
- def resolve_name(self, modname: str | None, parents: Any, path: str, base: str,
1014
- ) -> tuple[str | None, list[str]]:
1172
+ def resolve_name(
1173
+ self, modname: str | None, parents: Any, path: str, base: str
1174
+ ) -> tuple[str | None, list[str]]:
1015
1175
  if modname is not None:
1016
- logger.warning(__('"::" in automodule name doesn\'t make sense'),
1017
- type='autodoc')
1176
+ logger.warning(
1177
+ __('"::" in automodule name doesn\'t make sense'), type='autodoc'
1178
+ )
1018
1179
  return (path or '') + base, []
1019
1180
 
1020
1181
  def parse_name(self) -> bool:
1021
1182
  ret = super().parse_name()
1022
1183
  if self.args or self.retann:
1023
- logger.warning(__('signature arguments or return annotation '
1024
- 'given for automodule %s'), self.fullname,
1025
- type='autodoc')
1184
+ logger.warning(
1185
+ __('signature arguments or return annotation given for automodule %s'),
1186
+ self.fullname,
1187
+ type='autodoc',
1188
+ )
1026
1189
  return ret
1027
1190
 
1028
1191
  def import_object(self, raiseerror: bool = False) -> bool:
@@ -1033,9 +1196,15 @@ class ModuleDocumenter(Documenter):
1033
1196
  self.__all__ = inspect.getall(self.object)
1034
1197
  except ValueError as exc:
1035
1198
  # invalid __all__ found.
1036
- logger.warning(__('__all__ should be a list of strings, not %r '
1037
- '(in module %s) -- ignoring __all__'),
1038
- exc.args[0], self.fullname, type='autodoc')
1199
+ logger.warning(
1200
+ __(
1201
+ '__all__ should be a list of strings, not %r '
1202
+ '(in module %s) -- ignoring __all__'
1203
+ ),
1204
+ exc.args[0],
1205
+ self.fullname,
1206
+ type='autodoc',
1207
+ )
1039
1208
 
1040
1209
  return ret
1041
1210
 
@@ -1051,6 +1220,8 @@ class ModuleDocumenter(Documenter):
1051
1220
  self.add_line(' :platform: ' + self.options.platform, sourcename)
1052
1221
  if self.options.deprecated:
1053
1222
  self.add_line(' :deprecated:', sourcename)
1223
+ if self.options.no_index_entry:
1224
+ self.add_line(' :no-index-entry:', sourcename)
1054
1225
 
1055
1226
  def get_module_members(self) -> dict[str, ObjectMember]:
1056
1227
  """Get members of target module."""
@@ -1066,7 +1237,9 @@ class ModuleDocumenter(Documenter):
1066
1237
  if ismock(value):
1067
1238
  value = undecorate(value)
1068
1239
  docstring = attr_docs.get(('', name), [])
1069
- members[name] = ObjectMember(name, value, docstring="\n".join(docstring))
1240
+ members[name] = ObjectMember(
1241
+ name, value, docstring='\n'.join(docstring)
1242
+ )
1070
1243
  except AttributeError:
1071
1244
  continue
1072
1245
 
@@ -1074,8 +1247,9 @@ class ModuleDocumenter(Documenter):
1074
1247
  for name in inspect.getannotations(self.object):
1075
1248
  if name not in members:
1076
1249
  docstring = attr_docs.get(('', name), [])
1077
- members[name] = ObjectMember(name, INSTANCEATTR,
1078
- docstring="\n".join(docstring))
1250
+ members[name] = ObjectMember(
1251
+ name, INSTANCEATTR, docstring='\n'.join(docstring)
1252
+ )
1079
1253
 
1080
1254
  return members
1081
1255
 
@@ -1099,15 +1273,20 @@ class ModuleDocumenter(Documenter):
1099
1273
  if name in members:
1100
1274
  ret.append(members[name])
1101
1275
  else:
1102
- logger.warning(__('missing attribute mentioned in :members: option: '
1103
- 'module %s, attribute %s'),
1104
- safe_getattr(self.object, '__name__', '???'),
1105
- name,
1106
- type='autodoc')
1276
+ logger.warning(
1277
+ __(
1278
+ 'missing attribute mentioned in :members: option: '
1279
+ 'module %s, attribute %s'
1280
+ ),
1281
+ safe_getattr(self.object, '__name__', '???'),
1282
+ name,
1283
+ type='autodoc',
1284
+ )
1107
1285
  return False, ret
1108
1286
 
1109
- def sort_members(self, documenters: list[tuple[Documenter, bool]],
1110
- order: str) -> list[tuple[Documenter, bool]]:
1287
+ def sort_members(
1288
+ self, documenters: list[tuple[Documenter, bool]], order: str
1289
+ ) -> list[tuple[Documenter, bool]]:
1111
1290
  if order == 'bysource' and self.__all__:
1112
1291
  assert self.__all__ is not None
1113
1292
  module_all = self.__all__
@@ -1124,6 +1303,7 @@ class ModuleDocumenter(Documenter):
1124
1303
  return module_all.index(name)
1125
1304
  else:
1126
1305
  return module_all_len
1306
+
1127
1307
  documenters.sort(key=keyfunc)
1128
1308
 
1129
1309
  return documenters
@@ -1132,13 +1312,13 @@ class ModuleDocumenter(Documenter):
1132
1312
 
1133
1313
 
1134
1314
  class ModuleLevelDocumenter(Documenter):
1135
- """
1136
- Specialized Documenter subclass for objects on module level (functions,
1315
+ """Specialized Documenter subclass for objects on module level (functions,
1137
1316
  classes, data/constants).
1138
1317
  """
1139
1318
 
1140
- def resolve_name(self, modname: str | None, parents: Any, path: str, base: str,
1141
- ) -> tuple[str | None, list[str]]:
1319
+ def resolve_name(
1320
+ self, modname: str | None, parents: Any, path: str, base: str
1321
+ ) -> tuple[str | None, list[str]]:
1142
1322
  if modname is not None:
1143
1323
  return modname, [*parents, base]
1144
1324
  if path:
@@ -1147,7 +1327,7 @@ class ModuleLevelDocumenter(Documenter):
1147
1327
 
1148
1328
  # if documenting a toplevel object without explicit module,
1149
1329
  # it can be contained in another auto directive ...
1150
- modname = self.env.temp_data.get('autodoc:module')
1330
+ modname = self._current_document.autodoc_module
1151
1331
  # ... or in the scope of a module directive
1152
1332
  if not modname:
1153
1333
  modname = self.env.ref_context.get('py:module')
@@ -1156,13 +1336,13 @@ class ModuleLevelDocumenter(Documenter):
1156
1336
 
1157
1337
 
1158
1338
  class ClassLevelDocumenter(Documenter):
1159
- """
1160
- Specialized Documenter subclass for objects on class level (methods,
1339
+ """Specialized Documenter subclass for objects on class level (methods,
1161
1340
  attributes).
1162
1341
  """
1163
1342
 
1164
- def resolve_name(self, modname: str | None, parents: Any, path: str, base: str,
1165
- ) -> tuple[str | None, list[str]]:
1343
+ def resolve_name(
1344
+ self, modname: str | None, parents: Any, path: str, base: str
1345
+ ) -> tuple[str | None, list[str]]:
1166
1346
  if modname is not None:
1167
1347
  return modname, [*parents, base]
1168
1348
 
@@ -1172,19 +1352,18 @@ class ClassLevelDocumenter(Documenter):
1172
1352
  # if documenting a class-level object without path,
1173
1353
  # there must be a current class, either from a parent
1174
1354
  # auto directive ...
1175
- mod_cls_ = self.env.temp_data.get('autodoc:class')
1355
+ mod_cls = self._current_document.autodoc_class
1176
1356
  # ... or from a class directive
1177
- if mod_cls_ is None:
1178
- mod_cls_ = self.env.ref_context.get('py:class')
1179
- # ... if still None, there's no way to know
1180
- if mod_cls_ is None:
1357
+ if not mod_cls:
1358
+ mod_cls = self.env.ref_context.get('py:class', '')
1359
+ # ... if still falsy, there's no way to know
1360
+ if not mod_cls:
1181
1361
  return None, []
1182
- mod_cls = mod_cls_
1183
1362
  modname, sep, cls = mod_cls.rpartition('.')
1184
1363
  parents = [cls]
1185
1364
  # if the module name is still missing, get it like above
1186
1365
  if not modname:
1187
- modname = self.env.temp_data.get('autodoc:module')
1366
+ modname = self._current_document.autodoc_module
1188
1367
  if not modname:
1189
1368
  modname = self.env.ref_context.get('py:module')
1190
1369
  # ... else, it stays None, which means invalid
@@ -1192,8 +1371,7 @@ class ClassLevelDocumenter(Documenter):
1192
1371
 
1193
1372
 
1194
1373
  class DocstringSignatureMixin:
1195
- """
1196
- Mixin for FunctionDocumenter and MethodDocumenter to provide the
1374
+ """Mixin for FunctionDocumenter and MethodDocumenter to provide the
1197
1375
  feature of reading the signature from the docstring.
1198
1376
  """
1199
1377
 
@@ -1236,15 +1414,16 @@ class DocstringSignatureMixin:
1236
1414
  # re-prepare docstring to ignore more leading indentation
1237
1415
  directive = self.directive # type: ignore[attr-defined]
1238
1416
  tab_width = directive.state.document.settings.tab_width
1239
- self._new_docstrings[i] = prepare_docstring('\n'.join(doclines[j + 1:]),
1240
- tab_width)
1417
+ self._new_docstrings[i] = prepare_docstring(
1418
+ '\n'.join(doclines[j + 1 :]), tab_width
1419
+ )
1241
1420
 
1242
1421
  if result is None:
1243
1422
  # first signature
1244
1423
  result = args, retann
1245
1424
  else:
1246
1425
  # subsequent signatures
1247
- self._signatures.append(f"({args}) -> {retann}")
1426
+ self._signatures.append(f'({args}) -> {retann}')
1248
1427
 
1249
1428
  if result is not None:
1250
1429
  # finish the loop when signature found
@@ -1259,8 +1438,7 @@ class DocstringSignatureMixin:
1259
1438
 
1260
1439
  def format_signature(self, **kwargs: Any) -> str:
1261
1440
  self.args: str | None
1262
- if (self.args is None
1263
- and self.config.autodoc_docstring_signature): # type: ignore[attr-defined]
1441
+ if self.args is None and self.config.autodoc_docstring_signature: # type: ignore[attr-defined]
1264
1442
  # only act if a signature is not explicitly given already, and if
1265
1443
  # the feature is enabled
1266
1444
  result = self._find_signature()
@@ -1268,22 +1446,18 @@ class DocstringSignatureMixin:
1268
1446
  self.args, self.retann = result
1269
1447
  sig = super().format_signature(**kwargs) # type: ignore[misc]
1270
1448
  if self._signatures:
1271
- return "\n".join((sig, *self._signatures))
1449
+ return '\n'.join((sig, *self._signatures))
1272
1450
  else:
1273
1451
  return sig
1274
1452
 
1275
1453
 
1276
1454
  class DocstringStripSignatureMixin(DocstringSignatureMixin):
1277
- """
1278
- Mixin for AttributeDocumenter to provide the
1455
+ """Mixin for AttributeDocumenter to provide the
1279
1456
  feature of stripping any function signature from the docstring.
1280
1457
  """
1281
1458
 
1282
1459
  def format_signature(self, **kwargs: Any) -> str:
1283
- if (
1284
- self.args is None
1285
- and self.config.autodoc_docstring_signature # type: ignore[attr-defined]
1286
- ):
1460
+ if self.args is None and self.config.autodoc_docstring_signature: # type: ignore[attr-defined]
1287
1461
  # only act if a signature is not explicitly given already, and if
1288
1462
  # the feature is enabled
1289
1463
  result = self._find_signature()
@@ -1296,34 +1470,40 @@ class DocstringStripSignatureMixin(DocstringSignatureMixin):
1296
1470
 
1297
1471
 
1298
1472
  class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: ignore[misc]
1299
- """
1300
- Specialized Documenter subclass for functions.
1301
- """
1473
+ """Specialized Documenter subclass for functions."""
1302
1474
 
1303
1475
  objtype = 'function'
1304
1476
  member_order = 30
1305
1477
 
1306
1478
  @classmethod
1307
1479
  def can_document_member(
1308
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
1480
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
1309
1481
  ) -> bool:
1310
1482
  # supports functions, builtins and bound methods exported at the module level
1311
- return (inspect.isfunction(member) or inspect.isbuiltin(member) or
1312
- (inspect.isroutine(member) and isinstance(parent, ModuleDocumenter)))
1483
+ return (
1484
+ inspect.isfunction(member)
1485
+ or inspect.isbuiltin(member)
1486
+ or (inspect.isroutine(member) and isinstance(parent, ModuleDocumenter))
1487
+ )
1313
1488
 
1314
1489
  def format_args(self, **kwargs: Any) -> str:
1315
- if self.config.autodoc_typehints in ('none', 'description'):
1490
+ if self.config.autodoc_typehints in {'none', 'description'}:
1316
1491
  kwargs.setdefault('show_annotation', False)
1317
- if self.config.autodoc_typehints_format == "short":
1492
+ if self.config.autodoc_typehints_format == 'short':
1318
1493
  kwargs.setdefault('unqualified_typehints', True)
1494
+ if self.config.python_display_short_literal_types:
1495
+ kwargs.setdefault('short_literals', True)
1319
1496
 
1320
1497
  try:
1321
- self.env.app.emit('autodoc-before-process-signature', self.object, False)
1322
- sig = inspect.signature(self.object, type_aliases=self.config.autodoc_type_aliases)
1498
+ self._events.emit('autodoc-before-process-signature', self.object, False)
1499
+ sig = inspect.signature(
1500
+ self.object, type_aliases=self.config.autodoc_type_aliases
1501
+ )
1323
1502
  args = stringify_signature(sig, **kwargs)
1324
1503
  except TypeError as exc:
1325
- logger.warning(__("Failed to get a function signature for %s: %s"),
1326
- self.fullname, exc)
1504
+ logger.warning(
1505
+ __('Failed to get a function signature for %s: %s'), self.fullname, exc
1506
+ )
1327
1507
  return ''
1328
1508
  except ValueError:
1329
1509
  args = ''
@@ -1340,17 +1520,23 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
1340
1520
  sourcename = self.get_sourcename()
1341
1521
  super().add_directive_header(sig)
1342
1522
 
1343
- if inspect.iscoroutinefunction(self.object) or inspect.isasyncgenfunction(self.object):
1523
+ is_coro = inspect.iscoroutinefunction(self.object)
1524
+ is_acoro = inspect.isasyncgenfunction(self.object)
1525
+ if is_coro or is_acoro:
1344
1526
  self.add_line(' :async:', sourcename)
1345
1527
 
1346
1528
  def format_signature(self, **kwargs: Any) -> str:
1347
- if self.config.autodoc_typehints_format == "short":
1529
+ if self.config.autodoc_typehints_format == 'short':
1348
1530
  kwargs.setdefault('unqualified_typehints', True)
1531
+ if self.config.python_display_short_literal_types:
1532
+ kwargs.setdefault('short_literals', True)
1349
1533
 
1350
1534
  sigs = []
1351
- if (self.analyzer and
1352
- '.'.join(self.objpath) in self.analyzer.overloads and
1353
- self.config.autodoc_typehints != 'none'):
1535
+ if (
1536
+ self.analyzer
1537
+ and '.'.join(self.objpath) in self.analyzer.overloads
1538
+ and self.config.autodoc_typehints != 'none'
1539
+ ):
1354
1540
  # Use signatures for overloaded functions instead of the implementation function.
1355
1541
  overloaded = True
1356
1542
  else:
@@ -1371,18 +1557,20 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
1371
1557
  documenter.objpath = ['']
1372
1558
  sigs.append(documenter.format_signature())
1373
1559
  if overloaded and self.analyzer is not None:
1374
- actual = inspect.signature(self.object,
1375
- type_aliases=self.config.autodoc_type_aliases)
1560
+ actual = inspect.signature(
1561
+ self.object, type_aliases=self.config.autodoc_type_aliases
1562
+ )
1376
1563
  __globals__ = safe_getattr(self.object, '__globals__', {})
1377
1564
  for overload in self.analyzer.overloads['.'.join(self.objpath)]:
1378
1565
  overload = self.merge_default_value(actual, overload)
1379
- overload = evaluate_signature(overload, __globals__,
1380
- self.config.autodoc_type_aliases)
1566
+ overload = evaluate_signature(
1567
+ overload, __globals__, self.config.autodoc_type_aliases
1568
+ )
1381
1569
 
1382
1570
  sig = stringify_signature(overload, **kwargs)
1383
1571
  sigs.append(sig)
1384
1572
 
1385
- return "\n".join(sigs)
1573
+ return '\n'.join(sigs)
1386
1574
 
1387
1575
  def merge_default_value(self, actual: Signature, overload: Signature) -> Signature:
1388
1576
  """Merge default values of actual implementation to the overload variants."""
@@ -1394,13 +1582,16 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
1394
1582
 
1395
1583
  return overload.replace(parameters=parameters)
1396
1584
 
1397
- def annotate_to_first_argument(self, func: Callable, typ: type) -> Callable | None:
1585
+ def annotate_to_first_argument(
1586
+ self, func: Callable[..., Any], typ: type
1587
+ ) -> Callable[..., Any] | None:
1398
1588
  """Annotate type hint to the first argument of function if needed."""
1399
1589
  try:
1400
1590
  sig = inspect.signature(func, type_aliases=self.config.autodoc_type_aliases)
1401
1591
  except TypeError as exc:
1402
- logger.warning(__("Failed to get a function signature for %s: %s"),
1403
- self.fullname, exc)
1592
+ logger.warning(
1593
+ __('Failed to get a function signature for %s: %s'), self.fullname, exc
1594
+ )
1404
1595
  return None
1405
1596
  except ValueError:
1406
1597
  return None
@@ -1415,8 +1606,7 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
1415
1606
  if params[0].annotation is Parameter.empty:
1416
1607
  params[0] = params[0].replace(annotation=typ)
1417
1608
  try:
1418
- dummy.__signature__ = sig.replace( # type: ignore[attr-defined]
1419
- parameters=params)
1609
+ dummy.__signature__ = sig.replace(parameters=params) # type: ignore[attr-defined]
1420
1610
  return dummy
1421
1611
  except (AttributeError, TypeError):
1422
1612
  # failed to update signature (ex. built-in or extension types)
@@ -1426,9 +1616,7 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
1426
1616
 
1427
1617
 
1428
1618
  class DecoratorDocumenter(FunctionDocumenter):
1429
- """
1430
- Specialized Documenter subclass for decorator functions.
1431
- """
1619
+ """Specialized Documenter subclass for decorator functions."""
1432
1620
 
1433
1621
  objtype = 'decorator'
1434
1622
 
@@ -1446,30 +1634,33 @@ class DecoratorDocumenter(FunctionDocumenter):
1446
1634
  # Types which have confusing metaclass signatures it would be best not to show.
1447
1635
  # These are listed by name, rather than storing the objects themselves, to avoid
1448
1636
  # needing to import the modules.
1449
- _METACLASS_CALL_BLACKLIST = [
1450
- 'enum.EnumMeta.__call__',
1451
- ]
1637
+ _METACLASS_CALL_BLACKLIST = frozenset({
1638
+ 'enum.EnumType.__call__',
1639
+ })
1452
1640
 
1453
1641
 
1454
1642
  # Types whose __new__ signature is a pass-through.
1455
- _CLASS_NEW_BLACKLIST = [
1643
+ _CLASS_NEW_BLACKLIST = frozenset({
1456
1644
  'typing.Generic.__new__',
1457
- ]
1645
+ })
1458
1646
 
1459
1647
 
1460
1648
  class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: ignore[misc]
1461
- """
1462
- Specialized Documenter subclass for classes.
1463
- """
1649
+ """Specialized Documenter subclass for classes."""
1464
1650
 
1465
1651
  objtype = 'class'
1466
1652
  member_order = 20
1467
1653
  option_spec: ClassVar[OptionSpec] = {
1468
- 'members': members_option, 'undoc-members': bool_option,
1469
- 'no-index': bool_option, 'inherited-members': inherited_members_option,
1470
- 'show-inheritance': bool_option, 'member-order': member_order_option,
1654
+ 'members': members_option,
1655
+ 'undoc-members': bool_option,
1656
+ 'no-index': bool_option,
1657
+ 'no-index-entry': bool_option,
1658
+ 'inherited-members': inherited_members_option,
1659
+ 'show-inheritance': bool_option,
1660
+ 'member-order': member_order_option,
1471
1661
  'exclude-members': exclude_members_option,
1472
- 'private-members': members_option, 'special-members': members_option,
1662
+ 'private-members': members_option,
1663
+ 'special-members': members_option,
1473
1664
  'class-doc-from': class_doc_from_option,
1474
1665
  'noindex': bool_option,
1475
1666
  }
@@ -1499,10 +1690,11 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1499
1690
 
1500
1691
  @classmethod
1501
1692
  def can_document_member(
1502
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
1693
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
1503
1694
  ) -> bool:
1504
1695
  return isinstance(member, type) or (
1505
- isattr and isinstance(member, NewType | TypeVar))
1696
+ isattr and isinstance(member, NewType | TypeVar)
1697
+ )
1506
1698
 
1507
1699
  def import_object(self, raiseerror: bool = False) -> bool:
1508
1700
  ret = super().import_object(raiseerror)
@@ -1510,13 +1702,13 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1510
1702
  # as data/attribute
1511
1703
  if ret:
1512
1704
  if hasattr(self.object, '__name__'):
1513
- self.doc_as_attr = (self.objpath[-1] != self.object.__name__)
1705
+ self.doc_as_attr = self.objpath[-1] != self.object.__name__
1514
1706
  else:
1515
1707
  self.doc_as_attr = True
1516
1708
  if isinstance(self.object, NewType | TypeVar):
1517
1709
  modname = getattr(self.object, '__module__', self.modname)
1518
1710
  if modname != self.modname and self.modname.startswith(modname):
1519
- bases = self.modname[len(modname):].strip('.').split('.')
1711
+ bases = self.modname[len(modname) :].strip('.').split('.')
1520
1712
  self.objpath = bases + self.objpath
1521
1713
  self.modname = modname
1522
1714
  return ret
@@ -1538,24 +1730,32 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1538
1730
  # This sequence is copied from inspect._signature_from_callable.
1539
1731
  # ValueError means that no signature could be found, so we keep going.
1540
1732
 
1541
- # First, we check the obj has a __signature__ attribute
1542
- if (hasattr(self.object, '__signature__') and
1543
- isinstance(self.object.__signature__, Signature)):
1544
- return None, None, self.object.__signature__
1733
+ # First, we check if obj has a __signature__ attribute
1734
+ if hasattr(self.object, '__signature__'):
1735
+ object_sig = self.object.__signature__
1736
+ if isinstance(object_sig, Signature):
1737
+ return None, None, object_sig
1738
+ if sys.version_info[:2] in {(3, 12), (3, 13)} and callable(object_sig):
1739
+ # Support for enum.Enum.__signature__ in Python 3.12
1740
+ if isinstance(object_sig_str := object_sig(), str):
1741
+ return None, None, inspect.signature_from_str(object_sig_str)
1545
1742
 
1546
1743
  # Next, let's see if it has an overloaded __call__ defined
1547
1744
  # in its metaclass
1548
1745
  call = get_user_defined_function_or_method(type(self.object), '__call__')
1549
1746
 
1550
1747
  if call is not None:
1551
- if f"{call.__module__}.{call.__qualname__}" in _METACLASS_CALL_BLACKLIST:
1748
+ if f'{call.__module__}.{call.__qualname__}' in _METACLASS_CALL_BLACKLIST:
1552
1749
  call = None
1553
1750
 
1554
1751
  if call is not None:
1555
- self.env.app.emit('autodoc-before-process-signature', call, True)
1752
+ self._events.emit('autodoc-before-process-signature', call, True)
1556
1753
  try:
1557
- sig = inspect.signature(call, bound_method=True,
1558
- type_aliases=self.config.autodoc_type_aliases)
1754
+ sig = inspect.signature(
1755
+ call,
1756
+ bound_method=True,
1757
+ type_aliases=self.config.autodoc_type_aliases,
1758
+ )
1559
1759
  return type(self.object), '__call__', sig
1560
1760
  except ValueError:
1561
1761
  pass
@@ -1564,14 +1764,17 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1564
1764
  new = get_user_defined_function_or_method(self.object, '__new__')
1565
1765
 
1566
1766
  if new is not None:
1567
- if f"{new.__module__}.{new.__qualname__}" in _CLASS_NEW_BLACKLIST:
1767
+ if f'{new.__module__}.{new.__qualname__}' in _CLASS_NEW_BLACKLIST:
1568
1768
  new = None
1569
1769
 
1570
1770
  if new is not None:
1571
- self.env.app.emit('autodoc-before-process-signature', new, True)
1771
+ self._events.emit('autodoc-before-process-signature', new, True)
1572
1772
  try:
1573
- sig = inspect.signature(new, bound_method=True,
1574
- type_aliases=self.config.autodoc_type_aliases)
1773
+ sig = inspect.signature(
1774
+ new,
1775
+ bound_method=True,
1776
+ type_aliases=self.config.autodoc_type_aliases,
1777
+ )
1575
1778
  return self.object, '__new__', sig
1576
1779
  except ValueError:
1577
1780
  pass
@@ -1579,10 +1782,13 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1579
1782
  # Finally, we should have at least __init__ implemented
1580
1783
  init = get_user_defined_function_or_method(self.object, '__init__')
1581
1784
  if init is not None:
1582
- self.env.app.emit('autodoc-before-process-signature', init, True)
1785
+ self._events.emit('autodoc-before-process-signature', init, True)
1583
1786
  try:
1584
- sig = inspect.signature(init, bound_method=True,
1585
- type_aliases=self.config.autodoc_type_aliases)
1787
+ sig = inspect.signature(
1788
+ init,
1789
+ bound_method=True,
1790
+ type_aliases=self.config.autodoc_type_aliases,
1791
+ )
1586
1792
  return self.object, '__init__', sig
1587
1793
  except ValueError:
1588
1794
  pass
@@ -1591,10 +1797,13 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1591
1797
  # handle it.
1592
1798
  # We don't know the exact method that inspect.signature will read
1593
1799
  # the signature from, so just pass the object itself to our hook.
1594
- self.env.app.emit('autodoc-before-process-signature', self.object, False)
1800
+ self._events.emit('autodoc-before-process-signature', self.object, False)
1595
1801
  try:
1596
- sig = inspect.signature(self.object, bound_method=False,
1597
- type_aliases=self.config.autodoc_type_aliases)
1802
+ sig = inspect.signature(
1803
+ self.object,
1804
+ bound_method=False,
1805
+ type_aliases=self.config.autodoc_type_aliases,
1806
+ )
1598
1807
  return None, None, sig
1599
1808
  except ValueError:
1600
1809
  pass
@@ -1604,17 +1813,22 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1604
1813
  return None, None, None
1605
1814
 
1606
1815
  def format_args(self, **kwargs: Any) -> str:
1607
- if self.config.autodoc_typehints in ('none', 'description'):
1816
+ if self.config.autodoc_typehints in {'none', 'description'}:
1608
1817
  kwargs.setdefault('show_annotation', False)
1609
- if self.config.autodoc_typehints_format == "short":
1818
+ if self.config.autodoc_typehints_format == 'short':
1610
1819
  kwargs.setdefault('unqualified_typehints', True)
1820
+ if self.config.python_display_short_literal_types:
1821
+ kwargs.setdefault('short_literals', True)
1611
1822
 
1612
1823
  try:
1613
1824
  self._signature_class, _signature_method_name, sig = self._get_signature()
1614
1825
  except TypeError as exc:
1615
1826
  # __signature__ attribute contained junk
1616
- logger.warning(__("Failed to get a constructor signature for %s: %s"),
1617
- self.fullname, exc)
1827
+ logger.warning(
1828
+ __('Failed to get a constructor signature for %s: %s'),
1829
+ self.fullname,
1830
+ exc,
1831
+ )
1618
1832
  return ''
1619
1833
  self._signature_method_name = _signature_method_name or ''
1620
1834
 
@@ -1644,8 +1858,10 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1644
1858
  # do not show signatures
1645
1859
  return ''
1646
1860
 
1647
- if self.config.autodoc_typehints_format == "short":
1861
+ if self.config.autodoc_typehints_format == 'short':
1648
1862
  kwargs.setdefault('unqualified_typehints', True)
1863
+ if self.config.python_display_short_literal_types:
1864
+ kwargs.setdefault('short_literals', True)
1649
1865
 
1650
1866
  sig = super().format_signature()
1651
1867
  sigs = []
@@ -1653,21 +1869,25 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1653
1869
  overloads = self.get_overloaded_signatures()
1654
1870
  if overloads and self.config.autodoc_typehints != 'none':
1655
1871
  # Use signatures for overloaded methods instead of the implementation method.
1656
- method = safe_getattr(self._signature_class, self._signature_method_name, None)
1872
+ method = safe_getattr(
1873
+ self._signature_class, self._signature_method_name, None
1874
+ )
1657
1875
  __globals__ = safe_getattr(method, '__globals__', {})
1658
1876
  for overload in overloads:
1659
- overload = evaluate_signature(overload, __globals__,
1660
- self.config.autodoc_type_aliases)
1877
+ overload = evaluate_signature(
1878
+ overload, __globals__, self.config.autodoc_type_aliases
1879
+ )
1661
1880
 
1662
1881
  parameters = list(overload.parameters.values())
1663
- overload = overload.replace(parameters=parameters[1:],
1664
- return_annotation=Parameter.empty)
1882
+ overload = overload.replace(
1883
+ parameters=parameters[1:], return_annotation=Parameter.empty
1884
+ )
1665
1885
  sig = stringify_signature(overload, **kwargs)
1666
1886
  sigs.append(sig)
1667
1887
  else:
1668
1888
  sigs.append(sig)
1669
1889
 
1670
- return "\n".join(sigs)
1890
+ return '\n'.join(sigs)
1671
1891
 
1672
1892
  def get_overloaded_signatures(self) -> list[Signature]:
1673
1893
  if self._signature_class and self._signature_method_name:
@@ -1714,8 +1934,12 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1714
1934
  self.add_line(' :final:', sourcename)
1715
1935
 
1716
1936
  canonical_fullname = self.get_canonical_fullname()
1717
- if (not self.doc_as_attr and not isinstance(self.object, NewType)
1718
- and canonical_fullname and self.fullname != canonical_fullname):
1937
+ if (
1938
+ not self.doc_as_attr
1939
+ and not isinstance(self.object, NewType)
1940
+ and canonical_fullname
1941
+ and self.fullname != canonical_fullname
1942
+ ):
1719
1943
  self.add_line(' :canonical: %s' % canonical_fullname, sourcename)
1720
1944
 
1721
1945
  # add inheritance info, if wanted
@@ -1730,21 +1954,24 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1730
1954
  else:
1731
1955
  bases = []
1732
1956
 
1733
- self.env.events.emit('autodoc-process-bases',
1734
- self.fullname, self.object, self.options, bases)
1957
+ self._events.emit(
1958
+ 'autodoc-process-bases', self.fullname, self.object, self.options, bases
1959
+ )
1735
1960
 
1736
- if self.config.autodoc_typehints_format == "short":
1737
- base_classes = [restify(cls, "smart") for cls in bases]
1738
- else:
1739
- base_classes = [restify(cls) for cls in bases]
1961
+ mode = _get_render_mode(self.config.autodoc_typehints_format)
1962
+ base_classes = [restify(cls, mode=mode) for cls in bases]
1740
1963
 
1741
1964
  sourcename = self.get_sourcename()
1742
1965
  self.add_line('', sourcename)
1743
1966
  self.add_line(' ' + _('Bases: %s') % ', '.join(base_classes), sourcename)
1744
1967
 
1745
1968
  def get_object_members(self, want_all: bool) -> tuple[bool, list[ObjectMember]]:
1746
- members = get_class_members(self.object, self.objpath, self.get_attr,
1747
- self.config.autodoc_inherit_docstrings)
1969
+ members = get_class_members(
1970
+ self.object,
1971
+ self.objpath,
1972
+ self.get_attr,
1973
+ self.config.autodoc_inherit_docstrings,
1974
+ )
1748
1975
  if not want_all:
1749
1976
  if not self.options.members:
1750
1977
  return False, []
@@ -1754,8 +1981,12 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1754
1981
  if name in members:
1755
1982
  selected.append(members[name])
1756
1983
  else:
1757
- logger.warning(__('missing attribute %s in object %s'),
1758
- name, self.fullname, type='autodoc')
1984
+ logger.warning(
1985
+ __('missing attribute %s in object %s'),
1986
+ name,
1987
+ self.fullname,
1988
+ type='autodoc',
1989
+ )
1759
1990
  return False, selected
1760
1991
  elif self.options.inherited_members:
1761
1992
  return False, list(members.values())
@@ -1777,7 +2008,9 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1777
2008
  if lines is not None:
1778
2009
  return lines
1779
2010
 
1780
- classdoc_from = self.options.get('class-doc-from', self.config.autoclass_content)
2011
+ classdoc_from = self.options.get(
2012
+ 'class-doc-from', self.config.autoclass_content
2013
+ )
1781
2014
 
1782
2015
  docstrings = []
1783
2016
  attrdocstring = getdoc(self.object, self.get_attr)
@@ -1786,26 +2019,36 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1786
2019
 
1787
2020
  # for classes, what the "docstring" is can be controlled via a
1788
2021
  # config value; the default is only the class docstring
1789
- if classdoc_from in ('both', 'init'):
2022
+ if classdoc_from in {'both', 'init'}:
1790
2023
  __init__ = self.get_attr(self.object, '__init__', None)
1791
- initdocstring = getdoc(__init__, self.get_attr,
1792
- self.config.autodoc_inherit_docstrings,
1793
- self.object, '__init__')
2024
+ initdocstring = getdoc(
2025
+ __init__,
2026
+ self.get_attr,
2027
+ self.config.autodoc_inherit_docstrings,
2028
+ self.object,
2029
+ '__init__',
2030
+ )
1794
2031
  # for new-style classes, no __init__ means default __init__
1795
- if (initdocstring is not None and
1796
- (initdocstring == object.__init__.__doc__ or # for pypy
1797
- initdocstring.strip() == object.__init__.__doc__)): # for !pypy
2032
+ if initdocstring is not None and (
2033
+ initdocstring == object.__init__.__doc__ # for pypy
2034
+ or initdocstring.strip() == object.__init__.__doc__ # for !pypy
2035
+ ):
1798
2036
  initdocstring = None
1799
2037
  if not initdocstring:
1800
2038
  # try __new__
1801
2039
  __new__ = self.get_attr(self.object, '__new__', None)
1802
- initdocstring = getdoc(__new__, self.get_attr,
1803
- self.config.autodoc_inherit_docstrings,
1804
- self.object, '__new__')
2040
+ initdocstring = getdoc(
2041
+ __new__,
2042
+ self.get_attr,
2043
+ self.config.autodoc_inherit_docstrings,
2044
+ self.object,
2045
+ '__new__',
2046
+ )
1805
2047
  # for new-style classes, no __new__ means default __new__
1806
- if (initdocstring is not None and
1807
- (initdocstring == object.__new__.__doc__ or # for pypy
1808
- initdocstring.strip() == object.__new__.__doc__)): # for !pypy
2048
+ if initdocstring is not None and (
2049
+ initdocstring == object.__new__.__doc__ # for pypy
2050
+ or initdocstring.strip() == object.__new__.__doc__ # for !pypy
2051
+ ):
1809
2052
  initdocstring = None
1810
2053
  if initdocstring:
1811
2054
  if classdoc_from == 'init':
@@ -1829,34 +2072,29 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1829
2072
  return None
1830
2073
 
1831
2074
  def add_content(self, more_content: StringList | None) -> None:
2075
+ mode = _get_render_mode(self.config.autodoc_typehints_format)
2076
+ short_literals = self.config.python_display_short_literal_types
2077
+
1832
2078
  if isinstance(self.object, NewType):
1833
- if self.config.autodoc_typehints_format == "short":
1834
- supertype = restify(self.object.__supertype__, "smart")
1835
- else:
1836
- supertype = restify(self.object.__supertype__)
2079
+ supertype = restify(self.object.__supertype__, mode=mode)
1837
2080
 
1838
2081
  more_content = StringList([_('alias of %s') % supertype, ''], source='')
1839
2082
  if isinstance(self.object, TypeVar):
1840
2083
  attrs = [repr(self.object.__name__)]
1841
- for constraint in self.object.__constraints__:
1842
- if self.config.autodoc_typehints_format == "short":
1843
- attrs.append(stringify_annotation(constraint, "smart"))
1844
- else:
1845
- attrs.append(stringify_annotation(constraint))
2084
+ attrs.extend(
2085
+ stringify_annotation(constraint, mode, short_literals=short_literals)
2086
+ for constraint in self.object.__constraints__
2087
+ )
1846
2088
  if self.object.__bound__:
1847
- if self.config.autodoc_typehints_format == "short":
1848
- bound = restify(self.object.__bound__, "smart")
1849
- else:
1850
- bound = restify(self.object.__bound__)
1851
- attrs.append(r"bound=\ " + bound)
2089
+ bound = restify(self.object.__bound__, mode=mode)
2090
+ attrs.append(r'bound=\ ' + bound)
1852
2091
  if self.object.__covariant__:
1853
- attrs.append("covariant=True")
2092
+ attrs.append('covariant=True')
1854
2093
  if self.object.__contravariant__:
1855
- attrs.append("contravariant=True")
2094
+ attrs.append('contravariant=True')
1856
2095
 
1857
2096
  more_content = StringList(
1858
- [_('alias of TypeVar(%s)') % ", ".join(attrs), ''],
1859
- source='',
2097
+ [_('alias of TypeVar(%s)') % ', '.join(attrs), ''], source=''
1860
2098
  )
1861
2099
  if self.doc_as_attr and self.modname != self.get_real_modname():
1862
2100
  try:
@@ -1868,10 +2106,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1868
2106
 
1869
2107
  if self.doc_as_attr and not self.get_variable_comment():
1870
2108
  try:
1871
- if self.config.autodoc_typehints_format == "short":
1872
- alias = restify(self.object, "smart")
1873
- else:
1874
- alias = restify(self.object)
2109
+ alias = restify(self.object, mode=mode)
1875
2110
  more_content = StringList([_('alias of %s') % alias], source='')
1876
2111
  except AttributeError:
1877
2112
  pass # Invalid class object is passed.
@@ -1895,15 +2130,15 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1895
2130
  # If a class gets imported into the module real_modname
1896
2131
  # the analyzer won't find the source of the class, if
1897
2132
  # it looks in real_modname.
1898
- return super().generate(more_content=more_content,
1899
- check_module=check_module,
1900
- all_members=all_members)
2133
+ return super().generate(
2134
+ more_content=more_content,
2135
+ check_module=check_module,
2136
+ all_members=all_members,
2137
+ )
1901
2138
 
1902
2139
 
1903
2140
  class ExceptionDocumenter(ClassDocumenter):
1904
- """
1905
- Specialized ClassDocumenter subclass for exceptions.
1906
- """
2141
+ """Specialized ClassDocumenter subclass for exceptions."""
1907
2142
 
1908
2143
  objtype = 'exception'
1909
2144
  member_order = 10
@@ -1913,7 +2148,7 @@ class ExceptionDocumenter(ClassDocumenter):
1913
2148
 
1914
2149
  @classmethod
1915
2150
  def can_document_member(
1916
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
2151
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
1917
2152
  ) -> bool:
1918
2153
  try:
1919
2154
  return isinstance(member, type) and issubclass(member, BaseException)
@@ -1951,21 +2186,20 @@ class DataDocumenterMixinBase:
1951
2186
 
1952
2187
 
1953
2188
  class GenericAliasMixin(DataDocumenterMixinBase):
1954
- """
1955
- Mixin for DataDocumenter and AttributeDocumenter to provide the feature for
2189
+ """Mixin for DataDocumenter and AttributeDocumenter to provide the feature for
1956
2190
  supporting GenericAliases.
1957
2191
  """
1958
2192
 
1959
2193
  def should_suppress_directive_header(self) -> bool:
1960
- return (inspect.isgenericalias(self.object) or
1961
- super().should_suppress_directive_header())
2194
+ return (
2195
+ inspect.isgenericalias(self.object)
2196
+ or super().should_suppress_directive_header()
2197
+ )
1962
2198
 
1963
2199
  def update_content(self, more_content: StringList) -> None:
1964
2200
  if inspect.isgenericalias(self.object):
1965
- if self.config.autodoc_typehints_format == "short":
1966
- alias = restify(self.object, "smart")
1967
- else:
1968
- alias = restify(self.object)
2201
+ mode = _get_render_mode(self.config.autodoc_typehints_format)
2202
+ alias = restify(self.object, mode=mode)
1969
2203
 
1970
2204
  more_content.append(_('alias of %s') % alias, '')
1971
2205
  more_content.append('', '')
@@ -1974,8 +2208,7 @@ class GenericAliasMixin(DataDocumenterMixinBase):
1974
2208
 
1975
2209
 
1976
2210
  class UninitializedGlobalVariableMixin(DataDocumenterMixinBase):
1977
- """
1978
- Mixin for DataDocumenter to provide the feature for supporting uninitialized
2211
+ """Mixin for DataDocumenter to provide the feature for supporting uninitialized
1979
2212
  (type annotation only) global variables.
1980
2213
  """
1981
2214
 
@@ -1987,9 +2220,12 @@ class UninitializedGlobalVariableMixin(DataDocumenterMixinBase):
1987
2220
  try:
1988
2221
  with mock(self.config.autodoc_mock_imports):
1989
2222
  parent = import_module(self.modname)
1990
- annotations = get_type_hints(parent, None,
1991
- self.config.autodoc_type_aliases,
1992
- include_extras=True)
2223
+ annotations = get_type_hints(
2224
+ parent,
2225
+ None,
2226
+ self.config.autodoc_type_aliases,
2227
+ include_extras=True,
2228
+ )
1993
2229
  if self.objpath[-1] in annotations:
1994
2230
  self.object = UNINITIALIZED_ATTR
1995
2231
  self.parent = parent
@@ -2004,8 +2240,9 @@ class UninitializedGlobalVariableMixin(DataDocumenterMixinBase):
2004
2240
  return False
2005
2241
 
2006
2242
  def should_suppress_value_header(self) -> bool:
2007
- return (self.object is UNINITIALIZED_ATTR or
2008
- super().should_suppress_value_header())
2243
+ return (
2244
+ self.object is UNINITIALIZED_ATTR or super().should_suppress_value_header()
2245
+ )
2009
2246
 
2010
2247
  def get_doc(self) -> list[list[str]] | None:
2011
2248
  if self.object is UNINITIALIZED_ATTR:
@@ -2014,22 +2251,21 @@ class UninitializedGlobalVariableMixin(DataDocumenterMixinBase):
2014
2251
  return super().get_doc() # type: ignore[misc]
2015
2252
 
2016
2253
 
2017
- class DataDocumenter(GenericAliasMixin,
2018
- UninitializedGlobalVariableMixin, ModuleLevelDocumenter):
2019
- """
2020
- Specialized Documenter subclass for data items.
2021
- """
2254
+ class DataDocumenter(
2255
+ GenericAliasMixin, UninitializedGlobalVariableMixin, ModuleLevelDocumenter
2256
+ ):
2257
+ """Specialized Documenter subclass for data items."""
2022
2258
 
2023
2259
  objtype = 'data'
2024
2260
  member_order = 40
2025
2261
  priority = -10
2026
2262
  option_spec: ClassVar[OptionSpec] = dict(ModuleLevelDocumenter.option_spec)
2027
- option_spec["annotation"] = annotation_option
2028
- option_spec["no-value"] = bool_option
2263
+ option_spec['annotation'] = annotation_option
2264
+ option_spec['no-value'] = bool_option
2029
2265
 
2030
2266
  @classmethod
2031
2267
  def can_document_member(
2032
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
2268
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
2033
2269
  ) -> bool:
2034
2270
  return isinstance(parent, ModuleDocumenter) and isattr
2035
2271
 
@@ -2042,7 +2278,7 @@ class DataDocumenter(GenericAliasMixin,
2042
2278
  analyzer = ModuleAnalyzer.for_module(self.modname)
2043
2279
  analyzer.analyze()
2044
2280
  for (classname, attrname), annotation in analyzer.annotations.items():
2045
- if classname == '' and attrname not in annotations:
2281
+ if not classname and attrname not in annotations:
2046
2282
  annotations[attrname] = annotation
2047
2283
  except PycodeError:
2048
2284
  pass
@@ -2060,7 +2296,8 @@ class DataDocumenter(GenericAliasMixin,
2060
2296
  else:
2061
2297
  doc = self.get_doc() or []
2062
2298
  docstring, metadata = separate_metadata(
2063
- '\n'.join(functools.reduce(operator.iadd, doc, [])))
2299
+ '\n'.join(functools.reduce(operator.iadd, doc, []))
2300
+ )
2064
2301
  if 'hide-value' in metadata:
2065
2302
  return True
2066
2303
 
@@ -2069,29 +2306,38 @@ class DataDocumenter(GenericAliasMixin,
2069
2306
  def add_directive_header(self, sig: str) -> None:
2070
2307
  super().add_directive_header(sig)
2071
2308
  sourcename = self.get_sourcename()
2072
- if self.options.annotation is SUPPRESS or self.should_suppress_directive_header():
2309
+ if (
2310
+ self.options.annotation is SUPPRESS
2311
+ or self.should_suppress_directive_header()
2312
+ ):
2073
2313
  pass
2074
2314
  elif self.options.annotation:
2075
- self.add_line(' :annotation: %s' % self.options.annotation,
2076
- sourcename)
2315
+ self.add_line(' :annotation: %s' % self.options.annotation, sourcename)
2077
2316
  else:
2078
2317
  if self.config.autodoc_typehints != 'none':
2079
2318
  # obtain annotation for this data
2080
- annotations = get_type_hints(self.parent, None,
2081
- self.config.autodoc_type_aliases,
2082
- include_extras=True)
2319
+ annotations = get_type_hints(
2320
+ self.parent,
2321
+ None,
2322
+ self.config.autodoc_type_aliases,
2323
+ include_extras=True,
2324
+ )
2083
2325
  if self.objpath[-1] in annotations:
2084
- if self.config.autodoc_typehints_format == "short":
2085
- objrepr = stringify_annotation(annotations.get(self.objpath[-1]),
2086
- "smart")
2087
- else:
2088
- objrepr = stringify_annotation(annotations.get(self.objpath[-1]),
2089
- "fully-qualified-except-typing")
2326
+ mode = _get_render_mode(self.config.autodoc_typehints_format)
2327
+ short_literals = self.config.python_display_short_literal_types
2328
+ objrepr = stringify_annotation(
2329
+ annotations.get(self.objpath[-1]),
2330
+ mode,
2331
+ short_literals=short_literals,
2332
+ )
2090
2333
  self.add_line(' :type: ' + objrepr, sourcename)
2091
2334
 
2092
2335
  try:
2093
- if (self.options.no_value or self.should_suppress_value_header() or
2094
- ismock(self.object)):
2336
+ if (
2337
+ self.options.no_value
2338
+ or self.should_suppress_value_header()
2339
+ or ismock(self.object)
2340
+ ):
2095
2341
  pass
2096
2342
  else:
2097
2343
  objrepr = object_description(self.object)
@@ -2139,9 +2385,7 @@ class DataDocumenter(GenericAliasMixin,
2139
2385
 
2140
2386
 
2141
2387
  class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type: ignore[misc]
2142
- """
2143
- Specialized Documenter subclass for methods (normal, static and class).
2144
- """
2388
+ """Specialized Documenter subclass for methods (normal, static and class)."""
2145
2389
 
2146
2390
  objtype = 'method'
2147
2391
  directivetype = 'method'
@@ -2150,7 +2394,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2150
2394
 
2151
2395
  @classmethod
2152
2396
  def can_document_member(
2153
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
2397
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
2154
2398
  ) -> bool:
2155
2399
  return inspect.isroutine(member) and not isinstance(parent, ModuleDocumenter)
2156
2400
 
@@ -2160,22 +2404,23 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2160
2404
  return ret
2161
2405
 
2162
2406
  # to distinguish classmethod/staticmethod
2163
- obj = self.parent.__dict__.get(self.object_name)
2164
- if obj is None:
2165
- obj = self.object
2166
-
2167
- if (inspect.isclassmethod(obj) or
2168
- inspect.isstaticmethod(obj, cls=self.parent, name=self.object_name)):
2169
- # document class and static members before ordinary ones
2170
- self.member_order = self.member_order - 1
2171
-
2407
+ obj = self.parent.__dict__.get(self.object_name, self.object)
2408
+ if inspect.isstaticmethod(obj, cls=self.parent, name=self.object_name):
2409
+ # document static members before regular methods
2410
+ self.member_order -= 1
2411
+ elif inspect.isclassmethod(obj):
2412
+ # document class methods before static methods as
2413
+ # they usually behave as alternative constructors
2414
+ self.member_order -= 2
2172
2415
  return ret
2173
2416
 
2174
2417
  def format_args(self, **kwargs: Any) -> str:
2175
- if self.config.autodoc_typehints in ('none', 'description'):
2418
+ if self.config.autodoc_typehints in {'none', 'description'}:
2176
2419
  kwargs.setdefault('show_annotation', False)
2177
- if self.config.autodoc_typehints_format == "short":
2420
+ if self.config.autodoc_typehints_format == 'short':
2178
2421
  kwargs.setdefault('unqualified_typehints', True)
2422
+ if self.config.python_display_short_literal_types:
2423
+ kwargs.setdefault('short_literals', True)
2179
2424
 
2180
2425
  try:
2181
2426
  if self.object == object.__init__ and self.parent != object: # NoQA: E721
@@ -2185,18 +2430,31 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2185
2430
  # But it makes users confused.
2186
2431
  args = '()'
2187
2432
  else:
2188
- if inspect.isstaticmethod(self.object, cls=self.parent, name=self.object_name):
2189
- self.env.app.emit('autodoc-before-process-signature', self.object, False)
2190
- sig = inspect.signature(self.object, bound_method=False,
2191
- type_aliases=self.config.autodoc_type_aliases)
2433
+ if inspect.isstaticmethod(
2434
+ self.object, cls=self.parent, name=self.object_name
2435
+ ):
2436
+ self._events.emit(
2437
+ 'autodoc-before-process-signature', self.object, False
2438
+ )
2439
+ sig = inspect.signature(
2440
+ self.object,
2441
+ bound_method=False,
2442
+ type_aliases=self.config.autodoc_type_aliases,
2443
+ )
2192
2444
  else:
2193
- self.env.app.emit('autodoc-before-process-signature', self.object, True)
2194
- sig = inspect.signature(self.object, bound_method=True,
2195
- type_aliases=self.config.autodoc_type_aliases)
2445
+ self._events.emit(
2446
+ 'autodoc-before-process-signature', self.object, True
2447
+ )
2448
+ sig = inspect.signature(
2449
+ self.object,
2450
+ bound_method=True,
2451
+ type_aliases=self.config.autodoc_type_aliases,
2452
+ )
2196
2453
  args = stringify_signature(sig, **kwargs)
2197
2454
  except TypeError as exc:
2198
- logger.warning(__("Failed to get a method signature for %s: %s"),
2199
- self.fullname, exc)
2455
+ logger.warning(
2456
+ __('Failed to get a method signature for %s: %s'), self.fullname, exc
2457
+ )
2200
2458
  return ''
2201
2459
  except ValueError:
2202
2460
  args = ''
@@ -2215,8 +2473,11 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2215
2473
  self.add_line(' :abstractmethod:', sourcename)
2216
2474
  if inspect.iscoroutinefunction(obj) or inspect.isasyncgenfunction(obj):
2217
2475
  self.add_line(' :async:', sourcename)
2218
- if (inspect.isclassmethod(obj) or
2219
- inspect.is_singledispatch_method(obj) and inspect.isclassmethod(obj.func)):
2476
+ if (
2477
+ inspect.is_classmethod_like(obj)
2478
+ or inspect.is_singledispatch_method(obj)
2479
+ and inspect.is_classmethod_like(obj.func)
2480
+ ):
2220
2481
  self.add_line(' :classmethod:', sourcename)
2221
2482
  if inspect.isstaticmethod(obj, cls=self.parent, name=self.object_name):
2222
2483
  self.add_line(' :staticmethod:', sourcename)
@@ -2227,13 +2488,17 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2227
2488
  pass
2228
2489
 
2229
2490
  def format_signature(self, **kwargs: Any) -> str:
2230
- if self.config.autodoc_typehints_format == "short":
2491
+ if self.config.autodoc_typehints_format == 'short':
2231
2492
  kwargs.setdefault('unqualified_typehints', True)
2493
+ if self.config.python_display_short_literal_types:
2494
+ kwargs.setdefault('short_literals', True)
2232
2495
 
2233
2496
  sigs = []
2234
- if (self.analyzer and
2235
- '.'.join(self.objpath) in self.analyzer.overloads and
2236
- self.config.autodoc_typehints != 'none'):
2497
+ if (
2498
+ self.analyzer
2499
+ and '.'.join(self.objpath) in self.analyzer.overloads
2500
+ and self.config.autodoc_typehints != 'none'
2501
+ ):
2237
2502
  # Use signatures for overloaded methods instead of the implementation method.
2238
2503
  overloaded = True
2239
2504
  else:
@@ -2258,27 +2523,37 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2258
2523
  documenter.objpath = ['']
2259
2524
  sigs.append(documenter.format_signature())
2260
2525
  if overloaded and self.analyzer is not None:
2261
- if inspect.isstaticmethod(self.object, cls=self.parent, name=self.object_name):
2262
- actual = inspect.signature(self.object, bound_method=False,
2263
- type_aliases=self.config.autodoc_type_aliases)
2526
+ if inspect.isstaticmethod(
2527
+ self.object, cls=self.parent, name=self.object_name
2528
+ ):
2529
+ actual = inspect.signature(
2530
+ self.object,
2531
+ bound_method=False,
2532
+ type_aliases=self.config.autodoc_type_aliases,
2533
+ )
2264
2534
  else:
2265
- actual = inspect.signature(self.object, bound_method=True,
2266
- type_aliases=self.config.autodoc_type_aliases)
2535
+ actual = inspect.signature(
2536
+ self.object,
2537
+ bound_method=True,
2538
+ type_aliases=self.config.autodoc_type_aliases,
2539
+ )
2267
2540
 
2268
2541
  __globals__ = safe_getattr(self.object, '__globals__', {})
2269
2542
  for overload in self.analyzer.overloads['.'.join(self.objpath)]:
2270
2543
  overload = self.merge_default_value(actual, overload)
2271
- overload = evaluate_signature(overload, __globals__,
2272
- self.config.autodoc_type_aliases)
2544
+ overload = evaluate_signature(
2545
+ overload, __globals__, self.config.autodoc_type_aliases
2546
+ )
2273
2547
 
2274
- if not inspect.isstaticmethod(self.object, cls=self.parent,
2275
- name=self.object_name):
2548
+ if not inspect.isstaticmethod(
2549
+ self.object, cls=self.parent, name=self.object_name
2550
+ ):
2276
2551
  parameters = list(overload.parameters.values())
2277
2552
  overload = overload.replace(parameters=parameters[1:])
2278
2553
  sig = stringify_signature(overload, **kwargs)
2279
2554
  sigs.append(sig)
2280
2555
 
2281
- return "\n".join(sigs)
2556
+ return '\n'.join(sigs)
2282
2557
 
2283
2558
  def merge_default_value(self, actual: Signature, overload: Signature) -> Signature:
2284
2559
  """Merge default values of actual implementation to the overload variants."""
@@ -2290,13 +2565,16 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2290
2565
 
2291
2566
  return overload.replace(parameters=parameters)
2292
2567
 
2293
- def annotate_to_first_argument(self, func: Callable, typ: type) -> Callable | None:
2568
+ def annotate_to_first_argument(
2569
+ self, func: Callable[..., Any], typ: type
2570
+ ) -> Callable[..., Any] | None:
2294
2571
  """Annotate type hint to the first argument of function if needed."""
2295
2572
  try:
2296
2573
  sig = inspect.signature(func, type_aliases=self.config.autodoc_type_aliases)
2297
2574
  except TypeError as exc:
2298
- logger.warning(__("Failed to get a method signature for %s: %s"),
2299
- self.fullname, exc)
2575
+ logger.warning(
2576
+ __('Failed to get a method signature for %s: %s'), self.fullname, exc
2577
+ )
2300
2578
  return None
2301
2579
  except ValueError:
2302
2580
  return None
@@ -2312,7 +2590,8 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2312
2590
  params[1] = params[1].replace(annotation=typ)
2313
2591
  try:
2314
2592
  dummy.__signature__ = sig.replace( # type: ignore[attr-defined]
2315
- parameters=params)
2593
+ parameters=params
2594
+ )
2316
2595
  return dummy
2317
2596
  except (AttributeError, TypeError):
2318
2597
  # failed to update signature (ex. built-in or extension types)
@@ -2328,12 +2607,17 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2328
2607
  # `DocstringSignatureMixin`.
2329
2608
  return self._new_docstrings
2330
2609
  if self.objpath[-1] == '__init__':
2331
- docstring = getdoc(self.object, self.get_attr,
2332
- self.config.autodoc_inherit_docstrings,
2333
- self.parent, self.object_name)
2334
- if (docstring is not None and
2335
- (docstring == object.__init__.__doc__ or # for pypy
2336
- docstring.strip() == object.__init__.__doc__)): # for !pypy
2610
+ docstring = getdoc(
2611
+ self.object,
2612
+ self.get_attr,
2613
+ self.config.autodoc_inherit_docstrings,
2614
+ self.parent,
2615
+ self.object_name,
2616
+ )
2617
+ if docstring is not None and (
2618
+ docstring == object.__init__.__doc__ # for pypy
2619
+ or docstring.strip() == object.__init__.__doc__ # for !pypy
2620
+ ):
2337
2621
  docstring = None
2338
2622
  if docstring:
2339
2623
  tab_width = self.directive.state.document.settings.tab_width
@@ -2341,12 +2625,17 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2341
2625
  else:
2342
2626
  return []
2343
2627
  elif self.objpath[-1] == '__new__':
2344
- docstring = getdoc(self.object, self.get_attr,
2345
- self.config.autodoc_inherit_docstrings,
2346
- self.parent, self.object_name)
2347
- if (docstring is not None and
2348
- (docstring == object.__new__.__doc__ or # for pypy
2349
- docstring.strip() == object.__new__.__doc__)): # for !pypy
2628
+ docstring = getdoc(
2629
+ self.object,
2630
+ self.get_attr,
2631
+ self.config.autodoc_inherit_docstrings,
2632
+ self.parent,
2633
+ self.object_name,
2634
+ )
2635
+ if docstring is not None and (
2636
+ docstring == object.__new__.__doc__ # for pypy
2637
+ or docstring.strip() == object.__new__.__doc__ # for !pypy
2638
+ ):
2350
2639
  docstring = None
2351
2640
  if docstring:
2352
2641
  tab_width = self.directive.state.document.settings.tab_width
@@ -2358,8 +2647,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2358
2647
 
2359
2648
 
2360
2649
  class NonDataDescriptorMixin(DataDocumenterMixinBase):
2361
- """
2362
- Mixin for AttributeDocumenter to provide the feature for supporting non
2650
+ """Mixin for AttributeDocumenter to provide the feature for supporting non
2363
2651
  data-descriptors.
2364
2652
 
2365
2653
  .. note:: This mix-in must be inherited after other mix-ins. Otherwise, docstring
@@ -2376,8 +2664,10 @@ class NonDataDescriptorMixin(DataDocumenterMixinBase):
2376
2664
  return ret
2377
2665
 
2378
2666
  def should_suppress_value_header(self) -> bool:
2379
- return (not getattr(self, 'non_data_descriptor', False) or
2380
- super().should_suppress_directive_header())
2667
+ return (
2668
+ not getattr(self, 'non_data_descriptor', False)
2669
+ or super().should_suppress_directive_header()
2670
+ )
2381
2671
 
2382
2672
  def get_doc(self) -> list[list[str]] | None:
2383
2673
  if getattr(self, 'non_data_descriptor', False):
@@ -2389,9 +2679,7 @@ class NonDataDescriptorMixin(DataDocumenterMixinBase):
2389
2679
 
2390
2680
 
2391
2681
  class SlotsMixin(DataDocumenterMixinBase):
2392
- """
2393
- Mixin for AttributeDocumenter to provide the feature for supporting __slots__.
2394
- """
2682
+ """Mixin for AttributeDocumenter to provide the feature for supporting __slots__."""
2395
2683
 
2396
2684
  def isslotsattribute(self) -> bool:
2397
2685
  """Check the subject is an attribute in __slots__."""
@@ -2420,25 +2708,29 @@ class SlotsMixin(DataDocumenterMixinBase):
2420
2708
  if self.object is SLOTSATTR:
2421
2709
  try:
2422
2710
  parent___slots__ = inspect.getslots(self.parent)
2423
- if parent___slots__ and (docstring := parent___slots__.get(self.objpath[-1])):
2711
+ if parent___slots__ and (
2712
+ docstring := parent___slots__.get(self.objpath[-1])
2713
+ ):
2424
2714
  docstring = prepare_docstring(docstring)
2425
2715
  return [docstring]
2426
2716
  else:
2427
2717
  return []
2428
2718
  except ValueError as exc:
2429
- logger.warning(__('Invalid __slots__ found on %s. Ignored.'),
2430
- (self.parent.__qualname__, exc), type='autodoc')
2719
+ logger.warning(
2720
+ __('Invalid __slots__ found on %s. Ignored.'),
2721
+ (self.parent.__qualname__, exc),
2722
+ type='autodoc',
2723
+ )
2431
2724
  return []
2432
2725
  else:
2433
2726
  return super().get_doc() # type: ignore[misc]
2434
2727
 
2435
2728
 
2436
2729
  class RuntimeInstanceAttributeMixin(DataDocumenterMixinBase):
2437
- """
2438
- Mixin for AttributeDocumenter to provide the feature for supporting runtime
2730
+ """Mixin for AttributeDocumenter to provide the feature for supporting runtime
2439
2731
  instance attributes (that are defined in __init__() methods with doc-comments).
2440
2732
 
2441
- Example:
2733
+ Example::
2442
2734
 
2443
2735
  class Foo:
2444
2736
  def __init__(self):
@@ -2482,7 +2774,9 @@ class RuntimeInstanceAttributeMixin(DataDocumenterMixinBase):
2482
2774
  try:
2483
2775
  with mock(self.config.autodoc_mock_imports):
2484
2776
  ret = import_object(
2485
- self.modname, self.objpath[:-1], 'class',
2777
+ self.modname,
2778
+ self.objpath[:-1],
2779
+ 'class',
2486
2780
  attrgetter=self.get_attr, # type: ignore[attr-defined]
2487
2781
  )
2488
2782
  parent = ret[3]
@@ -2500,23 +2794,26 @@ class RuntimeInstanceAttributeMixin(DataDocumenterMixinBase):
2500
2794
  return False
2501
2795
 
2502
2796
  def should_suppress_value_header(self) -> bool:
2503
- return (self.object is self.RUNTIME_INSTANCE_ATTRIBUTE or
2504
- super().should_suppress_value_header())
2797
+ return (
2798
+ self.object is self.RUNTIME_INSTANCE_ATTRIBUTE
2799
+ or super().should_suppress_value_header()
2800
+ )
2505
2801
 
2506
2802
  def get_doc(self) -> list[list[str]] | None:
2507
- if (self.object is self.RUNTIME_INSTANCE_ATTRIBUTE and
2508
- self.is_runtime_instance_attribute_not_commented(self.parent)):
2803
+ if (
2804
+ self.object is self.RUNTIME_INSTANCE_ATTRIBUTE
2805
+ and self.is_runtime_instance_attribute_not_commented(self.parent)
2806
+ ):
2509
2807
  return None
2510
2808
  else:
2511
2809
  return super().get_doc() # type: ignore[misc]
2512
2810
 
2513
2811
 
2514
2812
  class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
2515
- """
2516
- Mixin for AttributeDocumenter to provide the feature for supporting uninitialized
2813
+ """Mixin for AttributeDocumenter to provide the feature for supporting uninitialized
2517
2814
  instance attributes (PEP-526 styled, annotation only attributes).
2518
2815
 
2519
- Example:
2816
+ Example::
2520
2817
 
2521
2818
  class Foo:
2522
2819
  attr: int #: This is a target of this mix-in.
@@ -2524,8 +2821,9 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
2524
2821
 
2525
2822
  def is_uninitialized_instance_attribute(self, parent: Any) -> bool:
2526
2823
  """Check the subject is an annotation only attribute."""
2527
- annotations = get_type_hints(parent, None, self.config.autodoc_type_aliases,
2528
- include_extras=True)
2824
+ annotations = get_type_hints(
2825
+ parent, None, self.config.autodoc_type_aliases, include_extras=True
2826
+ )
2529
2827
  return self.objpath[-1] in annotations
2530
2828
 
2531
2829
  def import_object(self, raiseerror: bool = False) -> bool:
@@ -2537,7 +2835,9 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
2537
2835
  except ImportError as exc:
2538
2836
  try:
2539
2837
  ret = import_object(
2540
- self.modname, self.objpath[:-1], 'class',
2838
+ self.modname,
2839
+ self.objpath[:-1],
2840
+ 'class',
2541
2841
  attrgetter=self.get_attr, # type: ignore[attr-defined]
2542
2842
  )
2543
2843
  parent = ret[3]
@@ -2555,8 +2855,9 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
2555
2855
  return False
2556
2856
 
2557
2857
  def should_suppress_value_header(self) -> bool:
2558
- return (self.object is UNINITIALIZED_ATTR or
2559
- super().should_suppress_value_header())
2858
+ return (
2859
+ self.object is UNINITIALIZED_ATTR or super().should_suppress_value_header()
2860
+ )
2560
2861
 
2561
2862
  def get_doc(self) -> list[list[str]] | None:
2562
2863
  if self.object is UNINITIALIZED_ATTR:
@@ -2564,19 +2865,22 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
2564
2865
  return super().get_doc() # type: ignore[misc]
2565
2866
 
2566
2867
 
2567
- class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2568
- RuntimeInstanceAttributeMixin,
2569
- UninitializedInstanceAttributeMixin, NonDataDescriptorMixin,
2570
- DocstringStripSignatureMixin, ClassLevelDocumenter):
2571
- """
2572
- Specialized Documenter subclass for attributes.
2573
- """
2868
+ class AttributeDocumenter( # type: ignore[misc]
2869
+ GenericAliasMixin,
2870
+ SlotsMixin,
2871
+ RuntimeInstanceAttributeMixin,
2872
+ UninitializedInstanceAttributeMixin,
2873
+ NonDataDescriptorMixin,
2874
+ DocstringStripSignatureMixin,
2875
+ ClassLevelDocumenter,
2876
+ ):
2877
+ """Specialized Documenter subclass for attributes."""
2574
2878
 
2575
2879
  objtype = 'attribute'
2576
2880
  member_order = 60
2577
2881
  option_spec: ClassVar[OptionSpec] = dict(ModuleLevelDocumenter.option_spec)
2578
- option_spec["annotation"] = annotation_option
2579
- option_spec["no-value"] = bool_option
2882
+ option_spec['annotation'] = annotation_option
2883
+ option_spec['no-value'] = bool_option
2580
2884
 
2581
2885
  # must be higher than the MethodDocumenter, else it will recognize
2582
2886
  # some non-data descriptors as methods
@@ -2584,11 +2888,13 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2584
2888
 
2585
2889
  @staticmethod
2586
2890
  def is_function_or_method(obj: Any) -> bool:
2587
- return inspect.isfunction(obj) or inspect.isbuiltin(obj) or inspect.ismethod(obj)
2891
+ return (
2892
+ inspect.isfunction(obj) or inspect.isbuiltin(obj) or inspect.ismethod(obj)
2893
+ )
2588
2894
 
2589
2895
  @classmethod
2590
2896
  def can_document_member(
2591
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
2897
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
2592
2898
  ) -> bool:
2593
2899
  if isinstance(parent, ModuleDocumenter):
2594
2900
  return False
@@ -2612,7 +2918,8 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2612
2918
 
2613
2919
  analyzer = ModuleAnalyzer.for_module(module)
2614
2920
  analyzer.analyze()
2615
- for (classname, attrname), annotation in analyzer.annotations.items():
2921
+ anns = analyzer.annotations
2922
+ for (classname, attrname), annotation in anns.items():
2616
2923
  if classname == qualname and attrname not in annotations:
2617
2924
  annotations[attrname] = annotation
2618
2925
  except (AttributeError, PycodeError):
@@ -2641,7 +2948,8 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2641
2948
  doc = self.get_doc()
2642
2949
  if doc:
2643
2950
  docstring, metadata = separate_metadata(
2644
- '\n'.join(functools.reduce(operator.iadd, doc, [])))
2951
+ '\n'.join(functools.reduce(operator.iadd, doc, []))
2952
+ )
2645
2953
  if 'hide-value' in metadata:
2646
2954
  return True
2647
2955
 
@@ -2650,28 +2958,38 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2650
2958
  def add_directive_header(self, sig: str) -> None:
2651
2959
  super().add_directive_header(sig)
2652
2960
  sourcename = self.get_sourcename()
2653
- if self.options.annotation is SUPPRESS or self.should_suppress_directive_header():
2961
+ if (
2962
+ self.options.annotation is SUPPRESS
2963
+ or self.should_suppress_directive_header()
2964
+ ):
2654
2965
  pass
2655
2966
  elif self.options.annotation:
2656
2967
  self.add_line(' :annotation: %s' % self.options.annotation, sourcename)
2657
2968
  else:
2658
2969
  if self.config.autodoc_typehints != 'none':
2659
2970
  # obtain type annotation for this attribute
2660
- annotations = get_type_hints(self.parent, None,
2661
- self.config.autodoc_type_aliases,
2662
- include_extras=True)
2971
+ annotations = get_type_hints(
2972
+ self.parent,
2973
+ None,
2974
+ self.config.autodoc_type_aliases,
2975
+ include_extras=True,
2976
+ )
2663
2977
  if self.objpath[-1] in annotations:
2664
- if self.config.autodoc_typehints_format == "short":
2665
- objrepr = stringify_annotation(annotations.get(self.objpath[-1]),
2666
- "smart")
2667
- else:
2668
- objrepr = stringify_annotation(annotations.get(self.objpath[-1]),
2669
- "fully-qualified-except-typing")
2978
+ mode = _get_render_mode(self.config.autodoc_typehints_format)
2979
+ short_literals = self.config.python_display_short_literal_types
2980
+ objrepr = stringify_annotation(
2981
+ annotations.get(self.objpath[-1]),
2982
+ mode,
2983
+ short_literals=short_literals,
2984
+ )
2670
2985
  self.add_line(' :type: ' + objrepr, sourcename)
2671
2986
 
2672
2987
  try:
2673
- if (self.options.no_value or self.should_suppress_value_header() or
2674
- ismock(self.object)):
2988
+ if (
2989
+ self.options.no_value
2990
+ or self.should_suppress_value_header()
2991
+ or ismock(self.object)
2992
+ ):
2675
2993
  pass
2676
2994
  else:
2677
2995
  objrepr = object_description(self.object)
@@ -2705,7 +3023,7 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2705
3023
  try:
2706
3024
  # Disable `autodoc_inherit_docstring` temporarily to avoid to obtain
2707
3025
  # a docstring from the value which descriptor returns unexpectedly.
2708
- # ref: https://github.com/sphinx-doc/sphinx/issues/7805
3026
+ # See: https://github.com/sphinx-doc/sphinx/issues/7805
2709
3027
  orig = self.config.autodoc_inherit_docstrings
2710
3028
  self.config.autodoc_inherit_docstrings = False
2711
3029
  return super().get_doc()
@@ -2723,11 +3041,8 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2723
3041
  super().add_content(more_content)
2724
3042
 
2725
3043
 
2726
- class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
2727
- ClassLevelDocumenter):
2728
- """
2729
- Specialized Documenter subclass for properties.
2730
- """
3044
+ class PropertyDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore[misc]
3045
+ """Specialized Documenter subclass for properties."""
2731
3046
 
2732
3047
  objtype = 'property'
2733
3048
  member_order = 60
@@ -2737,7 +3052,7 @@ class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
2737
3052
 
2738
3053
  @classmethod
2739
3054
  def can_document_member(
2740
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
3055
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
2741
3056
  ) -> bool:
2742
3057
  if isinstance(parent, ClassDocumenter):
2743
3058
  if inspect.isproperty(member):
@@ -2773,7 +3088,7 @@ class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
2773
3088
  return ''
2774
3089
 
2775
3090
  # update the annotations of the property getter
2776
- self.env.app.emit('autodoc-before-process-signature', func, False)
3091
+ self._events.emit('autodoc-before-process-signature', func, False)
2777
3092
  # correctly format the arguments for a property
2778
3093
  return super().format_args(**kwargs)
2779
3094
 
@@ -2797,23 +3112,25 @@ class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
2797
3112
  return
2798
3113
 
2799
3114
  try:
2800
- signature = inspect.signature(func,
2801
- type_aliases=self.config.autodoc_type_aliases)
3115
+ signature = inspect.signature(
3116
+ func, type_aliases=self.config.autodoc_type_aliases
3117
+ )
2802
3118
  if signature.return_annotation is not Parameter.empty:
2803
- if self.config.autodoc_typehints_format == "short":
2804
- objrepr = stringify_annotation(signature.return_annotation, "smart")
2805
- else:
2806
- objrepr = stringify_annotation(signature.return_annotation,
2807
- "fully-qualified-except-typing")
3119
+ mode = _get_render_mode(self.config.autodoc_typehints_format)
3120
+ short_literals = self.config.python_display_short_literal_types
3121
+ objrepr = stringify_annotation(
3122
+ signature.return_annotation, mode, short_literals=short_literals
3123
+ )
2808
3124
  self.add_line(' :type: ' + objrepr, sourcename)
2809
3125
  except TypeError as exc:
2810
- logger.warning(__("Failed to get a function signature for %s: %s"),
2811
- self.fullname, exc)
3126
+ logger.warning(
3127
+ __('Failed to get a function signature for %s: %s'), self.fullname, exc
3128
+ )
2812
3129
  pass
2813
3130
  except ValueError:
2814
3131
  pass
2815
3132
 
2816
- def _get_property_getter(self) -> Callable | None:
3133
+ def _get_property_getter(self) -> Callable[..., Any] | None:
2817
3134
  if safe_getattr(self.object, 'fget', None): # property
2818
3135
  return self.object.fget
2819
3136
  if safe_getattr(self.object, 'func', None): # cached_property
@@ -2821,9 +3138,11 @@ class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
2821
3138
  return None
2822
3139
 
2823
3140
 
2824
- def autodoc_attrgetter(app: Sphinx, obj: Any, name: str, *defargs: Any) -> Any:
3141
+ def autodoc_attrgetter(
3142
+ obj: Any, name: str, *defargs: Any, registry: SphinxComponentRegistry
3143
+ ) -> Any:
2825
3144
  """Alternative getattr() for types"""
2826
- for typ, func in app.registry.autodoc_attrgetters.items():
3145
+ for typ, func in registry.autodoc_attrgetters.items():
2827
3146
  if isinstance(obj, typ):
2828
3147
  return func(obj, name, *defargs)
2829
3148
 
@@ -2841,22 +3160,54 @@ def setup(app: Sphinx) -> ExtensionMetadata:
2841
3160
  app.add_autodocumenter(AttributeDocumenter)
2842
3161
  app.add_autodocumenter(PropertyDocumenter)
2843
3162
 
2844
- app.add_config_value('autoclass_content', 'class', 'env', ENUM('both', 'class', 'init'))
2845
- app.add_config_value('autodoc_member_order', 'alphabetical', 'env',
2846
- ENUM('alphabetical', 'bysource', 'groupwise'))
2847
- app.add_config_value('autodoc_class_signature', 'mixed', 'env', ENUM('mixed', 'separated'))
2848
- app.add_config_value('autodoc_default_options', {}, 'env')
2849
- app.add_config_value('autodoc_docstring_signature', True, 'env')
2850
- app.add_config_value('autodoc_mock_imports', [], 'env')
2851
- app.add_config_value('autodoc_typehints', "signature", 'env',
2852
- ENUM("signature", "description", "none", "both"))
2853
- app.add_config_value('autodoc_typehints_description_target', 'all', 'env',
2854
- ENUM('all', 'documented', 'documented_params'))
2855
- app.add_config_value('autodoc_type_aliases', {}, 'env')
2856
- app.add_config_value('autodoc_typehints_format', "short", 'env',
2857
- ENUM("fully-qualified", "short"))
2858
- app.add_config_value('autodoc_warningiserror', True, 'env')
2859
- app.add_config_value('autodoc_inherit_docstrings', True, 'env')
3163
+ app.add_config_value(
3164
+ 'autoclass_content',
3165
+ 'class',
3166
+ 'env',
3167
+ types=ENUM('both', 'class', 'init'),
3168
+ )
3169
+ app.add_config_value(
3170
+ 'autodoc_member_order',
3171
+ 'alphabetical',
3172
+ 'env',
3173
+ types=ENUM('alphabetical', 'bysource', 'groupwise'),
3174
+ )
3175
+ app.add_config_value(
3176
+ 'autodoc_class_signature',
3177
+ 'mixed',
3178
+ 'env',
3179
+ types=ENUM('mixed', 'separated'),
3180
+ )
3181
+ app.add_config_value('autodoc_default_options', {}, 'env', types=frozenset({dict}))
3182
+ app.add_config_value(
3183
+ 'autodoc_docstring_signature', True, 'env', types=frozenset({bool})
3184
+ )
3185
+ app.add_config_value(
3186
+ 'autodoc_mock_imports', [], 'env', types=frozenset({list, tuple})
3187
+ )
3188
+ app.add_config_value(
3189
+ 'autodoc_typehints',
3190
+ 'signature',
3191
+ 'env',
3192
+ types=ENUM('signature', 'description', 'none', 'both'),
3193
+ )
3194
+ app.add_config_value(
3195
+ 'autodoc_typehints_description_target',
3196
+ 'all',
3197
+ 'env',
3198
+ types=ENUM('all', 'documented', 'documented_params'),
3199
+ )
3200
+ app.add_config_value('autodoc_type_aliases', {}, 'env', types=frozenset({dict}))
3201
+ app.add_config_value(
3202
+ 'autodoc_typehints_format',
3203
+ 'short',
3204
+ 'env',
3205
+ types=ENUM('fully-qualified', 'short'),
3206
+ )
3207
+ app.add_config_value('autodoc_warningiserror', True, 'env', types=frozenset({bool}))
3208
+ app.add_config_value(
3209
+ 'autodoc_inherit_docstrings', True, 'env', types=frozenset({bool})
3210
+ )
2860
3211
  app.add_event('autodoc-before-process-signature')
2861
3212
  app.add_event('autodoc-process-docstring')
2862
3213
  app.add_event('autodoc-process-signature')
@@ -2867,4 +3218,7 @@ def setup(app: Sphinx) -> ExtensionMetadata:
2867
3218
  app.setup_extension('sphinx.ext.autodoc.type_comment')
2868
3219
  app.setup_extension('sphinx.ext.autodoc.typehints')
2869
3220
 
2870
- return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
3221
+ return {
3222
+ 'version': sphinx.__display_version__,
3223
+ 'parallel_read_safe': True,
3224
+ }