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/cmd/make_mode.py CHANGED
@@ -13,10 +13,16 @@ import os
13
13
  import subprocess
14
14
  import sys
15
15
  from os import path
16
+ from typing import TYPE_CHECKING
16
17
 
17
18
  import sphinx
18
19
  from sphinx.cmd.build import build_main
19
- from sphinx.util.console import blue, bold, color_terminal, nocolor # type: ignore
20
+ from sphinx.util.console import ( # type: ignore[attr-defined]
21
+ blue,
22
+ bold,
23
+ color_terminal,
24
+ nocolor,
25
+ )
20
26
  from sphinx.util.osutil import rmtree
21
27
 
22
28
  try:
@@ -24,6 +30,9 @@ try:
24
30
  except ImportError:
25
31
  from sphinx.util.osutil import _chdir as chdir
26
32
 
33
+ if TYPE_CHECKING:
34
+ from collections.abc import Sequence
35
+
27
36
  BUILDERS = [
28
37
  ("", "html", "to make standalone HTML files"),
29
38
  ("", "dirhtml", "to make HTML files named index.html in directories"),
@@ -54,10 +63,10 @@ BUILDERS = [
54
63
 
55
64
 
56
65
  class Make:
57
- def __init__(self, srcdir: str, builddir: str, opts: list[str]) -> None:
66
+ def __init__(self, srcdir: str, builddir: str, opts: Sequence[str]) -> None:
58
67
  self.srcdir = srcdir
59
68
  self.builddir = builddir
60
- self.opts = opts
69
+ self.opts = [*opts]
61
70
  self.makecmd = os.environ.get('MAKE', 'make') # refer $MAKE to determine make command
62
71
 
63
72
  def builddir_join(self, *comps: str) -> str:
@@ -154,7 +163,7 @@ class Make:
154
163
  return build_main(args + opts)
155
164
 
156
165
 
157
- def run_make_mode(args: list[str]) -> int:
166
+ def run_make_mode(args: Sequence[str]) -> int:
158
167
  if len(args) < 3:
159
168
  print('Error: at least 3 arguments (builder, source '
160
169
  'dir, build dir) are required.', file=sys.stderr)
sphinx/cmd/quickstart.py CHANGED
@@ -31,10 +31,19 @@ from docutils.utils import column_width
31
31
  import sphinx.locale
32
32
  from sphinx import __display_version__, package_dir
33
33
  from sphinx.locale import __
34
- from sphinx.util.console import bold, color_terminal, colorize, nocolor, red # type: ignore
34
+ from sphinx.util.console import ( # type: ignore[attr-defined]
35
+ bold,
36
+ color_terminal,
37
+ colorize,
38
+ nocolor,
39
+ red,
40
+ )
35
41
  from sphinx.util.osutil import ensuredir
36
42
  from sphinx.util.template import SphinxRenderer
37
43
 
44
+ if TYPE_CHECKING:
45
+ from collections.abc import Sequence
46
+
38
47
  EXTENSIONS = {
39
48
  'autodoc': __('automatically insert docstrings from modules'),
40
49
  'doctest': __('automatically test code snippets in doctest blocks'),
@@ -539,7 +548,7 @@ def get_parser() -> argparse.ArgumentParser:
539
548
  return parser
540
549
 
541
550
 
542
- def main(argv: list[str] = sys.argv[1:]) -> int:
551
+ def main(argv: Sequence[str] = (), /) -> int:
543
552
  locale.setlocale(locale.LC_ALL, '')
544
553
  sphinx.locale.init_console()
545
554
 
@@ -549,7 +558,7 @@ def main(argv: list[str] = sys.argv[1:]) -> int:
549
558
  # parse options
550
559
  parser = get_parser()
551
560
  try:
552
- args = parser.parse_args(argv)
561
+ args = parser.parse_args(argv or sys.argv[1:])
553
562
  except SystemExit as err:
554
563
  return err.code # type: ignore[return-value]
555
564
 
@@ -605,4 +614,4 @@ def main(argv: list[str] = sys.argv[1:]) -> int:
605
614
 
606
615
 
607
616
  if __name__ == '__main__':
608
- raise SystemExit(main())
617
+ raise SystemExit(main(sys.argv[1:]))
sphinx/config.py CHANGED
@@ -6,13 +6,12 @@ import time
6
6
  import traceback
7
7
  import types
8
8
  from os import getenv, path
9
- from typing import TYPE_CHECKING, Any, Callable, Generator, Iterator, NamedTuple
9
+ from typing import TYPE_CHECKING, Any, Callable, NamedTuple
10
10
 
11
11
  from sphinx.errors import ConfigError, ExtensionError
12
12
  from sphinx.locale import _, __
13
13
  from sphinx.util import logging
14
14
  from sphinx.util.osutil import fs_encoding
15
- from sphinx.util.tags import Tags
16
15
  from sphinx.util.typing import NoneType
17
16
 
18
17
  try:
@@ -21,10 +20,12 @@ except ImportError:
21
20
  from sphinx.util.osutil import _chdir as chdir
22
21
 
23
22
  if TYPE_CHECKING:
24
- from collections.abc import Sequence
23
+ import os
24
+ from collections.abc import Generator, Iterator, Sequence
25
25
 
26
26
  from sphinx.application import Sphinx
27
27
  from sphinx.environment import BuildEnvironment
28
+ from sphinx.util.tags import Tags
28
29
 
29
30
  logger = logging.getLogger(__name__)
30
31
 
@@ -58,7 +59,7 @@ class ENUM:
58
59
  Example:
59
60
  app.add_config_value('latex_show_urls', 'no', None, ENUM('no', 'footnote', 'inline'))
60
61
  """
61
- def __init__(self, *candidates: str | bool) -> None:
62
+ def __init__(self, *candidates: str | bool | None) -> None:
62
63
  self.candidates = candidates
63
64
 
64
65
  def match(self, value: str | list | tuple) -> bool:
@@ -154,8 +155,10 @@ class Config:
154
155
  'option_emphasise_placeholders': (False, 'env', []),
155
156
  }
156
157
 
157
- def __init__(self, config: dict[str, Any] = {}, overrides: dict[str, Any] = {}) -> None:
158
- self.overrides = dict(overrides)
158
+ def __init__(self, config: dict[str, Any] | None = None,
159
+ overrides: dict[str, Any] | None = None) -> None:
160
+ config = config or {}
161
+ self.overrides = dict(overrides) if overrides is not None else {}
159
162
  self.values = Config.config_values.copy()
160
163
  self._raw_config = config
161
164
  self.setup: Callable | None = config.get('setup', None)
@@ -168,9 +171,8 @@ class Config:
168
171
  self.extensions: list[str] = config.get('extensions', [])
169
172
 
170
173
  @classmethod
171
- def read(
172
- cls, confdir: str, overrides: dict | None = None, tags: Tags | None = None,
173
- ) -> Config:
174
+ def read(cls, confdir: str | os.PathLike[str], overrides: dict | None = None,
175
+ tags: Tags | None = None) -> Config:
174
176
  """Create a Config object from configuration file."""
175
177
  filename = path.join(confdir, CONFIG_FILENAME)
176
178
  if not path.isfile(filename):
@@ -310,7 +312,7 @@ class Config:
310
312
  raise ExtensionError(__('Config value %r already present') % name)
311
313
  self.values[name] = (default, rebuild, types)
312
314
 
313
- def filter(self, rebuild: str | list[str]) -> Iterator[ConfigValue]:
315
+ def filter(self, rebuild: str | Sequence[str]) -> Iterator[ConfigValue]:
314
316
  if isinstance(rebuild, str):
315
317
  rebuild = [rebuild]
316
318
  return (value for value in self if value.rebuild in rebuild)
@@ -402,7 +404,8 @@ def convert_highlight_options(app: Sphinx, config: Config) -> None:
402
404
  options = config.highlight_options
403
405
  if options and not all(isinstance(v, dict) for v in options.values()):
404
406
  # old styled option detected because all values are not dictionary.
405
- config.highlight_options = {config.highlight_language: options} # type: ignore
407
+ config.highlight_options = {config.highlight_language: # type: ignore[attr-defined]
408
+ options}
406
409
 
407
410
 
408
411
  def init_numfig_format(app: Sphinx, config: Config) -> None:
@@ -414,7 +417,7 @@ def init_numfig_format(app: Sphinx, config: Config) -> None:
414
417
 
415
418
  # override default labels by configuration
416
419
  numfig_format.update(config.numfig_format)
417
- config.numfig_format = numfig_format # type: ignore
420
+ config.numfig_format = numfig_format # type: ignore[attr-defined]
418
421
 
419
422
 
420
423
  def correct_copyright_year(_app: Sphinx, config: Config) -> None:
@@ -523,7 +526,7 @@ def check_primary_domain(app: Sphinx, config: Config) -> None:
523
526
  primary_domain = config.primary_domain
524
527
  if primary_domain and not app.registry.has_domain(primary_domain):
525
528
  logger.warning(__('primary_domain %r not found, ignored.'), primary_domain)
526
- config.primary_domain = None # type: ignore
529
+ config.primary_domain = None # type: ignore[attr-defined]
527
530
 
528
531
 
529
532
  def check_root_doc(app: Sphinx, env: BuildEnvironment, added: set[str],
@@ -536,7 +539,7 @@ def check_root_doc(app: Sphinx, env: BuildEnvironment, added: set[str],
536
539
  'contents' in app.project.docnames):
537
540
  logger.warning(__('Since v2.0, Sphinx uses "index" as root_doc by default. '
538
541
  'Please add "root_doc = \'contents\'" to your conf.py.'))
539
- app.config.root_doc = "contents" # type: ignore
542
+ app.config.root_doc = "contents" # type: ignore[attr-defined]
540
543
 
541
544
  return changed
542
545
 
sphinx/deprecation.py CHANGED
@@ -37,7 +37,8 @@ def _deprecation_warning(
37
37
 
38
38
  def __getattr__(name):
39
39
  if name not in _DEPRECATED_OBJECTS:
40
- raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
40
+ msg = f'module {__name__!r} has no attribute {name!r}'
41
+ raise AttributeError(msg)
41
42
 
42
43
  from sphinx.deprecation import _deprecation_warning
43
44
 
@@ -51,7 +52,8 @@ def _deprecation_warning(
51
52
  elif remove == (9, 0):
52
53
  warning_class = RemovedInSphinx90Warning
53
54
  else:
54
- raise RuntimeError(f'removal version {remove!r} is invalid!')
55
+ msg = f'removal version {remove!r} is invalid!'
56
+ raise RuntimeError(msg)
55
57
 
56
58
  qualified_name = f'{module}.{attribute}'
57
59
  if canonical_name:
@@ -3,21 +3,22 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import re
6
- from typing import TYPE_CHECKING, Any, Generic, List, TypeVar, cast
6
+ from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast
7
7
 
8
8
  from docutils import nodes
9
- from docutils.nodes import Node
10
9
  from docutils.parsers.rst import directives, roles
11
10
 
12
11
  from sphinx import addnodes
13
- from sphinx.addnodes import desc_signature
12
+ from sphinx.addnodes import desc_signature # NoQA: TCH001
14
13
  from sphinx.util import docutils
15
14
  from sphinx.util.docfields import DocFieldTransformer, Field, TypedField
16
15
  from sphinx.util.docutils import SphinxDirective
17
16
  from sphinx.util.nodes import nested_parse_with_titles
18
- from sphinx.util.typing import OptionSpec
17
+ from sphinx.util.typing import OptionSpec # NoQA: TCH001
19
18
 
20
19
  if TYPE_CHECKING:
20
+ from docutils.nodes import Node
21
+
21
22
  from sphinx.application import Sphinx
22
23
 
23
24
 
@@ -35,7 +36,8 @@ def optional_int(argument: str) -> int | None:
35
36
  else:
36
37
  value = int(argument)
37
38
  if value < 0:
38
- raise ValueError('negative value; must be positive or zero')
39
+ msg = 'negative value; must be positive or zero'
40
+ raise ValueError(msg)
39
41
  return value
40
42
 
41
43
 
@@ -54,6 +56,10 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
54
56
  optional_arguments = 0
55
57
  final_argument_whitespace = True
56
58
  option_spec: OptionSpec = {
59
+ 'no-index': directives.flag,
60
+ 'no-index-entry': directives.flag,
61
+ 'no-contents-entry': directives.flag,
62
+ 'no-typesetting': directives.flag,
57
63
  'noindex': directives.flag,
58
64
  'noindexentry': directives.flag,
59
65
  'nocontentsentry': directives.flag,
@@ -185,7 +191,7 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
185
191
 
186
192
  * find out if called as a domain-specific directive, set self.domain
187
193
  * create a `desc` node to fit all description inside
188
- * parse standard options, currently `noindex`
194
+ * parse standard options, currently `no-index`
189
195
  * create an index node if needed as self.indexnode
190
196
  * parse all given signatures (as returned by self.get_signatures())
191
197
  using self.handle_signature(), which should either return a name
@@ -215,9 +221,22 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
215
221
  node['domain'] = self.domain
216
222
  # 'desctype' is a backwards compatible attribute
217
223
  node['objtype'] = node['desctype'] = self.objtype
218
- node['noindex'] = noindex = ('noindex' in self.options)
219
- node['noindexentry'] = ('noindexentry' in self.options)
220
- node['nocontentsentry'] = ('nocontentsentry' in self.options)
224
+ node['no-index'] = node['noindex'] = no_index = (
225
+ 'no-index' in self.options
226
+ # xref RemovedInSphinx90Warning
227
+ # deprecate noindex in Sphinx 9.0
228
+ or 'noindex' in self.options)
229
+ node['no-index-entry'] = node['noindexentry'] = (
230
+ 'no-index-entry' in self.options
231
+ # xref RemovedInSphinx90Warning
232
+ # deprecate noindexentry in Sphinx 9.0
233
+ or 'noindexentry' in self.options)
234
+ node['no-contents-entry'] = node['nocontentsentry'] = (
235
+ 'no-contents-entry' in self.options
236
+ # xref RemovedInSphinx90Warning
237
+ # deprecate nocontentsentry in Sphinx 9.0
238
+ or 'nocontentsentry' in self.options)
239
+ node['no-typesetting'] = ('no-typesetting' in self.options)
221
240
  if self.domain:
222
241
  node['classes'].append(self.domain)
223
242
  node['classes'].append(node['objtype'])
@@ -251,7 +270,7 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
251
270
  signode['_toc_name'] = ''
252
271
  if name not in self.names:
253
272
  self.names.append(name)
254
- if not noindex:
273
+ if not no_index:
255
274
  # only add target and index entry if this is the first
256
275
  # description of the object with this name in this desc block
257
276
  self.add_target_and_index(name, sig, signode)
@@ -270,6 +289,19 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
270
289
  DocFieldTransformer(self).transform_all(contentnode)
271
290
  self.env.temp_data['object'] = None
272
291
  self.after_content()
292
+
293
+ if node['no-typesetting']:
294
+ # Attempt to return the index node, and a new target node
295
+ # containing all the ids of this node and its children.
296
+ # If ``:no-index:`` is set, or there are no ids on the node
297
+ # or any of its children, then just return the index node,
298
+ # as Docutils expects a target node to have at least one id.
299
+ if node_ids := [node_id for el in node.findall(nodes.Element)
300
+ for node_id in el.get('ids', ())]:
301
+ target_node = nodes.target(ids=node_ids)
302
+ self.set_source_info(target_node)
303
+ return [self.indexnode, target_node]
304
+ return [self.indexnode]
273
305
  return [self.indexnode, node]
274
306
 
275
307
 
@@ -289,7 +321,7 @@ class DefaultRole(SphinxDirective):
289
321
  role, messages = roles.role(role_name, self.state_machine.language,
290
322
  self.lineno, self.state.reporter)
291
323
  if role: # type: ignore[truthy-function]
292
- docutils.register_role('', role)
324
+ docutils.register_role('', role) # type: ignore[arg-type]
293
325
  self.env.temp_data['default_role'] = role_name
294
326
  else:
295
327
  literal_block = nodes.literal_block(self.block_text, self.block_text)
@@ -298,7 +330,7 @@ class DefaultRole(SphinxDirective):
298
330
  literal_block, line=self.lineno)
299
331
  messages += [error]
300
332
 
301
- return cast(List[nodes.Node], messages)
333
+ return cast(list[nodes.Node], messages)
302
334
 
303
335
 
304
336
  class DefaultDomain(SphinxDirective):
sphinx/directives/code.py CHANGED
@@ -6,20 +6,21 @@ from difflib import unified_diff
6
6
  from typing import TYPE_CHECKING, Any
7
7
 
8
8
  from docutils import nodes
9
- from docutils.nodes import Element, Node
10
9
  from docutils.parsers.rst import directives
11
10
  from docutils.statemachine import StringList
12
11
 
13
12
  from sphinx import addnodes
14
- from sphinx.config import Config
15
13
  from sphinx.directives import optional_int
16
14
  from sphinx.locale import __
17
15
  from sphinx.util import logging, parselinenos
18
16
  from sphinx.util.docutils import SphinxDirective
19
- from sphinx.util.typing import OptionSpec
20
17
 
21
18
  if TYPE_CHECKING:
19
+ from docutils.nodes import Element, Node
20
+
22
21
  from sphinx.application import Sphinx
22
+ from sphinx.config import Config
23
+ from sphinx.util.typing import OptionSpec
23
24
 
24
25
  logger = logging.getLogger(__name__)
25
26
 
@@ -244,7 +245,7 @@ class LiteralIncludeReader:
244
245
  new_lines = self.read_file(self.filename)
245
246
  old_filename = self.options['diff']
246
247
  old_lines = self.read_file(old_filename)
247
- diff = unified_diff(old_lines, new_lines, old_filename, self.filename)
248
+ diff = unified_diff(old_lines, new_lines, str(old_filename), str(self.filename))
248
249
  return list(diff)
249
250
 
250
251
  def pyobject_filter(
@@ -4,23 +4,27 @@ import re
4
4
  from typing import TYPE_CHECKING, Any, cast
5
5
 
6
6
  from docutils import nodes
7
- from docutils.nodes import Element, Node
8
7
  from docutils.parsers.rst import directives
9
8
  from docutils.parsers.rst.directives.admonitions import BaseAdmonition
10
9
  from docutils.parsers.rst.directives.misc import Class
11
10
  from docutils.parsers.rst.directives.misc import Include as BaseInclude
11
+ from docutils.statemachine import StateMachine
12
12
 
13
13
  from sphinx import addnodes
14
14
  from sphinx.domains.changeset import VersionChange # noqa: F401 # for compatibility
15
+ from sphinx.domains.std import StandardDomain
15
16
  from sphinx.locale import _, __
16
17
  from sphinx.util import docname_join, logging, url_re
17
18
  from sphinx.util.docutils import SphinxDirective
18
19
  from sphinx.util.matching import Matcher, patfilter
19
20
  from sphinx.util.nodes import explicit_title_re
20
- from sphinx.util.typing import OptionSpec
21
+ from sphinx.util.osutil import os_path
21
22
 
22
23
  if TYPE_CHECKING:
24
+ from docutils.nodes import Element, Node
25
+
23
26
  from sphinx.application import Sphinx
27
+ from sphinx.util.typing import OptionSpec
24
28
 
25
29
 
26
30
  glob_re = re.compile(r'.*[*?\[].*')
@@ -79,71 +83,81 @@ class TocTree(SphinxDirective):
79
83
  return ret
80
84
 
81
85
  def parse_content(self, toctree: addnodes.toctree) -> list[Node]:
82
- generated_docnames = frozenset(self.env.domains['std']._virtual_doc_names)
86
+ generated_docnames = frozenset(StandardDomain._virtual_doc_names)
83
87
  suffixes = self.config.source_suffix
88
+ current_docname = self.env.docname
89
+ glob = toctree['glob']
84
90
 
85
91
  # glob target documents
86
92
  all_docnames = self.env.found_docs.copy() | generated_docnames
87
- all_docnames.remove(self.env.docname) # remove current document
93
+ all_docnames.remove(current_docname) # remove current document
94
+ frozen_all_docnames = frozenset(all_docnames)
88
95
 
89
96
  ret: list[Node] = []
90
97
  excluded = Matcher(self.config.exclude_patterns)
91
98
  for entry in self.content:
92
99
  if not entry:
93
100
  continue
101
+
94
102
  # look for explicit titles ("Some Title <document>")
95
103
  explicit = explicit_title_re.match(entry)
96
- if (toctree['glob'] and glob_re.match(entry) and
97
- not explicit and not url_re.match(entry)):
98
- patname = docname_join(self.env.docname, entry)
99
- docnames = sorted(patfilter(all_docnames, patname))
100
- for docname in docnames:
104
+ url_match = url_re.match(entry) is not None
105
+ if glob and glob_re.match(entry) and not explicit and not url_match:
106
+ pat_name = docname_join(current_docname, entry)
107
+ doc_names = sorted(patfilter(all_docnames, pat_name))
108
+ for docname in doc_names:
101
109
  if docname in generated_docnames:
102
110
  # don't include generated documents in globs
103
111
  continue
104
112
  all_docnames.remove(docname) # don't include it again
105
113
  toctree['entries'].append((None, docname))
106
114
  toctree['includefiles'].append(docname)
107
- if not docnames:
115
+ if not doc_names:
108
116
  logger.warning(__("toctree glob pattern %r didn't match any documents"),
109
117
  entry, location=toctree)
118
+ continue
119
+
120
+ if explicit:
121
+ ref = explicit.group(2)
122
+ title = explicit.group(1)
123
+ docname = ref
110
124
  else:
111
- if explicit:
112
- ref = explicit.group(2)
113
- title = explicit.group(1)
114
- docname = ref
115
- else:
116
- ref = docname = entry
117
- title = None
118
- # remove suffixes (backwards compatibility)
119
- for suffix in suffixes:
120
- if docname.endswith(suffix):
121
- docname = docname[:-len(suffix)]
122
- break
123
- # absolutize filenames
124
- docname = docname_join(self.env.docname, docname)
125
- if url_re.match(ref) or ref == 'self':
126
- toctree['entries'].append((title, ref))
127
- elif docname not in self.env.found_docs | generated_docnames:
128
- if excluded(self.env.doc2path(docname, False)):
129
- message = __('toctree contains reference to excluded document %r')
130
- subtype = 'excluded'
131
- else:
132
- message = __('toctree contains reference to nonexisting document %r')
133
- subtype = 'not_readable'
134
-
135
- logger.warning(message, docname, type='toc', subtype=subtype,
136
- location=toctree)
137
- self.env.note_reread()
125
+ ref = docname = entry
126
+ title = None
127
+
128
+ # remove suffixes (backwards compatibility)
129
+ for suffix in suffixes:
130
+ if docname.endswith(suffix):
131
+ docname = docname.removesuffix(suffix)
132
+ break
133
+
134
+ # absolutise filenames
135
+ docname = docname_join(current_docname, docname)
136
+ if url_match or ref == 'self':
137
+ toctree['entries'].append((title, ref))
138
+ continue
139
+
140
+ if docname not in frozen_all_docnames:
141
+ if excluded(self.env.doc2path(docname, False)):
142
+ message = __('toctree contains reference to excluded document %r')
143
+ subtype = 'excluded'
138
144
  else:
139
- if docname in all_docnames:
140
- all_docnames.remove(docname)
141
- else:
142
- logger.warning(__('duplicated entry found in toctree: %s'), docname,
143
- location=toctree)
145
+ message = __('toctree contains reference to nonexisting document %r')
146
+ subtype = 'not_readable'
144
147
 
145
- toctree['entries'].append((title, docname))
146
- toctree['includefiles'].append(docname)
148
+ logger.warning(message, docname, type='toc', subtype=subtype,
149
+ location=toctree)
150
+ self.env.note_reread()
151
+ continue
152
+
153
+ if docname in all_docnames:
154
+ all_docnames.remove(docname)
155
+ else:
156
+ logger.warning(__('duplicated entry found in toctree: %s'), docname,
157
+ location=toctree)
158
+
159
+ toctree['entries'].append((title, docname))
160
+ toctree['includefiles'].append(docname)
147
161
 
148
162
  # entries contains all entries (self references, external links etc.)
149
163
  if 'reversed' in self.options:
@@ -357,6 +371,40 @@ class Include(BaseInclude, SphinxDirective):
357
371
  """
358
372
 
359
373
  def run(self) -> list[Node]:
374
+
375
+ # To properly emit "source-read" events from included RST text,
376
+ # we must patch the ``StateMachine.insert_input()`` method.
377
+ # In the future, docutils will hopefully offer a way for Sphinx
378
+ # to provide the RST parser to use
379
+ # when parsing RST text that comes in via Include directive.
380
+ def _insert_input(include_lines, path):
381
+ # First, we need to combine the lines back into text so that
382
+ # we can send it with the source-read event.
383
+ # In docutils 0.18 and later, there are two lines at the end
384
+ # that act as markers.
385
+ # We must preserve them and leave them out of the source-read event:
386
+ text = "\n".join(include_lines[:-2])
387
+
388
+ # The docname to pass into the source-read event
389
+ docname = self.env.path2doc(os_path(path))
390
+ # Emit the "source-read" event
391
+ arg = [text]
392
+ self.env.app.events.emit("source-read", docname, arg)
393
+ text = arg[0]
394
+
395
+ # Split back into lines and reattach the two marker lines
396
+ include_lines = text.splitlines() + include_lines[-2:]
397
+
398
+ # Call the parent implementation.
399
+ # Note that this snake does not eat its tail because we patch
400
+ # the *Instance* method and this call is to the *Class* method.
401
+ return StateMachine.insert_input(self.state_machine, include_lines, path)
402
+
403
+ # Only enable this patch if there are listeners for 'source-read'.
404
+ if self.env.app.events.listeners.get('source-read'):
405
+ # See https://github.com/python/mypy/issues/2427 for details on the mypy issue
406
+ self.state_machine.insert_input = _insert_input # type: ignore[method-assign]
407
+
360
408
  if self.arguments[0].startswith('<') and \
361
409
  self.arguments[0].endswith('>'):
362
410
  # docutils "standard" includes, do not do path processing
@@ -18,10 +18,10 @@ from sphinx.util import logging
18
18
  from sphinx.util.docutils import SphinxDirective
19
19
  from sphinx.util.nodes import set_source_info
20
20
  from sphinx.util.osutil import SEP, os_path, relpath
21
- from sphinx.util.typing import OptionSpec
22
21
 
23
22
  if TYPE_CHECKING:
24
23
  from sphinx.application import Sphinx
24
+ from sphinx.util.typing import OptionSpec
25
25
 
26
26
 
27
27
  logger = logging.getLogger(__name__)
@@ -8,23 +8,25 @@ from __future__ import annotations
8
8
 
9
9
  import copy
10
10
  from abc import ABC, abstractmethod
11
- from typing import TYPE_CHECKING, Any, Callable, Iterable, NamedTuple, Optional, cast
11
+ from typing import TYPE_CHECKING, Any, Callable, NamedTuple, Optional, cast
12
12
 
13
- from docutils import nodes
14
13
  from docutils.nodes import Element, Node, system_message
15
- from docutils.parsers.rst.states import Inliner
16
14
 
17
- from sphinx.addnodes import pending_xref
18
15
  from sphinx.errors import SphinxError
19
16
  from sphinx.locale import _
20
- from sphinx.roles import XRefRole
21
- from sphinx.util.typing import RoleFunction
22
17
 
23
18
  if TYPE_CHECKING:
19
+ from collections.abc import Iterable, Sequence
20
+
21
+ from docutils import nodes
24
22
  from docutils.parsers.rst import Directive
23
+ from docutils.parsers.rst.states import Inliner
25
24
 
25
+ from sphinx.addnodes import pending_xref
26
26
  from sphinx.builders import Builder
27
27
  from sphinx.environment import BuildEnvironment
28
+ from sphinx.roles import XRefRole
29
+ from sphinx.util.typing import RoleFunction
28
30
 
29
31
 
30
32
  class ObjType:
@@ -262,10 +264,11 @@ class Domain:
262
264
  fullname = f'{self.name}:{name}'
263
265
 
264
266
  def role_adapter(typ: str, rawtext: str, text: str, lineno: int,
265
- inliner: Inliner, options: dict = {}, content: list[str] = [],
267
+ inliner: Inliner, options: dict | None = None,
268
+ content: Sequence[str] = (),
266
269
  ) -> tuple[list[Node], list[system_message]]:
267
270
  return self.roles[name](fullname, rawtext, text, lineno,
268
- inliner, options, content)
271
+ inliner, options or {}, content)
269
272
  self._role_cache[name] = role_adapter
270
273
  return role_adapter
271
274