Sphinx 8.1.3__py3-none-any.whl → 8.2.0rc1__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 (193) 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 +48 -40
  55. sphinx/domains/python/__init__.py +402 -211
  56. sphinx/domains/python/_annotations.py +114 -57
  57. sphinx/domains/python/_object.py +151 -67
  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 +21 -0
  73. sphinx/ext/apidoc/__main__.py +9 -0
  74. sphinx/ext/apidoc/_cli.py +356 -0
  75. sphinx/ext/apidoc/_generate.py +356 -0
  76. sphinx/ext/apidoc/_shared.py +66 -0
  77. sphinx/ext/autodoc/__init__.py +829 -480
  78. sphinx/ext/autodoc/directive.py +57 -21
  79. sphinx/ext/autodoc/importer.py +184 -67
  80. sphinx/ext/autodoc/mock.py +25 -10
  81. sphinx/ext/autodoc/preserve_defaults.py +17 -9
  82. sphinx/ext/autodoc/type_comment.py +56 -29
  83. sphinx/ext/autodoc/typehints.py +49 -26
  84. sphinx/ext/autosectionlabel.py +28 -11
  85. sphinx/ext/autosummary/__init__.py +271 -143
  86. sphinx/ext/autosummary/generate.py +121 -51
  87. sphinx/ext/coverage.py +152 -91
  88. sphinx/ext/doctest.py +169 -101
  89. sphinx/ext/duration.py +12 -6
  90. sphinx/ext/extlinks.py +33 -21
  91. sphinx/ext/githubpages.py +8 -8
  92. sphinx/ext/graphviz.py +175 -109
  93. sphinx/ext/ifconfig.py +11 -6
  94. sphinx/ext/imgconverter.py +48 -25
  95. sphinx/ext/imgmath.py +127 -97
  96. sphinx/ext/inheritance_diagram.py +177 -103
  97. sphinx/ext/intersphinx/__init__.py +22 -13
  98. sphinx/ext/intersphinx/__main__.py +3 -1
  99. sphinx/ext/intersphinx/_cli.py +18 -14
  100. sphinx/ext/intersphinx/_load.py +91 -82
  101. sphinx/ext/intersphinx/_resolve.py +108 -74
  102. sphinx/ext/intersphinx/_shared.py +2 -2
  103. sphinx/ext/linkcode.py +28 -12
  104. sphinx/ext/mathjax.py +60 -29
  105. sphinx/ext/napoleon/__init__.py +19 -7
  106. sphinx/ext/napoleon/docstring.py +229 -231
  107. sphinx/ext/todo.py +44 -49
  108. sphinx/ext/viewcode.py +105 -57
  109. sphinx/extension.py +3 -1
  110. sphinx/highlighting.py +13 -7
  111. sphinx/io.py +9 -13
  112. sphinx/jinja2glue.py +29 -26
  113. sphinx/locale/__init__.py +8 -9
  114. sphinx/parsers.py +8 -7
  115. sphinx/project.py +2 -2
  116. sphinx/pycode/__init__.py +31 -21
  117. sphinx/pycode/ast.py +6 -3
  118. sphinx/pycode/parser.py +14 -8
  119. sphinx/pygments_styles.py +4 -5
  120. sphinx/registry.py +192 -92
  121. sphinx/roles.py +58 -7
  122. sphinx/search/__init__.py +75 -54
  123. sphinx/search/en.py +11 -13
  124. sphinx/search/fi.py +1 -1
  125. sphinx/search/ja.py +8 -6
  126. sphinx/search/nl.py +1 -1
  127. sphinx/search/zh.py +19 -21
  128. sphinx/testing/fixtures.py +26 -29
  129. sphinx/testing/path.py +26 -62
  130. sphinx/testing/restructuredtext.py +14 -8
  131. sphinx/testing/util.py +21 -19
  132. sphinx/texinputs/make.bat.jinja +50 -50
  133. sphinx/texinputs/sphinx.sty +4 -3
  134. sphinx/texinputs/sphinxlatexadmonitions.sty +1 -1
  135. sphinx/texinputs/sphinxlatexobjects.sty +29 -10
  136. sphinx/themes/basic/static/searchtools.js +8 -5
  137. sphinx/theming.py +49 -61
  138. sphinx/transforms/__init__.py +17 -38
  139. sphinx/transforms/compact_bullet_list.py +5 -3
  140. sphinx/transforms/i18n.py +8 -21
  141. sphinx/transforms/post_transforms/__init__.py +142 -93
  142. sphinx/transforms/post_transforms/code.py +5 -5
  143. sphinx/transforms/post_transforms/images.py +28 -24
  144. sphinx/transforms/references.py +3 -1
  145. sphinx/util/__init__.py +109 -60
  146. sphinx/util/_files.py +39 -23
  147. sphinx/util/_importer.py +4 -1
  148. sphinx/util/_inventory_file_reader.py +76 -0
  149. sphinx/util/_io.py +2 -2
  150. sphinx/util/_lines.py +6 -3
  151. sphinx/util/_pathlib.py +40 -2
  152. sphinx/util/build_phase.py +2 -0
  153. sphinx/util/cfamily.py +19 -14
  154. sphinx/util/console.py +44 -179
  155. sphinx/util/display.py +9 -10
  156. sphinx/util/docfields.py +140 -122
  157. sphinx/util/docstrings.py +1 -1
  158. sphinx/util/docutils.py +118 -77
  159. sphinx/util/fileutil.py +25 -26
  160. sphinx/util/http_date.py +2 -0
  161. sphinx/util/i18n.py +77 -64
  162. sphinx/util/images.py +8 -6
  163. sphinx/util/inspect.py +147 -38
  164. sphinx/util/inventory.py +215 -116
  165. sphinx/util/logging.py +33 -33
  166. sphinx/util/matching.py +12 -4
  167. sphinx/util/nodes.py +18 -13
  168. sphinx/util/osutil.py +38 -39
  169. sphinx/util/parallel.py +22 -13
  170. sphinx/util/parsing.py +2 -1
  171. sphinx/util/png.py +6 -2
  172. sphinx/util/requests.py +33 -2
  173. sphinx/util/rst.py +3 -2
  174. sphinx/util/tags.py +1 -1
  175. sphinx/util/template.py +18 -10
  176. sphinx/util/texescape.py +8 -6
  177. sphinx/util/typing.py +148 -122
  178. sphinx/versioning.py +3 -3
  179. sphinx/writers/html.py +3 -1
  180. sphinx/writers/html5.py +61 -50
  181. sphinx/writers/latex.py +80 -65
  182. sphinx/writers/manpage.py +19 -38
  183. sphinx/writers/texinfo.py +44 -45
  184. sphinx/writers/text.py +48 -30
  185. sphinx/writers/xml.py +11 -8
  186. {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/LICENSE.rst +1 -1
  187. {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/METADATA +23 -15
  188. {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/RECORD +190 -186
  189. {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/WHEEL +1 -1
  190. sphinx/builders/html/transforms.py +0 -90
  191. sphinx/ext/apidoc.py +0 -721
  192. sphinx/util/exceptions.py +0 -74
  193. {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.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,14 +186,16 @@ 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
200
  pre: int, post: int = 0, what: Sequence[str] | None = None
190
201
  ) -> _AutodocProcessDocstringListener:
@@ -195,6 +206,7 @@ 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`.
@@ -225,6 +237,7 @@ def cut_lines(
225
237
  # make sure there is a blank line at the end
226
238
  if lines and lines[-1]:
227
239
  lines.append('')
240
+
228
241
  return process
229
242
 
230
243
 
@@ -271,11 +284,13 @@ def between(
271
284
  # make sure there is a blank line at the end
272
285
  if lines and lines[-1]:
273
286
  lines.append('')
287
+
274
288
  return process
275
289
 
276
290
 
277
291
  # This class is used only in ``sphinx.ext.autodoc.directive``,
278
- # 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
279
294
  class Options(dict[str, Any]):
280
295
  """A dict/attribute hybrid that returns None on nonexisting keys."""
281
296
 
@@ -296,18 +311,43 @@ class ObjectMember:
296
311
  represent each member of the object.
297
312
  """
298
313
 
299
- def __init__(self, name: str, obj: Any, *, docstring: str | None = None,
300
- 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:
301
331
  self.__name__ = name
302
332
  self.object = obj
303
333
  self.docstring = docstring
304
- self.skipped = skipped
305
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
+ )
306
347
 
307
348
 
308
349
  class Documenter:
309
- """
310
- A Documenter knows how to autodocument a single object type. When
350
+ """A Documenter knows how to autodocument a single object type. When
311
351
  registered with the AutoDirective, it will be used to document objects
312
352
  of that type when needed by autodoc.
313
353
 
@@ -335,25 +375,30 @@ class Documenter:
335
375
 
336
376
  option_spec: ClassVar[OptionSpec] = {
337
377
  'no-index': bool_option,
378
+ 'no-index-entry': bool_option,
338
379
  'noindex': bool_option,
339
380
  }
340
381
 
341
382
  def get_attr(self, obj: Any, name: str, *defargs: Any) -> Any:
342
383
  """getattr() override for types such as Zope interfaces."""
343
- return autodoc_attrgetter(self.env.app, obj, name, *defargs)
384
+ return autodoc_attrgetter(self.env._registry, obj, name, *defargs)
344
385
 
345
386
  @classmethod
346
387
  def can_document_member(
347
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
388
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
348
389
  ) -> bool:
349
390
  """Called to see if a member can be documented by this Documenter."""
350
391
  msg = 'must be implemented in subclasses'
351
392
  raise NotImplementedError(msg)
352
393
 
353
- def __init__(self, directive: DocumenterBridge, name: str, indent: str = '') -> None:
394
+ def __init__(
395
+ self, directive: DocumenterBridge, name: str, indent: str = ''
396
+ ) -> None:
354
397
  self.directive = directive
355
398
  self.config: Config = directive.env.config
356
399
  self.env: BuildEnvironment = directive.env
400
+ self._current_document: _CurrentDocument = directive.env.current_document
401
+ self._events: EventManager = directive.env.events
357
402
  self.options = directive.genopt
358
403
  self.name = name
359
404
  self.indent = indent
@@ -378,7 +423,7 @@ class Documenter:
378
423
  @property
379
424
  def documenters(self) -> dict[str, type[Documenter]]:
380
425
  """Returns registered Documenter classes"""
381
- return self.env.app.registry.documenters
426
+ return self.env._registry.documenters
382
427
 
383
428
  def add_line(self, line: str, source: str, *lineno: int) -> None:
384
429
  """Append one line of generated reST to the output."""
@@ -387,8 +432,9 @@ class Documenter:
387
432
  else:
388
433
  self.directive.result.append('', source, *lineno)
389
434
 
390
- def resolve_name(self, modname: str | None, parents: Any, path: str, base: str,
391
- ) -> 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]]:
392
438
  """Resolve the module and name of the object to document given by the
393
439
  arguments and the current module/class.
394
440
 
@@ -410,8 +456,12 @@ class Documenter:
410
456
  # an autogenerated one
411
457
  matched = py_ext_sig_re.match(self.name)
412
458
  if matched is None:
413
- logger.warning(__('invalid signature for auto%s (%r)'), self.objtype, self.name,
414
- type='autodoc')
459
+ logger.warning(
460
+ __('invalid signature for auto%s (%r)'),
461
+ self.objtype,
462
+ self.name,
463
+ type='autodoc',
464
+ )
415
465
  return False
416
466
  explicit_modname, path, base, tp_list, args, retann = matched.groups()
417
467
 
@@ -432,8 +482,7 @@ class Documenter:
432
482
  self.modname = modname
433
483
  self.args = args
434
484
  self.retann = retann
435
- self.fullname = ((self.modname or '') +
436
- ('.' + '.'.join(self.objpath) if self.objpath else ''))
485
+ self.fullname = '.'.join((self.modname or '', *self.objpath))
437
486
  return True
438
487
 
439
488
  def import_object(self, raiseerror: bool = False) -> bool:
@@ -445,8 +494,7 @@ class Documenter:
445
494
  with mock(self.config.autodoc_mock_imports):
446
495
  try:
447
496
  ret = import_object(
448
- self.modname, self.objpath, self.objtype,
449
- attrgetter=self.get_attr,
497
+ self.modname, self.objpath, self.objtype, attrgetter=self.get_attr
450
498
  )
451
499
  self.module, self.parent, self.object_name, self.object = ret
452
500
  if ismock(self.object):
@@ -514,7 +562,7 @@ class Documenter:
514
562
  """
515
563
  if self.args is not None:
516
564
  # signature given explicitly
517
- args = "(%s)" % self.args
565
+ args = f'({self.args})'
518
566
  retann = self.retann
519
567
  else:
520
568
  # try to introspect the signature
@@ -527,13 +575,23 @@ class Documenter:
527
575
  args = matched.group(1)
528
576
  retann = matched.group(2)
529
577
  except Exception as exc:
530
- logger.warning(__('error while formatting arguments for %s: %s'),
531
- 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
+ )
532
584
  args = None
533
585
 
534
- result = self.env.events.emit_firstresult('autodoc-process-signature',
535
- self.objtype, self.fullname,
536
- 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
+ )
537
595
  if result:
538
596
  args, retann = result
539
597
 
@@ -551,14 +609,15 @@ class Documenter:
551
609
 
552
610
  # one signature per line, indented by column
553
611
  prefix = f'.. {domain}:{directive}:: '
554
- for i, sig_line in enumerate(sig.split("\n")):
555
- self.add_line(f'{prefix}{name}{sig_line}',
556
- sourcename)
612
+ for i, sig_line in enumerate(sig.split('\n')):
613
+ self.add_line(f'{prefix}{name}{sig_line}', sourcename)
557
614
  if i == 0:
558
- prefix = " " * len(prefix)
615
+ prefix = ' ' * len(prefix)
559
616
 
560
617
  if self.options.no_index or self.options.noindex:
561
618
  self.add_line(' :no-index:', sourcename)
619
+ if self.options.no_index_entry:
620
+ self.add_line(' :no-index-entry:', sourcename)
562
621
  if self.objpath:
563
622
  # Be explicit about the module, this is necessary since .. class::
564
623
  # etc. don't support a prepended module name
@@ -570,8 +629,13 @@ class Documenter:
570
629
  When it returns None, autodoc-process-docstring will not be called for this
571
630
  object.
572
631
  """
573
- docstring = getdoc(self.object, self.get_attr, self.config.autodoc_inherit_docstrings,
574
- 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
+ )
575
639
  if docstring:
576
640
  tab_width = self.directive.state.document.settings.tab_width
577
641
  return [prepare_docstring(docstring, tab_width)]
@@ -580,21 +644,27 @@ class Documenter:
580
644
  def process_doc(self, docstrings: list[list[str]]) -> Iterator[str]:
581
645
  """Let the user process the docstrings before adding them."""
582
646
  for docstringlines in docstrings:
583
- if self.env.app:
647
+ if self._events is not None:
584
648
  # let extensions preprocess docstrings
585
- self.env.app.emit('autodoc-process-docstring',
586
- self.objtype, self.fullname, self.object,
587
- 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
+ )
588
657
 
589
- if docstringlines and docstringlines[-1] != '':
658
+ if docstringlines and docstringlines[-1]:
590
659
  # append a blank line to the end of the docstring
591
660
  docstringlines.append('')
592
661
 
593
662
  yield from docstringlines
594
663
 
595
664
  def get_sourcename(self) -> str:
596
- if (inspect.safe_getattr(self.object, '__module__', None) and
597
- 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:
598
668
  # Get the correct location of docstring from self.object
599
669
  # to support inherited methods
600
670
  fullname = f'{self.object.__module__}.{self.object.__qualname__}'
@@ -655,8 +725,9 @@ class Documenter:
655
725
  msg = 'must be implemented in subclasses'
656
726
  raise NotImplementedError(msg)
657
727
 
658
- def filter_members(self, members: list[ObjectMember], want_all: bool,
659
- ) -> list[tuple[str, Any, bool]]:
728
+ def filter_members(
729
+ self, members: list[ObjectMember], want_all: bool
730
+ ) -> list[tuple[str, Any, bool]]:
660
731
  """Filter the given member list.
661
732
 
662
733
  Members are skipped if
@@ -670,12 +741,22 @@ class Documenter:
670
741
  The user can override the skipping decision by connecting to the
671
742
  ``autodoc-skip-member`` event.
672
743
  """
744
+
673
745
  def is_filtered_inherited_member(name: str, obj: Any) -> bool:
674
746
  inherited_members = self.options.inherited_members or set()
747
+ seen = set()
675
748
 
676
749
  if inspect.isclass(self.object):
677
750
  for cls in self.object.__mro__:
678
- 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
+ ):
679
760
  # given member is a member of specified *super class*
680
761
  return True
681
762
  if name in cls.__dict__:
@@ -706,8 +787,13 @@ class Documenter:
706
787
  isattr = member is INSTANCEATTR or (namespace, membername) in attr_docs
707
788
 
708
789
  try:
709
- doc = getdoc(member, self.get_attr, self.config.autodoc_inherit_docstrings,
710
- self.object, membername)
790
+ doc = getdoc(
791
+ member,
792
+ self.get_attr,
793
+ self.config.autodoc_inherit_docstrings,
794
+ self.object,
795
+ membername,
796
+ )
711
797
  if not isinstance(doc, str):
712
798
  # Ignore non-string __doc__
713
799
  doc = None
@@ -740,14 +826,18 @@ class Documenter:
740
826
  if ismock(member) and (namespace, membername) not in attr_docs:
741
827
  # mocked module or object
742
828
  pass
743
- elif (self.options.exclude_members and
744
- membername in self.options.exclude_members):
829
+ elif (
830
+ self.options.exclude_members
831
+ and membername in self.options.exclude_members
832
+ ):
745
833
  # remove members given by exclude-members
746
834
  keep = False
747
835
  elif want_all and special_member_re.match(membername):
748
836
  # special __methods__
749
- if (self.options.special_members and
750
- membername in self.options.special_members):
837
+ if (
838
+ self.options.special_members
839
+ and membername in self.options.special_members
840
+ ):
751
841
  if membername == '__doc__': # NoQA: SIM114
752
842
  keep = False
753
843
  elif is_filtered_inherited_member(membername, obj):
@@ -776,8 +866,9 @@ class Documenter:
776
866
  else:
777
867
  keep = False
778
868
  else:
779
- if (self.options.members is ALL and
780
- is_filtered_inherited_member(membername, obj)):
869
+ if self.options.members is ALL and is_filtered_inherited_member(
870
+ membername, obj
871
+ ):
781
872
  keep = False
782
873
  else:
783
874
  # ignore undocumented members if :undoc-members: is not given
@@ -789,17 +880,30 @@ class Documenter:
789
880
 
790
881
  # give the user a chance to decide whether this member
791
882
  # should be skipped
792
- if self.env.app:
883
+ if self._events is not None:
793
884
  # let extensions preprocess docstrings
794
- skip_user = self.env.app.emit_firstresult(
795
- 'autodoc-skip-member', self.objtype, membername, member,
796
- 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
+ )
797
893
  if skip_user is not None:
798
894
  keep = not skip_user
799
895
  except Exception as exc:
800
- logger.warning(__('autodoc: failed to determine %s.%s (%r) to be documented, '
801
- 'the following exception was raised:\n%s'),
802
- 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
+ )
803
907
  keep = False
804
908
 
805
909
  if keep:
@@ -814,21 +918,24 @@ class Documenter:
814
918
  *self.options.members*.
815
919
  """
816
920
  # set current namespace for finding members
817
- self.env.temp_data['autodoc:module'] = self.modname
921
+ self._current_document.autodoc_module = self.modname
818
922
  if self.objpath:
819
- self.env.temp_data['autodoc:class'] = self.objpath[0]
923
+ self._current_document.autodoc_class = self.objpath[0]
820
924
 
821
- want_all = (all_members or
822
- self.options.inherited_members or
823
- self.options.members is ALL)
925
+ want_all = (
926
+ all_members or self.options.inherited_members or self.options.members is ALL
927
+ )
824
928
  # find out which members are documentable
825
929
  members_check_module, members = self.get_object_members(want_all)
826
930
 
827
931
  # document non-skipped members
828
- memberdocumenters: list[tuple[Documenter, bool]] = []
829
- for (mname, member, isattr) in self.filter_members(members, want_all):
830
- classes = [cls for cls in self.documenters.values()
831
- 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
+ ]
832
939
  if not classes:
833
940
  # don't know how to document this member
834
941
  continue
@@ -838,22 +945,39 @@ class Documenter:
838
945
  # of inner classes can be documented
839
946
  full_mname = f'{self.modname}::' + '.'.join((*self.objpath, mname))
840
947
  documenter = classes[-1](self.directive, full_mname, self.indent)
841
- memberdocumenters.append((documenter, isattr))
948
+ member_documenters.append((documenter, isattr))
842
949
 
843
950
  member_order = self.options.member_order or self.config.autodoc_member_order
844
- memberdocumenters = self.sort_members(memberdocumenters, member_order)
845
-
846
- for documenter, isattr in memberdocumenters:
847
- documenter.generate(
848
- all_members=True, real_modname=self.real_modname,
849
- 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
+ )
850
973
 
851
974
  # reset current objects
852
- self.env.temp_data['autodoc:module'] = None
853
- self.env.temp_data['autodoc:class'] = None
975
+ self._current_document.autodoc_module = ''
976
+ self._current_document.autodoc_class = ''
854
977
 
855
- def sort_members(self, documenters: list[tuple[Documenter, bool]],
856
- order: str) -> list[tuple[Documenter, bool]]:
978
+ def sort_members(
979
+ self, documenters: list[tuple[Documenter, bool]], order: str
980
+ ) -> list[tuple[Documenter, bool]]:
857
981
  """Sort the given member list."""
858
982
  if order == 'groupwise':
859
983
  # sort by group; alphabetically within groups
@@ -868,6 +992,7 @@ class Documenter:
868
992
  def keyfunc(entry: tuple[Documenter, bool]) -> int:
869
993
  fullname = entry[0].name.split('::')[1]
870
994
  return tagorder.get(fullname, len(tagorder))
995
+
871
996
  documenters.sort(key=keyfunc)
872
997
  else: # alphabetical
873
998
  documenters.sort(key=lambda e: e[0].name)
@@ -892,16 +1017,29 @@ class Documenter:
892
1017
  if not self.parse_name():
893
1018
  # need a module to import
894
1019
  logger.warning(
895
- __("don't know which module to import for autodocumenting "
896
- '%r (try placing a "module" or "currentmodule" directive '
897
- 'in the document, or giving an explicit module name)'),
898
- 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
+ )
899
1028
  return
900
1029
 
901
1030
  # now, import the module and get object to document
902
1031
  if not self.import_object():
903
1032
  return
904
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:
905
1043
  # If there is no real module defined, figure out which to use.
906
1044
  # The real module is used in the module analyzer to look up the module
907
1045
  # where the attribute documentation would actually be found in.
@@ -934,10 +1072,16 @@ class Documenter:
934
1072
  except PycodeError:
935
1073
  pass
936
1074
 
937
- 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
+ )
938
1078
  if ismock(self.object) and not docstrings:
939
- logger.warning(__('A mocked object is detected: %r'),
940
- 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
+ )
941
1085
 
942
1086
  # check __module__ of object (for members not given explicitly)
943
1087
  if check_module:
@@ -955,8 +1099,12 @@ class Documenter:
955
1099
  try:
956
1100
  sig = self.format_signature()
957
1101
  except Exception as exc:
958
- logger.warning(__('error while formatting signature for %s: %s'),
959
- 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
+ )
960
1108
  return
961
1109
 
962
1110
  # generate the directive header and options, if applicable
@@ -974,22 +1122,28 @@ class Documenter:
974
1122
 
975
1123
 
976
1124
  class ModuleDocumenter(Documenter):
977
- """
978
- Specialized Documenter subclass for modules.
979
- """
1125
+ """Specialized Documenter subclass for modules."""
980
1126
 
981
1127
  objtype = 'module'
982
1128
  content_indent = ''
983
1129
  _extra_indent = ' '
984
1130
 
985
1131
  option_spec: ClassVar[OptionSpec] = {
986
- 'members': members_option, 'undoc-members': bool_option,
987
- 'no-index': bool_option, 'inherited-members': inherited_members_option,
988
- 'show-inheritance': bool_option, 'synopsis': identity,
989
- 'platform': identity, 'deprecated': bool_option,
990
- 'member-order': member_order_option, 'exclude-members': exclude_members_option,
991
- 'private-members': members_option, 'special-members': members_option,
992
- '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,
993
1147
  'no-value': bool_option,
994
1148
  'noindex': bool_option,
995
1149
  }
@@ -1010,24 +1164,28 @@ class ModuleDocumenter(Documenter):
1010
1164
 
1011
1165
  @classmethod
1012
1166
  def can_document_member(
1013
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
1167
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
1014
1168
  ) -> bool:
1015
1169
  # don't document submodules automatically
1016
1170
  return False
1017
1171
 
1018
- def resolve_name(self, modname: str | None, parents: Any, path: str, base: str,
1019
- ) -> 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]]:
1020
1175
  if modname is not None:
1021
- logger.warning(__('"::" in automodule name doesn\'t make sense'),
1022
- type='autodoc')
1176
+ logger.warning(
1177
+ __('"::" in automodule name doesn\'t make sense'), type='autodoc'
1178
+ )
1023
1179
  return (path or '') + base, []
1024
1180
 
1025
1181
  def parse_name(self) -> bool:
1026
1182
  ret = super().parse_name()
1027
1183
  if self.args or self.retann:
1028
- logger.warning(__('signature arguments or return annotation '
1029
- 'given for automodule %s'), self.fullname,
1030
- type='autodoc')
1184
+ logger.warning(
1185
+ __('signature arguments or return annotation given for automodule %s'),
1186
+ self.fullname,
1187
+ type='autodoc',
1188
+ )
1031
1189
  return ret
1032
1190
 
1033
1191
  def import_object(self, raiseerror: bool = False) -> bool:
@@ -1038,9 +1196,15 @@ class ModuleDocumenter(Documenter):
1038
1196
  self.__all__ = inspect.getall(self.object)
1039
1197
  except ValueError as exc:
1040
1198
  # invalid __all__ found.
1041
- logger.warning(__('__all__ should be a list of strings, not %r '
1042
- '(in module %s) -- ignoring __all__'),
1043
- 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
+ )
1044
1208
 
1045
1209
  return ret
1046
1210
 
@@ -1056,6 +1220,8 @@ class ModuleDocumenter(Documenter):
1056
1220
  self.add_line(' :platform: ' + self.options.platform, sourcename)
1057
1221
  if self.options.deprecated:
1058
1222
  self.add_line(' :deprecated:', sourcename)
1223
+ if self.options.no_index_entry:
1224
+ self.add_line(' :no-index-entry:', sourcename)
1059
1225
 
1060
1226
  def get_module_members(self) -> dict[str, ObjectMember]:
1061
1227
  """Get members of target module."""
@@ -1071,7 +1237,9 @@ class ModuleDocumenter(Documenter):
1071
1237
  if ismock(value):
1072
1238
  value = undecorate(value)
1073
1239
  docstring = attr_docs.get(('', name), [])
1074
- members[name] = ObjectMember(name, value, docstring="\n".join(docstring))
1240
+ members[name] = ObjectMember(
1241
+ name, value, docstring='\n'.join(docstring)
1242
+ )
1075
1243
  except AttributeError:
1076
1244
  continue
1077
1245
 
@@ -1079,8 +1247,9 @@ class ModuleDocumenter(Documenter):
1079
1247
  for name in inspect.getannotations(self.object):
1080
1248
  if name not in members:
1081
1249
  docstring = attr_docs.get(('', name), [])
1082
- members[name] = ObjectMember(name, INSTANCEATTR,
1083
- docstring="\n".join(docstring))
1250
+ members[name] = ObjectMember(
1251
+ name, INSTANCEATTR, docstring='\n'.join(docstring)
1252
+ )
1084
1253
 
1085
1254
  return members
1086
1255
 
@@ -1104,15 +1273,20 @@ class ModuleDocumenter(Documenter):
1104
1273
  if name in members:
1105
1274
  ret.append(members[name])
1106
1275
  else:
1107
- logger.warning(__('missing attribute mentioned in :members: option: '
1108
- 'module %s, attribute %s'),
1109
- safe_getattr(self.object, '__name__', '???'),
1110
- name,
1111
- 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
+ )
1112
1285
  return False, ret
1113
1286
 
1114
- def sort_members(self, documenters: list[tuple[Documenter, bool]],
1115
- order: str) -> list[tuple[Documenter, bool]]:
1287
+ def sort_members(
1288
+ self, documenters: list[tuple[Documenter, bool]], order: str
1289
+ ) -> list[tuple[Documenter, bool]]:
1116
1290
  if order == 'bysource' and self.__all__:
1117
1291
  assert self.__all__ is not None
1118
1292
  module_all = self.__all__
@@ -1129,6 +1303,7 @@ class ModuleDocumenter(Documenter):
1129
1303
  return module_all.index(name)
1130
1304
  else:
1131
1305
  return module_all_len
1306
+
1132
1307
  documenters.sort(key=keyfunc)
1133
1308
 
1134
1309
  return documenters
@@ -1137,13 +1312,13 @@ class ModuleDocumenter(Documenter):
1137
1312
 
1138
1313
 
1139
1314
  class ModuleLevelDocumenter(Documenter):
1140
- """
1141
- Specialized Documenter subclass for objects on module level (functions,
1315
+ """Specialized Documenter subclass for objects on module level (functions,
1142
1316
  classes, data/constants).
1143
1317
  """
1144
1318
 
1145
- def resolve_name(self, modname: str | None, parents: Any, path: str, base: str,
1146
- ) -> 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]]:
1147
1322
  if modname is not None:
1148
1323
  return modname, [*parents, base]
1149
1324
  if path:
@@ -1152,7 +1327,7 @@ class ModuleLevelDocumenter(Documenter):
1152
1327
 
1153
1328
  # if documenting a toplevel object without explicit module,
1154
1329
  # it can be contained in another auto directive ...
1155
- modname = self.env.temp_data.get('autodoc:module')
1330
+ modname = self._current_document.autodoc_module
1156
1331
  # ... or in the scope of a module directive
1157
1332
  if not modname:
1158
1333
  modname = self.env.ref_context.get('py:module')
@@ -1161,13 +1336,13 @@ class ModuleLevelDocumenter(Documenter):
1161
1336
 
1162
1337
 
1163
1338
  class ClassLevelDocumenter(Documenter):
1164
- """
1165
- Specialized Documenter subclass for objects on class level (methods,
1339
+ """Specialized Documenter subclass for objects on class level (methods,
1166
1340
  attributes).
1167
1341
  """
1168
1342
 
1169
- def resolve_name(self, modname: str | None, parents: Any, path: str, base: str,
1170
- ) -> 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]]:
1171
1346
  if modname is not None:
1172
1347
  return modname, [*parents, base]
1173
1348
 
@@ -1177,19 +1352,18 @@ class ClassLevelDocumenter(Documenter):
1177
1352
  # if documenting a class-level object without path,
1178
1353
  # there must be a current class, either from a parent
1179
1354
  # auto directive ...
1180
- mod_cls_ = self.env.temp_data.get('autodoc:class')
1355
+ mod_cls = self._current_document.autodoc_class
1181
1356
  # ... or from a class directive
1182
- if mod_cls_ is None:
1183
- mod_cls_ = self.env.ref_context.get('py:class')
1184
- # ... if still None, there's no way to know
1185
- 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:
1186
1361
  return None, []
1187
- mod_cls = mod_cls_
1188
1362
  modname, sep, cls = mod_cls.rpartition('.')
1189
1363
  parents = [cls]
1190
1364
  # if the module name is still missing, get it like above
1191
1365
  if not modname:
1192
- modname = self.env.temp_data.get('autodoc:module')
1366
+ modname = self._current_document.autodoc_module
1193
1367
  if not modname:
1194
1368
  modname = self.env.ref_context.get('py:module')
1195
1369
  # ... else, it stays None, which means invalid
@@ -1197,8 +1371,7 @@ class ClassLevelDocumenter(Documenter):
1197
1371
 
1198
1372
 
1199
1373
  class DocstringSignatureMixin:
1200
- """
1201
- Mixin for FunctionDocumenter and MethodDocumenter to provide the
1374
+ """Mixin for FunctionDocumenter and MethodDocumenter to provide the
1202
1375
  feature of reading the signature from the docstring.
1203
1376
  """
1204
1377
 
@@ -1241,15 +1414,16 @@ class DocstringSignatureMixin:
1241
1414
  # re-prepare docstring to ignore more leading indentation
1242
1415
  directive = self.directive # type: ignore[attr-defined]
1243
1416
  tab_width = directive.state.document.settings.tab_width
1244
- self._new_docstrings[i] = prepare_docstring('\n'.join(doclines[j + 1:]),
1245
- tab_width)
1417
+ self._new_docstrings[i] = prepare_docstring(
1418
+ '\n'.join(doclines[j + 1 :]), tab_width
1419
+ )
1246
1420
 
1247
1421
  if result is None:
1248
1422
  # first signature
1249
1423
  result = args, retann
1250
1424
  else:
1251
1425
  # subsequent signatures
1252
- self._signatures.append(f"({args}) -> {retann}")
1426
+ self._signatures.append(f'({args}) -> {retann}')
1253
1427
 
1254
1428
  if result is not None:
1255
1429
  # finish the loop when signature found
@@ -1264,8 +1438,7 @@ class DocstringSignatureMixin:
1264
1438
 
1265
1439
  def format_signature(self, **kwargs: Any) -> str:
1266
1440
  self.args: str | None
1267
- if (self.args is None
1268
- 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]
1269
1442
  # only act if a signature is not explicitly given already, and if
1270
1443
  # the feature is enabled
1271
1444
  result = self._find_signature()
@@ -1273,22 +1446,18 @@ class DocstringSignatureMixin:
1273
1446
  self.args, self.retann = result
1274
1447
  sig = super().format_signature(**kwargs) # type: ignore[misc]
1275
1448
  if self._signatures:
1276
- return "\n".join((sig, *self._signatures))
1449
+ return '\n'.join((sig, *self._signatures))
1277
1450
  else:
1278
1451
  return sig
1279
1452
 
1280
1453
 
1281
1454
  class DocstringStripSignatureMixin(DocstringSignatureMixin):
1282
- """
1283
- Mixin for AttributeDocumenter to provide the
1455
+ """Mixin for AttributeDocumenter to provide the
1284
1456
  feature of stripping any function signature from the docstring.
1285
1457
  """
1286
1458
 
1287
1459
  def format_signature(self, **kwargs: Any) -> str:
1288
- if (
1289
- self.args is None
1290
- and self.config.autodoc_docstring_signature # type: ignore[attr-defined]
1291
- ):
1460
+ if self.args is None and self.config.autodoc_docstring_signature: # type: ignore[attr-defined]
1292
1461
  # only act if a signature is not explicitly given already, and if
1293
1462
  # the feature is enabled
1294
1463
  result = self._find_signature()
@@ -1301,34 +1470,40 @@ class DocstringStripSignatureMixin(DocstringSignatureMixin):
1301
1470
 
1302
1471
 
1303
1472
  class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: ignore[misc]
1304
- """
1305
- Specialized Documenter subclass for functions.
1306
- """
1473
+ """Specialized Documenter subclass for functions."""
1307
1474
 
1308
1475
  objtype = 'function'
1309
1476
  member_order = 30
1310
1477
 
1311
1478
  @classmethod
1312
1479
  def can_document_member(
1313
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
1480
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
1314
1481
  ) -> bool:
1315
1482
  # supports functions, builtins and bound methods exported at the module level
1316
- return (inspect.isfunction(member) or inspect.isbuiltin(member) or
1317
- (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
+ )
1318
1488
 
1319
1489
  def format_args(self, **kwargs: Any) -> str:
1320
- if self.config.autodoc_typehints in ('none', 'description'):
1490
+ if self.config.autodoc_typehints in {'none', 'description'}:
1321
1491
  kwargs.setdefault('show_annotation', False)
1322
- if self.config.autodoc_typehints_format == "short":
1492
+ if self.config.autodoc_typehints_format == 'short':
1323
1493
  kwargs.setdefault('unqualified_typehints', True)
1494
+ if self.config.python_display_short_literal_types:
1495
+ kwargs.setdefault('short_literals', True)
1324
1496
 
1325
1497
  try:
1326
- self.env.app.emit('autodoc-before-process-signature', self.object, False)
1327
- 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
+ )
1328
1502
  args = stringify_signature(sig, **kwargs)
1329
1503
  except TypeError as exc:
1330
- logger.warning(__("Failed to get a function signature for %s: %s"),
1331
- self.fullname, exc)
1504
+ logger.warning(
1505
+ __('Failed to get a function signature for %s: %s'), self.fullname, exc
1506
+ )
1332
1507
  return ''
1333
1508
  except ValueError:
1334
1509
  args = ''
@@ -1345,17 +1520,23 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
1345
1520
  sourcename = self.get_sourcename()
1346
1521
  super().add_directive_header(sig)
1347
1522
 
1348
- 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:
1349
1526
  self.add_line(' :async:', sourcename)
1350
1527
 
1351
1528
  def format_signature(self, **kwargs: Any) -> str:
1352
- if self.config.autodoc_typehints_format == "short":
1529
+ if self.config.autodoc_typehints_format == 'short':
1353
1530
  kwargs.setdefault('unqualified_typehints', True)
1531
+ if self.config.python_display_short_literal_types:
1532
+ kwargs.setdefault('short_literals', True)
1354
1533
 
1355
1534
  sigs = []
1356
- if (self.analyzer and
1357
- '.'.join(self.objpath) in self.analyzer.overloads and
1358
- 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
+ ):
1359
1540
  # Use signatures for overloaded functions instead of the implementation function.
1360
1541
  overloaded = True
1361
1542
  else:
@@ -1376,18 +1557,20 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
1376
1557
  documenter.objpath = ['']
1377
1558
  sigs.append(documenter.format_signature())
1378
1559
  if overloaded and self.analyzer is not None:
1379
- actual = inspect.signature(self.object,
1380
- type_aliases=self.config.autodoc_type_aliases)
1560
+ actual = inspect.signature(
1561
+ self.object, type_aliases=self.config.autodoc_type_aliases
1562
+ )
1381
1563
  __globals__ = safe_getattr(self.object, '__globals__', {})
1382
1564
  for overload in self.analyzer.overloads['.'.join(self.objpath)]:
1383
1565
  overload = self.merge_default_value(actual, overload)
1384
- overload = evaluate_signature(overload, __globals__,
1385
- self.config.autodoc_type_aliases)
1566
+ overload = evaluate_signature(
1567
+ overload, __globals__, self.config.autodoc_type_aliases
1568
+ )
1386
1569
 
1387
1570
  sig = stringify_signature(overload, **kwargs)
1388
1571
  sigs.append(sig)
1389
1572
 
1390
- return "\n".join(sigs)
1573
+ return '\n'.join(sigs)
1391
1574
 
1392
1575
  def merge_default_value(self, actual: Signature, overload: Signature) -> Signature:
1393
1576
  """Merge default values of actual implementation to the overload variants."""
@@ -1399,13 +1582,16 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
1399
1582
 
1400
1583
  return overload.replace(parameters=parameters)
1401
1584
 
1402
- 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:
1403
1588
  """Annotate type hint to the first argument of function if needed."""
1404
1589
  try:
1405
1590
  sig = inspect.signature(func, type_aliases=self.config.autodoc_type_aliases)
1406
1591
  except TypeError as exc:
1407
- logger.warning(__("Failed to get a function signature for %s: %s"),
1408
- self.fullname, exc)
1592
+ logger.warning(
1593
+ __('Failed to get a function signature for %s: %s'), self.fullname, exc
1594
+ )
1409
1595
  return None
1410
1596
  except ValueError:
1411
1597
  return None
@@ -1420,8 +1606,7 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
1420
1606
  if params[0].annotation is Parameter.empty:
1421
1607
  params[0] = params[0].replace(annotation=typ)
1422
1608
  try:
1423
- dummy.__signature__ = sig.replace( # type: ignore[attr-defined]
1424
- parameters=params)
1609
+ dummy.__signature__ = sig.replace(parameters=params) # type: ignore[attr-defined]
1425
1610
  return dummy
1426
1611
  except (AttributeError, TypeError):
1427
1612
  # failed to update signature (ex. built-in or extension types)
@@ -1431,9 +1616,7 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
1431
1616
 
1432
1617
 
1433
1618
  class DecoratorDocumenter(FunctionDocumenter):
1434
- """
1435
- Specialized Documenter subclass for decorator functions.
1436
- """
1619
+ """Specialized Documenter subclass for decorator functions."""
1437
1620
 
1438
1621
  objtype = 'decorator'
1439
1622
 
@@ -1451,30 +1634,33 @@ class DecoratorDocumenter(FunctionDocumenter):
1451
1634
  # Types which have confusing metaclass signatures it would be best not to show.
1452
1635
  # These are listed by name, rather than storing the objects themselves, to avoid
1453
1636
  # needing to import the modules.
1454
- _METACLASS_CALL_BLACKLIST = [
1455
- 'enum.EnumMeta.__call__',
1456
- ]
1637
+ _METACLASS_CALL_BLACKLIST = frozenset({
1638
+ 'enum.EnumType.__call__',
1639
+ })
1457
1640
 
1458
1641
 
1459
1642
  # Types whose __new__ signature is a pass-through.
1460
- _CLASS_NEW_BLACKLIST = [
1643
+ _CLASS_NEW_BLACKLIST = frozenset({
1461
1644
  'typing.Generic.__new__',
1462
- ]
1645
+ })
1463
1646
 
1464
1647
 
1465
1648
  class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: ignore[misc]
1466
- """
1467
- Specialized Documenter subclass for classes.
1468
- """
1649
+ """Specialized Documenter subclass for classes."""
1469
1650
 
1470
1651
  objtype = 'class'
1471
1652
  member_order = 20
1472
1653
  option_spec: ClassVar[OptionSpec] = {
1473
- 'members': members_option, 'undoc-members': bool_option,
1474
- 'no-index': bool_option, 'inherited-members': inherited_members_option,
1475
- '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,
1476
1661
  'exclude-members': exclude_members_option,
1477
- 'private-members': members_option, 'special-members': members_option,
1662
+ 'private-members': members_option,
1663
+ 'special-members': members_option,
1478
1664
  'class-doc-from': class_doc_from_option,
1479
1665
  'noindex': bool_option,
1480
1666
  }
@@ -1504,10 +1690,11 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1504
1690
 
1505
1691
  @classmethod
1506
1692
  def can_document_member(
1507
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
1693
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
1508
1694
  ) -> bool:
1509
1695
  return isinstance(member, type) or (
1510
- isattr and isinstance(member, NewType | TypeVar))
1696
+ isattr and isinstance(member, NewType | TypeVar)
1697
+ )
1511
1698
 
1512
1699
  def import_object(self, raiseerror: bool = False) -> bool:
1513
1700
  ret = super().import_object(raiseerror)
@@ -1515,13 +1702,13 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1515
1702
  # as data/attribute
1516
1703
  if ret:
1517
1704
  if hasattr(self.object, '__name__'):
1518
- self.doc_as_attr = (self.objpath[-1] != self.object.__name__)
1705
+ self.doc_as_attr = self.objpath[-1] != self.object.__name__
1519
1706
  else:
1520
1707
  self.doc_as_attr = True
1521
1708
  if isinstance(self.object, NewType | TypeVar):
1522
1709
  modname = getattr(self.object, '__module__', self.modname)
1523
1710
  if modname != self.modname and self.modname.startswith(modname):
1524
- bases = self.modname[len(modname):].strip('.').split('.')
1711
+ bases = self.modname[len(modname) :].strip('.').split('.')
1525
1712
  self.objpath = bases + self.objpath
1526
1713
  self.modname = modname
1527
1714
  return ret
@@ -1543,24 +1730,32 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1543
1730
  # This sequence is copied from inspect._signature_from_callable.
1544
1731
  # ValueError means that no signature could be found, so we keep going.
1545
1732
 
1546
- # First, we check the obj has a __signature__ attribute
1547
- if (hasattr(self.object, '__signature__') and
1548
- isinstance(self.object.__signature__, Signature)):
1549
- 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)
1550
1742
 
1551
1743
  # Next, let's see if it has an overloaded __call__ defined
1552
1744
  # in its metaclass
1553
1745
  call = get_user_defined_function_or_method(type(self.object), '__call__')
1554
1746
 
1555
1747
  if call is not None:
1556
- if f"{call.__module__}.{call.__qualname__}" in _METACLASS_CALL_BLACKLIST:
1748
+ if f'{call.__module__}.{call.__qualname__}' in _METACLASS_CALL_BLACKLIST:
1557
1749
  call = None
1558
1750
 
1559
1751
  if call is not None:
1560
- self.env.app.emit('autodoc-before-process-signature', call, True)
1752
+ self._events.emit('autodoc-before-process-signature', call, True)
1561
1753
  try:
1562
- sig = inspect.signature(call, bound_method=True,
1563
- 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
+ )
1564
1759
  return type(self.object), '__call__', sig
1565
1760
  except ValueError:
1566
1761
  pass
@@ -1569,14 +1764,17 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1569
1764
  new = get_user_defined_function_or_method(self.object, '__new__')
1570
1765
 
1571
1766
  if new is not None:
1572
- if f"{new.__module__}.{new.__qualname__}" in _CLASS_NEW_BLACKLIST:
1767
+ if f'{new.__module__}.{new.__qualname__}' in _CLASS_NEW_BLACKLIST:
1573
1768
  new = None
1574
1769
 
1575
1770
  if new is not None:
1576
- self.env.app.emit('autodoc-before-process-signature', new, True)
1771
+ self._events.emit('autodoc-before-process-signature', new, True)
1577
1772
  try:
1578
- sig = inspect.signature(new, bound_method=True,
1579
- 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
+ )
1580
1778
  return self.object, '__new__', sig
1581
1779
  except ValueError:
1582
1780
  pass
@@ -1584,10 +1782,13 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1584
1782
  # Finally, we should have at least __init__ implemented
1585
1783
  init = get_user_defined_function_or_method(self.object, '__init__')
1586
1784
  if init is not None:
1587
- self.env.app.emit('autodoc-before-process-signature', init, True)
1785
+ self._events.emit('autodoc-before-process-signature', init, True)
1588
1786
  try:
1589
- sig = inspect.signature(init, bound_method=True,
1590
- 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
+ )
1591
1792
  return self.object, '__init__', sig
1592
1793
  except ValueError:
1593
1794
  pass
@@ -1596,10 +1797,13 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1596
1797
  # handle it.
1597
1798
  # We don't know the exact method that inspect.signature will read
1598
1799
  # the signature from, so just pass the object itself to our hook.
1599
- self.env.app.emit('autodoc-before-process-signature', self.object, False)
1800
+ self._events.emit('autodoc-before-process-signature', self.object, False)
1600
1801
  try:
1601
- sig = inspect.signature(self.object, bound_method=False,
1602
- 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
+ )
1603
1807
  return None, None, sig
1604
1808
  except ValueError:
1605
1809
  pass
@@ -1609,17 +1813,22 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1609
1813
  return None, None, None
1610
1814
 
1611
1815
  def format_args(self, **kwargs: Any) -> str:
1612
- if self.config.autodoc_typehints in ('none', 'description'):
1816
+ if self.config.autodoc_typehints in {'none', 'description'}:
1613
1817
  kwargs.setdefault('show_annotation', False)
1614
- if self.config.autodoc_typehints_format == "short":
1818
+ if self.config.autodoc_typehints_format == 'short':
1615
1819
  kwargs.setdefault('unqualified_typehints', True)
1820
+ if self.config.python_display_short_literal_types:
1821
+ kwargs.setdefault('short_literals', True)
1616
1822
 
1617
1823
  try:
1618
1824
  self._signature_class, _signature_method_name, sig = self._get_signature()
1619
1825
  except TypeError as exc:
1620
1826
  # __signature__ attribute contained junk
1621
- logger.warning(__("Failed to get a constructor signature for %s: %s"),
1622
- self.fullname, exc)
1827
+ logger.warning(
1828
+ __('Failed to get a constructor signature for %s: %s'),
1829
+ self.fullname,
1830
+ exc,
1831
+ )
1623
1832
  return ''
1624
1833
  self._signature_method_name = _signature_method_name or ''
1625
1834
 
@@ -1649,8 +1858,10 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1649
1858
  # do not show signatures
1650
1859
  return ''
1651
1860
 
1652
- if self.config.autodoc_typehints_format == "short":
1861
+ if self.config.autodoc_typehints_format == 'short':
1653
1862
  kwargs.setdefault('unqualified_typehints', True)
1863
+ if self.config.python_display_short_literal_types:
1864
+ kwargs.setdefault('short_literals', True)
1654
1865
 
1655
1866
  sig = super().format_signature()
1656
1867
  sigs = []
@@ -1658,21 +1869,25 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1658
1869
  overloads = self.get_overloaded_signatures()
1659
1870
  if overloads and self.config.autodoc_typehints != 'none':
1660
1871
  # Use signatures for overloaded methods instead of the implementation method.
1661
- 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
+ )
1662
1875
  __globals__ = safe_getattr(method, '__globals__', {})
1663
1876
  for overload in overloads:
1664
- overload = evaluate_signature(overload, __globals__,
1665
- self.config.autodoc_type_aliases)
1877
+ overload = evaluate_signature(
1878
+ overload, __globals__, self.config.autodoc_type_aliases
1879
+ )
1666
1880
 
1667
1881
  parameters = list(overload.parameters.values())
1668
- overload = overload.replace(parameters=parameters[1:],
1669
- return_annotation=Parameter.empty)
1882
+ overload = overload.replace(
1883
+ parameters=parameters[1:], return_annotation=Parameter.empty
1884
+ )
1670
1885
  sig = stringify_signature(overload, **kwargs)
1671
1886
  sigs.append(sig)
1672
1887
  else:
1673
1888
  sigs.append(sig)
1674
1889
 
1675
- return "\n".join(sigs)
1890
+ return '\n'.join(sigs)
1676
1891
 
1677
1892
  def get_overloaded_signatures(self) -> list[Signature]:
1678
1893
  if self._signature_class and self._signature_method_name:
@@ -1719,8 +1934,12 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1719
1934
  self.add_line(' :final:', sourcename)
1720
1935
 
1721
1936
  canonical_fullname = self.get_canonical_fullname()
1722
- if (not self.doc_as_attr and not isinstance(self.object, NewType)
1723
- 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
+ ):
1724
1943
  self.add_line(' :canonical: %s' % canonical_fullname, sourcename)
1725
1944
 
1726
1945
  # add inheritance info, if wanted
@@ -1735,21 +1954,24 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1735
1954
  else:
1736
1955
  bases = []
1737
1956
 
1738
- self.env.events.emit('autodoc-process-bases',
1739
- self.fullname, self.object, self.options, bases)
1957
+ self._events.emit(
1958
+ 'autodoc-process-bases', self.fullname, self.object, self.options, bases
1959
+ )
1740
1960
 
1741
- if self.config.autodoc_typehints_format == "short":
1742
- base_classes = [restify(cls, "smart") for cls in bases]
1743
- else:
1744
- 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]
1745
1963
 
1746
1964
  sourcename = self.get_sourcename()
1747
1965
  self.add_line('', sourcename)
1748
1966
  self.add_line(' ' + _('Bases: %s') % ', '.join(base_classes), sourcename)
1749
1967
 
1750
1968
  def get_object_members(self, want_all: bool) -> tuple[bool, list[ObjectMember]]:
1751
- members = get_class_members(self.object, self.objpath, self.get_attr,
1752
- 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
+ )
1753
1975
  if not want_all:
1754
1976
  if not self.options.members:
1755
1977
  return False, []
@@ -1759,8 +1981,12 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1759
1981
  if name in members:
1760
1982
  selected.append(members[name])
1761
1983
  else:
1762
- logger.warning(__('missing attribute %s in object %s'),
1763
- name, self.fullname, type='autodoc')
1984
+ logger.warning(
1985
+ __('missing attribute %s in object %s'),
1986
+ name,
1987
+ self.fullname,
1988
+ type='autodoc',
1989
+ )
1764
1990
  return False, selected
1765
1991
  elif self.options.inherited_members:
1766
1992
  return False, list(members.values())
@@ -1782,7 +2008,9 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1782
2008
  if lines is not None:
1783
2009
  return lines
1784
2010
 
1785
- 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
+ )
1786
2014
 
1787
2015
  docstrings = []
1788
2016
  attrdocstring = getdoc(self.object, self.get_attr)
@@ -1791,26 +2019,36 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1791
2019
 
1792
2020
  # for classes, what the "docstring" is can be controlled via a
1793
2021
  # config value; the default is only the class docstring
1794
- if classdoc_from in ('both', 'init'):
2022
+ if classdoc_from in {'both', 'init'}:
1795
2023
  __init__ = self.get_attr(self.object, '__init__', None)
1796
- initdocstring = getdoc(__init__, self.get_attr,
1797
- self.config.autodoc_inherit_docstrings,
1798
- self.object, '__init__')
2024
+ initdocstring = getdoc(
2025
+ __init__,
2026
+ self.get_attr,
2027
+ self.config.autodoc_inherit_docstrings,
2028
+ self.object,
2029
+ '__init__',
2030
+ )
1799
2031
  # for new-style classes, no __init__ means default __init__
1800
- if (initdocstring is not None and
1801
- (initdocstring == object.__init__.__doc__ or # for pypy
1802
- 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
+ ):
1803
2036
  initdocstring = None
1804
2037
  if not initdocstring:
1805
2038
  # try __new__
1806
2039
  __new__ = self.get_attr(self.object, '__new__', None)
1807
- initdocstring = getdoc(__new__, self.get_attr,
1808
- self.config.autodoc_inherit_docstrings,
1809
- self.object, '__new__')
2040
+ initdocstring = getdoc(
2041
+ __new__,
2042
+ self.get_attr,
2043
+ self.config.autodoc_inherit_docstrings,
2044
+ self.object,
2045
+ '__new__',
2046
+ )
1810
2047
  # for new-style classes, no __new__ means default __new__
1811
- if (initdocstring is not None and
1812
- (initdocstring == object.__new__.__doc__ or # for pypy
1813
- 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
+ ):
1814
2052
  initdocstring = None
1815
2053
  if initdocstring:
1816
2054
  if classdoc_from == 'init':
@@ -1834,34 +2072,29 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1834
2072
  return None
1835
2073
 
1836
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
+
1837
2078
  if isinstance(self.object, NewType):
1838
- if self.config.autodoc_typehints_format == "short":
1839
- supertype = restify(self.object.__supertype__, "smart")
1840
- else:
1841
- supertype = restify(self.object.__supertype__)
2079
+ supertype = restify(self.object.__supertype__, mode=mode)
1842
2080
 
1843
2081
  more_content = StringList([_('alias of %s') % supertype, ''], source='')
1844
2082
  if isinstance(self.object, TypeVar):
1845
2083
  attrs = [repr(self.object.__name__)]
1846
- for constraint in self.object.__constraints__:
1847
- if self.config.autodoc_typehints_format == "short":
1848
- attrs.append(stringify_annotation(constraint, "smart"))
1849
- else:
1850
- 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
+ )
1851
2088
  if self.object.__bound__:
1852
- if self.config.autodoc_typehints_format == "short":
1853
- bound = restify(self.object.__bound__, "smart")
1854
- else:
1855
- bound = restify(self.object.__bound__)
1856
- attrs.append(r"bound=\ " + bound)
2089
+ bound = restify(self.object.__bound__, mode=mode)
2090
+ attrs.append(r'bound=\ ' + bound)
1857
2091
  if self.object.__covariant__:
1858
- attrs.append("covariant=True")
2092
+ attrs.append('covariant=True')
1859
2093
  if self.object.__contravariant__:
1860
- attrs.append("contravariant=True")
2094
+ attrs.append('contravariant=True')
1861
2095
 
1862
2096
  more_content = StringList(
1863
- [_('alias of TypeVar(%s)') % ", ".join(attrs), ''],
1864
- source='',
2097
+ [_('alias of TypeVar(%s)') % ', '.join(attrs), ''], source=''
1865
2098
  )
1866
2099
  if self.doc_as_attr and self.modname != self.get_real_modname():
1867
2100
  try:
@@ -1873,10 +2106,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1873
2106
 
1874
2107
  if self.doc_as_attr and not self.get_variable_comment():
1875
2108
  try:
1876
- if self.config.autodoc_typehints_format == "short":
1877
- alias = restify(self.object, "smart")
1878
- else:
1879
- alias = restify(self.object)
2109
+ alias = restify(self.object, mode=mode)
1880
2110
  more_content = StringList([_('alias of %s') % alias], source='')
1881
2111
  except AttributeError:
1882
2112
  pass # Invalid class object is passed.
@@ -1900,15 +2130,15 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1900
2130
  # If a class gets imported into the module real_modname
1901
2131
  # the analyzer won't find the source of the class, if
1902
2132
  # it looks in real_modname.
1903
- return super().generate(more_content=more_content,
1904
- check_module=check_module,
1905
- all_members=all_members)
2133
+ return super().generate(
2134
+ more_content=more_content,
2135
+ check_module=check_module,
2136
+ all_members=all_members,
2137
+ )
1906
2138
 
1907
2139
 
1908
2140
  class ExceptionDocumenter(ClassDocumenter):
1909
- """
1910
- Specialized ClassDocumenter subclass for exceptions.
1911
- """
2141
+ """Specialized ClassDocumenter subclass for exceptions."""
1912
2142
 
1913
2143
  objtype = 'exception'
1914
2144
  member_order = 10
@@ -1918,7 +2148,7 @@ class ExceptionDocumenter(ClassDocumenter):
1918
2148
 
1919
2149
  @classmethod
1920
2150
  def can_document_member(
1921
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
2151
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
1922
2152
  ) -> bool:
1923
2153
  try:
1924
2154
  return isinstance(member, type) and issubclass(member, BaseException)
@@ -1956,21 +2186,20 @@ class DataDocumenterMixinBase:
1956
2186
 
1957
2187
 
1958
2188
  class GenericAliasMixin(DataDocumenterMixinBase):
1959
- """
1960
- Mixin for DataDocumenter and AttributeDocumenter to provide the feature for
2189
+ """Mixin for DataDocumenter and AttributeDocumenter to provide the feature for
1961
2190
  supporting GenericAliases.
1962
2191
  """
1963
2192
 
1964
2193
  def should_suppress_directive_header(self) -> bool:
1965
- return (inspect.isgenericalias(self.object) or
1966
- super().should_suppress_directive_header())
2194
+ return (
2195
+ inspect.isgenericalias(self.object)
2196
+ or super().should_suppress_directive_header()
2197
+ )
1967
2198
 
1968
2199
  def update_content(self, more_content: StringList) -> None:
1969
2200
  if inspect.isgenericalias(self.object):
1970
- if self.config.autodoc_typehints_format == "short":
1971
- alias = restify(self.object, "smart")
1972
- else:
1973
- alias = restify(self.object)
2201
+ mode = _get_render_mode(self.config.autodoc_typehints_format)
2202
+ alias = restify(self.object, mode=mode)
1974
2203
 
1975
2204
  more_content.append(_('alias of %s') % alias, '')
1976
2205
  more_content.append('', '')
@@ -1979,8 +2208,7 @@ class GenericAliasMixin(DataDocumenterMixinBase):
1979
2208
 
1980
2209
 
1981
2210
  class UninitializedGlobalVariableMixin(DataDocumenterMixinBase):
1982
- """
1983
- Mixin for DataDocumenter to provide the feature for supporting uninitialized
2211
+ """Mixin for DataDocumenter to provide the feature for supporting uninitialized
1984
2212
  (type annotation only) global variables.
1985
2213
  """
1986
2214
 
@@ -1992,9 +2220,12 @@ class UninitializedGlobalVariableMixin(DataDocumenterMixinBase):
1992
2220
  try:
1993
2221
  with mock(self.config.autodoc_mock_imports):
1994
2222
  parent = import_module(self.modname)
1995
- annotations = get_type_hints(parent, None,
1996
- self.config.autodoc_type_aliases,
1997
- include_extras=True)
2223
+ annotations = get_type_hints(
2224
+ parent,
2225
+ None,
2226
+ self.config.autodoc_type_aliases,
2227
+ include_extras=True,
2228
+ )
1998
2229
  if self.objpath[-1] in annotations:
1999
2230
  self.object = UNINITIALIZED_ATTR
2000
2231
  self.parent = parent
@@ -2009,8 +2240,9 @@ class UninitializedGlobalVariableMixin(DataDocumenterMixinBase):
2009
2240
  return False
2010
2241
 
2011
2242
  def should_suppress_value_header(self) -> bool:
2012
- return (self.object is UNINITIALIZED_ATTR or
2013
- super().should_suppress_value_header())
2243
+ return (
2244
+ self.object is UNINITIALIZED_ATTR or super().should_suppress_value_header()
2245
+ )
2014
2246
 
2015
2247
  def get_doc(self) -> list[list[str]] | None:
2016
2248
  if self.object is UNINITIALIZED_ATTR:
@@ -2019,22 +2251,21 @@ class UninitializedGlobalVariableMixin(DataDocumenterMixinBase):
2019
2251
  return super().get_doc() # type: ignore[misc]
2020
2252
 
2021
2253
 
2022
- class DataDocumenter(GenericAliasMixin,
2023
- UninitializedGlobalVariableMixin, ModuleLevelDocumenter):
2024
- """
2025
- Specialized Documenter subclass for data items.
2026
- """
2254
+ class DataDocumenter(
2255
+ GenericAliasMixin, UninitializedGlobalVariableMixin, ModuleLevelDocumenter
2256
+ ):
2257
+ """Specialized Documenter subclass for data items."""
2027
2258
 
2028
2259
  objtype = 'data'
2029
2260
  member_order = 40
2030
2261
  priority = -10
2031
2262
  option_spec: ClassVar[OptionSpec] = dict(ModuleLevelDocumenter.option_spec)
2032
- option_spec["annotation"] = annotation_option
2033
- option_spec["no-value"] = bool_option
2263
+ option_spec['annotation'] = annotation_option
2264
+ option_spec['no-value'] = bool_option
2034
2265
 
2035
2266
  @classmethod
2036
2267
  def can_document_member(
2037
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
2268
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
2038
2269
  ) -> bool:
2039
2270
  return isinstance(parent, ModuleDocumenter) and isattr
2040
2271
 
@@ -2047,7 +2278,7 @@ class DataDocumenter(GenericAliasMixin,
2047
2278
  analyzer = ModuleAnalyzer.for_module(self.modname)
2048
2279
  analyzer.analyze()
2049
2280
  for (classname, attrname), annotation in analyzer.annotations.items():
2050
- if classname == '' and attrname not in annotations:
2281
+ if not classname and attrname not in annotations:
2051
2282
  annotations[attrname] = annotation
2052
2283
  except PycodeError:
2053
2284
  pass
@@ -2065,7 +2296,8 @@ class DataDocumenter(GenericAliasMixin,
2065
2296
  else:
2066
2297
  doc = self.get_doc() or []
2067
2298
  docstring, metadata = separate_metadata(
2068
- '\n'.join(functools.reduce(operator.iadd, doc, [])))
2299
+ '\n'.join(functools.reduce(operator.iadd, doc, []))
2300
+ )
2069
2301
  if 'hide-value' in metadata:
2070
2302
  return True
2071
2303
 
@@ -2074,29 +2306,38 @@ class DataDocumenter(GenericAliasMixin,
2074
2306
  def add_directive_header(self, sig: str) -> None:
2075
2307
  super().add_directive_header(sig)
2076
2308
  sourcename = self.get_sourcename()
2077
- 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
+ ):
2078
2313
  pass
2079
2314
  elif self.options.annotation:
2080
- self.add_line(' :annotation: %s' % self.options.annotation,
2081
- sourcename)
2315
+ self.add_line(' :annotation: %s' % self.options.annotation, sourcename)
2082
2316
  else:
2083
2317
  if self.config.autodoc_typehints != 'none':
2084
2318
  # obtain annotation for this data
2085
- annotations = get_type_hints(self.parent, None,
2086
- self.config.autodoc_type_aliases,
2087
- include_extras=True)
2319
+ annotations = get_type_hints(
2320
+ self.parent,
2321
+ None,
2322
+ self.config.autodoc_type_aliases,
2323
+ include_extras=True,
2324
+ )
2088
2325
  if self.objpath[-1] in annotations:
2089
- if self.config.autodoc_typehints_format == "short":
2090
- objrepr = stringify_annotation(annotations.get(self.objpath[-1]),
2091
- "smart")
2092
- else:
2093
- objrepr = stringify_annotation(annotations.get(self.objpath[-1]),
2094
- "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
+ )
2095
2333
  self.add_line(' :type: ' + objrepr, sourcename)
2096
2334
 
2097
2335
  try:
2098
- if (self.options.no_value or self.should_suppress_value_header() or
2099
- ismock(self.object)):
2336
+ if (
2337
+ self.options.no_value
2338
+ or self.should_suppress_value_header()
2339
+ or ismock(self.object)
2340
+ ):
2100
2341
  pass
2101
2342
  else:
2102
2343
  objrepr = object_description(self.object)
@@ -2144,9 +2385,7 @@ class DataDocumenter(GenericAliasMixin,
2144
2385
 
2145
2386
 
2146
2387
  class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type: ignore[misc]
2147
- """
2148
- Specialized Documenter subclass for methods (normal, static and class).
2149
- """
2388
+ """Specialized Documenter subclass for methods (normal, static and class)."""
2150
2389
 
2151
2390
  objtype = 'method'
2152
2391
  directivetype = 'method'
@@ -2155,7 +2394,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2155
2394
 
2156
2395
  @classmethod
2157
2396
  def can_document_member(
2158
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
2397
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
2159
2398
  ) -> bool:
2160
2399
  return inspect.isroutine(member) and not isinstance(parent, ModuleDocumenter)
2161
2400
 
@@ -2165,22 +2404,23 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2165
2404
  return ret
2166
2405
 
2167
2406
  # to distinguish classmethod/staticmethod
2168
- obj = self.parent.__dict__.get(self.object_name)
2169
- if obj is None:
2170
- obj = self.object
2171
-
2172
- if (inspect.isclassmethod(obj) or
2173
- inspect.isstaticmethod(obj, cls=self.parent, name=self.object_name)):
2174
- # document class and static members before ordinary ones
2175
- self.member_order = self.member_order - 1
2176
-
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
2177
2415
  return ret
2178
2416
 
2179
2417
  def format_args(self, **kwargs: Any) -> str:
2180
- if self.config.autodoc_typehints in ('none', 'description'):
2418
+ if self.config.autodoc_typehints in {'none', 'description'}:
2181
2419
  kwargs.setdefault('show_annotation', False)
2182
- if self.config.autodoc_typehints_format == "short":
2420
+ if self.config.autodoc_typehints_format == 'short':
2183
2421
  kwargs.setdefault('unqualified_typehints', True)
2422
+ if self.config.python_display_short_literal_types:
2423
+ kwargs.setdefault('short_literals', True)
2184
2424
 
2185
2425
  try:
2186
2426
  if self.object == object.__init__ and self.parent != object: # NoQA: E721
@@ -2190,18 +2430,31 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2190
2430
  # But it makes users confused.
2191
2431
  args = '()'
2192
2432
  else:
2193
- if inspect.isstaticmethod(self.object, cls=self.parent, name=self.object_name):
2194
- self.env.app.emit('autodoc-before-process-signature', self.object, False)
2195
- sig = inspect.signature(self.object, bound_method=False,
2196
- 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
+ )
2197
2444
  else:
2198
- self.env.app.emit('autodoc-before-process-signature', self.object, True)
2199
- sig = inspect.signature(self.object, bound_method=True,
2200
- 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
+ )
2201
2453
  args = stringify_signature(sig, **kwargs)
2202
2454
  except TypeError as exc:
2203
- logger.warning(__("Failed to get a method signature for %s: %s"),
2204
- self.fullname, exc)
2455
+ logger.warning(
2456
+ __('Failed to get a method signature for %s: %s'), self.fullname, exc
2457
+ )
2205
2458
  return ''
2206
2459
  except ValueError:
2207
2460
  args = ''
@@ -2220,8 +2473,11 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2220
2473
  self.add_line(' :abstractmethod:', sourcename)
2221
2474
  if inspect.iscoroutinefunction(obj) or inspect.isasyncgenfunction(obj):
2222
2475
  self.add_line(' :async:', sourcename)
2223
- if (inspect.isclassmethod(obj) or
2224
- 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
+ ):
2225
2481
  self.add_line(' :classmethod:', sourcename)
2226
2482
  if inspect.isstaticmethod(obj, cls=self.parent, name=self.object_name):
2227
2483
  self.add_line(' :staticmethod:', sourcename)
@@ -2232,13 +2488,17 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2232
2488
  pass
2233
2489
 
2234
2490
  def format_signature(self, **kwargs: Any) -> str:
2235
- if self.config.autodoc_typehints_format == "short":
2491
+ if self.config.autodoc_typehints_format == 'short':
2236
2492
  kwargs.setdefault('unqualified_typehints', True)
2493
+ if self.config.python_display_short_literal_types:
2494
+ kwargs.setdefault('short_literals', True)
2237
2495
 
2238
2496
  sigs = []
2239
- if (self.analyzer and
2240
- '.'.join(self.objpath) in self.analyzer.overloads and
2241
- 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
+ ):
2242
2502
  # Use signatures for overloaded methods instead of the implementation method.
2243
2503
  overloaded = True
2244
2504
  else:
@@ -2263,27 +2523,37 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2263
2523
  documenter.objpath = ['']
2264
2524
  sigs.append(documenter.format_signature())
2265
2525
  if overloaded and self.analyzer is not None:
2266
- if inspect.isstaticmethod(self.object, cls=self.parent, name=self.object_name):
2267
- actual = inspect.signature(self.object, bound_method=False,
2268
- 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
+ )
2269
2534
  else:
2270
- actual = inspect.signature(self.object, bound_method=True,
2271
- 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
+ )
2272
2540
 
2273
2541
  __globals__ = safe_getattr(self.object, '__globals__', {})
2274
2542
  for overload in self.analyzer.overloads['.'.join(self.objpath)]:
2275
2543
  overload = self.merge_default_value(actual, overload)
2276
- overload = evaluate_signature(overload, __globals__,
2277
- self.config.autodoc_type_aliases)
2544
+ overload = evaluate_signature(
2545
+ overload, __globals__, self.config.autodoc_type_aliases
2546
+ )
2278
2547
 
2279
- if not inspect.isstaticmethod(self.object, cls=self.parent,
2280
- name=self.object_name):
2548
+ if not inspect.isstaticmethod(
2549
+ self.object, cls=self.parent, name=self.object_name
2550
+ ):
2281
2551
  parameters = list(overload.parameters.values())
2282
2552
  overload = overload.replace(parameters=parameters[1:])
2283
2553
  sig = stringify_signature(overload, **kwargs)
2284
2554
  sigs.append(sig)
2285
2555
 
2286
- return "\n".join(sigs)
2556
+ return '\n'.join(sigs)
2287
2557
 
2288
2558
  def merge_default_value(self, actual: Signature, overload: Signature) -> Signature:
2289
2559
  """Merge default values of actual implementation to the overload variants."""
@@ -2295,13 +2565,16 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2295
2565
 
2296
2566
  return overload.replace(parameters=parameters)
2297
2567
 
2298
- 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:
2299
2571
  """Annotate type hint to the first argument of function if needed."""
2300
2572
  try:
2301
2573
  sig = inspect.signature(func, type_aliases=self.config.autodoc_type_aliases)
2302
2574
  except TypeError as exc:
2303
- logger.warning(__("Failed to get a method signature for %s: %s"),
2304
- self.fullname, exc)
2575
+ logger.warning(
2576
+ __('Failed to get a method signature for %s: %s'), self.fullname, exc
2577
+ )
2305
2578
  return None
2306
2579
  except ValueError:
2307
2580
  return None
@@ -2317,7 +2590,8 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2317
2590
  params[1] = params[1].replace(annotation=typ)
2318
2591
  try:
2319
2592
  dummy.__signature__ = sig.replace( # type: ignore[attr-defined]
2320
- parameters=params)
2593
+ parameters=params
2594
+ )
2321
2595
  return dummy
2322
2596
  except (AttributeError, TypeError):
2323
2597
  # failed to update signature (ex. built-in or extension types)
@@ -2333,12 +2607,17 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2333
2607
  # `DocstringSignatureMixin`.
2334
2608
  return self._new_docstrings
2335
2609
  if self.objpath[-1] == '__init__':
2336
- docstring = getdoc(self.object, self.get_attr,
2337
- self.config.autodoc_inherit_docstrings,
2338
- self.parent, self.object_name)
2339
- if (docstring is not None and
2340
- (docstring == object.__init__.__doc__ or # for pypy
2341
- 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
+ ):
2342
2621
  docstring = None
2343
2622
  if docstring:
2344
2623
  tab_width = self.directive.state.document.settings.tab_width
@@ -2346,12 +2625,17 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2346
2625
  else:
2347
2626
  return []
2348
2627
  elif self.objpath[-1] == '__new__':
2349
- docstring = getdoc(self.object, self.get_attr,
2350
- self.config.autodoc_inherit_docstrings,
2351
- self.parent, self.object_name)
2352
- if (docstring is not None and
2353
- (docstring == object.__new__.__doc__ or # for pypy
2354
- 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
+ ):
2355
2639
  docstring = None
2356
2640
  if docstring:
2357
2641
  tab_width = self.directive.state.document.settings.tab_width
@@ -2363,8 +2647,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2363
2647
 
2364
2648
 
2365
2649
  class NonDataDescriptorMixin(DataDocumenterMixinBase):
2366
- """
2367
- Mixin for AttributeDocumenter to provide the feature for supporting non
2650
+ """Mixin for AttributeDocumenter to provide the feature for supporting non
2368
2651
  data-descriptors.
2369
2652
 
2370
2653
  .. note:: This mix-in must be inherited after other mix-ins. Otherwise, docstring
@@ -2381,8 +2664,10 @@ class NonDataDescriptorMixin(DataDocumenterMixinBase):
2381
2664
  return ret
2382
2665
 
2383
2666
  def should_suppress_value_header(self) -> bool:
2384
- return (not getattr(self, 'non_data_descriptor', False) or
2385
- super().should_suppress_directive_header())
2667
+ return (
2668
+ not getattr(self, 'non_data_descriptor', False)
2669
+ or super().should_suppress_directive_header()
2670
+ )
2386
2671
 
2387
2672
  def get_doc(self) -> list[list[str]] | None:
2388
2673
  if getattr(self, 'non_data_descriptor', False):
@@ -2394,9 +2679,7 @@ class NonDataDescriptorMixin(DataDocumenterMixinBase):
2394
2679
 
2395
2680
 
2396
2681
  class SlotsMixin(DataDocumenterMixinBase):
2397
- """
2398
- Mixin for AttributeDocumenter to provide the feature for supporting __slots__.
2399
- """
2682
+ """Mixin for AttributeDocumenter to provide the feature for supporting __slots__."""
2400
2683
 
2401
2684
  def isslotsattribute(self) -> bool:
2402
2685
  """Check the subject is an attribute in __slots__."""
@@ -2425,25 +2708,29 @@ class SlotsMixin(DataDocumenterMixinBase):
2425
2708
  if self.object is SLOTSATTR:
2426
2709
  try:
2427
2710
  parent___slots__ = inspect.getslots(self.parent)
2428
- 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
+ ):
2429
2714
  docstring = prepare_docstring(docstring)
2430
2715
  return [docstring]
2431
2716
  else:
2432
2717
  return []
2433
2718
  except ValueError as exc:
2434
- logger.warning(__('Invalid __slots__ found on %s. Ignored.'),
2435
- (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
+ )
2436
2724
  return []
2437
2725
  else:
2438
2726
  return super().get_doc() # type: ignore[misc]
2439
2727
 
2440
2728
 
2441
2729
  class RuntimeInstanceAttributeMixin(DataDocumenterMixinBase):
2442
- """
2443
- Mixin for AttributeDocumenter to provide the feature for supporting runtime
2730
+ """Mixin for AttributeDocumenter to provide the feature for supporting runtime
2444
2731
  instance attributes (that are defined in __init__() methods with doc-comments).
2445
2732
 
2446
- Example:
2733
+ Example::
2447
2734
 
2448
2735
  class Foo:
2449
2736
  def __init__(self):
@@ -2487,7 +2774,9 @@ class RuntimeInstanceAttributeMixin(DataDocumenterMixinBase):
2487
2774
  try:
2488
2775
  with mock(self.config.autodoc_mock_imports):
2489
2776
  ret = import_object(
2490
- self.modname, self.objpath[:-1], 'class',
2777
+ self.modname,
2778
+ self.objpath[:-1],
2779
+ 'class',
2491
2780
  attrgetter=self.get_attr, # type: ignore[attr-defined]
2492
2781
  )
2493
2782
  parent = ret[3]
@@ -2505,23 +2794,26 @@ class RuntimeInstanceAttributeMixin(DataDocumenterMixinBase):
2505
2794
  return False
2506
2795
 
2507
2796
  def should_suppress_value_header(self) -> bool:
2508
- return (self.object is self.RUNTIME_INSTANCE_ATTRIBUTE or
2509
- super().should_suppress_value_header())
2797
+ return (
2798
+ self.object is self.RUNTIME_INSTANCE_ATTRIBUTE
2799
+ or super().should_suppress_value_header()
2800
+ )
2510
2801
 
2511
2802
  def get_doc(self) -> list[list[str]] | None:
2512
- if (self.object is self.RUNTIME_INSTANCE_ATTRIBUTE and
2513
- 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
+ ):
2514
2807
  return None
2515
2808
  else:
2516
2809
  return super().get_doc() # type: ignore[misc]
2517
2810
 
2518
2811
 
2519
2812
  class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
2520
- """
2521
- Mixin for AttributeDocumenter to provide the feature for supporting uninitialized
2813
+ """Mixin for AttributeDocumenter to provide the feature for supporting uninitialized
2522
2814
  instance attributes (PEP-526 styled, annotation only attributes).
2523
2815
 
2524
- Example:
2816
+ Example::
2525
2817
 
2526
2818
  class Foo:
2527
2819
  attr: int #: This is a target of this mix-in.
@@ -2529,8 +2821,9 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
2529
2821
 
2530
2822
  def is_uninitialized_instance_attribute(self, parent: Any) -> bool:
2531
2823
  """Check the subject is an annotation only attribute."""
2532
- annotations = get_type_hints(parent, None, self.config.autodoc_type_aliases,
2533
- include_extras=True)
2824
+ annotations = get_type_hints(
2825
+ parent, None, self.config.autodoc_type_aliases, include_extras=True
2826
+ )
2534
2827
  return self.objpath[-1] in annotations
2535
2828
 
2536
2829
  def import_object(self, raiseerror: bool = False) -> bool:
@@ -2542,7 +2835,9 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
2542
2835
  except ImportError as exc:
2543
2836
  try:
2544
2837
  ret = import_object(
2545
- self.modname, self.objpath[:-1], 'class',
2838
+ self.modname,
2839
+ self.objpath[:-1],
2840
+ 'class',
2546
2841
  attrgetter=self.get_attr, # type: ignore[attr-defined]
2547
2842
  )
2548
2843
  parent = ret[3]
@@ -2560,8 +2855,9 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
2560
2855
  return False
2561
2856
 
2562
2857
  def should_suppress_value_header(self) -> bool:
2563
- return (self.object is UNINITIALIZED_ATTR or
2564
- super().should_suppress_value_header())
2858
+ return (
2859
+ self.object is UNINITIALIZED_ATTR or super().should_suppress_value_header()
2860
+ )
2565
2861
 
2566
2862
  def get_doc(self) -> list[list[str]] | None:
2567
2863
  if self.object is UNINITIALIZED_ATTR:
@@ -2569,19 +2865,22 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
2569
2865
  return super().get_doc() # type: ignore[misc]
2570
2866
 
2571
2867
 
2572
- class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2573
- RuntimeInstanceAttributeMixin,
2574
- UninitializedInstanceAttributeMixin, NonDataDescriptorMixin,
2575
- DocstringStripSignatureMixin, ClassLevelDocumenter):
2576
- """
2577
- Specialized Documenter subclass for attributes.
2578
- """
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."""
2579
2878
 
2580
2879
  objtype = 'attribute'
2581
2880
  member_order = 60
2582
2881
  option_spec: ClassVar[OptionSpec] = dict(ModuleLevelDocumenter.option_spec)
2583
- option_spec["annotation"] = annotation_option
2584
- option_spec["no-value"] = bool_option
2882
+ option_spec['annotation'] = annotation_option
2883
+ option_spec['no-value'] = bool_option
2585
2884
 
2586
2885
  # must be higher than the MethodDocumenter, else it will recognize
2587
2886
  # some non-data descriptors as methods
@@ -2589,11 +2888,13 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2589
2888
 
2590
2889
  @staticmethod
2591
2890
  def is_function_or_method(obj: Any) -> bool:
2592
- 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
+ )
2593
2894
 
2594
2895
  @classmethod
2595
2896
  def can_document_member(
2596
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
2897
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
2597
2898
  ) -> bool:
2598
2899
  if isinstance(parent, ModuleDocumenter):
2599
2900
  return False
@@ -2617,7 +2918,8 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2617
2918
 
2618
2919
  analyzer = ModuleAnalyzer.for_module(module)
2619
2920
  analyzer.analyze()
2620
- for (classname, attrname), annotation in analyzer.annotations.items():
2921
+ anns = analyzer.annotations
2922
+ for (classname, attrname), annotation in anns.items():
2621
2923
  if classname == qualname and attrname not in annotations:
2622
2924
  annotations[attrname] = annotation
2623
2925
  except (AttributeError, PycodeError):
@@ -2646,7 +2948,8 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2646
2948
  doc = self.get_doc()
2647
2949
  if doc:
2648
2950
  docstring, metadata = separate_metadata(
2649
- '\n'.join(functools.reduce(operator.iadd, doc, [])))
2951
+ '\n'.join(functools.reduce(operator.iadd, doc, []))
2952
+ )
2650
2953
  if 'hide-value' in metadata:
2651
2954
  return True
2652
2955
 
@@ -2655,28 +2958,38 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2655
2958
  def add_directive_header(self, sig: str) -> None:
2656
2959
  super().add_directive_header(sig)
2657
2960
  sourcename = self.get_sourcename()
2658
- 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
+ ):
2659
2965
  pass
2660
2966
  elif self.options.annotation:
2661
2967
  self.add_line(' :annotation: %s' % self.options.annotation, sourcename)
2662
2968
  else:
2663
2969
  if self.config.autodoc_typehints != 'none':
2664
2970
  # obtain type annotation for this attribute
2665
- annotations = get_type_hints(self.parent, None,
2666
- self.config.autodoc_type_aliases,
2667
- include_extras=True)
2971
+ annotations = get_type_hints(
2972
+ self.parent,
2973
+ None,
2974
+ self.config.autodoc_type_aliases,
2975
+ include_extras=True,
2976
+ )
2668
2977
  if self.objpath[-1] in annotations:
2669
- if self.config.autodoc_typehints_format == "short":
2670
- objrepr = stringify_annotation(annotations.get(self.objpath[-1]),
2671
- "smart")
2672
- else:
2673
- objrepr = stringify_annotation(annotations.get(self.objpath[-1]),
2674
- "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
+ )
2675
2985
  self.add_line(' :type: ' + objrepr, sourcename)
2676
2986
 
2677
2987
  try:
2678
- if (self.options.no_value or self.should_suppress_value_header() or
2679
- ismock(self.object)):
2988
+ if (
2989
+ self.options.no_value
2990
+ or self.should_suppress_value_header()
2991
+ or ismock(self.object)
2992
+ ):
2680
2993
  pass
2681
2994
  else:
2682
2995
  objrepr = object_description(self.object)
@@ -2710,7 +3023,7 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2710
3023
  try:
2711
3024
  # Disable `autodoc_inherit_docstring` temporarily to avoid to obtain
2712
3025
  # a docstring from the value which descriptor returns unexpectedly.
2713
- # ref: https://github.com/sphinx-doc/sphinx/issues/7805
3026
+ # See: https://github.com/sphinx-doc/sphinx/issues/7805
2714
3027
  orig = self.config.autodoc_inherit_docstrings
2715
3028
  self.config.autodoc_inherit_docstrings = False
2716
3029
  return super().get_doc()
@@ -2728,11 +3041,8 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2728
3041
  super().add_content(more_content)
2729
3042
 
2730
3043
 
2731
- class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
2732
- ClassLevelDocumenter):
2733
- """
2734
- Specialized Documenter subclass for properties.
2735
- """
3044
+ class PropertyDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore[misc]
3045
+ """Specialized Documenter subclass for properties."""
2736
3046
 
2737
3047
  objtype = 'property'
2738
3048
  member_order = 60
@@ -2742,7 +3052,7 @@ class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
2742
3052
 
2743
3053
  @classmethod
2744
3054
  def can_document_member(
2745
- cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
3055
+ cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
2746
3056
  ) -> bool:
2747
3057
  if isinstance(parent, ClassDocumenter):
2748
3058
  if inspect.isproperty(member):
@@ -2778,7 +3088,7 @@ class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
2778
3088
  return ''
2779
3089
 
2780
3090
  # update the annotations of the property getter
2781
- self.env.app.emit('autodoc-before-process-signature', func, False)
3091
+ self._events.emit('autodoc-before-process-signature', func, False)
2782
3092
  # correctly format the arguments for a property
2783
3093
  return super().format_args(**kwargs)
2784
3094
 
@@ -2802,23 +3112,25 @@ class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
2802
3112
  return
2803
3113
 
2804
3114
  try:
2805
- signature = inspect.signature(func,
2806
- type_aliases=self.config.autodoc_type_aliases)
3115
+ signature = inspect.signature(
3116
+ func, type_aliases=self.config.autodoc_type_aliases
3117
+ )
2807
3118
  if signature.return_annotation is not Parameter.empty:
2808
- if self.config.autodoc_typehints_format == "short":
2809
- objrepr = stringify_annotation(signature.return_annotation, "smart")
2810
- else:
2811
- objrepr = stringify_annotation(signature.return_annotation,
2812
- "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
+ )
2813
3124
  self.add_line(' :type: ' + objrepr, sourcename)
2814
3125
  except TypeError as exc:
2815
- logger.warning(__("Failed to get a function signature for %s: %s"),
2816
- self.fullname, exc)
3126
+ logger.warning(
3127
+ __('Failed to get a function signature for %s: %s'), self.fullname, exc
3128
+ )
2817
3129
  pass
2818
3130
  except ValueError:
2819
3131
  pass
2820
3132
 
2821
- def _get_property_getter(self) -> Callable | None:
3133
+ def _get_property_getter(self) -> Callable[..., Any] | None:
2822
3134
  if safe_getattr(self.object, 'fget', None): # property
2823
3135
  return self.object.fget
2824
3136
  if safe_getattr(self.object, 'func', None): # cached_property
@@ -2826,9 +3138,11 @@ class PropertyDocumenter(DocstringStripSignatureMixin, # type: ignore[misc]
2826
3138
  return None
2827
3139
 
2828
3140
 
2829
- def autodoc_attrgetter(app: Sphinx, obj: Any, name: str, *defargs: Any) -> Any:
3141
+ def autodoc_attrgetter(
3142
+ registry: SphinxComponentRegistry, obj: Any, name: str, *defargs: Any
3143
+ ) -> Any:
2830
3144
  """Alternative getattr() for types"""
2831
- for typ, func in app.registry.autodoc_attrgetters.items():
3145
+ for typ, func in registry.autodoc_attrgetters.items():
2832
3146
  if isinstance(obj, typ):
2833
3147
  return func(obj, name, *defargs)
2834
3148
 
@@ -2846,22 +3160,54 @@ def setup(app: Sphinx) -> ExtensionMetadata:
2846
3160
  app.add_autodocumenter(AttributeDocumenter)
2847
3161
  app.add_autodocumenter(PropertyDocumenter)
2848
3162
 
2849
- app.add_config_value('autoclass_content', 'class', 'env', ENUM('both', 'class', 'init'))
2850
- app.add_config_value('autodoc_member_order', 'alphabetical', 'env',
2851
- ENUM('alphabetical', 'bysource', 'groupwise'))
2852
- app.add_config_value('autodoc_class_signature', 'mixed', 'env', ENUM('mixed', 'separated'))
2853
- app.add_config_value('autodoc_default_options', {}, 'env')
2854
- app.add_config_value('autodoc_docstring_signature', True, 'env')
2855
- app.add_config_value('autodoc_mock_imports', [], 'env')
2856
- app.add_config_value('autodoc_typehints', "signature", 'env',
2857
- ENUM("signature", "description", "none", "both"))
2858
- app.add_config_value('autodoc_typehints_description_target', 'all', 'env',
2859
- ENUM('all', 'documented', 'documented_params'))
2860
- app.add_config_value('autodoc_type_aliases', {}, 'env')
2861
- app.add_config_value('autodoc_typehints_format', "short", 'env',
2862
- ENUM("fully-qualified", "short"))
2863
- app.add_config_value('autodoc_warningiserror', True, 'env')
2864
- 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
+ )
2865
3211
  app.add_event('autodoc-before-process-signature')
2866
3212
  app.add_event('autodoc-process-docstring')
2867
3213
  app.add_event('autodoc-process-signature')
@@ -2872,4 +3218,7 @@ def setup(app: Sphinx) -> ExtensionMetadata:
2872
3218
  app.setup_extension('sphinx.ext.autodoc.type_comment')
2873
3219
  app.setup_extension('sphinx.ext.autodoc.typehints')
2874
3220
 
2875
- return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
3221
+ return {
3222
+ 'version': sphinx.__display_version__,
3223
+ 'parallel_read_safe': True,
3224
+ }