Sphinx 7.1.2__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 +18 -11
  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.2.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.2.dist-info/RECORD +0 -564
  311. {sphinx-7.1.2.dist-info → sphinx-7.2.0.dist-info}/LICENSE +0 -0
  312. {sphinx-7.1.2.dist-info → sphinx-7.2.0.dist-info}/WHEEL +0 -0
  313. {sphinx-7.1.2.dist-info → sphinx-7.2.0.dist-info}/entry_points.txt +0 -0
sphinx/util/typing.py CHANGED
@@ -4,22 +4,26 @@ from __future__ import annotations
4
4
 
5
5
  import sys
6
6
  import typing
7
+ from collections.abc import Sequence
7
8
  from struct import Struct
8
9
  from types import TracebackType
9
- from typing import Any, Callable, Dict, ForwardRef, List, Tuple, TypeVar, Union
10
+ from typing import TYPE_CHECKING, Any, Callable, ForwardRef, TypeVar, Union
10
11
 
11
12
  from docutils import nodes
12
13
  from docutils.parsers.rst.states import Inliner
13
14
 
15
+ if TYPE_CHECKING:
16
+ import enum
17
+
14
18
  try:
15
- from types import UnionType # type: ignore # python 3.10 or above
19
+ from types import UnionType # type: ignore[attr-defined] # python 3.10 or above
16
20
  except ImportError:
17
21
  UnionType = None
18
22
 
19
- # builtin classes that have incorrect __module__
23
+ # classes that have incorrect __module__
20
24
  INVALID_BUILTIN_CLASSES = {
21
- Struct: 'struct.Struct', # Before Python 3.9
22
- TracebackType: 'types.TracebackType',
25
+ Struct: 'struct.Struct', # Struct.__module__ == '_struct'
26
+ TracebackType: 'types.TracebackType', # TracebackType.__module__ == 'builtins'
23
27
  }
24
28
 
25
29
 
@@ -41,23 +45,23 @@ NoneType = type(None)
41
45
  PathMatcher = Callable[[str], bool]
42
46
 
43
47
  # common role functions
44
- RoleFunction = Callable[[str, str, str, int, Inliner, Dict[str, Any], List[str]],
45
- Tuple[List[nodes.Node], List[nodes.system_message]]]
48
+ RoleFunction = Callable[[str, str, str, int, Inliner, dict[str, Any], Sequence[str]],
49
+ tuple[list[nodes.Node], list[nodes.system_message]]]
46
50
 
47
51
  # A option spec for directive
48
- OptionSpec = Dict[str, Callable[[str], Any]]
52
+ OptionSpec = dict[str, Callable[[str], Any]]
49
53
 
50
54
  # title getter functions for enumerable nodes (see sphinx.domains.std)
51
55
  TitleGetter = Callable[[nodes.Node], str]
52
56
 
53
57
  # inventory data on memory
54
- InventoryItem = Tuple[
58
+ InventoryItem = tuple[
55
59
  str, # project name
56
60
  str, # project version
57
61
  str, # URL
58
62
  str, # display name
59
63
  ]
60
- Inventory = Dict[str, Dict[str, InventoryItem]]
64
+ Inventory = dict[str, dict[str, InventoryItem]]
61
65
 
62
66
 
63
67
  def get_type_hints(
@@ -80,8 +84,7 @@ def get_type_hints(
80
84
  # Failed to evaluate ForwardRef (maybe not runtime checkable)
81
85
  return safe_getattr(obj, '__annotations__', {})
82
86
  except TypeError:
83
- # Invalid object is given. But try to get __annotations__ as a fallback for
84
- # the code using type union operator (PEP 604) in python 3.9 or below.
87
+ # Invalid object is given. But try to get __annotations__ as a fallback.
85
88
  return safe_getattr(obj, '__annotations__', {})
86
89
  except KeyError:
87
90
  # a broken class found (refs: https://github.com/sphinx-doc/sphinx/issues/8084)
@@ -140,6 +143,9 @@ def restify(cls: type | None, mode: str = 'fully-qualified-except-typing') -> st
140
143
  return ' | '.join(restify(a, mode) for a in cls.__args__)
141
144
  elif cls.__module__ in ('__builtin__', 'builtins'):
142
145
  if hasattr(cls, '__args__'):
146
+ if not cls.__args__: # Empty tuple, list, ...
147
+ return fr':py:class:`{cls.__name__}`\ [{cls.__args__!r}]'
148
+
143
149
  concatenated_args = ', '.join(restify(arg, mode) for arg in cls.__args__)
144
150
  return fr':py:class:`{cls.__name__}`\ [{concatenated_args}]'
145
151
  else:
@@ -162,7 +168,7 @@ def restify(cls: type | None, mode: str = 'fully-qualified-except-typing') -> st
162
168
  return ':py:obj:`~typing.Union`\\ [%s]' % args
163
169
  elif inspect.isgenericalias(cls):
164
170
  if isinstance(cls.__origin__, typing._SpecialForm): # type: ignore[attr-defined]
165
- text = restify(cls.__origin__, mode) # type: ignore
171
+ text = restify(cls.__origin__, mode) # type: ignore[attr-defined,arg-type]
166
172
  elif getattr(cls, '_name', None):
167
173
  cls_name = cls._name # type: ignore[attr-defined]
168
174
  if cls.__module__ == 'typing':
@@ -183,7 +189,14 @@ def restify(cls: type | None, mode: str = 'fully-qualified-except-typing') -> st
183
189
  args = ', '.join(restify(a, mode) for a in cls.__args__[:-1])
184
190
  text += fr"\ [[{args}], {restify(cls.__args__[-1], mode)}]"
185
191
  elif cls.__module__ == 'typing' and getattr(origin, '_name', None) == 'Literal':
186
- text += r"\ [%s]" % ', '.join(repr(a) for a in cls.__args__)
192
+ literal_args = []
193
+ for a in cls.__args__:
194
+ if inspect.isenumattribute(a):
195
+ literal_args.append(_format_literal_enum_arg(a, mode=mode))
196
+ else:
197
+ literal_args.append(repr(a))
198
+ text += r"\ [%s]" % ', '.join(literal_args)
199
+ del literal_args
187
200
  elif cls.__args__:
188
201
  text += r"\ [%s]" % ", ".join(restify(a, mode) for a in cls.__args__)
189
202
 
@@ -232,8 +245,9 @@ def stringify_annotation(
232
245
  from sphinx.util.inspect import isNewType # lazy loading
233
246
 
234
247
  if mode not in {'fully-qualified-except-typing', 'fully-qualified', 'smart'}:
235
- raise ValueError("'mode' must be one of 'fully-qualified-except-typing', "
236
- f"'fully-qualified', or 'smart'; got {mode!r}.")
248
+ msg = ("'mode' must be one of 'fully-qualified-except-typing', "
249
+ f"'fully-qualified', or 'smart'; got {mode!r}.")
250
+ raise ValueError(msg)
237
251
 
238
252
  if mode == 'smart':
239
253
  module_prefix = '~'
@@ -275,8 +289,12 @@ def stringify_annotation(
275
289
  elif str(annotation).startswith('typing.Annotated'): # for py310+
276
290
  pass
277
291
  elif annotation_module == 'builtins' and annotation_qualname:
278
- if hasattr(annotation, '__args__'): # PEP 585 generic
279
- return repr(annotation)
292
+ if (args := getattr(annotation, '__args__', None)) is not None: # PEP 585 generic
293
+ if not args: # Empty tuple, list, ...
294
+ return repr(annotation)
295
+
296
+ concatenated_args = ', '.join(stringify_annotation(arg, mode) for arg in args)
297
+ return f'{annotation_qualname}[{concatenated_args}]'
280
298
  else:
281
299
  return annotation_qualname
282
300
  elif annotation is Ellipsis:
@@ -330,7 +348,21 @@ def stringify_annotation(
330
348
  returns = stringify_annotation(annotation_args[-1], mode)
331
349
  return f'{module_prefix}Callable[[{args}], {returns}]'
332
350
  elif qualname == 'Literal':
333
- args = ', '.join(repr(a) for a in annotation_args)
351
+ from sphinx.util.inspect import isenumattribute # lazy loading
352
+
353
+ def format_literal_arg(arg):
354
+ if isenumattribute(arg):
355
+ enumcls = arg.__class__
356
+
357
+ if mode == 'smart':
358
+ # MyEnum.member
359
+ return f'{enumcls.__qualname__}.{arg.name}'
360
+
361
+ # module.MyEnum.member
362
+ return f'{enumcls.__module__}.{enumcls.__qualname__}.{arg.name}'
363
+ return repr(arg)
364
+
365
+ args = ', '.join(map(format_literal_arg, annotation_args))
334
366
  return f'{module_prefix}Literal[{args}]'
335
367
  elif str(annotation).startswith('typing.Annotated'): # for py39+
336
368
  return stringify_annotation(annotation_args[0], mode)
@@ -344,6 +376,14 @@ def stringify_annotation(
344
376
  return module_prefix + qualname
345
377
 
346
378
 
379
+ def _format_literal_enum_arg(arg: enum.Enum, /, *, mode: str) -> str:
380
+ enum_cls = arg.__class__
381
+ if mode == 'smart' or enum_cls.__module__ == 'typing':
382
+ return f':py:attr:`~{enum_cls.__module__}.{enum_cls.__qualname__}.{arg.name}`'
383
+ else:
384
+ return f':py:attr:`{enum_cls.__module__}.{enum_cls.__qualname__}.{arg.name}`'
385
+
386
+
347
387
  # deprecated name -> (object to return, canonical path or empty string)
348
388
  _DEPRECATED_OBJECTS = {
349
389
  'stringify': (stringify_annotation, 'sphinx.util.typing.stringify_annotation'),
@@ -352,7 +392,8 @@ _DEPRECATED_OBJECTS = {
352
392
 
353
393
  def __getattr__(name):
354
394
  if name not in _DEPRECATED_OBJECTS:
355
- raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
395
+ msg = f'module {__name__!r} has no attribute {name!r}'
396
+ raise AttributeError(msg)
356
397
 
357
398
  from sphinx.deprecation import _deprecation_warning
358
399
 
sphinx/versioning.py CHANGED
@@ -5,14 +5,16 @@ import pickle
5
5
  from itertools import product, zip_longest
6
6
  from operator import itemgetter
7
7
  from os import path
8
- from typing import TYPE_CHECKING, Any, Iterator
8
+ from typing import TYPE_CHECKING, Any
9
9
  from uuid import uuid4
10
10
 
11
- from docutils.nodes import Node
12
-
13
11
  from sphinx.transforms import SphinxTransform
14
12
 
15
13
  if TYPE_CHECKING:
14
+ from collections.abc import Iterator
15
+
16
+ from docutils.nodes import Node
17
+
16
18
  from sphinx.application import Sphinx
17
19
 
18
20
  try:
@@ -89,7 +91,7 @@ def merge_doctrees(old: Node, new: Node, condition: Any) -> Iterator[Node]:
89
91
  # choose the old node with the best ratio for each new node and set the uid
90
92
  # as long as the ratio is under a certain value, in which case we consider
91
93
  # them not changed but different
92
- ratios = sorted(ratios.items(), key=itemgetter(1)) # type: ignore
94
+ ratios = sorted(ratios.items(), key=itemgetter(1)) # type: ignore[assignment]
93
95
  for (old_node, new_node), ratio in ratios:
94
96
  if new_node in seen:
95
97
  continue
sphinx/writers/html.py CHANGED
@@ -39,6 +39,6 @@ class HTMLWriter(Writer):
39
39
  'body_pre_docinfo', 'docinfo', 'body', 'fragment',
40
40
  'body_suffix', 'meta', 'title', 'subtitle', 'header',
41
41
  'footer', 'html_prolog', 'html_head', 'html_title',
42
- 'html_subtitle', 'html_body', ):
42
+ 'html_subtitle', 'html_body'):
43
43
  setattr(self, attr, getattr(visitor, attr, None))
44
44
  self.clean_meta = ''.join(self.visitor.meta[2:])
sphinx/writers/html5.py CHANGED
@@ -6,20 +6,22 @@ import os
6
6
  import posixpath
7
7
  import re
8
8
  import urllib.parse
9
- from typing import TYPE_CHECKING, Iterable, cast
9
+ from collections.abc import Iterable
10
+ from typing import TYPE_CHECKING, cast
10
11
 
11
12
  from docutils import nodes
12
- from docutils.nodes import Element, Node, Text
13
13
  from docutils.writers.html5_polyglot import HTMLTranslator as BaseTranslator
14
14
 
15
15
  from sphinx import addnodes
16
- from sphinx.builders import Builder
17
16
  from sphinx.locale import _, __, admonitionlabels
18
17
  from sphinx.util import logging
19
18
  from sphinx.util.docutils import SphinxTranslator
20
19
  from sphinx.util.images import get_image_size
21
20
 
22
21
  if TYPE_CHECKING:
22
+ from docutils.nodes import Element, Node, Text
23
+
24
+ from sphinx.builders import Builder
23
25
  from sphinx.builders.html import StandaloneHTMLBuilder
24
26
 
25
27
 
@@ -95,7 +97,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
95
97
  def depart_desc_signature(self, node: Element) -> None:
96
98
  self.protect_literal_text -= 1
97
99
  if not node.get('is_multiline'):
98
- self.add_permalink_ref(node, _('Permalink to this definition'))
100
+ self.add_permalink_ref(node, _('Link to this definition'))
99
101
  self.body.append('</dt>\n')
100
102
 
101
103
  def visit_desc_signature_line(self, node: Element) -> None:
@@ -104,7 +106,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
104
106
  def depart_desc_signature_line(self, node: Element) -> None:
105
107
  if node.get('add_permalink'):
106
108
  # the permalink info is on the parent desc_signature node
107
- self.add_permalink_ref(node.parent, _('Permalink to this definition'))
109
+ self.add_permalink_ref(node.parent, _('Link to this definition'))
108
110
  self.body.append('<br />')
109
111
 
110
112
  def visit_desc_content(self, node: Element) -> None:
@@ -336,7 +338,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
336
338
  self.depart_reference(node)
337
339
 
338
340
  # overwritten -- we don't want source comments to show up in the HTML
339
- def visit_comment(self, node: Element) -> None: # type: ignore
341
+ def visit_comment(self, node: Element) -> None: # type: ignore[override]
340
342
  raise nodes.SkipNode
341
343
 
342
344
  # overwritten
@@ -408,10 +410,11 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
408
410
  append_fignumber(figtype, node['ids'][0])
409
411
 
410
412
  def add_permalink_ref(self, node: Element, title: str) -> None:
413
+ icon = self.config.html_permalinks_icon
411
414
  if node['ids'] and self.config.html_permalinks and self.builder.add_permalinks:
412
- format = '<a class="headerlink" href="#%s" title="%s">%s</a>'
413
- self.body.append(format % (node['ids'][0], title,
414
- self.config.html_permalinks_icon))
415
+ self.body.append(
416
+ f'<a class="headerlink" href="#{node["ids"][0]}" title="{title}">{icon}</a>',
417
+ )
415
418
 
416
419
  # overwritten
417
420
  def visit_bullet_list(self, node: Element) -> None:
@@ -456,7 +459,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
456
459
  else:
457
460
  if isinstance(node.parent.parent.parent, addnodes.glossary):
458
461
  # add permalink if glossary terms
459
- self.add_permalink_ref(node, _('Permalink to this term'))
462
+ self.add_permalink_ref(node, _('Link to this term'))
460
463
 
461
464
  self.body.append('</dt>')
462
465
 
@@ -479,16 +482,16 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
479
482
  node.parent.hasattr('ids') and node.parent['ids']):
480
483
  # add permalink anchor
481
484
  if close_tag.startswith('</h'):
482
- self.add_permalink_ref(node.parent, _('Permalink to this heading'))
485
+ self.add_permalink_ref(node.parent, _('Link to this heading'))
483
486
  elif close_tag.startswith('</a></h'):
484
487
  self.body.append('</a><a class="headerlink" href="#%s" ' %
485
488
  node.parent['ids'][0] +
486
489
  'title="{}">{}'.format(
487
- _('Permalink to this heading'),
490
+ _('Link to this heading'),
488
491
  self.config.html_permalinks_icon))
489
492
  elif isinstance(node.parent, nodes.table):
490
493
  self.body.append('</span>')
491
- self.add_permalink_ref(node.parent, _('Permalink to this table'))
494
+ self.add_permalink_ref(node.parent, _('Link to this table'))
492
495
  elif isinstance(node.parent, nodes.table):
493
496
  self.body.append('</span>')
494
497
 
@@ -531,11 +534,11 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
531
534
 
532
535
  # append permalink if available
533
536
  if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'):
534
- self.add_permalink_ref(node.parent, _('Permalink to this code'))
537
+ self.add_permalink_ref(node.parent, _('Link to this code'))
535
538
  elif isinstance(node.parent, nodes.figure):
536
- self.add_permalink_ref(node.parent, _('Permalink to this image'))
539
+ self.add_permalink_ref(node.parent, _('Link to this image'))
537
540
  elif node.parent.get('toctree'):
538
- self.add_permalink_ref(node.parent.parent, _('Permalink to this toctree'))
541
+ self.add_permalink_ref(node.parent.parent, _('Link to this toctree'))
539
542
 
540
543
  if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'):
541
544
  self.body.append('</div>\n')
@@ -669,7 +672,8 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
669
672
  # but it tries the final file name, which does not necessarily exist
670
673
  # yet at the time the HTML file is written.
671
674
  if not ('width' in node and 'height' in node):
672
- size = get_image_size(os.path.join(self.builder.srcdir, olduri))
675
+ path = os.path.join(self.builder.srcdir, olduri) # type: ignore[has-type]
676
+ size = get_image_size(path)
673
677
  if size is None:
674
678
  logger.warning(
675
679
  __('Could not obtain image size. :scale: option is ignored.'),
@@ -879,7 +883,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
879
883
  else:
880
884
  node['classes'].append('row-odd')
881
885
  self.body.append(self.starttag(node, 'tr', ''))
882
- node.column = 0 # type: ignore
886
+ node.column = 0 # type: ignore[attr-defined]
883
887
 
884
888
  def visit_field_list(self, node: Element) -> None:
885
889
  self._fieldlist_row_indices.append(0)
@@ -897,25 +901,29 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
897
901
  node['classes'].append('field-odd')
898
902
 
899
903
  def visit_math(self, node: Element, math_env: str = '') -> None:
900
- name = self.builder.math_renderer_name
904
+ # see validate_math_renderer
905
+ name: str = self.builder.math_renderer_name # type: ignore[assignment]
901
906
  visit, _ = self.builder.app.registry.html_inline_math_renderers[name]
902
907
  visit(self, node)
903
908
 
904
909
  def depart_math(self, node: Element, math_env: str = '') -> None:
905
- name = self.builder.math_renderer_name
910
+ # see validate_math_renderer
911
+ name: str = self.builder.math_renderer_name # type: ignore[assignment]
906
912
  _, depart = self.builder.app.registry.html_inline_math_renderers[name]
907
- if depart: # type: ignore[truthy-function]
913
+ if depart:
908
914
  depart(self, node)
909
915
 
910
916
  def visit_math_block(self, node: Element, math_env: str = '') -> None:
911
- name = self.builder.math_renderer_name
917
+ # see validate_math_renderer
918
+ name: str = self.builder.math_renderer_name # type: ignore[assignment]
912
919
  visit, _ = self.builder.app.registry.html_block_math_renderers[name]
913
920
  visit(self, node)
914
921
 
915
922
  def depart_math_block(self, node: Element, math_env: str = '') -> None:
916
- name = self.builder.math_renderer_name
923
+ # see validate_math_renderer
924
+ name: str = self.builder.math_renderer_name # type: ignore[assignment]
917
925
  _, depart = self.builder.app.registry.html_block_math_renderers[name]
918
- if depart: # type: ignore[truthy-function]
926
+ if depart:
919
927
  depart(self, node)
920
928
 
921
929
  # See Docutils r9413