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/__init__.py CHANGED
@@ -19,7 +19,7 @@ warnings.filterwarnings('ignore', "'U' mode is deprecated",
19
19
  warnings.filterwarnings('ignore', 'The frontend.Option class .*',
20
20
  DeprecationWarning, module='docutils.frontend')
21
21
 
22
- __version__ = '7.1.2'
22
+ __version__ = '7.2.0'
23
23
  __display_version__ = __version__ # used for command line version
24
24
 
25
25
  #: Version info for better programmatic use.
@@ -30,7 +30,7 @@ __display_version__ = __version__ # used for command line version
30
30
  #:
31
31
  #: .. versionadded:: 1.2
32
32
  #: Before version 1.2, check the string ``sphinx.__version__``.
33
- version_info = (7, 1, 2, 'final', 0)
33
+ version_info = (7, 2, 0, 'final', 0)
34
34
 
35
35
  package_dir = path.abspath(path.dirname(__file__))
36
36
 
@@ -40,13 +40,13 @@ if _in_development:
40
40
  import subprocess
41
41
 
42
42
  try:
43
- ret = subprocess.run(
44
- ['git', 'show', '-s', '--pretty=format:%h'],
43
+ if ret := subprocess.run(
44
+ ['git', 'rev-parse', '--short', 'HEAD'],
45
45
  cwd=package_dir,
46
46
  capture_output=True,
47
47
  encoding='ascii',
48
- ).stdout
49
- if ret:
48
+ errors='surrogateescape',
49
+ ).stdout:
50
50
  __display_version__ += '+/' + ret.strip()
51
51
  del ret
52
52
  finally:
sphinx/__main__.py CHANGED
@@ -1,5 +1,7 @@
1
1
  """The Sphinx documentation toolchain."""
2
2
 
3
+ import sys
4
+
3
5
  from sphinx.cmd.build import main
4
6
 
5
- raise SystemExit(main())
7
+ raise SystemExit(main(sys.argv[1:]))
sphinx/addnodes.py CHANGED
@@ -2,12 +2,15 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Any, Sequence
5
+ from typing import TYPE_CHECKING, Any
6
6
 
7
7
  from docutils import nodes
8
- from docutils.nodes import Element
9
8
 
10
9
  if TYPE_CHECKING:
10
+ from collections.abc import Sequence
11
+
12
+ from docutils.nodes import Element
13
+
11
14
  from sphinx.application import Sphinx
12
15
 
13
16
  # deprecated name -> (object to return, canonical path or empty string)
@@ -19,7 +22,8 @@ _DEPRECATED_OBJECTS = {
19
22
 
20
23
  def __getattr__(name):
21
24
  if name not in _DEPRECATED_OBJECTS:
22
- raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
25
+ msg = f'module {__name__!r} has no attribute {name!r}'
26
+ raise AttributeError(msg)
23
27
 
24
28
  from sphinx.deprecation import _deprecation_warning
25
29
 
@@ -40,7 +44,7 @@ class document(nodes.document):
40
44
 
41
45
  def set_id(self, node: Element, msgnode: Element | None = None,
42
46
  suggested_prefix: str = '') -> str:
43
- return super().set_id(node, msgnode, suggested_prefix) # type: ignore
47
+ return super().set_id(node, msgnode, suggested_prefix) # type: ignore[call-arg]
44
48
 
45
49
 
46
50
  class translatable(nodes.Node):
@@ -294,9 +298,20 @@ class desc_annotation(nodes.Part, nodes.Inline, nodes.FixedTextElement):
294
298
  # Leaf nodes for markup of text fragments
295
299
  #########################################
296
300
 
301
+ #: A set of classes inheriting :class:`desc_sig_element`. Each node class
302
+ #: is expected to be handled by the builder's translator class if the latter
303
+ #: does not inherit from SphinxTranslator.
304
+ #:
305
+ #: This set can be extended manually by third-party extensions or
306
+ #: by subclassing :class:`desc_sig_element` and using the class
307
+ #: keyword argument `_sig_element=True`.
308
+ SIG_ELEMENTS: set[type[desc_sig_element]] = set()
309
+
310
+
297
311
  # Signature text elements, generally translated to node.inline
298
312
  # in SigElementFallbackTransform.
299
- # When adding a new one, add it to SIG_ELEMENTS.
313
+ # When adding a new one, add it to SIG_ELEMENTS via the class
314
+ # keyword argument `_sig_element=True` (e.g., see `desc_sig_space`).
300
315
 
301
316
  class desc_sig_element(nodes.inline, _desc_classes_injector):
302
317
  """Common parent class of nodes for inline text of a signature."""
@@ -307,11 +322,17 @@ class desc_sig_element(nodes.inline, _desc_classes_injector):
307
322
  super().__init__(rawsource, text, *children, **attributes)
308
323
  self['classes'].extend(self.classes)
309
324
 
325
+ def __init_subclass__(cls, *, _sig_element=False, **kwargs):
326
+ super().__init_subclass__(**kwargs)
327
+ if _sig_element:
328
+ # add the class to the SIG_ELEMENTS set if asked
329
+ SIG_ELEMENTS.add(cls)
330
+
310
331
 
311
332
  # to not reinvent the wheel, the classes in the following desc_sig classes
312
333
  # are based on those used in Pygments
313
334
 
314
- class desc_sig_space(desc_sig_element):
335
+ class desc_sig_space(desc_sig_element, _sig_element=True):
315
336
  """Node for a space in a signature."""
316
337
  classes = ["w"]
317
338
 
@@ -320,54 +341,46 @@ class desc_sig_space(desc_sig_element):
320
341
  super().__init__(rawsource, text, *children, **attributes)
321
342
 
322
343
 
323
- class desc_sig_name(desc_sig_element):
344
+ class desc_sig_name(desc_sig_element, _sig_element=True):
324
345
  """Node for an identifier in a signature."""
325
346
  classes = ["n"]
326
347
 
327
348
 
328
- class desc_sig_operator(desc_sig_element):
349
+ class desc_sig_operator(desc_sig_element, _sig_element=True):
329
350
  """Node for an operator in a signature."""
330
351
  classes = ["o"]
331
352
 
332
353
 
333
- class desc_sig_punctuation(desc_sig_element):
354
+ class desc_sig_punctuation(desc_sig_element, _sig_element=True):
334
355
  """Node for punctuation in a signature."""
335
356
  classes = ["p"]
336
357
 
337
358
 
338
- class desc_sig_keyword(desc_sig_element):
359
+ class desc_sig_keyword(desc_sig_element, _sig_element=True):
339
360
  """Node for a general keyword in a signature."""
340
361
  classes = ["k"]
341
362
 
342
363
 
343
- class desc_sig_keyword_type(desc_sig_element):
364
+ class desc_sig_keyword_type(desc_sig_element, _sig_element=True):
344
365
  """Node for a keyword which is a built-in type in a signature."""
345
366
  classes = ["kt"]
346
367
 
347
368
 
348
- class desc_sig_literal_number(desc_sig_element):
369
+ class desc_sig_literal_number(desc_sig_element, _sig_element=True):
349
370
  """Node for a numeric literal in a signature."""
350
371
  classes = ["m"]
351
372
 
352
373
 
353
- class desc_sig_literal_string(desc_sig_element):
374
+ class desc_sig_literal_string(desc_sig_element, _sig_element=True):
354
375
  """Node for a string literal in a signature."""
355
376
  classes = ["s"]
356
377
 
357
378
 
358
- class desc_sig_literal_char(desc_sig_element):
379
+ class desc_sig_literal_char(desc_sig_element, _sig_element=True):
359
380
  """Node for a character literal in a signature."""
360
381
  classes = ["sc"]
361
382
 
362
383
 
363
- SIG_ELEMENTS = [desc_sig_space,
364
- desc_sig_name,
365
- desc_sig_operator,
366
- desc_sig_punctuation,
367
- desc_sig_keyword, desc_sig_keyword_type,
368
- desc_sig_literal_number, desc_sig_literal_string, desc_sig_literal_char]
369
-
370
-
371
384
  ###############################################################
372
385
  # new admonition-like constructs
373
386
 
sphinx/application.py CHANGED
@@ -9,46 +9,48 @@ import os
9
9
  import pickle
10
10
  import sys
11
11
  from collections import deque
12
+ from collections.abc import Sequence # NoQA: TCH003
12
13
  from io import StringIO
13
14
  from os import path
15
+ from pathlib import Path
14
16
  from typing import IO, TYPE_CHECKING, Any, Callable
15
17
 
16
- from docutils import nodes
17
- from docutils.nodes import Element, TextElement
18
- from docutils.parsers import Parser
18
+ from docutils.nodes import TextElement # NoQA: TCH002
19
19
  from docutils.parsers.rst import Directive, roles
20
- from docutils.transforms import Transform
21
- from pygments.lexer import Lexer
20
+ from docutils.transforms import Transform # NoQA: TCH002
21
+ from pygments.lexer import Lexer # NoQA: TCH002
22
22
 
23
23
  import sphinx
24
24
  from sphinx import locale, package_dir
25
25
  from sphinx.config import Config
26
- from sphinx.domains import Domain, Index
27
26
  from sphinx.environment import BuildEnvironment
28
- from sphinx.environment.collectors import EnvironmentCollector
29
27
  from sphinx.errors import ApplicationError, ConfigError, VersionRequirementError
30
28
  from sphinx.events import EventManager
31
- from sphinx.extension import Extension
32
29
  from sphinx.highlighting import lexer_classes
33
30
  from sphinx.locale import __
34
31
  from sphinx.project import Project
35
32
  from sphinx.registry import SphinxComponentRegistry
36
- from sphinx.roles import XRefRole
37
- from sphinx.theming import Theme
38
33
  from sphinx.util import docutils, logging
39
34
  from sphinx.util.build_phase import BuildPhase
40
- from sphinx.util.console import bold # type: ignore
35
+ from sphinx.util.console import bold # type: ignore[attr-defined]
41
36
  from sphinx.util.display import progress_message
42
37
  from sphinx.util.i18n import CatalogRepository
43
38
  from sphinx.util.logging import prefixed_warnings
44
- from sphinx.util.osutil import abspath, ensuredir, relpath
39
+ from sphinx.util.osutil import ensuredir, relpath
45
40
  from sphinx.util.tags import Tags
46
- from sphinx.util.typing import RoleFunction, TitleGetter
47
41
 
48
42
  if TYPE_CHECKING:
49
- from docutils.nodes import Node # noqa: F401
43
+ from docutils import nodes
44
+ from docutils.nodes import Element
45
+ from docutils.parsers import Parser
50
46
 
51
47
  from sphinx.builders import Builder
48
+ from sphinx.domains import Domain, Index
49
+ from sphinx.environment.collectors import EnvironmentCollector
50
+ from sphinx.extension import Extension
51
+ from sphinx.roles import XRefRole
52
+ from sphinx.theming import Theme
53
+ from sphinx.util.typing import RoleFunction, TitleGetter
52
54
 
53
55
 
54
56
  builtin_extensions: tuple[str, ...] = (
@@ -132,7 +134,8 @@ class Sphinx:
132
134
  warningiserror: bool
133
135
  _warncount: int
134
136
 
135
- def __init__(self, srcdir: str, confdir: str | None, outdir: str, doctreedir: str,
137
+ def __init__(self, srcdir: str | os.PathLike[str], confdir: str | os.PathLike[str] | None,
138
+ outdir: str | os.PathLike[str], doctreedir: str | os.PathLike[str],
136
139
  buildername: str, confoverrides: dict | None = None,
137
140
  status: IO | None = sys.stdout, warning: IO | None = sys.stderr,
138
141
  freshenv: bool = False, warningiserror: bool = False,
@@ -145,9 +148,9 @@ class Sphinx:
145
148
  self.registry = SphinxComponentRegistry()
146
149
 
147
150
  # validate provided directories
148
- self.srcdir = abspath(srcdir)
149
- self.outdir = abspath(outdir)
150
- self.doctreedir = abspath(doctreedir)
151
+ self.srcdir = Path(srcdir).resolve()
152
+ self.outdir = Path(outdir).resolve()
153
+ self.doctreedir = Path(doctreedir).resolve()
151
154
 
152
155
  if not path.isdir(self.srcdir):
153
156
  raise ApplicationError(__('Cannot find source directory (%s)') %
@@ -203,7 +206,7 @@ class Sphinx:
203
206
  self.confdir = self.srcdir
204
207
  self.config = Config({}, confoverrides or {})
205
208
  else:
206
- self.confdir = abspath(confdir)
209
+ self.confdir = Path(confdir).resolve()
207
210
  self.config = Config.read(self.confdir, confoverrides or {}, self.tags)
208
211
 
209
212
  # initialize some limited config variables before initialize i18n and loading
@@ -307,13 +310,13 @@ class Sphinx:
307
310
  self._fresh_env_used = True
308
311
  return env
309
312
 
313
+ @progress_message(__('loading pickled environment'))
310
314
  def _load_existing_env(self, filename: str) -> BuildEnvironment:
311
315
  try:
312
- with progress_message(__('loading pickled environment')):
313
- with open(filename, 'rb') as f:
314
- env = pickle.load(f)
315
- env.setup(self)
316
- self._fresh_env_used = False
316
+ with open(filename, 'rb') as f:
317
+ env = pickle.load(f)
318
+ env.setup(self)
319
+ self._fresh_env_used = False
317
320
  except Exception as err:
318
321
  logger.info(__('failed: %s'), err)
319
322
  env = self._create_fresh_env()
@@ -420,7 +423,8 @@ class Sphinx:
420
423
  else:
421
424
  major, minor = map(int, version.split('.')[:2])
422
425
  if (major, minor) > sphinx.version_info[:2]:
423
- raise VersionRequirementError(f'{major}.{minor}')
426
+ req = f'{major}.{minor}'
427
+ raise VersionRequirementError(req)
424
428
 
425
429
  # event interface
426
430
  def connect(self, event: str, callback: Callable, priority: int = 500) -> int:
@@ -734,7 +738,7 @@ class Sphinx:
734
738
  logger.warning(__('role %r is already registered, it will be overridden'),
735
739
  name, type='app', subtype='add_generic_role')
736
740
  role = roles.GenericRole(name, nodeclass)
737
- docutils.register_role(name, role)
741
+ docutils.register_role(name, role) # type: ignore[arg-type]
738
742
 
739
743
  def add_domain(self, domain: type[Domain], override: bool = False) -> None:
740
744
  """Register a domain.
@@ -811,7 +815,8 @@ class Sphinx:
811
815
  def add_object_type(self, directivename: str, rolename: str, indextemplate: str = '',
812
816
  parse_node: Callable | None = None,
813
817
  ref_nodeclass: type[TextElement] | None = None,
814
- objname: str = '', doc_field_types: list = [], override: bool = False,
818
+ objname: str = '', doc_field_types: Sequence = (),
819
+ override: bool = False,
815
820
  ) -> None:
816
821
  """Register a new object type.
817
822
 
@@ -1028,9 +1033,6 @@ class Sphinx:
1028
1033
  kwargs['defer'] = 'defer'
1029
1034
 
1030
1035
  self.registry.add_js_file(filename, priority=priority, **kwargs)
1031
- if hasattr(self, 'builder') and hasattr(self.builder, 'add_js_file'):
1032
- self.builder.add_js_file(filename,
1033
- priority=priority, **kwargs)
1034
1036
 
1035
1037
  def add_css_file(self, filename: str, priority: int = 500, **kwargs: Any) -> None:
1036
1038
  """Register a stylesheet to include in the HTML output.
@@ -1091,9 +1093,6 @@ class Sphinx:
1091
1093
  """
1092
1094
  logger.debug('[app] adding stylesheet: %r', filename)
1093
1095
  self.registry.add_css_files(filename, priority=priority, **kwargs)
1094
- if hasattr(self, 'builder') and hasattr(self.builder, 'add_css_file'):
1095
- self.builder.add_css_file(filename,
1096
- priority=priority, **kwargs)
1097
1096
 
1098
1097
  def add_latex_package(self, packagename: str, options: str | None = None,
1099
1098
  after_hyperref: bool = False) -> None:
@@ -1240,8 +1239,8 @@ class Sphinx:
1240
1239
  def add_html_math_renderer(
1241
1240
  self,
1242
1241
  name: str,
1243
- inline_renderers: tuple[Callable | None, Callable | None] | None = None,
1244
- block_renderers: tuple[Callable | None, Callable | None] | None = None,
1242
+ inline_renderers: tuple[Callable, Callable | None] | None = None,
1243
+ block_renderers: tuple[Callable, Callable | None] | None = None,
1245
1244
  ) -> None:
1246
1245
  """Register a math renderer for HTML.
1247
1246
 
@@ -1338,7 +1337,8 @@ class TemplateBridge:
1338
1337
  *theme* is a :class:`sphinx.theming.Theme` object or None; in the latter
1339
1338
  case, *dirs* can be list of fixed directories to look for templates.
1340
1339
  """
1341
- raise NotImplementedError('must be implemented in subclasses')
1340
+ msg = 'must be implemented in subclasses'
1341
+ raise NotImplementedError(msg)
1342
1342
 
1343
1343
  def newest_template_mtime(self) -> float:
1344
1344
  """Called by the builder to determine if output files are outdated
@@ -1351,10 +1351,12 @@ class TemplateBridge:
1351
1351
  """Called by the builder to render a template given as a filename with
1352
1352
  a specified context (a Python dictionary).
1353
1353
  """
1354
- raise NotImplementedError('must be implemented in subclasses')
1354
+ msg = 'must be implemented in subclasses'
1355
+ raise NotImplementedError(msg)
1355
1356
 
1356
1357
  def render_string(self, template: str, context: dict) -> str:
1357
1358
  """Called by the builder to render a template given as a string with a
1358
1359
  specified context (a Python dictionary).
1359
1360
  """
1360
- raise NotImplementedError('must be implemented in subclasses')
1361
+ msg = 'must be implemented in subclasses'
1362
+ raise NotImplementedError(msg)
@@ -6,35 +6,38 @@ import codecs
6
6
  import pickle
7
7
  import time
8
8
  from os import path
9
- from typing import TYPE_CHECKING, Any, Iterable, Sequence
9
+ from typing import TYPE_CHECKING, Any
10
10
 
11
11
  from docutils import nodes
12
- from docutils.nodes import Node
13
12
  from docutils.utils import DependencyList
14
13
 
15
- from sphinx.config import Config
16
14
  from sphinx.environment import CONFIG_CHANGED_REASON, CONFIG_OK, BuildEnvironment
17
15
  from sphinx.environment.adapters.asset import ImageAdapter
18
16
  from sphinx.errors import SphinxError
19
- from sphinx.events import EventManager
20
17
  from sphinx.locale import __
21
18
  from sphinx.util import UnicodeDecodeErrorHandler, get_filetype, import_object, logging, rst
22
19
  from sphinx.util.build_phase import BuildPhase
23
- from sphinx.util.console import bold # type: ignore
20
+ from sphinx.util.console import bold # type: ignore[attr-defined]
24
21
  from sphinx.util.display import progress_message, status_iterator
25
22
  from sphinx.util.docutils import sphinx_domains
26
23
  from sphinx.util.i18n import CatalogInfo, CatalogRepository, docname_to_domain
27
24
  from sphinx.util.osutil import SEP, ensuredir, relative_uri, relpath
28
25
  from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, parallel_available
29
- from sphinx.util.tags import Tags
30
- from sphinx.util.typing import NoneType
31
26
 
32
27
  # side effect: registers roles and directives
33
28
  from sphinx import directives # noqa: F401 isort:skip
34
29
  from sphinx import roles # noqa: F401 isort:skip
35
30
 
36
31
  if TYPE_CHECKING:
32
+ from collections.abc import Iterable, Sequence
33
+
34
+ from docutils.nodes import Node
35
+
37
36
  from sphinx.application import Sphinx
37
+ from sphinx.config import Config
38
+ from sphinx.events import EventManager
39
+ from sphinx.util.tags import Tags
40
+ from sphinx.util.typing import NoneType
38
41
 
39
42
 
40
43
  logger = logging.getLogger(__name__)
@@ -260,7 +263,7 @@ class Builder:
260
263
  filename)
261
264
  continue
262
265
 
263
- if not filename.startswith(self.srcdir):
266
+ if not filename.startswith(str(self.srcdir)):
264
267
  logger.warning(__('file %r given on command line is not under the '
265
268
  'source directory, ignoring'), filename)
266
269
  continue
@@ -322,9 +325,9 @@ class Builder:
322
325
  if updated_docnames:
323
326
  # save the environment
324
327
  from sphinx.application import ENV_PICKLE_FILENAME
325
- with progress_message(__('pickling environment')):
326
- with open(path.join(self.doctreedir, ENV_PICKLE_FILENAME), 'wb') as f:
327
- pickle.dump(self.env, f, pickle.HIGHEST_PROTOCOL)
328
+ with progress_message(__('pickling environment')), \
329
+ open(path.join(self.doctreedir, ENV_PICKLE_FILENAME), 'wb') as f:
330
+ pickle.dump(self.env, f, pickle.HIGHEST_PROTOCOL)
328
331
 
329
332
  # global actions
330
333
  self.app.phase = BuildPhase.CONSISTENCY_CHECK
@@ -488,7 +491,8 @@ class Builder:
488
491
  publisher.settings.record_dependencies = DependencyList()
489
492
  with sphinx_domains(self.env), rst.default_role(docname, self.config.default_role):
490
493
  # set up error_handler for the target document
491
- codecs.register_error('sphinx', UnicodeDecodeErrorHandler(docname)) # type: ignore
494
+ codecs.register_error('sphinx',
495
+ UnicodeDecodeErrorHandler(docname)) # type: ignore[arg-type]
492
496
 
493
497
  publisher.set_source(source_path=filename)
494
498
  publisher.publish()
@@ -5,13 +5,13 @@ from __future__ import annotations
5
5
  import html
6
6
  import os
7
7
  import re
8
+ import time
8
9
  from os import path
9
- from typing import Any, NamedTuple
10
+ from typing import TYPE_CHECKING, Any, NamedTuple
10
11
  from urllib.parse import quote
11
12
  from zipfile import ZIP_DEFLATED, ZIP_STORED, ZipFile
12
13
 
13
14
  from docutils import nodes
14
- from docutils.nodes import Element, Node
15
15
  from docutils.utils import smartquotes
16
16
 
17
17
  from sphinx import addnodes
@@ -20,8 +20,10 @@ from sphinx.locale import __
20
20
  from sphinx.util import logging
21
21
  from sphinx.util.display import status_iterator
22
22
  from sphinx.util.fileutil import copy_asset_file
23
- from sphinx.util.i18n import format_date
24
- from sphinx.util.osutil import copyfile, ensuredir
23
+ from sphinx.util.osutil import copyfile, ensuredir, relpath
24
+
25
+ if TYPE_CHECKING:
26
+ from docutils.nodes import Element, Node
25
27
 
26
28
  try:
27
29
  from PIL import Image
@@ -100,8 +102,7 @@ class NavPoint(NamedTuple):
100
102
  playorder: int
101
103
  text: str
102
104
  refuri: str
103
- children: list[Any] # mypy does not support recursive types
104
- # https://github.com/python/mypy/issues/7069
105
+ children: list[NavPoint]
105
106
 
106
107
 
107
108
  def sphinx_smarty_pants(t: str, language: str = 'en') -> str:
@@ -479,6 +480,12 @@ class EpubBuilder(StandaloneHTMLBuilder):
479
480
  """Create a dictionary with all metadata for the content.opf
480
481
  file properly escaped.
481
482
  """
483
+
484
+ if (source_date_epoch := os.getenv('SOURCE_DATE_EPOCH')) is not None:
485
+ time_tuple = time.gmtime(int(source_date_epoch))
486
+ else:
487
+ time_tuple = time.gmtime()
488
+
482
489
  metadata: dict[str, Any] = {}
483
490
  metadata['title'] = html.escape(self.config.epub_title)
484
491
  metadata['author'] = html.escape(self.config.epub_author)
@@ -488,7 +495,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
488
495
  metadata['copyright'] = html.escape(self.config.epub_copyright)
489
496
  metadata['scheme'] = html.escape(self.config.epub_scheme)
490
497
  metadata['id'] = html.escape(self.config.epub_identifier)
491
- metadata['date'] = html.escape(format_date("%Y-%m-%d", language='en'))
498
+ metadata['date'] = html.escape(time.strftime('%Y-%m-%d', time_tuple))
492
499
  metadata['manifest_items'] = []
493
500
  metadata['spines'] = []
494
501
  metadata['guides'] = []
@@ -502,9 +509,6 @@ class EpubBuilder(StandaloneHTMLBuilder):
502
509
  metadata = self.content_metadata()
503
510
 
504
511
  # files
505
- if not self.outdir.endswith(os.sep):
506
- self.outdir += os.sep
507
- olen = len(self.outdir)
508
512
  self.files: list[str] = []
509
513
  self.ignored_files = ['.buildinfo', 'mimetype', 'content.opf',
510
514
  'toc.ncx', 'META-INF/container.xml',
@@ -516,7 +520,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
516
520
  for root, dirs, files in os.walk(self.outdir):
517
521
  dirs.sort()
518
522
  for fn in sorted(files):
519
- filename = path.join(root, fn)[olen:]
523
+ filename = relpath(path.join(root, fn), self.outdir)
520
524
  if filename in self.ignored_files:
521
525
  continue
522
526
  ext = path.splitext(filename)[-1]
@@ -4,19 +4,21 @@ from __future__ import annotations
4
4
 
5
5
  import html
6
6
  from os import path
7
- from typing import Any, cast
7
+ from typing import TYPE_CHECKING, Any, cast
8
8
 
9
9
  from sphinx import package_dir
10
- from sphinx.application import Sphinx
11
10
  from sphinx.builders import Builder
12
11
  from sphinx.domains.changeset import ChangeSetDomain
13
12
  from sphinx.locale import _, __
14
13
  from sphinx.theming import HTMLThemeFactory
15
14
  from sphinx.util import logging
16
- from sphinx.util.console import bold # type: ignore
15
+ from sphinx.util.console import bold # type: ignore[attr-defined]
17
16
  from sphinx.util.fileutil import copy_asset_file
18
17
  from sphinx.util.osutil import ensuredir, os_path
19
18
 
19
+ if TYPE_CHECKING:
20
+ from sphinx.application import Sphinx
21
+
20
22
  logger = logging.getLogger(__name__)
21
23
 
22
24
 
@@ -34,7 +36,7 @@ class ChangesBuilder(Builder):
34
36
  self.templates.init(self, self.theme)
35
37
 
36
38
  def get_outdated_docs(self) -> str:
37
- return self.outdir
39
+ return str(self.outdir)
38
40
 
39
41
  typemap = {
40
42
  'versionadded': 'added',
@@ -3,13 +3,15 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from os import path
6
- from typing import Any
6
+ from typing import TYPE_CHECKING, Any
7
7
 
8
- from sphinx.application import Sphinx
9
8
  from sphinx.builders.html import StandaloneHTMLBuilder
10
9
  from sphinx.util import logging
11
10
  from sphinx.util.osutil import SEP, os_path
12
11
 
12
+ if TYPE_CHECKING:
13
+ from sphinx.application import Sphinx
14
+
13
15
  logger = logging.getLogger(__name__)
14
16
 
15
17
 
sphinx/builders/dummy.py CHANGED
@@ -2,14 +2,16 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Any
5
+ from typing import TYPE_CHECKING, Any
6
6
 
7
- from docutils.nodes import Node
8
-
9
- from sphinx.application import Sphinx
10
7
  from sphinx.builders import Builder
11
8
  from sphinx.locale import __
12
9
 
10
+ if TYPE_CHECKING:
11
+ from docutils.nodes import Node
12
+
13
+ from sphinx.application import Sphinx
14
+
13
15
 
14
16
  class DummyBuilder(Builder):
15
17
  name = 'dummy'