Sphinx 7.4.6__py3-none-any.whl → 8.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of Sphinx might be problematic. Click here for more details.

Files changed (242) hide show
  1. sphinx/__init__.py +2 -2
  2. sphinx/_cli/__init__.py +4 -4
  3. sphinx/application.py +2 -2
  4. sphinx/builders/__init__.py +2 -3
  5. sphinx/builders/_epub_base.py +33 -12
  6. sphinx/builders/changes.py +13 -5
  7. sphinx/builders/epub3.py +6 -2
  8. sphinx/builders/html/__init__.py +90 -59
  9. sphinx/builders/latex/__init__.py +38 -12
  10. sphinx/builders/latex/transforms.py +1 -1
  11. sphinx/builders/linkcheck.py +8 -49
  12. sphinx/builders/texinfo.py +12 -6
  13. sphinx/builders/text.py +7 -3
  14. sphinx/builders/xml.py +7 -3
  15. sphinx/cmd/quickstart.py +10 -20
  16. sphinx/config.py +13 -13
  17. sphinx/deprecation.py +8 -8
  18. sphinx/directives/__init__.py +14 -9
  19. sphinx/directives/other.py +2 -3
  20. sphinx/directives/patches.py +2 -2
  21. sphinx/domains/__init__.py +4 -2
  22. sphinx/domains/c/__init__.py +2 -2
  23. sphinx/domains/c/_ast.py +3 -2
  24. sphinx/domains/c/_parser.py +4 -3
  25. sphinx/domains/cpp/__init__.py +2 -2
  26. sphinx/domains/cpp/_ast.py +1 -2
  27. sphinx/domains/cpp/_parser.py +2 -2
  28. sphinx/domains/cpp/_symbol.py +2 -2
  29. sphinx/domains/javascript.py +1 -1
  30. sphinx/domains/math.py +1 -1
  31. sphinx/domains/python/__init__.py +1 -1
  32. sphinx/domains/python/_annotations.py +23 -1
  33. sphinx/domains/python/_object.py +0 -1
  34. sphinx/domains/std/__init__.py +7 -8
  35. sphinx/environment/__init__.py +15 -32
  36. sphinx/environment/adapters/indexentries.py +4 -6
  37. sphinx/environment/adapters/toctree.py +4 -4
  38. sphinx/environment/collectors/title.py +1 -1
  39. sphinx/environment/collectors/toctree.py +1 -1
  40. sphinx/events.py +3 -1
  41. sphinx/ext/autodoc/__init__.py +25 -67
  42. sphinx/ext/autodoc/directive.py +7 -5
  43. sphinx/ext/autodoc/importer.py +2 -1
  44. sphinx/ext/autodoc/preserve_defaults.py +2 -2
  45. sphinx/ext/autosummary/__init__.py +15 -7
  46. sphinx/ext/autosummary/generate.py +5 -4
  47. sphinx/ext/doctest.py +5 -5
  48. sphinx/ext/graphviz.py +1 -1
  49. sphinx/ext/imgmath.py +1 -1
  50. sphinx/ext/inheritance_diagram.py +1 -1
  51. sphinx/ext/intersphinx/__init__.py +25 -5
  52. sphinx/ext/intersphinx/_cli.py +7 -6
  53. sphinx/ext/intersphinx/_load.py +240 -115
  54. sphinx/ext/intersphinx/_resolve.py +12 -11
  55. sphinx/ext/intersphinx/_shared.py +102 -9
  56. sphinx/ext/mathjax.py +1 -1
  57. sphinx/ext/napoleon/docstring.py +2 -2
  58. sphinx/ext/todo.py +2 -2
  59. sphinx/ext/viewcode.py +2 -1
  60. sphinx/highlighting.py +3 -3
  61. sphinx/io.py +2 -2
  62. sphinx/jinja2glue.py +13 -6
  63. sphinx/locale/__init__.py +4 -3
  64. sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
  65. sphinx/locale/ar/LC_MESSAGES/sphinx.po +2383 -2186
  66. sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
  67. sphinx/locale/bg/LC_MESSAGES/sphinx.po +2249 -2052
  68. sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
  69. sphinx/locale/bn/LC_MESSAGES/sphinx.po +2412 -2215
  70. sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
  71. sphinx/locale/ca/LC_MESSAGES/sphinx.po +3029 -2832
  72. sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
  73. sphinx/locale/cak/LC_MESSAGES/sphinx.po +2308 -2111
  74. sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
  75. sphinx/locale/cs/LC_MESSAGES/sphinx.po +2469 -2272
  76. sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
  77. sphinx/locale/cy/LC_MESSAGES/sphinx.po +2393 -2196
  78. sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
  79. sphinx/locale/da/LC_MESSAGES/sphinx.po +2532 -2335
  80. sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
  81. sphinx/locale/de/LC_MESSAGES/sphinx.po +2492 -2295
  82. sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
  83. sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2250 -2053
  84. sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
  85. sphinx/locale/el/LC_MESSAGES/sphinx.po +2879 -2682
  86. sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
  87. sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2250 -2053
  88. sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
  89. sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2250 -2053
  90. sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
  91. sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2989 -2792
  92. sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
  93. sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2250 -2053
  94. sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
  95. sphinx/locale/eo/LC_MESSAGES/sphinx.po +2297 -2100
  96. sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
  97. sphinx/locale/es/LC_MESSAGES/sphinx.po +3017 -2820
  98. sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
  99. sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2250 -2053
  100. sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
  101. sphinx/locale/et/LC_MESSAGES/sphinx.po +2748 -2551
  102. sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
  103. sphinx/locale/eu/LC_MESSAGES/sphinx.po +2459 -2262
  104. sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
  105. sphinx/locale/fa/LC_MESSAGES/sphinx.po +2957 -2760
  106. sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
  107. sphinx/locale/fi/LC_MESSAGES/sphinx.po +2321 -2124
  108. sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
  109. sphinx/locale/fr/LC_MESSAGES/sphinx.po +2977 -2780
  110. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
  111. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +2250 -2053
  112. sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
  113. sphinx/locale/gl/LC_MESSAGES/sphinx.po +2992 -2795
  114. sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
  115. sphinx/locale/he/LC_MESSAGES/sphinx.po +2375 -2178
  116. sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
  117. sphinx/locale/hi/LC_MESSAGES/sphinx.po +2937 -2740
  118. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
  119. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +2250 -2053
  120. sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
  121. sphinx/locale/hr/LC_MESSAGES/sphinx.po +2532 -2335
  122. sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
  123. sphinx/locale/hu/LC_MESSAGES/sphinx.po +2505 -2308
  124. sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
  125. sphinx/locale/id/LC_MESSAGES/sphinx.po +2925 -2728
  126. sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
  127. sphinx/locale/is/LC_MESSAGES/sphinx.po +2307 -2110
  128. sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
  129. sphinx/locale/it/LC_MESSAGES/sphinx.po +2514 -2317
  130. sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
  131. sphinx/locale/ja/LC_MESSAGES/sphinx.po +2970 -2773
  132. sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
  133. sphinx/locale/ka/LC_MESSAGES/sphinx.po +2868 -2671
  134. sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
  135. sphinx/locale/ko/LC_MESSAGES/sphinx.po +3016 -2819
  136. sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
  137. sphinx/locale/lt/LC_MESSAGES/sphinx.po +2476 -2279
  138. sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
  139. sphinx/locale/lv/LC_MESSAGES/sphinx.po +2477 -2280
  140. sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
  141. sphinx/locale/mk/LC_MESSAGES/sphinx.po +2292 -2095
  142. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
  143. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2479 -2282
  144. sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
  145. sphinx/locale/ne/LC_MESSAGES/sphinx.po +2481 -2284
  146. sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
  147. sphinx/locale/nl/LC_MESSAGES/sphinx.po +2557 -2360
  148. sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
  149. sphinx/locale/pl/LC_MESSAGES/sphinx.po +2696 -2499
  150. sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
  151. sphinx/locale/pt/LC_MESSAGES/sphinx.po +2250 -2053
  152. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
  153. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2979 -2782
  154. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
  155. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2469 -2272
  156. sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
  157. sphinx/locale/ro/LC_MESSAGES/sphinx.po +2473 -2276
  158. sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
  159. sphinx/locale/ru/LC_MESSAGES/sphinx.po +2746 -2549
  160. sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
  161. sphinx/locale/si/LC_MESSAGES/sphinx.po +2331 -2134
  162. sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
  163. sphinx/locale/sk/LC_MESSAGES/sphinx.po +2966 -2769
  164. sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
  165. sphinx/locale/sl/LC_MESSAGES/sphinx.po +2404 -2207
  166. sphinx/locale/sphinx.pot +2262 -2065
  167. sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
  168. sphinx/locale/sq/LC_MESSAGES/sphinx.po +2972 -2775
  169. sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
  170. sphinx/locale/sr/LC_MESSAGES/sphinx.po +2440 -2243
  171. sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
  172. sphinx/locale/sv/LC_MESSAGES/sphinx.po +2483 -2286
  173. sphinx/locale/ta/LC_MESSAGES/sphinx.js +54 -54
  174. sphinx/locale/ta/LC_MESSAGES/sphinx.mo +0 -0
  175. sphinx/locale/ta/LC_MESSAGES/sphinx.po +1578 -1843
  176. sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
  177. sphinx/locale/te/LC_MESSAGES/sphinx.po +2250 -2053
  178. sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
  179. sphinx/locale/tr/LC_MESSAGES/sphinx.po +2892 -2695
  180. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
  181. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2400 -2203
  182. sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
  183. sphinx/locale/ur/LC_MESSAGES/sphinx.po +2250 -2053
  184. sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
  185. sphinx/locale/vi/LC_MESSAGES/sphinx.po +2422 -2225
  186. sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
  187. sphinx/locale/yue/LC_MESSAGES/sphinx.po +2250 -2053
  188. sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +496 -704
  189. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
  190. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2250 -2053
  191. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
  192. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +3028 -2831
  193. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
  194. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2250 -2053
  195. sphinx/project.py +25 -20
  196. sphinx/pycode/ast.py +2 -2
  197. sphinx/pycode/parser.py +2 -2
  198. sphinx/pygments_styles.py +3 -3
  199. sphinx/registry.py +3 -8
  200. sphinx/search/__init__.py +1 -1
  201. sphinx/testing/path.py +2 -1
  202. sphinx/testing/util.py +1 -1
  203. sphinx/texinputs/Makefile.jinja +2 -1
  204. sphinx/texinputs_win/Makefile.jinja +2 -1
  205. sphinx/theming.py +3 -12
  206. sphinx/transforms/__init__.py +5 -5
  207. sphinx/transforms/references.py +1 -1
  208. sphinx/util/__init__.py +11 -35
  209. sphinx/util/_pathlib.py +31 -19
  210. sphinx/util/_timestamps.py +12 -0
  211. sphinx/util/cfamily.py +5 -5
  212. sphinx/util/console.py +4 -3
  213. sphinx/util/display.py +3 -3
  214. sphinx/util/docfields.py +1 -1
  215. sphinx/util/docutils.py +44 -10
  216. sphinx/util/fileutil.py +41 -9
  217. sphinx/util/i18n.py +9 -4
  218. sphinx/util/images.py +3 -2
  219. sphinx/util/inspect.py +29 -44
  220. sphinx/util/inventory.py +2 -2
  221. sphinx/util/matching.py +2 -2
  222. sphinx/util/math.py +1 -1
  223. sphinx/util/nodes.py +8 -8
  224. sphinx/util/osutil.py +52 -26
  225. sphinx/util/parallel.py +2 -2
  226. sphinx/util/requests.py +1 -1
  227. sphinx/util/template.py +3 -3
  228. sphinx/util/typing.py +67 -70
  229. sphinx/writers/html.py +1 -1
  230. sphinx/writers/html5.py +1 -1
  231. sphinx/writers/latex.py +4 -4
  232. sphinx/writers/manpage.py +2 -2
  233. sphinx/writers/texinfo.py +5 -5
  234. sphinx/writers/text.py +4 -4
  235. sphinx/writers/xml.py +2 -2
  236. {sphinx-7.4.6.dist-info → sphinx-8.0.0.dist-info}/METADATA +11 -10
  237. {sphinx-7.4.6.dist-info → sphinx-8.0.0.dist-info}/RECORD +240 -241
  238. sphinx/templates/quickstart/Makefile.jinja +0 -98
  239. sphinx/templates/quickstart/make.bat.jinja +0 -110
  240. {sphinx-7.4.6.dist-info → sphinx-8.0.0.dist-info}/LICENSE.rst +0 -0
  241. {sphinx-7.4.6.dist-info → sphinx-8.0.0.dist-info}/WHEEL +0 -0
  242. {sphinx-7.4.6.dist-info → sphinx-8.0.0.dist-info}/entry_points.txt +0 -0
@@ -24,18 +24,17 @@ from sphinx.util.cfamily import (
24
24
  ASTBaseBase,
25
25
  ASTBaseParenExprList,
26
26
  NoOldIdError,
27
- StringifyTransform,
28
27
  UnsupportedMultiCharacterCharLiteral,
29
28
  verify_description_mode,
30
29
  )
31
30
 
32
31
  if TYPE_CHECKING:
33
-
34
32
  from docutils.nodes import Element, TextElement
35
33
 
36
34
  from sphinx.addnodes import desc_signature
37
35
  from sphinx.domains.cpp._symbol import Symbol
38
36
  from sphinx.environment import BuildEnvironment
37
+ from sphinx.util.cfamily import StringifyTransform
39
38
 
40
39
 
41
40
  class ASTBase(ASTBaseBase):
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import re
4
- from typing import TYPE_CHECKING, Any, Callable
4
+ from typing import TYPE_CHECKING, Any
5
5
 
6
6
  from sphinx.domains.cpp._ast import (
7
7
  ASTAlignofExpr,
@@ -127,7 +127,7 @@ from sphinx.util.cfamily import (
127
127
  )
128
128
 
129
129
  if TYPE_CHECKING:
130
- from collections.abc import Sequence
130
+ from collections.abc import Callable, Sequence
131
131
 
132
132
  logger = logging.getLogger(__name__)
133
133
 
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Any, Callable, NoReturn
3
+ from typing import TYPE_CHECKING, Any, NoReturn
4
4
 
5
5
  from sphinx.domains.cpp._ast import (
6
6
  ASTDeclaration,
@@ -17,7 +17,7 @@ from sphinx.locale import __
17
17
  from sphinx.util import logging
18
18
 
19
19
  if TYPE_CHECKING:
20
- from collections.abc import Iterator
20
+ from collections.abc import Callable, Iterator
21
21
 
22
22
  from sphinx.environment import BuildEnvironment
23
23
 
@@ -309,7 +309,7 @@ class JSModule(SphinxDirective):
309
309
  def run(self) -> list[Node]:
310
310
  mod_name = self.arguments[0].strip()
311
311
  self.env.ref_context['js:module'] = mod_name
312
- no_index = 'no-index' in self.options or 'noindex' in self.options
312
+ no_index = 'no-index' in self.options
313
313
 
314
314
  content_nodes = self.parse_content_to_nodes(allow_section_headings=True)
315
315
 
sphinx/domains/math.py CHANGED
@@ -74,7 +74,7 @@ class MathDomain(Domain):
74
74
  def process_doc(self, env: BuildEnvironment, docname: str,
75
75
  document: nodes.document) -> None:
76
76
  def math_node(node: Node) -> bool:
77
- return isinstance(node, (nodes.math, nodes.math_block))
77
+ return isinstance(node, nodes.math | nodes.math_block)
78
78
 
79
79
  self.data['has_equations'][docname] = any(document.findall(math_node))
80
80
 
@@ -452,7 +452,7 @@ class PyModule(SphinxDirective):
452
452
  domain = cast(PythonDomain, self.env.get_domain('py'))
453
453
 
454
454
  modname = self.arguments[0].strip()
455
- no_index = 'no-index' in self.options or 'noindex' in self.options
455
+ no_index = 'no-index' in self.options
456
456
  self.env.ref_context['py:module'] = modname
457
457
 
458
458
  content_nodes = self.parse_content_to_nodes(allow_section_headings=True)
@@ -161,7 +161,29 @@ def _parse_annotation(annotation: str, env: BuildEnvironment) -> list[Node]:
161
161
  addnodes.desc_sig_punctuation('', ')')]
162
162
 
163
163
  return result
164
- raise SyntaxError # unsupported syntax
164
+ if isinstance(node, ast.Call):
165
+ # Call nodes can be used in Annotated type metadata,
166
+ # for example Annotated[str, ArbitraryTypeValidator(str, len=10)]
167
+ args = []
168
+ for arg in node.args:
169
+ args += unparse(arg)
170
+ args.append(addnodes.desc_sig_punctuation('', ','))
171
+ args.append(addnodes.desc_sig_space())
172
+ for kwd in node.keywords:
173
+ args.append(addnodes.desc_sig_name(kwd.arg, kwd.arg)) # type: ignore[arg-type]
174
+ args.append(addnodes.desc_sig_operator('', '='))
175
+ args += unparse(kwd.value)
176
+ args.append(addnodes.desc_sig_punctuation('', ','))
177
+ args.append(addnodes.desc_sig_space())
178
+ result = [
179
+ *unparse(node.func),
180
+ addnodes.desc_sig_punctuation('', '('),
181
+ *args[:-2], # skip the final comma and space
182
+ addnodes.desc_sig_punctuation('', ')'),
183
+ ]
184
+ return result
185
+ msg = f'unsupported syntax: {node}'
186
+ raise SyntaxError(msg) # unsupported syntax
165
187
 
166
188
  def _unparse_pep_604_annotation(node: ast.Subscript) -> list[Node]:
167
189
  subscript = node.slice
@@ -25,7 +25,6 @@ from sphinx.util.nodes import (
25
25
  )
26
26
 
27
27
  if TYPE_CHECKING:
28
-
29
28
  from docutils.nodes import Node
30
29
  from docutils.parsers.rst.states import Inliner
31
30
 
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import re
6
6
  from copy import copy
7
- from typing import TYPE_CHECKING, Any, Callable, ClassVar, Final, cast
7
+ from typing import TYPE_CHECKING, Any, ClassVar, Final, cast
8
8
 
9
9
  from docutils import nodes
10
10
  from docutils.nodes import Element, Node, system_message
@@ -23,7 +23,7 @@ from sphinx.util.nodes import clean_astext, make_id, make_refnode
23
23
  from sphinx.util.parsing import nested_parse_to_nodes
24
24
 
25
25
  if TYPE_CHECKING:
26
- from collections.abc import Iterable, Iterator
26
+ from collections.abc import Callable, Iterable, Iterator
27
27
 
28
28
  from sphinx.application import Sphinx
29
29
  from sphinx.builders import Builder
@@ -402,7 +402,7 @@ class Glossary(SphinxDirective):
402
402
  in_comment = False
403
403
  was_empty = True
404
404
  messages: list[Node] = []
405
- for line, (source, lineno) in zip(self.content, self.content.items):
405
+ for line, (source, lineno) in zip(self.content, self.content.items, strict=True):
406
406
  # empty line -> add to last definition
407
407
  if not line:
408
408
  if in_definition and entries:
@@ -814,13 +814,12 @@ class StandardDomain(Domain):
814
814
  if not sectname:
815
815
  continue
816
816
  else:
817
- if (isinstance(node, (nodes.definition_list,
818
- nodes.field_list)) and
817
+ if (isinstance(node, nodes.definition_list | nodes.field_list) and
819
818
  node.children):
820
819
  node = cast(nodes.Element, node.children[0])
821
- if isinstance(node, (nodes.field, nodes.definition_list_item)):
820
+ if isinstance(node, nodes.field | nodes.definition_list_item):
822
821
  node = cast(nodes.Element, node.children[0])
823
- if isinstance(node, (nodes.term, nodes.field_name)):
822
+ if isinstance(node, nodes.term | nodes.field_name):
824
823
  sectname = clean_astext(node)
825
824
  else:
826
825
  toctree = next(node.findall(addnodes.toctree), None)
@@ -1114,7 +1113,7 @@ class StandardDomain(Domain):
1114
1113
  return title_getter(elem)
1115
1114
  else:
1116
1115
  for subnode in elem:
1117
- if isinstance(subnode, (nodes.caption, nodes.title)):
1116
+ if isinstance(subnode, nodes.caption | nodes.title):
1118
1117
  return clean_astext(subnode)
1119
1118
 
1120
1119
  return None
@@ -5,11 +5,10 @@ from __future__ import annotations
5
5
  import functools
6
6
  import os
7
7
  import pickle
8
- import time
9
8
  from collections import defaultdict
10
9
  from copy import copy
11
10
  from os import path
12
- from typing import TYPE_CHECKING, Any, Callable, NoReturn
11
+ from typing import TYPE_CHECKING, Any, NoReturn
13
12
 
14
13
  from sphinx import addnodes
15
14
  from sphinx.environment.adapters import toctree as toctree_adapters
@@ -17,13 +16,14 @@ from sphinx.errors import BuildEnvironmentError, DocumentError, ExtensionError,
17
16
  from sphinx.locale import __
18
17
  from sphinx.transforms import SphinxTransformer
19
18
  from sphinx.util import DownloadFiles, FilenameUniqDict, logging
19
+ from sphinx.util._timestamps import _format_rfc3339_microseconds
20
20
  from sphinx.util.docutils import LoggingReporter
21
21
  from sphinx.util.i18n import CatalogRepository, docname_to_domain
22
22
  from sphinx.util.nodes import is_translatable
23
- from sphinx.util.osutil import canon_path, os_path
23
+ from sphinx.util.osutil import _last_modified_time, canon_path, os_path
24
24
 
25
25
  if TYPE_CHECKING:
26
- from collections.abc import Iterator
26
+ from collections.abc import Callable, Iterator
27
27
  from pathlib import Path
28
28
 
29
29
  from docutils import nodes
@@ -36,6 +36,7 @@ if TYPE_CHECKING:
36
36
  from sphinx.domains import Domain
37
37
  from sphinx.events import EventManager
38
38
  from sphinx.project import Project
39
+ from sphinx.util._pathlib import _StrPath
39
40
 
40
41
  logger = logging.getLogger(__name__)
41
42
 
@@ -59,7 +60,7 @@ default_settings: dict[str, Any] = {
59
60
 
60
61
  # This is increased every time an environment attribute is added
61
62
  # or changed to properly invalidate pickle files.
62
- ENV_VERSION = 62
63
+ ENV_VERSION = 63
63
64
 
64
65
  # config status
65
66
  CONFIG_UNSET = -1
@@ -124,7 +125,7 @@ if TYPE_CHECKING:
124
125
  def __getitem__(self, key: Literal["todo"]) -> TodoDomain: ... # NoQA: E704
125
126
  @overload
126
127
  def __getitem__(self, key: str) -> Domain: ... # NoQA: E704
127
- def __getitem__(self, key): raise NotImplementedError # NoQA: E704
128
+ def __getitem__(self, _key: str) -> Domain: raise NotImplementedError # NoQA: E704
128
129
  def __setitem__( # NoQA: E301,E704
129
130
  self, key: str, value: Domain,
130
131
  ) -> NoReturn: raise NotImplementedError
@@ -413,13 +414,13 @@ class BuildEnvironment:
413
414
  """
414
415
  return self.project.path2doc(filename)
415
416
 
416
- def doc2path(self, docname: str, base: bool = True) -> str:
417
+ def doc2path(self, docname: str, base: bool = True) -> _StrPath:
417
418
  """Return the filename for the document name.
418
419
 
419
420
  If *base* is True, return absolute path under self.srcdir.
420
421
  If *base* is False, return relative path to self.srcdir.
421
422
  """
422
- return self.project.doc2path(docname, base)
423
+ return self.project.doc2path(docname, absolute=base)
423
424
 
424
425
  def relfn2path(self, filename: str, docname: str | None = None) -> tuple[str, str]:
425
426
  """Return paths to a file referenced from a document, relative to
@@ -508,7 +509,8 @@ class BuildEnvironment:
508
509
  if newmtime > mtime:
509
510
  logger.debug('[build target] outdated %r: %s -> %s',
510
511
  docname,
511
- _format_modified_time(mtime), _format_modified_time(newmtime))
512
+ _format_rfc3339_microseconds(mtime),
513
+ _format_rfc3339_microseconds(newmtime))
512
514
  changed.add(docname)
513
515
  continue
514
516
  # finally, check the mtime of dependencies
@@ -528,7 +530,8 @@ class BuildEnvironment:
528
530
  logger.debug(
529
531
  '[build target] outdated %r from dependency %r: %s -> %s',
530
532
  docname, deppath,
531
- _format_modified_time(mtime), _format_modified_time(depmtime),
533
+ _format_rfc3339_microseconds(mtime),
534
+ _format_rfc3339_microseconds(depmtime),
532
535
  )
533
536
  changed.add(docname)
534
537
  break
@@ -628,7 +631,7 @@ class BuildEnvironment:
628
631
 
629
632
  doctree = pickle.loads(serialised)
630
633
  doctree.settings.env = self
631
- doctree.reporter = LoggingReporter(self.doc2path(docname))
634
+ doctree.reporter = LoggingReporter(str(self.doc2path(docname)))
632
635
  return doctree
633
636
 
634
637
  @functools.cached_property
@@ -650,7 +653,7 @@ class BuildEnvironment:
650
653
  try:
651
654
  doctree = self._write_doc_doctree_cache.pop(docname)
652
655
  doctree.settings.env = self
653
- doctree.reporter = LoggingReporter(self.doc2path(docname))
656
+ doctree.reporter = LoggingReporter(str(self.doc2path(docname)))
654
657
  except KeyError:
655
658
  doctree = self.get_doctree(docname)
656
659
 
@@ -756,26 +759,6 @@ class BuildEnvironment:
756
759
  self.events.emit('env-check-consistency', self)
757
760
 
758
761
 
759
- def _last_modified_time(filename: str | os.PathLike[str]) -> int:
760
- """Return the last modified time of ``filename``.
761
-
762
- The time is returned as integer microseconds.
763
- The lowest common denominator of modern file-systems seems to be
764
- microsecond-level precision.
765
-
766
- We prefer to err on the side of re-rendering a file,
767
- so we round up to the nearest microsecond.
768
- """
769
- # upside-down floor division to get the ceiling
770
- return -(os.stat(filename).st_mtime_ns // -1_000)
771
-
772
-
773
- def _format_modified_time(timestamp: int) -> str:
774
- """Return an RFC 3339 formatted string representing the given timestamp."""
775
- seconds, fraction = divmod(timestamp, 10**6)
776
- return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(seconds)) + f'.{fraction // 1_000}'
777
-
778
-
779
762
  def _traverse_toctree(
780
763
  traversed: set[str],
781
764
  parent: str | None,
@@ -13,16 +13,14 @@ from sphinx.util import logging
13
13
  from sphinx.util.index_entries import _split_into
14
14
 
15
15
  if TYPE_CHECKING:
16
- from typing import Literal, Optional, Union
17
-
18
- from typing_extensions import TypeAlias
16
+ from typing import Literal, TypeAlias
19
17
 
20
18
  from sphinx.builders import Builder
21
19
  from sphinx.environment import BuildEnvironment
22
20
 
23
- _IndexEntryTarget: TypeAlias = tuple[Optional[str], Union[str, Literal[False]]]
21
+ _IndexEntryTarget: TypeAlias = tuple[str | None, str | Literal[False]]
24
22
  _IndexEntryTargets: TypeAlias = list[_IndexEntryTarget]
25
- _IndexEntryCategoryKey: TypeAlias = Optional[str]
23
+ _IndexEntryCategoryKey: TypeAlias = str | None
26
24
  _IndexEntrySubItems: TypeAlias = dict[
27
25
  str,
28
26
  tuple[_IndexEntryTargets, _IndexEntryCategoryKey],
@@ -32,7 +30,7 @@ if TYPE_CHECKING:
32
30
  _IndexEntrySubItems,
33
31
  _IndexEntryCategoryKey,
34
32
  ]
35
- _IndexEntryMap = dict[str, _IndexEntry]
33
+ _IndexEntryMap: TypeAlias = dict[str, _IndexEntry]
36
34
  _Index: TypeAlias = list[
37
35
  tuple[
38
36
  str,
@@ -319,7 +319,7 @@ def _toctree_entry(
319
319
  ref, location=toctreenode, type='toc', subtype='no_title')
320
320
  except KeyError:
321
321
  # this is raised if the included file does not exist
322
- ref_path = env.doc2path(ref, False)
322
+ ref_path = str(env.doc2path(ref, False))
323
323
  if excluded(ref_path):
324
324
  message = __('toctree contains reference to excluded document %r')
325
325
  elif not included(ref_path):
@@ -404,7 +404,7 @@ def _toctree_standard_entry(
404
404
  def _toctree_add_classes(node: Element, depth: int, docname: str) -> None:
405
405
  """Add 'toctree-l%d' and 'current' classes to the toctree."""
406
406
  for subnode in node.children:
407
- if isinstance(subnode, (addnodes.compact_paragraph, nodes.list_item)):
407
+ if isinstance(subnode, addnodes.compact_paragraph | nodes.list_item):
408
408
  # for <p> and <li>, indicate the depth level and recurse
409
409
  subnode['classes'].append(f'toctree-l{depth - 1}')
410
410
  _toctree_add_classes(subnode, depth, docname)
@@ -442,7 +442,7 @@ def _toctree_copy(node: ET, depth: int, maxdepth: int, collapse: bool, tags: Tag
442
442
 
443
443
  copy = node.copy()
444
444
  for subnode in node.children:
445
- if isinstance(subnode, (addnodes.compact_paragraph, nodes.list_item)):
445
+ if isinstance(subnode, addnodes.compact_paragraph | nodes.list_item):
446
446
  # for <p> and <li>, just recurse
447
447
  copy.append(_toctree_copy(subnode, depth, maxdepth, collapse, tags))
448
448
  elif isinstance(subnode, nodes.bullet_list):
@@ -462,7 +462,7 @@ def _toctree_copy(node: ET, depth: int, maxdepth: int, collapse: bool, tags: Tag
462
462
  copy.append(_toctree_copy(
463
463
  child, depth, maxdepth, collapse, tags, # type: ignore[type-var]
464
464
  ))
465
- elif isinstance(subnode, (nodes.reference, nodes.title)):
465
+ elif isinstance(subnode, nodes.reference | nodes.title):
466
466
  # deep copy references and captions
467
467
  sub_node_copy = subnode.copy()
468
468
  sub_node_copy.children = [child.deepcopy() for child in subnode.children]
@@ -43,7 +43,7 @@ class TitleCollector(EnvironmentCollector):
43
43
  for node in doctree.findall(nodes.section):
44
44
  visitor = SphinxContentsFilter(doctree)
45
45
  node[0].walkabout(visitor)
46
- titlenode += visitor.get_entry_text()
46
+ titlenode += visitor.get_entry_text() # type: ignore[no-untyped-call]
47
47
  break
48
48
  else:
49
49
  # document has no title
@@ -78,7 +78,7 @@ class TocTreeCollector(EnvironmentCollector):
78
78
  # and unnecessary stuff
79
79
  visitor = SphinxContentsFilter(doctree)
80
80
  title.walkabout(visitor)
81
- nodetext = visitor.get_entry_text()
81
+ nodetext = visitor.get_entry_text() # type: ignore[no-untyped-call]
82
82
  anchorname = _make_anchor_name(sectionnode['ids'], numentries)
83
83
  # make these nodes:
84
84
  # list_item -> compact_paragraph -> reference
sphinx/events.py CHANGED
@@ -8,7 +8,7 @@ from __future__ import annotations
8
8
  import contextlib
9
9
  from collections import defaultdict
10
10
  from operator import attrgetter
11
- from typing import TYPE_CHECKING, Any, Callable, NamedTuple
11
+ from typing import TYPE_CHECKING, Any, NamedTuple
12
12
 
13
13
  from sphinx.errors import ExtensionError, SphinxError
14
14
  from sphinx.locale import __
@@ -16,6 +16,8 @@ from sphinx.util import logging
16
16
  from sphinx.util.inspect import safe_getattr
17
17
 
18
18
  if TYPE_CHECKING:
19
+ from collections.abc import Callable
20
+
19
21
  from sphinx.application import Sphinx
20
22
 
21
23
 
@@ -10,20 +10,18 @@ from __future__ import annotations
10
10
  import functools
11
11
  import operator
12
12
  import re
13
- import sys
14
- import warnings
15
13
  from inspect import Parameter, Signature
16
- from typing import TYPE_CHECKING, Any, Callable, ClassVar, TypeVar
14
+ from typing import TYPE_CHECKING, Any, ClassVar, NewType, TypeVar
17
15
 
18
16
  from docutils.statemachine import StringList
19
17
 
20
18
  import sphinx
21
19
  from sphinx.config import ENUM, Config
22
- from sphinx.deprecation import RemovedInSphinx80Warning
20
+ from sphinx.errors import PycodeError
23
21
  from sphinx.ext.autodoc.importer import get_class_members, import_module, import_object
24
22
  from sphinx.ext.autodoc.mock import ismock, mock, undecorate
25
23
  from sphinx.locale import _, __
26
- from sphinx.pycode import ModuleAnalyzer, PycodeError
24
+ from sphinx.pycode import ModuleAnalyzer
27
25
  from sphinx.util import inspect, logging
28
26
  from sphinx.util.docstrings import prepare_docstring, separate_metadata
29
27
  from sphinx.util.inspect import (
@@ -42,7 +40,7 @@ from sphinx.util.typing import (
42
40
  )
43
41
 
44
42
  if TYPE_CHECKING:
45
- from collections.abc import Iterator, Sequence
43
+ from collections.abc import Callable, Iterator, Sequence
46
44
  from types import ModuleType
47
45
 
48
46
  from sphinx.application import Sphinx
@@ -267,13 +265,6 @@ class ObjectMember:
267
265
 
268
266
  This is used for the result of `Documenter.get_module_members()` to
269
267
  represent each member of the object.
270
-
271
- .. Note::
272
-
273
- An instance of this class behaves as a tuple of (name, object)
274
- for compatibility to old Sphinx. The behavior will be dropped
275
- in the future. Therefore extensions should not use the tuple
276
- interface.
277
268
  """
278
269
 
279
270
  def __init__(self, name: str, obj: Any, *, docstring: str | None = None,
@@ -284,12 +275,6 @@ class ObjectMember:
284
275
  self.skipped = skipped
285
276
  self.class_ = class_
286
277
 
287
- def __getitem__(self, index: int) -> Any:
288
- warnings.warn('The tuple interface of ObjectMember is deprecated. '
289
- 'Use (obj.__name__, obj.object) instead.',
290
- RemovedInSphinx80Warning, stacklevel=2)
291
- return (self.__name__, self.object)[index]
292
-
293
278
 
294
279
  class Documenter:
295
280
  """
@@ -627,7 +612,7 @@ class Documenter:
627
612
 
628
613
  # add additional content (e.g. from document), if present
629
614
  if more_content:
630
- for line, src in zip(more_content.data, more_content.items):
615
+ for line, src in zip(more_content.data, more_content.items, strict=True):
631
616
  self.add_line(line, src[0], src[1])
632
617
 
633
618
  def get_object_members(self, want_all: bool) -> tuple[bool, list[ObjectMember]]:
@@ -684,21 +669,8 @@ class Documenter:
684
669
 
685
670
  # process members and determine which to skip
686
671
  for obj in members:
687
- try:
688
- membername = obj.__name__
689
- member = obj.object
690
- except AttributeError:
691
- if isinstance(obj, ObjectMember):
692
- raise
693
- # To be removed, retained for compatibility.
694
- # See https://github.com/sphinx-doc/sphinx/issues/11631
695
- membername, member = obj
696
- warnings.warn(
697
- 'Returning tuples of (name, object) as '
698
- 'the second return value from get_object_members() is deprecated. '
699
- 'Return ObjectMember(name, object) instances instead.',
700
- RemovedInSphinx80Warning, stacklevel=2,
701
- )
672
+ membername = obj.__name__
673
+ member = obj.object
702
674
 
703
675
  # if isattr is True, the member is documented as an attribute
704
676
  isattr = member is INSTANCEATTR or (namespace, membername) in attr_docs
@@ -1003,7 +975,7 @@ class ModuleDocumenter(Documenter):
1003
975
  super().add_content(None)
1004
976
  self.indent = old_indent
1005
977
  if more_content:
1006
- for line, src in zip(more_content.data, more_content.items):
978
+ for line, src in zip(more_content.data, more_content.items, strict=True):
1007
979
  self.add_line(line, src[0], src[1])
1008
980
 
1009
981
  @classmethod
@@ -1410,7 +1382,7 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
1410
1382
  if len(sig.parameters) == 0:
1411
1383
  return None
1412
1384
 
1413
- def dummy(): # NoQA: ANN202
1385
+ def dummy(): # type: ignore[no-untyped-def] # NoQA: ANN202
1414
1386
  pass
1415
1387
 
1416
1388
  params = list(sig.parameters.values())
@@ -1478,7 +1450,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1478
1450
 
1479
1451
  # Must be higher than FunctionDocumenter, ClassDocumenter, and
1480
1452
  # AttributeDocumenter as NewType can be an attribute and is a class
1481
- # after Python 3.10. Before 3.10 it is a kind of function object
1453
+ # after Python 3.10.
1482
1454
  priority = 15
1483
1455
 
1484
1456
  _signature_class: Any = None
@@ -1504,7 +1476,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1504
1476
  cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
1505
1477
  ) -> bool:
1506
1478
  return isinstance(member, type) or (
1507
- isattr and (inspect.isNewType(member) or isinstance(member, TypeVar)))
1479
+ isattr and isinstance(member, NewType | TypeVar))
1508
1480
 
1509
1481
  def import_object(self, raiseerror: bool = False) -> bool:
1510
1482
  ret = super().import_object(raiseerror)
@@ -1515,7 +1487,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1515
1487
  self.doc_as_attr = (self.objpath[-1] != self.object.__name__)
1516
1488
  else:
1517
1489
  self.doc_as_attr = True
1518
- if inspect.isNewType(self.object) or isinstance(self.object, TypeVar):
1490
+ if isinstance(self.object, NewType | TypeVar):
1519
1491
  modname = getattr(self.object, '__module__', self.modname)
1520
1492
  if modname != self.modname and self.modname.startswith(modname):
1521
1493
  bases = self.modname[len(modname):].strip('.').split('.')
@@ -1524,7 +1496,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1524
1496
  return ret
1525
1497
 
1526
1498
  def _get_signature(self) -> tuple[Any | None, str | None, Signature | None]:
1527
- if inspect.isNewType(self.object) or isinstance(self.object, TypeVar):
1499
+ if isinstance(self.object, NewType | TypeVar):
1528
1500
  # Suppress signature
1529
1501
  return None, None, None
1530
1502
 
@@ -1709,14 +1681,14 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1709
1681
  self.directivetype = 'attribute'
1710
1682
  super().add_directive_header(sig)
1711
1683
 
1712
- if inspect.isNewType(self.object) or isinstance(self.object, TypeVar):
1684
+ if isinstance(self.object, NewType | TypeVar):
1713
1685
  return
1714
1686
 
1715
1687
  if self.analyzer and '.'.join(self.objpath) in self.analyzer.finals:
1716
1688
  self.add_line(' :final:', sourcename)
1717
1689
 
1718
1690
  canonical_fullname = self.get_canonical_fullname()
1719
- if (not self.doc_as_attr and not inspect.isNewType(self.object)
1691
+ if (not self.doc_as_attr and not isinstance(self.object, NewType)
1720
1692
  and canonical_fullname and self.fullname != canonical_fullname):
1721
1693
  self.add_line(' :canonical: %s' % canonical_fullname, sourcename)
1722
1694
 
@@ -1768,24 +1740,6 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1768
1740
  if isinstance(self.object, TypeVar):
1769
1741
  if self.object.__doc__ == TypeVar.__doc__:
1770
1742
  return []
1771
- if sys.version_info[:2] < (3, 10):
1772
- if inspect.isNewType(self.object) or isinstance(self.object, TypeVar):
1773
- parts = self.modname.strip('.').split('.')
1774
- orig_objpath = self.objpath
1775
- for i in range(len(parts)):
1776
- new_modname = '.'.join(parts[:len(parts) - i])
1777
- new_objpath = parts[len(parts) - i:] + orig_objpath
1778
- try:
1779
- analyzer = ModuleAnalyzer.for_module(new_modname)
1780
- analyzer.analyze()
1781
- key = ('', new_objpath[-1])
1782
- comment = list(analyzer.attr_docs.get(key, []))
1783
- if comment:
1784
- self.objpath = new_objpath
1785
- self.modname = new_modname
1786
- return [comment]
1787
- except PycodeError:
1788
- pass
1789
1743
  if self.doc_as_attr:
1790
1744
  # Don't show the docstring of the class when it is an alias.
1791
1745
  if self.get_variable_comment():
@@ -1849,7 +1803,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1849
1803
  return None
1850
1804
 
1851
1805
  def add_content(self, more_content: StringList | None) -> None:
1852
- if inspect.isNewType(self.object):
1806
+ if isinstance(self.object, NewType):
1853
1807
  if self.config.autodoc_typehints_format == "short":
1854
1808
  supertype = restify(self.object.__supertype__, "smart")
1855
1809
  else:
@@ -2008,7 +1962,8 @@ class UninitializedGlobalVariableMixin(DataDocumenterMixinBase):
2008
1962
  with mock(self.config.autodoc_mock_imports):
2009
1963
  parent = import_module(self.modname, self.config.autodoc_warningiserror)
2010
1964
  annotations = get_type_hints(parent, None,
2011
- self.config.autodoc_type_aliases)
1965
+ self.config.autodoc_type_aliases,
1966
+ include_extras=True)
2012
1967
  if self.objpath[-1] in annotations:
2013
1968
  self.object = UNINITIALIZED_ATTR
2014
1969
  self.parent = parent
@@ -2097,7 +2052,8 @@ class DataDocumenter(GenericAliasMixin,
2097
2052
  if self.config.autodoc_typehints != 'none':
2098
2053
  # obtain annotation for this data
2099
2054
  annotations = get_type_hints(self.parent, None,
2100
- self.config.autodoc_type_aliases)
2055
+ self.config.autodoc_type_aliases,
2056
+ include_extras=True)
2101
2057
  if self.objpath[-1] in annotations:
2102
2058
  if self.config.autodoc_typehints_format == "short":
2103
2059
  objrepr = stringify_annotation(annotations.get(self.objpath[-1]),
@@ -2322,7 +2278,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2322
2278
  if len(sig.parameters) == 1:
2323
2279
  return None
2324
2280
 
2325
- def dummy(): # NoQA: ANN202
2281
+ def dummy(): # type: ignore[no-untyped-def] # NoQA: ANN202
2326
2282
  pass
2327
2283
 
2328
2284
  params = list(sig.parameters.values())
@@ -2541,7 +2497,8 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
2541
2497
 
2542
2498
  def is_uninitialized_instance_attribute(self, parent: Any) -> bool:
2543
2499
  """Check the subject is an annotation only attribute."""
2544
- annotations = get_type_hints(parent, None, self.config.autodoc_type_aliases)
2500
+ annotations = get_type_hints(parent, None, self.config.autodoc_type_aliases,
2501
+ include_extras=True)
2545
2502
  return self.objpath[-1] in annotations
2546
2503
 
2547
2504
  def import_object(self, raiseerror: bool = False) -> bool:
@@ -2673,7 +2630,8 @@ class AttributeDocumenter(GenericAliasMixin, SlotsMixin, # type: ignore[misc]
2673
2630
  if self.config.autodoc_typehints != 'none':
2674
2631
  # obtain type annotation for this attribute
2675
2632
  annotations = get_type_hints(self.parent, None,
2676
- self.config.autodoc_type_aliases)
2633
+ self.config.autodoc_type_aliases,
2634
+ include_extras=True)
2677
2635
  if self.objpath[-1] in annotations:
2678
2636
  if self.config.autodoc_typehints_format == "short":
2679
2637
  objrepr = stringify_annotation(annotations.get(self.objpath[-1]),