Sphinx 7.1.1__py3-none-any.whl → 7.2.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (313) hide show
  1. sphinx/__init__.py +6 -6
  2. sphinx/__main__.py +3 -1
  3. sphinx/addnodes.py +35 -22
  4. sphinx/application.py +40 -38
  5. sphinx/builders/__init__.py +16 -12
  6. sphinx/builders/_epub_base.py +15 -11
  7. sphinx/builders/changes.py +6 -4
  8. sphinx/builders/dirhtml.py +4 -2
  9. sphinx/builders/dummy.py +6 -4
  10. sphinx/builders/epub3.py +16 -8
  11. sphinx/builders/gettext.py +40 -43
  12. sphinx/builders/html/__init__.py +166 -196
  13. sphinx/builders/html/_assets.py +116 -0
  14. sphinx/builders/html/transforms.py +4 -2
  15. sphinx/builders/latex/__init__.py +12 -7
  16. sphinx/builders/latex/theming.py +5 -2
  17. sphinx/builders/latex/transforms.py +6 -3
  18. sphinx/builders/linkcheck.py +21 -13
  19. sphinx/builders/manpage.py +6 -4
  20. sphinx/builders/singlehtml.py +16 -9
  21. sphinx/builders/texinfo.py +11 -6
  22. sphinx/builders/text.py +8 -3
  23. sphinx/builders/xml.py +9 -4
  24. sphinx/cmd/build.py +27 -14
  25. sphinx/cmd/make_mode.py +13 -4
  26. sphinx/cmd/quickstart.py +13 -4
  27. sphinx/config.py +17 -14
  28. sphinx/deprecation.py +4 -2
  29. sphinx/directives/__init__.py +44 -12
  30. sphinx/directives/code.py +5 -4
  31. sphinx/directives/other.py +92 -44
  32. sphinx/directives/patches.py +1 -1
  33. sphinx/domains/__init__.py +11 -8
  34. sphinx/domains/c.py +67 -57
  35. sphinx/domains/changeset.py +3 -2
  36. sphinx/domains/citation.py +2 -1
  37. sphinx/domains/cpp.py +136 -93
  38. sphinx/domains/index.py +9 -5
  39. sphinx/domains/javascript.py +32 -19
  40. sphinx/domains/math.py +5 -3
  41. sphinx/domains/python.py +69 -57
  42. sphinx/domains/rst.py +20 -11
  43. sphinx/domains/std.py +21 -15
  44. sphinx/environment/__init__.py +97 -65
  45. sphinx/environment/adapters/indexentries.py +13 -10
  46. sphinx/environment/adapters/toctree.py +485 -308
  47. sphinx/environment/collectors/__init__.py +3 -4
  48. sphinx/environment/collectors/asset.py +10 -4
  49. sphinx/environment/collectors/dependencies.py +7 -4
  50. sphinx/environment/collectors/metadata.py +7 -5
  51. sphinx/environment/collectors/title.py +5 -3
  52. sphinx/environment/collectors/toctree.py +13 -8
  53. sphinx/errors.py +1 -1
  54. sphinx/events.py +5 -5
  55. sphinx/ext/apidoc.py +49 -27
  56. sphinx/ext/autodoc/__init__.py +179 -161
  57. sphinx/ext/autodoc/directive.py +10 -6
  58. sphinx/ext/autodoc/importer.py +22 -13
  59. sphinx/ext/autodoc/mock.py +4 -1
  60. sphinx/ext/autodoc/preserve_defaults.py +80 -12
  61. sphinx/ext/autodoc/type_comment.py +14 -10
  62. sphinx/ext/autodoc/typehints.py +7 -3
  63. sphinx/ext/autosectionlabel.py +6 -3
  64. sphinx/ext/autosummary/__init__.py +21 -15
  65. sphinx/ext/autosummary/generate.py +176 -126
  66. sphinx/ext/coverage.py +93 -8
  67. sphinx/ext/doctest.py +28 -17
  68. sphinx/ext/duration.py +19 -17
  69. sphinx/ext/extlinks.py +11 -6
  70. sphinx/ext/githubpages.py +8 -7
  71. sphinx/ext/graphviz.py +61 -17
  72. sphinx/ext/ifconfig.py +7 -4
  73. sphinx/ext/imgconverter.py +4 -2
  74. sphinx/ext/imgmath.py +29 -23
  75. sphinx/ext/inheritance_diagram.py +41 -27
  76. sphinx/ext/intersphinx.py +45 -38
  77. sphinx/ext/linkcode.py +8 -5
  78. sphinx/ext/mathjax.py +13 -9
  79. sphinx/ext/napoleon/__init__.py +3 -3
  80. sphinx/ext/napoleon/docstring.py +40 -31
  81. sphinx/ext/todo.py +10 -7
  82. sphinx/ext/viewcode.py +46 -25
  83. sphinx/extension.py +1 -1
  84. sphinx/highlighting.py +20 -12
  85. sphinx/io.py +5 -4
  86. sphinx/jinja2glue.py +24 -19
  87. sphinx/locale/__init__.py +8 -2
  88. sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
  89. sphinx/locale/ar/LC_MESSAGES/sphinx.po +756 -740
  90. sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
  91. sphinx/locale/bg/LC_MESSAGES/sphinx.po +754 -738
  92. sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
  93. sphinx/locale/bn/LC_MESSAGES/sphinx.po +755 -739
  94. sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
  95. sphinx/locale/ca/LC_MESSAGES/sphinx.po +768 -752
  96. sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
  97. sphinx/locale/cak/LC_MESSAGES/sphinx.po +754 -738
  98. sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
  99. sphinx/locale/cs/LC_MESSAGES/sphinx.po +758 -742
  100. sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
  101. sphinx/locale/cy/LC_MESSAGES/sphinx.po +759 -743
  102. sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
  103. sphinx/locale/da/LC_MESSAGES/sphinx.po +760 -744
  104. sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
  105. sphinx/locale/de/LC_MESSAGES/sphinx.po +759 -743
  106. sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
  107. sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +754 -738
  108. sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
  109. sphinx/locale/el/LC_MESSAGES/sphinx.po +763 -747
  110. sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
  111. sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +754 -738
  112. sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
  113. sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +754 -738
  114. sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
  115. sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +768 -752
  116. sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
  117. sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +754 -738
  118. sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
  119. sphinx/locale/eo/LC_MESSAGES/sphinx.po +754 -738
  120. sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
  121. sphinx/locale/es/LC_MESSAGES/sphinx.po +767 -751
  122. sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
  123. sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +754 -738
  124. sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
  125. sphinx/locale/et/LC_MESSAGES/sphinx.po +762 -746
  126. sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
  127. sphinx/locale/eu/LC_MESSAGES/sphinx.po +755 -739
  128. sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
  129. sphinx/locale/fa/LC_MESSAGES/sphinx.po +766 -750
  130. sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
  131. sphinx/locale/fi/LC_MESSAGES/sphinx.po +754 -738
  132. sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
  133. sphinx/locale/fr/LC_MESSAGES/sphinx.po +768 -752
  134. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
  135. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +754 -738
  136. sphinx/locale/gl/LC_MESSAGES/sphinx.js +60 -0
  137. sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
  138. sphinx/locale/gl/LC_MESSAGES/sphinx.po +3695 -0
  139. sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
  140. sphinx/locale/he/LC_MESSAGES/sphinx.po +755 -739
  141. sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
  142. sphinx/locale/hi/LC_MESSAGES/sphinx.po +763 -747
  143. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
  144. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +754 -738
  145. sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
  146. sphinx/locale/hr/LC_MESSAGES/sphinx.po +760 -744
  147. sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
  148. sphinx/locale/hu/LC_MESSAGES/sphinx.po +759 -743
  149. sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
  150. sphinx/locale/id/LC_MESSAGES/sphinx.po +765 -749
  151. sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
  152. sphinx/locale/is/LC_MESSAGES/sphinx.po +760 -744
  153. sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
  154. sphinx/locale/it/LC_MESSAGES/sphinx.po +760 -744
  155. sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
  156. sphinx/locale/ja/LC_MESSAGES/sphinx.po +767 -751
  157. sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
  158. sphinx/locale/ka/LC_MESSAGES/sphinx.po +759 -743
  159. sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
  160. sphinx/locale/ko/LC_MESSAGES/sphinx.po +767 -751
  161. sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
  162. sphinx/locale/lt/LC_MESSAGES/sphinx.po +755 -739
  163. sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
  164. sphinx/locale/lv/LC_MESSAGES/sphinx.po +755 -739
  165. sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
  166. sphinx/locale/mk/LC_MESSAGES/sphinx.po +754 -738
  167. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
  168. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +755 -739
  169. sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
  170. sphinx/locale/ne/LC_MESSAGES/sphinx.po +755 -739
  171. sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
  172. sphinx/locale/nl/LC_MESSAGES/sphinx.po +760 -744
  173. sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
  174. sphinx/locale/pl/LC_MESSAGES/sphinx.po +762 -745
  175. sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
  176. sphinx/locale/pt/LC_MESSAGES/sphinx.po +754 -738
  177. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
  178. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +768 -752
  179. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
  180. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +755 -739
  181. sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
  182. sphinx/locale/ro/LC_MESSAGES/sphinx.po +759 -743
  183. sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
  184. sphinx/locale/ru/LC_MESSAGES/sphinx.po +760 -744
  185. sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
  186. sphinx/locale/si/LC_MESSAGES/sphinx.po +754 -738
  187. sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
  188. sphinx/locale/sk/LC_MESSAGES/sphinx.po +765 -749
  189. sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
  190. sphinx/locale/sl/LC_MESSAGES/sphinx.po +755 -739
  191. sphinx/locale/sphinx.pot +748 -740
  192. sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
  193. sphinx/locale/sq/LC_MESSAGES/sphinx.po +768 -752
  194. sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
  195. sphinx/locale/sr/LC_MESSAGES/sphinx.po +754 -738
  196. sphinx/locale/sr@latin/LC_MESSAGES/sphinx.mo +0 -0
  197. sphinx/locale/sr@latin/LC_MESSAGES/sphinx.po +754 -738
  198. sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo +0 -0
  199. sphinx/locale/sr_RS/LC_MESSAGES/sphinx.po +754 -738
  200. sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
  201. sphinx/locale/sv/LC_MESSAGES/sphinx.po +755 -739
  202. sphinx/locale/ta/LC_MESSAGES/sphinx.mo +0 -0
  203. sphinx/locale/ta/LC_MESSAGES/sphinx.po +754 -738
  204. sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
  205. sphinx/locale/te/LC_MESSAGES/sphinx.po +754 -738
  206. sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
  207. sphinx/locale/tr/LC_MESSAGES/sphinx.po +763 -747
  208. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
  209. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +760 -749
  210. sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
  211. sphinx/locale/ur/LC_MESSAGES/sphinx.po +759 -748
  212. sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
  213. sphinx/locale/vi/LC_MESSAGES/sphinx.po +754 -738
  214. sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
  215. sphinx/locale/yue/LC_MESSAGES/sphinx.po +754 -738
  216. sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo +0 -0
  217. sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +768 -752
  218. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
  219. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +754 -738
  220. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
  221. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +767 -751
  222. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
  223. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +754 -738
  224. sphinx/parsers.py +5 -4
  225. sphinx/project.py +52 -34
  226. sphinx/pycode/__init__.py +2 -1
  227. sphinx/pycode/ast.py +7 -13
  228. sphinx/pycode/parser.py +42 -38
  229. sphinx/registry.py +35 -29
  230. sphinx/roles.py +9 -4
  231. sphinx/search/__init__.py +5 -17
  232. sphinx/search/da.py +1 -1
  233. sphinx/search/de.py +1 -1
  234. sphinx/search/en.py +1 -1
  235. sphinx/search/es.py +1 -1
  236. sphinx/search/fi.py +1 -1
  237. sphinx/search/fr.py +1 -1
  238. sphinx/search/hu.py +1 -1
  239. sphinx/search/it.py +1 -1
  240. sphinx/search/ja.py +1 -1
  241. sphinx/search/nl.py +1 -1
  242. sphinx/search/no.py +1 -1
  243. sphinx/search/pt.py +1 -1
  244. sphinx/search/ro.py +1 -1
  245. sphinx/search/ru.py +1 -1
  246. sphinx/search/sv.py +1 -1
  247. sphinx/search/tr.py +1 -1
  248. sphinx/search/zh.py +1 -1
  249. sphinx/testing/fixtures.py +23 -30
  250. sphinx/testing/path.py +9 -0
  251. sphinx/testing/restructuredtext.py +13 -5
  252. sphinx/testing/util.py +20 -63
  253. sphinx/texinputs/sphinxlatexobjects.sty +15 -15
  254. sphinx/themes/agogo/static/agogo.css_t +10 -4
  255. sphinx/themes/basic/layout.html +1 -1
  256. sphinx/themes/basic/static/basic.css_t +4 -0
  257. sphinx/themes/basic/static/documentation_options.js_t +1 -2
  258. sphinx/themes/basic/static/searchtools.js +17 -9
  259. sphinx/themes/basic/static/sphinx_highlight.js +13 -3
  260. sphinx/themes/bizstyle/static/bizstyle.css_t +4 -0
  261. sphinx/themes/classic/theme.conf +1 -1
  262. sphinx/themes/epub/static/epub.css_t +6 -1
  263. sphinx/themes/haiku/theme.conf +1 -1
  264. sphinx/themes/nature/static/nature.css_t +4 -0
  265. sphinx/themes/nonav/static/nonav.css_t +6 -1
  266. sphinx/themes/pyramid/static/pyramid.css_t +4 -0
  267. sphinx/themes/scrolls/static/scrolls.css_t +4 -0
  268. sphinx/themes/scrolls/theme.conf +1 -1
  269. sphinx/themes/sphinxdoc/static/sphinxdoc.css_t +4 -0
  270. sphinx/theming.py +9 -7
  271. sphinx/transforms/__init__.py +79 -3
  272. sphinx/transforms/compact_bullet_list.py +6 -3
  273. sphinx/transforms/i18n.py +26 -10
  274. sphinx/transforms/post_transforms/__init__.py +21 -8
  275. sphinx/transforms/post_transforms/code.py +6 -3
  276. sphinx/transforms/post_transforms/images.py +13 -9
  277. sphinx/util/__init__.py +21 -92
  278. sphinx/util/cfamily.py +7 -4
  279. sphinx/util/display.py +3 -2
  280. sphinx/util/docfields.py +7 -6
  281. sphinx/util/docstrings.py +1 -1
  282. sphinx/util/docutils.py +41 -31
  283. sphinx/util/fileutil.py +9 -6
  284. sphinx/util/i18n.py +21 -18
  285. sphinx/util/images.py +2 -1
  286. sphinx/util/index_entries.py +27 -0
  287. sphinx/util/inspect.py +83 -67
  288. sphinx/util/inventory.py +4 -2
  289. sphinx/util/logging.py +9 -6
  290. sphinx/util/matching.py +5 -2
  291. sphinx/util/math.py +6 -3
  292. sphinx/util/nodes.py +70 -31
  293. sphinx/util/osutil.py +22 -40
  294. sphinx/util/parallel.py +4 -1
  295. sphinx/util/rst.py +7 -3
  296. sphinx/util/tags.py +11 -4
  297. sphinx/util/template.py +17 -14
  298. sphinx/util/typing.py +61 -20
  299. sphinx/versioning.py +6 -4
  300. sphinx/writers/html.py +1 -1
  301. sphinx/writers/html5.py +32 -24
  302. sphinx/writers/latex.py +67 -53
  303. sphinx/writers/manpage.py +9 -5
  304. sphinx/writers/texinfo.py +11 -9
  305. sphinx/writers/text.py +14 -9
  306. sphinx/writers/xml.py +3 -2
  307. {sphinx-7.1.1.dist-info → sphinx-7.2.0.dist-info}/METADATA +7 -5
  308. sphinx-7.2.0.dist-info/RECORD +568 -0
  309. sphinx/testing/comparer.py +0 -97
  310. sphinx-7.1.1.dist-info/RECORD +0 -564
  311. {sphinx-7.1.1.dist-info → sphinx-7.2.0.dist-info}/LICENSE +0 -0
  312. {sphinx-7.1.1.dist-info → sphinx-7.2.0.dist-info}/WHEEL +0 -0
  313. {sphinx-7.1.1.dist-info → sphinx-7.2.0.dist-info}/entry_points.txt +0 -0
@@ -1,20 +1,23 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Any, Callable
3
+ from typing import TYPE_CHECKING, Any, Callable
4
4
 
5
5
  from docutils import nodes
6
- from docutils.nodes import Element, Node
7
- from docutils.parsers.rst.states import RSTState
8
6
  from docutils.statemachine import StringList
9
7
  from docutils.utils import Reporter, assemble_option_dict
10
8
 
11
- from sphinx.config import Config
12
- from sphinx.environment import BuildEnvironment
13
9
  from sphinx.ext.autodoc import Documenter, Options
14
10
  from sphinx.util import logging
15
11
  from sphinx.util.docutils import SphinxDirective, switch_source_input
16
12
  from sphinx.util.nodes import nested_parse_with_titles
17
13
 
14
+ if TYPE_CHECKING:
15
+ from docutils.nodes import Element, Node
16
+ from docutils.parsers.rst.states import RSTState
17
+
18
+ from sphinx.config import Config
19
+ from sphinx.environment import BuildEnvironment
20
+
18
21
  logger = logging.getLogger(__name__)
19
22
 
20
23
 
@@ -111,7 +114,8 @@ class AutodocDirective(SphinxDirective):
111
114
  reporter = self.state.document.reporter
112
115
 
113
116
  try:
114
- source, lineno = reporter.get_source_and_line(self.lineno) # type: ignore
117
+ source, lineno = reporter.get_source_and_line( # type: ignore[attr-defined]
118
+ self.lineno)
115
119
  except AttributeError:
116
120
  source, lineno = (None, None)
117
121
  logger.debug('[autodoc] %s:%s: input:\n%s', source, lineno, self.block_text)
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import importlib
6
6
  import traceback
7
- import warnings
7
+ import typing
8
8
  from typing import TYPE_CHECKING, Any, Callable, NamedTuple
9
9
 
10
10
  from sphinx.ext.autodoc.mock import ismock, undecorate
@@ -60,10 +60,8 @@ def import_module(modname: str, warningiserror: bool = False) -> Any:
60
60
  Call importlib.import_module(modname), convert exceptions to ImportError
61
61
  """
62
62
  try:
63
- with warnings.catch_warnings():
64
- warnings.filterwarnings("ignore", category=ImportWarning)
65
- with logging.skip_warningiserror(not warningiserror):
66
- return importlib.import_module(modname)
63
+ with logging.skip_warningiserror(not warningiserror):
64
+ return importlib.import_module(modname)
67
65
  except BaseException as exc:
68
66
  # Importing modules may cause any side effects, including
69
67
  # SystemExit, so we need to catch all errors.
@@ -84,7 +82,18 @@ def import_object(modname: str, objpath: list[str], objtype: str = '',
84
82
  objpath = list(objpath)
85
83
  while module is None:
86
84
  try:
87
- module = import_module(modname, warningiserror=warningiserror)
85
+ try:
86
+ # try importing with ``typing.TYPE_CHECKING == True``
87
+ typing.TYPE_CHECKING = True
88
+ module = import_module(modname, warningiserror=warningiserror)
89
+ except ImportError:
90
+ # if that fails (e.g. circular import), retry with
91
+ # ``typing.TYPE_CHECKING == False``
92
+ typing.TYPE_CHECKING = False
93
+ module = import_module(modname, warningiserror=warningiserror)
94
+ finally:
95
+ # ensure ``typing.TYPE_CHECKING == False``
96
+ typing.TYPE_CHECKING = False
88
97
  logger.debug('[autodoc] import %s => %r', modname, module)
89
98
  except ImportError as exc:
90
99
  logger.debug('[autodoc] import %s => failed', modname)
@@ -177,11 +186,11 @@ def get_object_members(
177
186
 
178
187
  # members in __slots__
179
188
  try:
180
- __slots__ = getslots(subject)
181
- if __slots__:
189
+ subject___slots__ = getslots(subject)
190
+ if subject___slots__:
182
191
  from sphinx.ext.autodoc import SLOTSATTR
183
192
 
184
- for name in __slots__:
193
+ for name in subject___slots__:
185
194
  members[name] = Attribute(name, True, SLOTSATTR)
186
195
  except (TypeError, ValueError):
187
196
  pass
@@ -214,7 +223,7 @@ def get_object_members(
214
223
  return members
215
224
 
216
225
 
217
- def get_class_members(subject: Any, objpath: list[str], attrgetter: Callable,
226
+ def get_class_members(subject: Any, objpath: Any, attrgetter: Callable,
218
227
  inherit_docstrings: bool = True) -> dict[str, ObjectMember]:
219
228
  """Get members and attributes of target class."""
220
229
  from sphinx.ext.autodoc import INSTANCEATTR, ObjectMember
@@ -238,11 +247,11 @@ def get_class_members(subject: Any, objpath: list[str], attrgetter: Callable,
238
247
 
239
248
  # members in __slots__
240
249
  try:
241
- __slots__ = getslots(subject)
242
- if __slots__:
250
+ subject___slots__ = getslots(subject)
251
+ if subject___slots__:
243
252
  from sphinx.ext.autodoc import SLOTSATTR
244
253
 
245
- for name, docstring in __slots__.items():
254
+ for name, docstring in subject___slots__.items():
246
255
  members[name] = ObjectMember(name, SLOTSATTR, class_=subject,
247
256
  docstring=docstring)
248
257
  except (TypeError, ValueError):
@@ -8,11 +8,14 @@ import sys
8
8
  from importlib.abc import Loader, MetaPathFinder
9
9
  from importlib.machinery import ModuleSpec
10
10
  from types import MethodType, ModuleType
11
- from typing import Any, Generator, Iterator, Sequence
11
+ from typing import TYPE_CHECKING, Any
12
12
 
13
13
  from sphinx.util import logging
14
14
  from sphinx.util.inspect import isboundmethod, safe_getattr
15
15
 
16
+ if TYPE_CHECKING:
17
+ from collections.abc import Generator, Iterator, Sequence
18
+
16
19
  logger = logging.getLogger(__name__)
17
20
 
18
21
 
@@ -8,15 +8,23 @@ from __future__ import annotations
8
8
 
9
9
  import ast
10
10
  import inspect
11
- from typing import Any
11
+ import types
12
+ import warnings
13
+ from typing import TYPE_CHECKING
12
14
 
13
15
  import sphinx
14
- from sphinx.application import Sphinx
16
+ from sphinx.deprecation import RemovedInSphinx90Warning
15
17
  from sphinx.locale import __
16
18
  from sphinx.pycode.ast import unparse as ast_unparse
17
19
  from sphinx.util import logging
18
20
 
21
+ if TYPE_CHECKING:
22
+ from typing import Any
23
+
24
+ from sphinx.application import Sphinx
25
+
19
26
  logger = logging.getLogger(__name__)
27
+ _LAMBDA_NAME = (lambda: None).__name__
20
28
 
21
29
 
22
30
  class DefaultValue:
@@ -29,23 +37,77 @@ class DefaultValue:
29
37
 
30
38
  def get_function_def(obj: Any) -> ast.FunctionDef | None:
31
39
  """Get FunctionDef object from living object.
40
+
32
41
  This tries to parse original code for living object and returns
33
42
  AST node for given *obj*.
34
43
  """
44
+ warnings.warn('sphinx.ext.autodoc.preserve_defaults.get_function_def is'
45
+ ' deprecated and scheduled for removal in Sphinx 9.'
46
+ ' Use sphinx.ext.autodoc.preserve_defaults._get_arguments() to'
47
+ ' extract AST arguments objects from a lambda or regular'
48
+ ' function.', RemovedInSphinx90Warning, stacklevel=2)
49
+
35
50
  try:
36
51
  source = inspect.getsource(obj)
37
- if source.startswith((' ', r'\t')):
52
+ if source.startswith((' ', '\t')):
38
53
  # subject is placed inside class or block. To read its docstring,
39
54
  # this adds if-block before the declaration.
40
55
  module = ast.parse('if True:\n' + source)
41
- return module.body[0].body[0] # type: ignore
56
+ return module.body[0].body[0] # type: ignore[attr-defined]
42
57
  else:
43
58
  module = ast.parse(source)
44
- return module.body[0] # type: ignore
59
+ return module.body[0] # type: ignore[return-value]
45
60
  except (OSError, TypeError): # failed to load source code
46
61
  return None
47
62
 
48
63
 
64
+ def _get_arguments(obj: Any, /) -> ast.arguments | None:
65
+ """Parse 'ast.arguments' from an object.
66
+
67
+ This tries to parse the original code for an object and returns
68
+ an 'ast.arguments' node.
69
+ """
70
+ try:
71
+ source = inspect.getsource(obj)
72
+ if source.startswith((' ', '\t')):
73
+ # 'obj' is in some indented block.
74
+ module = ast.parse('if True:\n' + source)
75
+ subject = module.body[0].body[0] # type: ignore[attr-defined]
76
+ else:
77
+ module = ast.parse(source)
78
+ subject = module.body[0]
79
+ except (OSError, TypeError):
80
+ # bail; failed to load source for 'obj'.
81
+ return None
82
+ except SyntaxError:
83
+ if _is_lambda(obj):
84
+ # Most likely a multi-line arising from detecting a lambda, e.g.:
85
+ #
86
+ # class Egg:
87
+ # x = property(
88
+ # lambda self: 1, doc="...")
89
+ return None
90
+
91
+ # Other syntax errors that are not due to the fact that we are
92
+ # documenting a lambda function are propagated
93
+ # (in particular if a lambda is renamed by the user).
94
+ raise
95
+
96
+ return _get_arguments_inner(subject)
97
+
98
+
99
+ def _is_lambda(x, /):
100
+ return isinstance(x, types.LambdaType) and x.__name__ == _LAMBDA_NAME
101
+
102
+
103
+ def _get_arguments_inner(x: Any, /) -> ast.arguments | None:
104
+ if isinstance(x, (ast.AsyncFunctionDef, ast.FunctionDef, ast.Lambda)):
105
+ return x.args
106
+ if isinstance(x, (ast.Assign, ast.AnnAssign)):
107
+ return _get_arguments_inner(x.value)
108
+ return None
109
+
110
+
49
111
  def get_default_value(lines: list[str], position: ast.AST) -> str | None:
50
112
  try:
51
113
  if position.lineno == position.end_lineno:
@@ -65,18 +127,24 @@ def update_defvalue(app: Sphinx, obj: Any, bound_method: bool) -> None:
65
127
 
66
128
  try:
67
129
  lines = inspect.getsource(obj).splitlines()
68
- if lines[0].startswith((' ', r'\t')):
69
- lines.insert(0, '') # insert a dummy line to follow what get_function_def() does.
130
+ if lines[0].startswith((' ', '\t')):
131
+ # insert a dummy line to follow what _get_arguments() does.
132
+ lines.insert(0, '')
70
133
  except (OSError, TypeError):
71
134
  lines = []
72
135
 
73
136
  try:
74
- function = get_function_def(obj)
75
- assert function is not None # for mypy
76
- if function.args.defaults or function.args.kw_defaults:
137
+ args = _get_arguments(obj)
138
+ if args is None:
139
+ # If the object is a built-in, we won't be always able to recover
140
+ # the function definition and its arguments. This happens if *obj*
141
+ # is the `__init__` method generated automatically for dataclasses.
142
+ return
143
+
144
+ if args.defaults or args.kw_defaults:
77
145
  sig = inspect.signature(obj)
78
- defaults = list(function.args.defaults)
79
- kw_defaults = list(function.args.kw_defaults)
146
+ defaults = list(args.defaults)
147
+ kw_defaults = list(args.kw_defaults)
80
148
  parameters = list(sig.parameters.values())
81
149
  for i, param in enumerate(parameters):
82
150
  if param.default is param.empty:
@@ -4,26 +4,29 @@ from __future__ import annotations
4
4
 
5
5
  import ast
6
6
  from inspect import Parameter, Signature, getsource
7
- from typing import Any, cast
7
+ from typing import TYPE_CHECKING, Any, cast
8
8
 
9
9
  import sphinx
10
- from sphinx.application import Sphinx
11
10
  from sphinx.locale import __
12
11
  from sphinx.pycode.ast import unparse as ast_unparse
13
12
  from sphinx.util import inspect, logging
14
13
 
14
+ if TYPE_CHECKING:
15
+ from collections.abc import Sequence
16
+
17
+ from sphinx.application import Sphinx
18
+
15
19
  logger = logging.getLogger(__name__)
16
20
 
17
21
 
18
- def not_suppressed(argtypes: list[ast.AST] = []) -> bool:
22
+ def not_suppressed(argtypes: Sequence[ast.expr] = ()) -> bool:
19
23
  """Check given *argtypes* is suppressed type_comment or not."""
20
24
  if len(argtypes) == 0: # no argtypees
21
25
  return False
22
- if len(argtypes) == 1 and ast_unparse(argtypes[0]) == "...": # suppressed
23
- # Note: To support multiple versions of python, this uses ``ast_unparse()`` for
24
- # comparison with Ellipsis. Since 3.8, ast.Constant has been used to represent
25
- # Ellipsis node instead of ast.Ellipsis.
26
- return False
26
+ if len(argtypes) == 1:
27
+ arg = argtypes[0]
28
+ if isinstance(arg, ast.Constant) and arg.value is ...: # suppressed
29
+ return False
27
30
  # not suppressed
28
31
  return True
29
32
 
@@ -64,9 +67,10 @@ def signature_from_ast(node: ast.FunctionDef, bound_method: bool,
64
67
  params.pop(0)
65
68
 
66
69
  # merge type_comment into signature
67
- if not_suppressed(type_comment.argtypes): # type: ignore
70
+ if not_suppressed(type_comment.argtypes): # type: ignore[attr-defined]
68
71
  for i, param in enumerate(params):
69
- params[i] = param.replace(annotation=type_comment.argtypes[i]) # type: ignore
72
+ params[i] = param.replace(
73
+ annotation=type_comment.argtypes[i]) # type: ignore[attr-defined]
70
74
 
71
75
  if node.returns:
72
76
  return Signature(params, return_annotation=node.returns)
@@ -3,17 +3,21 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import re
6
- from typing import Any, Iterable, cast
6
+ from collections.abc import Iterable
7
+ from typing import TYPE_CHECKING, Any, cast
7
8
 
8
9
  from docutils import nodes
9
- from docutils.nodes import Element
10
10
 
11
11
  import sphinx
12
12
  from sphinx import addnodes
13
- from sphinx.application import Sphinx
14
13
  from sphinx.util import inspect
15
14
  from sphinx.util.typing import stringify_annotation
16
15
 
16
+ if TYPE_CHECKING:
17
+ from docutils.nodes import Element
18
+
19
+ from sphinx.application import Sphinx
20
+
17
21
 
18
22
  def record_typehints(app: Sphinx, objtype: str, name: str, obj: Any,
19
23
  options: dict, args: str, retann: str) -> None:
@@ -2,18 +2,21 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Any, cast
5
+ from typing import TYPE_CHECKING, Any, cast
6
6
 
7
7
  from docutils import nodes
8
- from docutils.nodes import Node
9
8
 
10
9
  import sphinx
11
- from sphinx.application import Sphinx
12
10
  from sphinx.domains.std import StandardDomain
13
11
  from sphinx.locale import __
14
12
  from sphinx.util import logging
15
13
  from sphinx.util.nodes import clean_astext
16
14
 
15
+ if TYPE_CHECKING:
16
+ from docutils.nodes import Node
17
+
18
+ from sphinx.application import Sphinx
19
+
17
20
  logger = logging.getLogger(__name__)
18
21
 
19
22
 
@@ -56,24 +56,21 @@ import sys
56
56
  from inspect import Parameter
57
57
  from os import path
58
58
  from types import ModuleType
59
- from typing import Any, List, Sequence, cast
59
+ from typing import TYPE_CHECKING, Any, cast
60
60
 
61
61
  from docutils import nodes
62
- from docutils.nodes import Node, system_message
63
62
  from docutils.parsers.rst import directives
64
63
  from docutils.parsers.rst.states import RSTStateMachine, Struct, state_classes
65
64
  from docutils.statemachine import StringList
66
65
 
67
66
  import sphinx
68
67
  from sphinx import addnodes
69
- from sphinx.application import Sphinx
70
68
  from sphinx.config import Config
71
69
  from sphinx.environment import BuildEnvironment
72
70
  from sphinx.ext.autodoc import INSTANCEATTR, Documenter
73
71
  from sphinx.ext.autodoc.directive import DocumenterBridge, Options
74
72
  from sphinx.ext.autodoc.importer import import_module
75
73
  from sphinx.ext.autodoc.mock import mock
76
- from sphinx.extension import Extension
77
74
  from sphinx.locale import __
78
75
  from sphinx.project import Project
79
76
  from sphinx.pycode import ModuleAnalyzer, PycodeError
@@ -88,8 +85,16 @@ from sphinx.util.docutils import (
88
85
  )
89
86
  from sphinx.util.inspect import getmro, signature_from_str
90
87
  from sphinx.util.matching import Matcher
91
- from sphinx.util.typing import OptionSpec
92
- from sphinx.writers.html import HTML5Translator
88
+
89
+ if TYPE_CHECKING:
90
+ from collections.abc import Sequence
91
+
92
+ from docutils.nodes import Node, system_message
93
+
94
+ from sphinx.application import Sphinx
95
+ from sphinx.extension import Extension
96
+ from sphinx.util.typing import OptionSpec
97
+ from sphinx.writers.html import HTML5Translator
93
98
 
94
99
  logger = logging.getLogger(__name__)
95
100
 
@@ -97,7 +102,7 @@ logger = logging.getLogger(__name__)
97
102
  periods_re = re.compile(r'\.(?:\s+)')
98
103
  literal_re = re.compile(r'::\s*$')
99
104
 
100
- WELL_KNOWN_ABBREVIATIONS = ('et al.', ' i.e.',)
105
+ WELL_KNOWN_ABBREVIATIONS = ('et al.', 'e.g.', 'i.e.')
101
106
 
102
107
 
103
108
  # -- autosummary_toc node ------------------------------------------------------
@@ -127,7 +132,7 @@ def autosummary_table_visit_html(self: HTML5Translator, node: autosummary_table)
127
132
  table = cast(nodes.table, node[0])
128
133
  tgroup = cast(nodes.tgroup, table[0])
129
134
  tbody = cast(nodes.tbody, tgroup[-1])
130
- rows = cast(List[nodes.row], tbody)
135
+ rows = cast(list[nodes.row], tbody)
131
136
  for row in rows:
132
137
  col1_entry = cast(nodes.entry, row[0])
133
138
  par = cast(nodes.paragraph, col1_entry[0])
@@ -148,7 +153,7 @@ class FakeApplication:
148
153
  self.extensions: dict[str, Extension] = {}
149
154
  self.srcdir = None
150
155
  self.config = Config()
151
- self.project = Project(None, None)
156
+ self.project = Project('', {})
152
157
  self.registry = SphinxComponentRegistry()
153
158
 
154
159
 
@@ -158,7 +163,7 @@ class FakeDirective(DocumenterBridge):
158
163
  document = Struct(settings=settings)
159
164
  app = FakeApplication()
160
165
  app.config.add('autodoc_class_signature', 'mixed', True, None)
161
- env = BuildEnvironment(app) # type: ignore
166
+ env = BuildEnvironment(app) # type: ignore[arg-type]
162
167
  state = Struct(document=document)
163
168
  super().__init__(env, None, Options(), 0, state)
164
169
 
@@ -283,7 +288,7 @@ class Autosummary(SphinxDirective):
283
288
  else:
284
289
  errors = exc.exceptions + [exc2]
285
290
 
286
- raise ImportExceptionGroup(exc.args[0], errors)
291
+ raise ImportExceptionGroup(exc.args[0], errors) from None
287
292
 
288
293
  def create_documenter(self, app: Sphinx, obj: Any,
289
294
  parent: Any, full_name: str) -> Documenter:
@@ -625,7 +630,7 @@ def get_import_prefixes_from_env(env: BuildEnvironment) -> list[str | None]:
625
630
 
626
631
 
627
632
  def import_by_name(
628
- name: str, prefixes: list[str | None] = [None],
633
+ name: str, prefixes: Sequence[str | None] = (None,),
629
634
  ) -> tuple[str, Any, Any, str]:
630
635
  """Import a Python object that has the given *name*, under one of the
631
636
  *prefixes*. The first name that succeeds is used.
@@ -668,7 +673,7 @@ def _import_by_name(name: str, grouped_exception: bool = True) -> tuple[Any, Any
668
673
 
669
674
  # ... then as MODNAME, MODNAME.OBJ1, MODNAME.OBJ1.OBJ2, ...
670
675
  last_j = 0
671
- modname = None
676
+ modname = ''
672
677
  for j in reversed(range(1, len(name_parts) + 1)):
673
678
  last_j = j
674
679
  modname = '.'.join(name_parts[:j])
@@ -692,12 +697,12 @@ def _import_by_name(name: str, grouped_exception: bool = True) -> tuple[Any, Any
692
697
  except (ValueError, ImportError, AttributeError, KeyError) as exc:
693
698
  errors.append(exc)
694
699
  if grouped_exception:
695
- raise ImportExceptionGroup('', errors)
700
+ raise ImportExceptionGroup('', errors) from None # NoQA: EM101
696
701
  else:
697
702
  raise ImportError(*exc.args) from exc
698
703
 
699
704
 
700
- def import_ivar_by_name(name: str, prefixes: list[str | None] = [None],
705
+ def import_ivar_by_name(name: str, prefixes: Sequence[str | None] = (None,),
701
706
  grouped_exception: bool = True) -> tuple[str, Any, Any, str]:
702
707
  """Import an instance variable that has the given *name*, under one of the
703
708
  *prefixes*. The first name that succeeds is used.
@@ -739,6 +744,7 @@ class AutoLink(SphinxRole):
739
744
  """
740
745
  def run(self) -> tuple[list[Node], list[system_message]]:
741
746
  pyobj_role = self.env.get_domain('py').role('obj')
747
+ assert pyobj_role is not None
742
748
  objects, errors = pyobj_role('obj', self.rawtext, self.text, self.lineno,
743
749
  self.inliner, self.options, self.content)
744
750
  if errors: