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
@@ -7,13 +7,18 @@ import pickle
7
7
  import re
8
8
  import time
9
9
  from contextlib import nullcontext
10
- from os import path
11
- from typing import TYPE_CHECKING, Any, Literal, final
10
+ from pathlib import Path
11
+ from typing import TYPE_CHECKING, final
12
12
 
13
13
  from docutils import nodes
14
14
  from docutils.utils import DependencyList
15
15
 
16
- from sphinx.environment import CONFIG_CHANGED_REASON, CONFIG_OK, BuildEnvironment
16
+ from sphinx._cli.util.colour import bold
17
+ from sphinx.environment import (
18
+ CONFIG_CHANGED_REASON,
19
+ CONFIG_OK,
20
+ _CurrentDocument,
21
+ )
17
22
  from sphinx.environment.adapters.asset import ImageAdapter
18
23
  from sphinx.errors import SphinxError
19
24
  from sphinx.locale import __
@@ -23,12 +28,12 @@ from sphinx.util import (
23
28
  rst,
24
29
  )
25
30
  from sphinx.util._importer import import_object
31
+ from sphinx.util._pathlib import _StrPathProperty
26
32
  from sphinx.util.build_phase import BuildPhase
27
- from sphinx.util.console import bold
28
33
  from sphinx.util.display import progress_message, status_iterator
29
34
  from sphinx.util.docutils import sphinx_domains
30
- from sphinx.util.i18n import CatalogInfo, CatalogRepository, docname_to_domain
31
- from sphinx.util.osutil import SEP, canon_path, ensuredir, relative_uri, relpath
35
+ from sphinx.util.i18n import CatalogRepository, docname_to_domain
36
+ from sphinx.util.osutil import ensuredir, relative_uri, relpath
32
37
  from sphinx.util.parallel import (
33
38
  ParallelTasks,
34
39
  SerialTasks,
@@ -42,12 +47,18 @@ from sphinx import roles # NoQA: F401 isort:skip
42
47
 
43
48
  if TYPE_CHECKING:
44
49
  from collections.abc import Iterable, Sequence, Set
50
+ from gettext import NullTranslations
51
+ from typing import Any, Literal
45
52
 
46
53
  from docutils.nodes import Node
47
54
 
48
55
  from sphinx.application import Sphinx
49
56
  from sphinx.config import Config
57
+ from sphinx.environment import (
58
+ BuildEnvironment,
59
+ )
50
60
  from sphinx.events import EventManager
61
+ from sphinx.util.i18n import CatalogInfo
51
62
  from sphinx.util.tags import Tags
52
63
 
53
64
 
@@ -55,9 +66,7 @@ logger = logging.getLogger(__name__)
55
66
 
56
67
 
57
68
  class Builder:
58
- """
59
- Builds target formats from the reST sources.
60
- """
69
+ """Builds target formats from the reST sources."""
61
70
 
62
71
  #: The builder's name.
63
72
  #: This is the value used to select builders on the command line.
@@ -80,7 +89,7 @@ class Builder:
80
89
  # doctree versioning method
81
90
  versioning_method = 'none'
82
91
  versioning_compare = False
83
- #: Whether it is safe to make parallel :meth:`~.Builder.write_doc()` calls.
92
+ #: Whether it is safe to make parallel :meth:`~.Builder.write_doc` calls.
84
93
  allow_parallel: bool = False
85
94
  # support translation
86
95
  use_message_catalog = True
@@ -93,6 +102,11 @@ class Builder:
93
102
  #: The file format produced by the builder allows images to be embedded using data-URIs.
94
103
  supported_data_uri_images: bool = False
95
104
 
105
+ srcdir = _StrPathProperty()
106
+ confdir = _StrPathProperty()
107
+ outdir = _StrPathProperty()
108
+ doctreedir = _StrPathProperty()
109
+
96
110
  def __init__(self, app: Sphinx, env: BuildEnvironment) -> None:
97
111
  self.srcdir = app.srcdir
98
112
  self.confdir = app.confdir
@@ -122,9 +136,13 @@ class Builder:
122
136
  self.parallel_ok = False
123
137
  self.finish_tasks: Any = None
124
138
 
139
+ @property
140
+ def _translator(self) -> NullTranslations | None:
141
+ return self.app.translator
142
+
125
143
  def get_translator_class(self, *args: Any) -> type[nodes.NodeVisitor]:
126
144
  """Return a class of translator."""
127
- return self.app.registry.get_translator_class(self)
145
+ return self.env._registry.get_translator_class(self)
128
146
 
129
147
  def create_translator(self, *args: Any) -> nodes.NodeVisitor:
130
148
  """Return an instance of translator.
@@ -132,7 +150,7 @@ class Builder:
132
150
  This method returns an instance of ``default_translator_class`` by default.
133
151
  Users can replace the translator class with ``app.set_translator()`` API.
134
152
  """
135
- return self.app.registry.create_translator(self, *args)
153
+ return self.env._registry.create_translator(self, *args)
136
154
 
137
155
  # helper methods
138
156
  def init(self) -> None:
@@ -203,7 +221,7 @@ class Builder:
203
221
  image_uri = images.get_original_image_uri(node['uri'])
204
222
  if mimetypes:
205
223
  logger.warning(
206
- __('a suitable image for %s builder not found: ' '%s (%s)'),
224
+ __('a suitable image for %s builder not found: %s (%s)'),
207
225
  self.name,
208
226
  mimetypes,
209
227
  image_uri,
@@ -231,10 +249,10 @@ class Builder:
231
249
  if not self.config.gettext_auto_build:
232
250
  return
233
251
 
234
- def cat2relpath(cat: CatalogInfo) -> str:
235
- return relpath(cat.mo_path, self.env.srcdir).replace(path.sep, SEP)
252
+ def cat2relpath(cat: CatalogInfo, srcdir: Path = self.srcdir) -> str:
253
+ return Path(relpath(cat.mo_path, srcdir)).as_posix()
236
254
 
237
- logger.info(bold(__('building [mo]: ')) + message)
255
+ logger.info(bold(__('building [mo]: ')) + message) # NoQA: G003
238
256
  for catalog in status_iterator(
239
257
  catalogs,
240
258
  __('writing output... '),
@@ -257,16 +275,16 @@ class Builder:
257
275
  message = __('all of %d po files') % len(list(repo.catalogs))
258
276
  self.compile_catalogs(set(repo.catalogs), message)
259
277
 
260
- def compile_specific_catalogs(self, specified_files: list[str]) -> None:
261
- def to_domain(fpath: str) -> str | None:
262
- docname = self.env.path2doc(path.abspath(fpath))
263
- if docname:
264
- return docname_to_domain(docname, self.config.gettext_compact)
265
- else:
266
- return None
278
+ def compile_specific_catalogs(self, specified_files: Iterable[Path]) -> None:
279
+ env = self.env
280
+ gettext_compact = self.config.gettext_compact
267
281
 
282
+ domains = {
283
+ docname_to_domain(docname, gettext_compact) if docname else None
284
+ for file in specified_files
285
+ if (docname := env.path2doc(file))
286
+ }
268
287
  catalogs = set()
269
- domains = set(map(to_domain, specified_files))
270
288
  repo = CatalogRepository(
271
289
  self.srcdir,
272
290
  self.config.locale_dirs,
@@ -301,20 +319,19 @@ class Builder:
301
319
  self.build(None, summary=__('all source files'), method='all')
302
320
 
303
321
  @final
304
- def build_specific(self, filenames: list[str]) -> None:
322
+ def build_specific(self, filenames: Sequence[Path]) -> None:
305
323
  """Only rebuild as much as needed for changes in the *filenames*."""
306
324
  docnames: list[str] = []
307
325
 
326
+ filenames = [Path(filename).resolve() for filename in filenames]
308
327
  for filename in filenames:
309
- filename = path.normpath(path.abspath(filename))
310
-
311
- if not path.isfile(filename):
328
+ if not filename.is_file():
312
329
  logger.warning(
313
330
  __('file %r given on command line does not exist, '), filename
314
331
  )
315
332
  continue
316
333
 
317
- if not filename.startswith(str(self.srcdir)):
334
+ if not filename.is_relative_to(self.srcdir):
318
335
  logger.warning(
319
336
  __(
320
337
  'file %r given on command line is not under the '
@@ -341,8 +358,8 @@ class Builder:
341
358
 
342
359
  self.build(
343
360
  docnames,
344
- method='specific',
345
361
  summary=__('%d source files given on command line') % len(docnames),
362
+ method='specific',
346
363
  )
347
364
 
348
365
  @final
@@ -352,13 +369,14 @@ class Builder:
352
369
 
353
370
  to_build = self.get_outdated_docs()
354
371
  if isinstance(to_build, str):
355
- self.build(['__all__'], to_build)
372
+ self.build(['__all__'], summary=to_build, method='update')
356
373
  else:
357
- to_build = list(to_build)
374
+ to_build = set(to_build)
358
375
  self.build(
359
376
  to_build,
360
377
  summary=__('targets for %d source files that are out of date')
361
378
  % len(to_build),
379
+ method='update',
362
380
  )
363
381
 
364
382
  @final
@@ -374,7 +392,7 @@ class Builder:
374
392
  :meth:`!write`.
375
393
  """
376
394
  if summary:
377
- logger.info(bold(__('building [%s]: ')) + summary, self.name)
395
+ logger.info(bold(__('building [%s]: ')) + summary, self.name) # NoQA: G003
378
396
 
379
397
  # while reading, collect all warnings from docutils
380
398
  with (
@@ -399,7 +417,7 @@ class Builder:
399
417
 
400
418
  with (
401
419
  progress_message(__('pickling environment')),
402
- open(path.join(self.doctreedir, ENV_PICKLE_FILENAME), 'wb') as f,
420
+ open(self.doctreedir / ENV_PICKLE_FILENAME, 'wb') as f,
403
421
  ):
404
422
  pickle.dump(self.env, f, pickle.HIGHEST_PROTOCOL)
405
423
 
@@ -410,7 +428,6 @@ class Builder:
410
428
  else:
411
429
  if method == 'update' and not docnames:
412
430
  logger.info(bold(__('no targets are out of date.')))
413
- return
414
431
 
415
432
  self.app.phase = BuildPhase.RESOLVING
416
433
 
@@ -434,7 +451,7 @@ class Builder:
434
451
  self.finish_tasks = SerialTasks()
435
452
 
436
453
  # write all "normal" documents (or everything for some builders)
437
- self.write(docnames, list(updated_docnames), method)
454
+ self.write(docnames, updated_docnames, method)
438
455
 
439
456
  # finish (write static files etc.)
440
457
  self.finish()
@@ -506,7 +523,7 @@ class Builder:
506
523
  from sphinx.util.matching import _translate_pattern
507
524
 
508
525
  master_doc_path = self.env.doc2path(self.config.master_doc)
509
- master_doc_canon = canon_path(master_doc_path)
526
+ master_doc_canon = master_doc_path.as_posix()
510
527
  for pat in EXCLUDE_PATHS:
511
528
  if not re.match(_translate_pattern(pat), master_doc_canon):
512
529
  continue
@@ -604,22 +621,23 @@ class Builder:
604
621
  @final
605
622
  def read_doc(self, docname: str, *, _cache: bool = True) -> None:
606
623
  """Parse a file and add/update inventory entries for the doctree."""
607
- self.env.prepare_settings(docname)
624
+ env = self.env
625
+ env.prepare_settings(docname)
608
626
 
609
627
  # Add confdir/docutils.conf to dependencies list if exists
610
- docutilsconf = path.join(self.confdir, 'docutils.conf')
611
- if path.isfile(docutilsconf):
612
- self.env.note_dependency(docutilsconf)
628
+ docutils_conf = self.confdir / 'docutils.conf'
629
+ if docutils_conf.is_file():
630
+ env.note_dependency(docutils_conf)
613
631
 
614
- filename = str(self.env.doc2path(docname))
632
+ filename = str(env.doc2path(docname))
615
633
  filetype = get_filetype(self.app.config.source_suffix, filename)
616
- publisher = self.app.registry.get_publisher(self.app, filetype)
617
- self.env.temp_data['_parser'] = publisher.parser
634
+ publisher = self.env._registry.get_publisher(self.app, filetype)
635
+ self.env.current_document._parser = publisher.parser
618
636
  # record_dependencies is mutable even though it is in settings,
619
637
  # explicitly re-initialise for each document
620
638
  publisher.settings.record_dependencies = DependencyList()
621
639
  with (
622
- sphinx_domains(self.env),
640
+ sphinx_domains(env),
623
641
  rst.default_role(docname, self.config.default_role),
624
642
  ):
625
643
  # set up error_handler for the target document
@@ -631,11 +649,11 @@ class Builder:
631
649
  doctree = publisher.document
632
650
 
633
651
  # store time of reading, for outdated files detection
634
- self.env.all_docs[docname] = time.time_ns() // 1_000
652
+ env.all_docs[docname] = time.time_ns() // 1_000
635
653
 
636
654
  # cleanup
637
- self.env.temp_data.clear()
638
- self.env.ref_context.clear()
655
+ env.current_document = _CurrentDocument()
656
+ env.ref_context.clear()
639
657
 
640
658
  self.write_doctree(docname, doctree, _cache=_cache)
641
659
 
@@ -648,7 +666,7 @@ class Builder:
648
666
  _cache: bool = True,
649
667
  ) -> None:
650
668
  """Write the doctree to a file, to be used as a cache by re-builds."""
651
- # make it picklable
669
+ # make it pickleable
652
670
  doctree.reporter = None # type: ignore[assignment]
653
671
  doctree.transformer = None # type: ignore[assignment]
654
672
 
@@ -659,8 +677,8 @@ class Builder:
659
677
  doctree.settings.env = None
660
678
  doctree.settings.record_dependencies = None
661
679
 
662
- doctree_filename = path.join(self.doctreedir, docname + '.doctree')
663
- ensuredir(path.dirname(doctree_filename))
680
+ doctree_filename = self.doctreedir / f'{docname}.doctree'
681
+ doctree_filename.parent.mkdir(parents=True, exist_ok=True)
664
682
  with open(doctree_filename, 'wb') as f:
665
683
  pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
666
684
 
@@ -674,33 +692,38 @@ class Builder:
674
692
  def write(
675
693
  self,
676
694
  build_docnames: Iterable[str] | None,
677
- updated_docnames: Sequence[str],
695
+ updated_docnames: Iterable[str],
678
696
  method: Literal['all', 'specific', 'update'] = 'update',
679
697
  ) -> None:
680
698
  """Write builder specific output files."""
699
+ env = self.env
700
+
681
701
  # Allow any extensions to perform setup for writing
682
702
  self.events.emit('write-started', self)
683
703
 
684
704
  if build_docnames is None or build_docnames == ['__all__']:
685
705
  # build_all
686
- build_docnames = self.env.found_docs
706
+ build_docnames = env.found_docs
687
707
  if method == 'update':
688
708
  # build updated ones as well
689
709
  docnames = set(build_docnames) | set(updated_docnames)
690
710
  else:
691
711
  docnames = set(build_docnames)
692
- logger.debug(__('docnames to write: %s'), ', '.join(sorted(docnames)))
712
+ if docnames:
713
+ logger.debug(__('docnames to write: %s'), ', '.join(sorted(docnames)))
714
+ else:
715
+ logger.debug(__('no docnames to write!'))
693
716
 
694
717
  # add all toctree-containing files that may have changed
695
- extra = {self.config.root_doc}
696
- for docname in docnames:
697
- for tocdocname in self.env.files_to_rebuild.get(docname, set()):
698
- if tocdocname in self.env.found_docs:
699
- extra.add(tocdocname)
700
- docnames |= extra
718
+ docnames |= {
719
+ toc_docname
720
+ for docname in docnames
721
+ for toc_docname in env.files_to_rebuild.get(docname, ())
722
+ if toc_docname in env.found_docs
723
+ }
701
724
 
702
725
  # sort to ensure deterministic toctree generation
703
- self.env.toctree_includes = dict(sorted(self.env.toctree_includes.items()))
726
+ env.toctree_includes = dict(sorted(env.toctree_includes.items()))
704
727
 
705
728
  with progress_message(__('preparing documents')):
706
729
  self.prepare_writing(docnames)
@@ -708,7 +731,8 @@ class Builder:
708
731
  with progress_message(__('copying assets'), nonl=False):
709
732
  self.copy_assets()
710
733
 
711
- self.write_documents(docnames)
734
+ if docnames:
735
+ self.write_documents(docnames)
712
736
 
713
737
  def write_documents(self, docnames: Set[str]) -> None:
714
738
  """Write all documents in *docnames*.
@@ -795,8 +819,7 @@ class Builder:
795
819
  pass
796
820
 
797
821
  def write_doc(self, docname: str, doctree: nodes.document) -> None:
798
- """
799
- Write the output file for the document
822
+ """Write the output file for the document
800
823
 
801
824
  :param docname: the :term:`docname <document name>`.
802
825
  :param doctree: defines the content to be written.