Sphinx 8.1.2__py3-none-any.whl → 8.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 (328) hide show
  1. sphinx/__init__.py +8 -4
  2. sphinx/__main__.py +2 -0
  3. sphinx/_cli/__init__.py +2 -5
  4. sphinx/_cli/util/colour.py +34 -11
  5. sphinx/_cli/util/errors.py +128 -61
  6. sphinx/addnodes.py +51 -35
  7. sphinx/application.py +362 -230
  8. sphinx/builders/__init__.py +87 -64
  9. sphinx/builders/_epub_base.py +65 -56
  10. sphinx/builders/changes.py +17 -23
  11. sphinx/builders/dirhtml.py +8 -13
  12. sphinx/builders/epub3.py +70 -38
  13. sphinx/builders/gettext.py +93 -73
  14. sphinx/builders/html/__init__.py +240 -186
  15. sphinx/builders/html/_assets.py +9 -2
  16. sphinx/builders/html/_build_info.py +3 -0
  17. sphinx/builders/latex/__init__.py +64 -54
  18. sphinx/builders/latex/constants.py +14 -11
  19. sphinx/builders/latex/nodes.py +2 -0
  20. sphinx/builders/latex/theming.py +8 -9
  21. sphinx/builders/latex/transforms.py +7 -5
  22. sphinx/builders/linkcheck.py +193 -149
  23. sphinx/builders/manpage.py +17 -17
  24. sphinx/builders/singlehtml.py +28 -16
  25. sphinx/builders/texinfo.py +28 -21
  26. sphinx/builders/text.py +10 -15
  27. sphinx/builders/xml.py +10 -19
  28. sphinx/cmd/build.py +49 -119
  29. sphinx/cmd/make_mode.py +35 -31
  30. sphinx/cmd/quickstart.py +78 -62
  31. sphinx/config.py +265 -163
  32. sphinx/directives/__init__.py +51 -54
  33. sphinx/directives/admonitions.py +107 -0
  34. sphinx/directives/code.py +24 -19
  35. sphinx/directives/other.py +21 -42
  36. sphinx/directives/patches.py +28 -16
  37. sphinx/domains/__init__.py +54 -31
  38. sphinx/domains/_domains_container.py +22 -17
  39. sphinx/domains/_index.py +5 -8
  40. sphinx/domains/c/__init__.py +366 -245
  41. sphinx/domains/c/_ast.py +378 -256
  42. sphinx/domains/c/_ids.py +89 -31
  43. sphinx/domains/c/_parser.py +283 -214
  44. sphinx/domains/c/_symbol.py +269 -198
  45. sphinx/domains/changeset.py +39 -24
  46. sphinx/domains/citation.py +54 -24
  47. sphinx/domains/cpp/__init__.py +517 -362
  48. sphinx/domains/cpp/_ast.py +999 -682
  49. sphinx/domains/cpp/_ids.py +133 -65
  50. sphinx/domains/cpp/_parser.py +746 -588
  51. sphinx/domains/cpp/_symbol.py +692 -489
  52. sphinx/domains/index.py +10 -8
  53. sphinx/domains/javascript.py +152 -74
  54. sphinx/domains/math.py +50 -40
  55. sphinx/domains/python/__init__.py +402 -211
  56. sphinx/domains/python/_annotations.py +134 -61
  57. sphinx/domains/python/_object.py +155 -68
  58. sphinx/domains/rst.py +94 -49
  59. sphinx/domains/std/__init__.py +510 -249
  60. sphinx/environment/__init__.py +345 -61
  61. sphinx/environment/adapters/asset.py +7 -1
  62. sphinx/environment/adapters/indexentries.py +15 -20
  63. sphinx/environment/adapters/toctree.py +19 -9
  64. sphinx/environment/collectors/__init__.py +3 -1
  65. sphinx/environment/collectors/asset.py +18 -15
  66. sphinx/environment/collectors/dependencies.py +8 -10
  67. sphinx/environment/collectors/metadata.py +6 -4
  68. sphinx/environment/collectors/title.py +3 -1
  69. sphinx/environment/collectors/toctree.py +4 -4
  70. sphinx/errors.py +1 -3
  71. sphinx/events.py +4 -4
  72. sphinx/ext/apidoc/__init__.py +66 -0
  73. sphinx/ext/apidoc/__main__.py +9 -0
  74. sphinx/ext/apidoc/_cli.py +356 -0
  75. sphinx/ext/apidoc/_extension.py +262 -0
  76. sphinx/ext/apidoc/_generate.py +356 -0
  77. sphinx/ext/apidoc/_shared.py +99 -0
  78. sphinx/ext/autodoc/__init__.py +837 -483
  79. sphinx/ext/autodoc/directive.py +57 -21
  80. sphinx/ext/autodoc/importer.py +184 -67
  81. sphinx/ext/autodoc/mock.py +25 -10
  82. sphinx/ext/autodoc/preserve_defaults.py +17 -9
  83. sphinx/ext/autodoc/type_comment.py +56 -29
  84. sphinx/ext/autodoc/typehints.py +49 -26
  85. sphinx/ext/autosectionlabel.py +28 -11
  86. sphinx/ext/autosummary/__init__.py +281 -142
  87. sphinx/ext/autosummary/generate.py +121 -51
  88. sphinx/ext/coverage.py +152 -91
  89. sphinx/ext/doctest.py +169 -101
  90. sphinx/ext/duration.py +12 -6
  91. sphinx/ext/extlinks.py +33 -21
  92. sphinx/ext/githubpages.py +8 -8
  93. sphinx/ext/graphviz.py +175 -109
  94. sphinx/ext/ifconfig.py +11 -6
  95. sphinx/ext/imgconverter.py +48 -25
  96. sphinx/ext/imgmath.py +127 -97
  97. sphinx/ext/inheritance_diagram.py +177 -103
  98. sphinx/ext/intersphinx/__init__.py +22 -13
  99. sphinx/ext/intersphinx/__main__.py +3 -1
  100. sphinx/ext/intersphinx/_cli.py +18 -14
  101. sphinx/ext/intersphinx/_load.py +91 -82
  102. sphinx/ext/intersphinx/_resolve.py +108 -74
  103. sphinx/ext/intersphinx/_shared.py +2 -2
  104. sphinx/ext/linkcode.py +28 -12
  105. sphinx/ext/mathjax.py +60 -29
  106. sphinx/ext/napoleon/__init__.py +19 -7
  107. sphinx/ext/napoleon/docstring.py +229 -231
  108. sphinx/ext/todo.py +44 -49
  109. sphinx/ext/viewcode.py +105 -57
  110. sphinx/extension.py +3 -1
  111. sphinx/highlighting.py +13 -7
  112. sphinx/io.py +9 -13
  113. sphinx/jinja2glue.py +29 -26
  114. sphinx/locale/__init__.py +8 -9
  115. sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
  116. sphinx/locale/ar/LC_MESSAGES/sphinx.po +2155 -2050
  117. sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
  118. sphinx/locale/bg/LC_MESSAGES/sphinx.po +2045 -1940
  119. sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
  120. sphinx/locale/bn/LC_MESSAGES/sphinx.po +2175 -2070
  121. sphinx/locale/ca/LC_MESSAGES/sphinx.js +3 -3
  122. sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
  123. sphinx/locale/ca/LC_MESSAGES/sphinx.po +2690 -2585
  124. sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.js +63 -0
  125. sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.mo +0 -0
  126. sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.po +4216 -0
  127. sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
  128. sphinx/locale/cak/LC_MESSAGES/sphinx.po +2096 -1991
  129. sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
  130. sphinx/locale/cs/LC_MESSAGES/sphinx.po +2248 -2143
  131. sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
  132. sphinx/locale/cy/LC_MESSAGES/sphinx.po +2201 -2096
  133. sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
  134. sphinx/locale/da/LC_MESSAGES/sphinx.po +2282 -2177
  135. sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
  136. sphinx/locale/de/LC_MESSAGES/sphinx.po +2261 -2156
  137. sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
  138. sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2045 -1940
  139. sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
  140. sphinx/locale/el/LC_MESSAGES/sphinx.po +2604 -2499
  141. sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
  142. sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2045 -1940
  143. sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
  144. sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2045 -1940
  145. sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
  146. sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2631 -2526
  147. sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
  148. sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2045 -1940
  149. sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
  150. sphinx/locale/eo/LC_MESSAGES/sphinx.po +2078 -1973
  151. sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
  152. sphinx/locale/es/LC_MESSAGES/sphinx.po +2633 -2528
  153. sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
  154. sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2045 -1940
  155. sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
  156. sphinx/locale/et/LC_MESSAGES/sphinx.po +2449 -2344
  157. sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
  158. sphinx/locale/eu/LC_MESSAGES/sphinx.po +2241 -2136
  159. sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
  160. sphinx/locale/fa/LC_MESSAGES/sphinx.po +504 -500
  161. sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
  162. sphinx/locale/fi/LC_MESSAGES/sphinx.po +499 -495
  163. sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
  164. sphinx/locale/fr/LC_MESSAGES/sphinx.po +513 -509
  165. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
  166. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +499 -495
  167. sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
  168. sphinx/locale/gl/LC_MESSAGES/sphinx.po +2644 -2539
  169. sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
  170. sphinx/locale/he/LC_MESSAGES/sphinx.po +499 -495
  171. sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
  172. sphinx/locale/hi/LC_MESSAGES/sphinx.po +504 -500
  173. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
  174. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +499 -495
  175. sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
  176. sphinx/locale/hr/LC_MESSAGES/sphinx.po +501 -497
  177. sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
  178. sphinx/locale/hu/LC_MESSAGES/sphinx.po +499 -495
  179. sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
  180. sphinx/locale/id/LC_MESSAGES/sphinx.po +2609 -2504
  181. sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
  182. sphinx/locale/is/LC_MESSAGES/sphinx.po +499 -495
  183. sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
  184. sphinx/locale/it/LC_MESSAGES/sphinx.po +2265 -2160
  185. sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
  186. sphinx/locale/ja/LC_MESSAGES/sphinx.po +2621 -2516
  187. sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
  188. sphinx/locale/ka/LC_MESSAGES/sphinx.po +2567 -2462
  189. sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
  190. sphinx/locale/ko/LC_MESSAGES/sphinx.po +2631 -2526
  191. sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
  192. sphinx/locale/lt/LC_MESSAGES/sphinx.po +2214 -2109
  193. sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
  194. sphinx/locale/lv/LC_MESSAGES/sphinx.po +2218 -2113
  195. sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
  196. sphinx/locale/mk/LC_MESSAGES/sphinx.po +2088 -1983
  197. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
  198. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2247 -2142
  199. sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
  200. sphinx/locale/ne/LC_MESSAGES/sphinx.po +2227 -2122
  201. sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
  202. sphinx/locale/nl/LC_MESSAGES/sphinx.po +2316 -2211
  203. sphinx/locale/pl/LC_MESSAGES/sphinx.js +2 -2
  204. sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
  205. sphinx/locale/pl/LC_MESSAGES/sphinx.po +2442 -2336
  206. sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
  207. sphinx/locale/pt/LC_MESSAGES/sphinx.po +2045 -1940
  208. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
  209. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2657 -2552
  210. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
  211. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2243 -2138
  212. sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
  213. sphinx/locale/ro/LC_MESSAGES/sphinx.po +2244 -2139
  214. sphinx/locale/ru/LC_MESSAGES/sphinx.js +1 -1
  215. sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
  216. sphinx/locale/ru/LC_MESSAGES/sphinx.po +2660 -2555
  217. sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
  218. sphinx/locale/si/LC_MESSAGES/sphinx.po +2134 -2029
  219. sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
  220. sphinx/locale/sk/LC_MESSAGES/sphinx.po +2614 -2509
  221. sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
  222. sphinx/locale/sl/LC_MESSAGES/sphinx.po +2167 -2062
  223. sphinx/locale/sphinx.pot +2069 -1964
  224. sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
  225. sphinx/locale/sq/LC_MESSAGES/sphinx.po +2661 -2556
  226. sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
  227. sphinx/locale/sr/LC_MESSAGES/sphinx.po +2213 -2108
  228. sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
  229. sphinx/locale/sv/LC_MESSAGES/sphinx.po +2229 -2124
  230. sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
  231. sphinx/locale/te/LC_MESSAGES/sphinx.po +2045 -1940
  232. sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
  233. sphinx/locale/tr/LC_MESSAGES/sphinx.po +2608 -2503
  234. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
  235. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2167 -2062
  236. sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
  237. sphinx/locale/ur/LC_MESSAGES/sphinx.po +2045 -1940
  238. sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
  239. sphinx/locale/vi/LC_MESSAGES/sphinx.po +2204 -2099
  240. sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
  241. sphinx/locale/yue/LC_MESSAGES/sphinx.po +2045 -1940
  242. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
  243. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2045 -1940
  244. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
  245. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +2659 -2554
  246. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
  247. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2045 -1940
  248. sphinx/parsers.py +8 -7
  249. sphinx/project.py +2 -2
  250. sphinx/pycode/__init__.py +31 -21
  251. sphinx/pycode/ast.py +6 -3
  252. sphinx/pycode/parser.py +14 -8
  253. sphinx/pygments_styles.py +4 -5
  254. sphinx/registry.py +192 -92
  255. sphinx/roles.py +58 -7
  256. sphinx/search/__init__.py +75 -54
  257. sphinx/search/en.py +11 -13
  258. sphinx/search/fi.py +1 -1
  259. sphinx/search/ja.py +8 -6
  260. sphinx/search/nl.py +1 -1
  261. sphinx/search/zh.py +19 -21
  262. sphinx/testing/fixtures.py +26 -29
  263. sphinx/testing/path.py +26 -62
  264. sphinx/testing/restructuredtext.py +14 -8
  265. sphinx/testing/util.py +21 -19
  266. sphinx/texinputs/make.bat.jinja +50 -50
  267. sphinx/texinputs/sphinx.sty +4 -3
  268. sphinx/texinputs/sphinxlatexadmonitions.sty +1 -1
  269. sphinx/texinputs/sphinxlatexobjects.sty +29 -10
  270. sphinx/themes/basic/static/searchtools.js +8 -5
  271. sphinx/theming.py +49 -61
  272. sphinx/transforms/__init__.py +17 -38
  273. sphinx/transforms/compact_bullet_list.py +5 -3
  274. sphinx/transforms/i18n.py +8 -21
  275. sphinx/transforms/post_transforms/__init__.py +142 -93
  276. sphinx/transforms/post_transforms/code.py +5 -5
  277. sphinx/transforms/post_transforms/images.py +28 -24
  278. sphinx/transforms/references.py +3 -1
  279. sphinx/util/__init__.py +109 -60
  280. sphinx/util/_files.py +39 -23
  281. sphinx/util/_importer.py +4 -1
  282. sphinx/util/_inventory_file_reader.py +76 -0
  283. sphinx/util/_io.py +2 -2
  284. sphinx/util/_lines.py +6 -3
  285. sphinx/util/_pathlib.py +40 -2
  286. sphinx/util/build_phase.py +2 -0
  287. sphinx/util/cfamily.py +19 -14
  288. sphinx/util/console.py +44 -179
  289. sphinx/util/display.py +9 -10
  290. sphinx/util/docfields.py +140 -122
  291. sphinx/util/docstrings.py +1 -1
  292. sphinx/util/docutils.py +118 -77
  293. sphinx/util/fileutil.py +25 -26
  294. sphinx/util/http_date.py +2 -0
  295. sphinx/util/i18n.py +77 -64
  296. sphinx/util/images.py +8 -6
  297. sphinx/util/inspect.py +147 -38
  298. sphinx/util/inventory.py +215 -116
  299. sphinx/util/logging.py +33 -33
  300. sphinx/util/matching.py +12 -4
  301. sphinx/util/nodes.py +18 -13
  302. sphinx/util/osutil.py +38 -39
  303. sphinx/util/parallel.py +22 -13
  304. sphinx/util/parsing.py +2 -1
  305. sphinx/util/png.py +6 -2
  306. sphinx/util/requests.py +33 -2
  307. sphinx/util/rst.py +3 -2
  308. sphinx/util/tags.py +1 -1
  309. sphinx/util/template.py +18 -10
  310. sphinx/util/texescape.py +8 -6
  311. sphinx/util/typing.py +148 -122
  312. sphinx/versioning.py +3 -3
  313. sphinx/writers/html.py +3 -1
  314. sphinx/writers/html5.py +63 -52
  315. sphinx/writers/latex.py +83 -67
  316. sphinx/writers/manpage.py +19 -38
  317. sphinx/writers/texinfo.py +47 -47
  318. sphinx/writers/text.py +50 -32
  319. sphinx/writers/xml.py +11 -8
  320. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/LICENSE.rst +1 -1
  321. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/METADATA +25 -15
  322. sphinx-8.2.0.dist-info/RECORD +606 -0
  323. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/WHEEL +1 -1
  324. sphinx/builders/html/transforms.py +0 -90
  325. sphinx/ext/apidoc.py +0 -721
  326. sphinx/util/exceptions.py +0 -74
  327. sphinx-8.1.2.dist-info/RECORD +0 -598
  328. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/entry_points.txt +0 -0
sphinx/ext/todo.py CHANGED
@@ -9,14 +9,13 @@ from __future__ import annotations
9
9
 
10
10
  import functools
11
11
  import operator
12
- from typing import TYPE_CHECKING, Any, ClassVar, cast
12
+ from typing import TYPE_CHECKING, cast
13
13
 
14
14
  from docutils import nodes
15
- from docutils.parsers.rst import directives
16
- from docutils.parsers.rst.directives.admonitions import BaseAdmonition
17
15
 
18
16
  import sphinx
19
17
  from sphinx import addnodes
18
+ from sphinx.directives.admonitions import SphinxAdmonition
20
19
  from sphinx.domains import Domain
21
20
  from sphinx.errors import NoUri
22
21
  from sphinx.locale import _, __
@@ -25,6 +24,7 @@ from sphinx.util.docutils import SphinxDirective, new_document
25
24
 
26
25
  if TYPE_CHECKING:
27
26
  from collections.abc import Set
27
+ from typing import Any, ClassVar
28
28
 
29
29
  from docutils.nodes import Element, Node
30
30
 
@@ -45,37 +45,25 @@ class todolist(nodes.General, nodes.Element):
45
45
  pass
46
46
 
47
47
 
48
- class Todo(BaseAdmonition, SphinxDirective):
49
- """
50
- A todo entry, displayed (if configured) in the form of an admonition.
51
- """
48
+ class Todo(SphinxAdmonition):
49
+ """A todo entry, displayed (if configured) in the form of an admonition."""
52
50
 
53
51
  node_class = todo_node
54
- has_content = True
55
- required_arguments = 0
56
- optional_arguments = 0
57
- final_argument_whitespace = False
58
- option_spec: ClassVar[OptionSpec] = {
59
- 'class': directives.class_option,
60
- 'name': directives.unchanged,
61
- }
62
52
 
63
53
  def run(self) -> list[Node]:
64
54
  if not self.options.get('class'):
65
55
  self.options['class'] = ['admonition-todo']
66
56
 
67
57
  (todo,) = super().run()
68
- if isinstance(todo, nodes.system_message):
58
+ if not isinstance(todo, todo_node):
69
59
  return [todo]
70
- elif isinstance(todo, todo_node):
71
- todo.insert(0, nodes.title(text=_('Todo')))
72
- todo['docname'] = self.env.docname
73
- self.add_name(todo)
74
- self.set_source_info(todo)
75
- self.state.document.note_explicit_target(todo)
76
- return [todo]
77
- else:
78
- raise RuntimeError # never reached here
60
+
61
+ todo.insert(0, nodes.title(text=_('Todo')))
62
+ todo['docname'] = self.env.docname
63
+ self.add_name(todo)
64
+ self.set_source_info(todo)
65
+ self.state.document.note_explicit_target(todo)
66
+ return [todo]
79
67
 
80
68
 
81
69
  class TodoDomain(Domain):
@@ -93,22 +81,22 @@ class TodoDomain(Domain):
93
81
  for docname in docnames:
94
82
  self.todos[docname] = otherdata['todos'][docname]
95
83
 
96
- def process_doc(self, env: BuildEnvironment, docname: str,
97
- document: nodes.document) -> None:
84
+ def process_doc(
85
+ self, env: BuildEnvironment, docname: str, document: nodes.document
86
+ ) -> None:
98
87
  todos = self.todos.setdefault(docname, [])
99
88
  for todo in document.findall(todo_node):
100
- env.app.emit('todo-defined', todo)
89
+ env.events.emit('todo-defined', todo)
101
90
  todos.append(todo)
102
91
 
103
92
  if env.config.todo_emit_warnings:
104
- logger.warning(__("TODO entry found: %s"), todo[1].astext(),
105
- location=todo)
93
+ logger.warning(
94
+ __('TODO entry found: %s'), todo[1].astext(), location=todo
95
+ )
106
96
 
107
97
 
108
98
  class TodoList(SphinxDirective):
109
- """
110
- A list of all todo entries.
111
- """
99
+ """A list of all todo entries."""
112
100
 
113
101
  has_content = False
114
102
  required_arguments = 0
@@ -134,7 +122,8 @@ class TodoListProcessor:
134
122
 
135
123
  def process(self, doctree: nodes.document, docname: str) -> None:
136
124
  todos: list[todo_node] = functools.reduce(
137
- operator.iadd, self.domain.todos.values(), [])
125
+ operator.iadd, self.domain.todos.values(), []
126
+ )
138
127
  for node in list(doctree.findall(todolist)):
139
128
  if not self.config.todo_include_todos:
140
129
  node.parent.remove(node)
@@ -162,11 +151,13 @@ class TodoListProcessor:
162
151
  if self.config.todo_link_only:
163
152
  description = _('<<original entry>>')
164
153
  else:
165
- description = (_('(The <<original entry>> is located in %s, line %d.)') %
166
- (todo.source, todo.line))
154
+ description = _('(The <<original entry>> is located in %s, line %d.)') % (
155
+ todo.source,
156
+ todo.line,
157
+ )
167
158
 
168
- prefix = description[:description.find('<<')]
169
- suffix = description[description.find('>>') + 2:]
159
+ prefix = description[: description.find('<<')]
160
+ suffix = description[description.find('>>') + 2 :]
170
161
 
171
162
  para = nodes.paragraph(classes=['todo-source'])
172
163
  para += nodes.Text(prefix)
@@ -175,7 +166,9 @@ class TodoListProcessor:
175
166
  linktext = nodes.emphasis(_('original entry'), _('original entry'))
176
167
  reference = nodes.reference('', '', linktext, internal=True)
177
168
  try:
178
- reference['refuri'] = self.builder.get_relative_uri(docname, todo['docname'])
169
+ reference['refuri'] = self.builder.get_relative_uri(
170
+ docname, todo['docname']
171
+ )
179
172
  reference['refuri'] += '#' + todo['ids'][0]
180
173
  except NoUri:
181
174
  # ignore if no URI can be determined, e.g. for LaTeX output
@@ -214,7 +207,7 @@ def latex_visit_todo_node(self: LaTeXTranslator, node: todo_node) -> None:
214
207
  self.body.append('\n\\begin{sphinxtodo}{')
215
208
  self.body.append(self.hypertarget_to(node))
216
209
 
217
- title_node = cast(nodes.title, node[0])
210
+ title_node = cast('nodes.title', node[0])
218
211
  title = texescape.escape(title_node.astext(), self.config.latex_engine)
219
212
  self.body.append('%s:}' % title)
220
213
  self.no_latex_floats += 1
@@ -232,17 +225,19 @@ def latex_depart_todo_node(self: LaTeXTranslator, node: todo_node) -> None:
232
225
 
233
226
  def setup(app: Sphinx) -> ExtensionMetadata:
234
227
  app.add_event('todo-defined')
235
- app.add_config_value('todo_include_todos', False, 'html')
236
- app.add_config_value('todo_link_only', False, 'html')
237
- app.add_config_value('todo_emit_warnings', False, 'html')
228
+ app.add_config_value('todo_include_todos', False, 'html', types=frozenset({bool}))
229
+ app.add_config_value('todo_link_only', False, 'html', types=frozenset({bool}))
230
+ app.add_config_value('todo_emit_warnings', False, 'html', types=frozenset({bool}))
238
231
 
239
232
  app.add_node(todolist)
240
- app.add_node(todo_node,
241
- html=(visit_todo_node, depart_todo_node),
242
- latex=(latex_visit_todo_node, latex_depart_todo_node),
243
- text=(visit_todo_node, depart_todo_node),
244
- man=(visit_todo_node, depart_todo_node),
245
- texinfo=(visit_todo_node, depart_todo_node))
233
+ app.add_node(
234
+ todo_node,
235
+ html=(visit_todo_node, depart_todo_node),
236
+ latex=(latex_visit_todo_node, latex_depart_todo_node),
237
+ text=(visit_todo_node, depart_todo_node),
238
+ man=(visit_todo_node, depart_todo_node),
239
+ texinfo=(visit_todo_node, depart_todo_node),
240
+ )
246
241
 
247
242
  app.add_directive('todo', Todo)
248
243
  app.add_directive('todolist', TodoList)
sphinx/ext/viewcode.py CHANGED
@@ -2,19 +2,18 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import importlib.util
5
6
  import operator
6
7
  import posixpath
7
8
  import traceback
8
- from importlib import import_module
9
- from os import path
10
- from typing import TYPE_CHECKING, Any, cast
9
+ from types import NoneType
10
+ from typing import TYPE_CHECKING, cast
11
11
 
12
12
  from docutils import nodes
13
- from docutils.nodes import Element, Node
13
+ from docutils.nodes import Element
14
14
 
15
15
  import sphinx
16
16
  from sphinx import addnodes
17
- from sphinx.builders.html import StandaloneHTMLBuilder
18
17
  from sphinx.locale import _, __
19
18
  from sphinx.pycode import ModuleAnalyzer
20
19
  from sphinx.transforms.post_transforms import SphinxPostTransform
@@ -24,11 +23,16 @@ from sphinx.util.nodes import make_refnode
24
23
  from sphinx.util.osutil import _last_modified_time
25
24
 
26
25
  if TYPE_CHECKING:
27
- from collections.abc import Iterable, Iterator
26
+ from collections.abc import Iterator, Set
27
+ from typing import Any
28
+
29
+ from docutils.nodes import Node
28
30
 
29
31
  from sphinx.application import Sphinx
30
32
  from sphinx.builders import Builder
33
+ from sphinx.builders.html import StandaloneHTMLBuilder
31
34
  from sphinx.environment import BuildEnvironment
35
+ from sphinx.util._pathlib import _StrPath
32
36
  from sphinx.util.typing import ExtensionMetadata
33
37
 
34
38
  logger = logging.getLogger(__name__)
@@ -47,12 +51,30 @@ class viewcode_anchor(Element):
47
51
 
48
52
 
49
53
  def _get_full_modname(modname: str, attribute: str) -> str | None:
54
+ if modname is None:
55
+ # Prevents a TypeError: if the last getattr() call will return None
56
+ # then it's better to return it directly
57
+ return None
58
+
50
59
  try:
51
- if modname is None:
52
- # Prevents a TypeError: if the last getattr() call will return None
53
- # then it's better to return it directly
60
+ # Attempt to find full path of module
61
+ module_path = modname.split('.')
62
+ num_parts = len(module_path)
63
+ for i in range(num_parts, 0, -1):
64
+ mod_root = '.'.join(module_path[:i])
65
+ module_spec = importlib.util.find_spec(mod_root)
66
+ if module_spec is not None:
67
+ break
68
+ else:
54
69
  return None
55
- module = import_module(modname)
70
+ # Load and execute the module
71
+ module = importlib.util.module_from_spec(module_spec)
72
+ if module_spec.loader is None:
73
+ return None
74
+ module_spec.loader.exec_module(module)
75
+ if i != num_parts:
76
+ for mod in module_path[i:]:
77
+ module = getattr(module, mod)
56
78
 
57
79
  # Allow an attribute to have multiple parts and incidentally allow
58
80
  # repeated .s in the attribute.
@@ -64,8 +86,8 @@ def _get_full_modname(modname: str, attribute: str) -> str | None:
64
86
  return getattr(value, '__module__', None)
65
87
  except AttributeError:
66
88
  # sphinx.ext.viewcode can't follow class instance attribute
67
- # then AttributeError logging output only verbose mode.
68
- logger.verbose("Didn't find %s in %s", attribute, modname)
89
+ # then AttributeError logging output only debug mode.
90
+ logger.debug("Didn't find %s in %s", attribute, modname)
69
91
  return None
70
92
  except Exception as e:
71
93
  # sphinx.ext.viewcode follow python domain directives.
@@ -78,15 +100,16 @@ def _get_full_modname(modname: str, attribute: str) -> str | None:
78
100
 
79
101
 
80
102
  def is_supported_builder(builder: Builder) -> bool:
81
- if builder.format != 'html':
82
- return False
83
- if builder.name == 'singlehtml':
84
- return False
85
- return not (builder.name.startswith('epub') and not builder.config.viewcode_enable_epub)
103
+ return (
104
+ builder.format == 'html'
105
+ and builder.name != 'singlehtml'
106
+ and (not builder.name.startswith('epub') or builder.config.viewcode_enable_epub)
107
+ )
86
108
 
87
109
 
88
110
  def doctree_read(app: Sphinx, doctree: Node) -> None:
89
- env = app.builder.env
111
+ env = app.env
112
+ events = app.events
90
113
  if not hasattr(env, '_viewcode_modules'):
91
114
  env._viewcode_modules = {} # type: ignore[attr-defined]
92
115
 
@@ -95,7 +118,7 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
95
118
  if entry is False:
96
119
  return False
97
120
 
98
- code_tags = app.emit_firstresult('viewcode-find-source', modname)
121
+ code_tags = events.emit_firstresult('viewcode-find-source', modname)
99
122
  if code_tags is None:
100
123
  try:
101
124
  analyzer = ModuleAnalyzer.for_module(modname)
@@ -130,8 +153,8 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
130
153
  fullname = signode.get('fullname')
131
154
  refname = modname
132
155
  if env.config.viewcode_follow_imported_members:
133
- new_modname = app.emit_firstresult(
134
- 'viewcode-follow-imported', modname, fullname,
156
+ new_modname = events.emit_firstresult(
157
+ 'viewcode-follow-imported', modname, fullname
135
158
  )
136
159
  if not new_modname:
137
160
  new_modname = _get_full_modname(modname, fullname)
@@ -146,11 +169,14 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
146
169
  continue
147
170
  names.add(fullname)
148
171
  pagename = posixpath.join(OUTPUT_DIRNAME, modname.replace('.', '/'))
149
- signode += viewcode_anchor(reftarget=pagename, refid=fullname, refdoc=env.docname)
172
+ signode += viewcode_anchor(
173
+ reftarget=pagename, refid=fullname, refdoc=env.docname
174
+ )
150
175
 
151
176
 
152
- def env_merge_info(app: Sphinx, env: BuildEnvironment, docnames: Iterable[str],
153
- other: BuildEnvironment) -> None:
177
+ def env_merge_info(
178
+ app: Sphinx, env: BuildEnvironment, docnames: Set[str], other: BuildEnvironment
179
+ ) -> None:
154
180
  if not hasattr(other, '_viewcode_modules'):
155
181
  return
156
182
  # create a _viewcode_modules dict on the main environment
@@ -198,8 +224,13 @@ class ViewcodeAnchorTransform(SphinxPostTransform):
198
224
  def convert_viewcode_anchors(self) -> None:
199
225
  for node in self.document.findall(viewcode_anchor):
200
226
  anchor = nodes.inline('', _('[source]'), classes=['viewcode-link'])
201
- refnode = make_refnode(self.app.builder, node['refdoc'], node['reftarget'],
202
- node['refid'], anchor)
227
+ refnode = make_refnode(
228
+ self.app.builder,
229
+ node['refdoc'],
230
+ node['reftarget'],
231
+ node['refid'],
232
+ anchor,
233
+ )
203
234
  node.replace_self(refnode)
204
235
 
205
236
  def remove_viewcode_anchors(self) -> None:
@@ -207,9 +238,10 @@ class ViewcodeAnchorTransform(SphinxPostTransform):
207
238
  node.parent.remove(node)
208
239
 
209
240
 
210
- def get_module_filename(app: Sphinx, modname: str) -> str | None:
241
+ def get_module_filename(app: Sphinx, modname: str) -> _StrPath | None:
211
242
  """Get module filename for *modname*."""
212
- source_info = app.emit_firstresult('viewcode-find-source', modname)
243
+ events = app.events
244
+ source_info = events.emit_firstresult('viewcode-find-source', modname)
213
245
  if source_info:
214
246
  return None
215
247
  else:
@@ -227,9 +259,9 @@ def should_generate_module_page(app: Sphinx, modname: str) -> bool:
227
259
  # Always (re-)generate module page when module filename is not found.
228
260
  return True
229
261
 
230
- builder = cast(StandaloneHTMLBuilder, app.builder)
262
+ builder = cast('StandaloneHTMLBuilder', app.builder)
231
263
  basename = modname.replace('.', '/') + builder.out_suffix
232
- page_filename = path.join(app.outdir, '_modules/', basename)
264
+ page_filename = app.outdir / '_modules' / basename
233
265
 
234
266
  try:
235
267
  if _last_modified_time(module_filename) <= _last_modified_time(page_filename):
@@ -242,7 +274,7 @@ def should_generate_module_page(app: Sphinx, modname: str) -> bool:
242
274
 
243
275
 
244
276
  def collect_pages(app: Sphinx) -> Iterator[tuple[str, dict[str, Any], str]]:
245
- env = app.builder.env
277
+ env = app.env
246
278
  if not hasattr(env, '_viewcode_modules'):
247
279
  return
248
280
  if not is_supported_builder(app.builder):
@@ -253,10 +285,13 @@ def collect_pages(app: Sphinx) -> Iterator[tuple[str, dict[str, Any], str]]:
253
285
  modnames = set(env._viewcode_modules)
254
286
 
255
287
  for modname, entry in status_iterator(
256
- sorted(env._viewcode_modules.items()),
257
- __('highlighting module code... '), "blue",
258
- len(env._viewcode_modules),
259
- app.verbosity, operator.itemgetter(0)):
288
+ sorted(env._viewcode_modules.items()),
289
+ __('highlighting module code... '),
290
+ 'blue',
291
+ len(env._viewcode_modules),
292
+ app.verbosity,
293
+ operator.itemgetter(0),
294
+ ):
260
295
  if not entry:
261
296
  continue
262
297
  if not should_generate_module_page(app, modname):
@@ -286,9 +321,11 @@ def collect_pages(app: Sphinx) -> Iterator[tuple[str, dict[str, Any], str]]:
286
321
  for name, docname in used.items():
287
322
  type, start, end = tags[name]
288
323
  backlink = urito(pagename, docname) + '#' + refname + '.' + name
289
- lines[start] = (f'<div class="viewcode-block" id="{name}">\n'
290
- f'<a class="viewcode-back" href="{backlink}">{link_text}</a>\n'
291
- + lines[start])
324
+ lines[start] = (
325
+ f'<div class="viewcode-block" id="{name}">\n'
326
+ f'<a class="viewcode-back" href="{backlink}">{link_text}</a>\n'
327
+ + lines[start]
328
+ )
292
329
  lines[min(end, max_index)] += '</div>\n'
293
330
 
294
331
  # try to find parents (for submodules)
@@ -298,20 +335,24 @@ def collect_pages(app: Sphinx) -> Iterator[tuple[str, dict[str, Any], str]]:
298
335
  parent = parent.rsplit('.', 1)[0]
299
336
  if parent in modnames:
300
337
  parents.append({
301
- 'link': urito(pagename,
302
- posixpath.join(OUTPUT_DIRNAME, parent.replace('.', '/'))),
303
- 'title': parent})
304
- parents.append({'link': urito(pagename, posixpath.join(OUTPUT_DIRNAME, 'index')),
305
- 'title': _('Module code')})
338
+ 'link': urito(
339
+ pagename,
340
+ posixpath.join(OUTPUT_DIRNAME, parent.replace('.', '/')),
341
+ ),
342
+ 'title': parent,
343
+ })
344
+ parents.append({
345
+ 'link': urito(pagename, posixpath.join(OUTPUT_DIRNAME, 'index')),
346
+ 'title': _('Module code'),
347
+ })
306
348
  parents.reverse()
307
349
  # putting it all together
308
350
  context = {
309
351
  'parents': parents,
310
352
  'title': modname,
311
- 'body': (_('<h1>Source code for %s</h1>') % modname +
312
- '\n'.join(lines)),
353
+ 'body': (_('<h1>Source code for %s</h1>') % modname + '\n'.join(lines)),
313
354
  }
314
- yield (pagename, context, 'page.html')
355
+ yield pagename, context, 'page.html'
315
356
 
316
357
  if not modnames:
317
358
  return
@@ -329,30 +370,37 @@ def collect_pages(app: Sphinx) -> Iterator[tuple[str, dict[str, Any], str]]:
329
370
  stack.pop()
330
371
  html.append('</ul>')
331
372
  stack.append(modname + '.')
332
- relative_uri = urito(posixpath.join(OUTPUT_DIRNAME, 'index'),
333
- posixpath.join(OUTPUT_DIRNAME, modname.replace('.', '/')))
373
+ relative_uri = urito(
374
+ posixpath.join(OUTPUT_DIRNAME, 'index'),
375
+ posixpath.join(OUTPUT_DIRNAME, modname.replace('.', '/')),
376
+ )
334
377
  html.append(f'<li><a href="{relative_uri}">{modname}</a></li>\n')
335
378
  html.append('</ul>' * (len(stack) - 1))
336
379
  context = {
337
380
  'title': _('Overview: module code'),
338
- 'body': (_('<h1>All modules for which code is available</h1>') +
339
- ''.join(html)),
381
+ 'body': (_('<h1>All modules for which code is available</h1>') + ''.join(html)),
340
382
  }
341
383
 
342
- yield (posixpath.join(OUTPUT_DIRNAME, 'index'), context, 'page.html')
384
+ yield posixpath.join(OUTPUT_DIRNAME, 'index'), context, 'page.html'
343
385
 
344
386
 
345
387
  def setup(app: Sphinx) -> ExtensionMetadata:
346
- app.add_config_value('viewcode_import', None, '')
347
- app.add_config_value('viewcode_enable_epub', False, '')
348
- app.add_config_value('viewcode_follow_imported_members', True, '')
349
- app.add_config_value('viewcode_line_numbers', False, 'env', bool)
388
+ app.add_config_value('viewcode_import', None, '', types=frozenset({NoneType}))
389
+ app.add_config_value('viewcode_enable_epub', False, '', types=frozenset({bool}))
390
+ app.add_config_value(
391
+ 'viewcode_follow_imported_members', True, '', types=frozenset({bool})
392
+ )
393
+ app.add_config_value('viewcode_line_numbers', False, 'env', types=frozenset({bool}))
350
394
  app.connect('doctree-read', doctree_read)
351
395
  app.connect('env-merge-info', env_merge_info)
352
396
  app.connect('env-purge-doc', env_purge_doc)
353
397
  app.connect('html-collect-pages', collect_pages)
354
- # app.add_config_value('viewcode_include_modules', [], 'env')
355
- # app.add_config_value('viewcode_exclude_modules', [], 'env')
398
+ # app.add_config_value(
399
+ # 'viewcode_include_modules', [], 'env', types=frozenset({list, tuple})
400
+ # )
401
+ # app.add_config_value(
402
+ # 'viewcode_exclude_modules', [], 'env', types=frozenset({list, tuple})
403
+ # )
356
404
  app.add_event('viewcode-find-source')
357
405
  app.add_event('viewcode-follow-imported')
358
406
  app.add_post_transform(ViewcodeAnchorTransform)
sphinx/extension.py CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Any
5
+ from typing import TYPE_CHECKING
6
6
 
7
7
  from packaging.version import InvalidVersion, Version
8
8
 
@@ -11,6 +11,8 @@ from sphinx.locale import __
11
11
  from sphinx.util import logging
12
12
 
13
13
  if TYPE_CHECKING:
14
+ from typing import Any
15
+
14
16
  from sphinx.application import Sphinx
15
17
  from sphinx.config import Config
16
18
  from sphinx.util.typing import ExtensionMetadata
sphinx/highlighting.py CHANGED
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  from functools import partial
6
6
  from importlib import import_module
7
- from typing import TYPE_CHECKING, Any
7
+ from typing import TYPE_CHECKING
8
8
 
9
9
  import pygments
10
10
  from pygments import highlight
@@ -27,12 +27,14 @@ from sphinx.pygments_styles import NoneStyle, SphinxStyle
27
27
  from sphinx.util import logging, texescape
28
28
 
29
29
  if TYPE_CHECKING:
30
+ from typing import Any
31
+
30
32
  from pygments.formatter import Formatter
31
33
  from pygments.lexer import Lexer
32
34
  from pygments.style import Style
33
35
 
34
- if tuple(map(int, pygments.__version__.split('.')))[:2] < (2, 18):
35
- from pygments.formatter import Formatter # NoQA: F811
36
+ if tuple(map(int, pygments.__version__.split('.')[:2])) < (2, 18):
37
+ from pygments.formatter import Formatter
36
38
 
37
39
  Formatter.__class_getitem__ = classmethod(lambda cls, name: cls) # type: ignore[attr-defined]
38
40
 
@@ -127,7 +129,7 @@ class PygmentsBridge:
127
129
  else:
128
130
  return get_style_by_name(stylename)
129
131
 
130
- def get_formatter(self, **kwargs: Any) -> Formatter:
132
+ def get_formatter(self, **kwargs: Any) -> Formatter[str]:
131
133
  kwargs.update(self.formatter_args)
132
134
  return self.formatter(**kwargs)
133
135
 
@@ -135,7 +137,7 @@ class PygmentsBridge:
135
137
  self,
136
138
  source: str,
137
139
  lang: str,
138
- opts: dict | None = None,
140
+ opts: dict[str, Any] | None = None,
139
141
  force: bool = False,
140
142
  location: Any = None,
141
143
  ) -> Lexer:
@@ -165,7 +167,11 @@ class PygmentsBridge:
165
167
  lexer = get_lexer_by_name(lang, **opts)
166
168
  except ClassNotFound:
167
169
  logger.warning(
168
- __('Pygments lexer name %r is not known'), lang, location=location
170
+ __('Pygments lexer name %r is not known'),
171
+ lang,
172
+ location=location,
173
+ type='misc',
174
+ subtype='higlighting_failure',
169
175
  )
170
176
  lexer = lexer_classes['none'](**opts)
171
177
 
@@ -178,7 +184,7 @@ class PygmentsBridge:
178
184
  self,
179
185
  source: str,
180
186
  lang: str,
181
- opts: dict | None = None,
187
+ opts: dict[str, Any] | None = None,
182
188
  force: bool = False,
183
189
  location: Any = None,
184
190
  **kwargs: Any,
sphinx/io.py CHANGED
@@ -2,15 +2,14 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Any
5
+ from typing import TYPE_CHECKING
6
6
 
7
7
  from docutils.core import Publisher
8
- from docutils.io import FileInput, Input, NullOutput
8
+ from docutils.io import FileInput, NullOutput
9
9
  from docutils.readers import standalone
10
10
  from docutils.transforms.references import DanglingReferences
11
11
  from docutils.writers import UnfilteredWriter
12
12
 
13
- from sphinx import addnodes
14
13
  from sphinx.transforms import AutoIndexUpgrader, DoctreeReadEvent, SphinxTransformer
15
14
  from sphinx.transforms.i18n import (
16
15
  Locale,
@@ -23,8 +22,11 @@ from sphinx.util.docutils import LoggingReporter
23
22
  from sphinx.versioning import UIDTransform
24
23
 
25
24
  if TYPE_CHECKING:
25
+ from typing import Any
26
+
26
27
  from docutils import nodes
27
28
  from docutils.frontend import Values
29
+ from docutils.io import Input
28
30
  from docutils.parsers import Parser
29
31
  from docutils.transforms import Transform
30
32
 
@@ -36,8 +38,7 @@ logger = logging.getLogger(__name__)
36
38
 
37
39
 
38
40
  class SphinxBaseReader(standalone.Reader): # type: ignore[misc]
39
- """
40
- A base class of readers for Sphinx.
41
+ """A base class of readers for Sphinx.
41
42
 
42
43
  This replaces reporter by Sphinx's on generating document.
43
44
  """
@@ -70,12 +71,10 @@ class SphinxBaseReader(standalone.Reader): # type: ignore[misc]
70
71
  return transforms
71
72
 
72
73
  def new_document(self) -> nodes.document:
73
- """
74
- Creates a new document object which has a special reporter object good
74
+ """Creates a new document object which has a special reporter object good
75
75
  for logging.
76
76
  """
77
77
  document = super().new_document()
78
- document.__class__ = addnodes.document # replace the class with patched version
79
78
 
80
79
  # substitute transformer
81
80
  document.transformer = SphinxTransformer(document)
@@ -89,9 +88,7 @@ class SphinxBaseReader(standalone.Reader): # type: ignore[misc]
89
88
 
90
89
 
91
90
  class SphinxStandaloneReader(SphinxBaseReader):
92
- """
93
- A basic document reader for Sphinx.
94
- """
91
+ """A basic document reader for Sphinx."""
95
92
 
96
93
  def setup(self, app: Sphinx) -> None:
97
94
  self.transforms = self.transforms + app.registry.get_transforms()
@@ -117,8 +114,7 @@ class SphinxStandaloneReader(SphinxBaseReader):
117
114
 
118
115
 
119
116
  class SphinxI18nReader(SphinxBaseReader):
120
- """
121
- A document reader for i18n.
117
+ """A document reader for i18n.
122
118
 
123
119
  This returns the source line number of original text as current source line number
124
120
  to let users know where the error happened.