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
@@ -3,13 +3,15 @@ from __future__ import annotations
3
3
  import os
4
4
  import warnings
5
5
  import zlib
6
- from typing import TYPE_CHECKING, Any, NoReturn
6
+ from functools import cache
7
+ from typing import TYPE_CHECKING
7
8
 
8
9
  from sphinx.deprecation import RemovedInSphinx90Warning
9
10
  from sphinx.errors import ThemeError
10
11
 
11
12
  if TYPE_CHECKING:
12
13
  from pathlib import Path
14
+ from typing import Any, NoReturn
13
15
 
14
16
 
15
17
  class _CascadingStyleSheet:
@@ -172,9 +174,14 @@ def _file_checksum(outdir: Path, filename: str | os.PathLike[str]) -> str:
172
174
  if '?' in filename:
173
175
  msg = f'Local asset file paths must not contain query strings: {filename!r}'
174
176
  raise ThemeError(msg)
177
+ return _file_checksum_inner(outdir.joinpath(filename).resolve())
178
+
179
+
180
+ @cache
181
+ def _file_checksum_inner(file: Path) -> str:
175
182
  try:
176
183
  # Remove all carriage returns to avoid checksum differences
177
- content = outdir.joinpath(filename).read_bytes().translate(None, b'\r')
184
+ content = file.read_bytes().translate(None, b'\r')
178
185
  except FileNotFoundError:
179
186
  return ''
180
187
  if not content:
@@ -65,6 +65,9 @@ class BuildInfo:
65
65
  self.config_hash == other.config_hash and self.tags_hash == other.tags_hash
66
66
  )
67
67
 
68
+ def __hash__(self) -> int:
69
+ return hash((self.config_hash, self.tags_hash))
70
+
68
71
  def dump(self, filename: Path, /) -> None:
69
72
  build_info = (
70
73
  '# Sphinx build info version 1\n'
@@ -3,14 +3,16 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import os
6
+ import os.path
6
7
  import warnings
7
- from os import path
8
- from typing import TYPE_CHECKING, Any
8
+ from pathlib import Path
9
+ from typing import TYPE_CHECKING
9
10
 
10
11
  from docutils.frontend import OptionParser
11
12
 
12
- import sphinx.builders.latex.nodes # NoQA: F401,E501 # Workaround: import this before writer to avoid ImportError
13
+ import sphinx.builders.latex.nodes # NoQA: F401 # Workaround: import this before writer to avoid ImportError
13
14
  from sphinx import addnodes, highlighting, package_dir
15
+ from sphinx._cli.util.colour import darkgreen
14
16
  from sphinx.builders import Builder
15
17
  from sphinx.builders.latex.constants import (
16
18
  ADDITIONAL_SETTINGS,
@@ -19,12 +21,11 @@ from sphinx.builders.latex.constants import (
19
21
  )
20
22
  from sphinx.builders.latex.theming import Theme, ThemeFactory
21
23
  from sphinx.builders.latex.util import ExtBabel
22
- from sphinx.config import ENUM, Config
24
+ from sphinx.config import ENUM
23
25
  from sphinx.environment.adapters.asset import ImageAdapter
24
26
  from sphinx.errors import NoUri, SphinxError
25
27
  from sphinx.locale import _, __
26
28
  from sphinx.util import logging, texescape
27
- from sphinx.util.console import darkgreen
28
29
  from sphinx.util.display import progress_message, status_iterator
29
30
  from sphinx.util.docutils import SphinxFileOutput, new_document
30
31
  from sphinx.util.fileutil import copy_asset_file
@@ -39,10 +40,12 @@ from docutils import nodes # isort:skip
39
40
 
40
41
  if TYPE_CHECKING:
41
42
  from collections.abc import Iterable, Set
43
+ from typing import Any
42
44
 
43
45
  from docutils.nodes import Node
44
46
 
45
47
  from sphinx.application import Sphinx
48
+ from sphinx.config import Config
46
49
  from sphinx.util.typing import ExtensionMetadata
47
50
 
48
51
  XINDY_LANG_OPTIONS = {
@@ -102,15 +105,13 @@ XINDY_LANG_OPTIONS = {
102
105
  'el-polyton': '-L greek-polytonic -C utf8 ',
103
106
  } # fmt: skip
104
107
 
105
- XINDY_CYRILLIC_SCRIPTS = ['be', 'bg', 'mk', 'mn', 'ru', 'sr', 'sh', 'uk']
108
+ XINDY_CYRILLIC_SCRIPTS = frozenset({'be', 'bg', 'mk', 'mn', 'ru', 'sr', 'sh', 'uk'})
106
109
 
107
110
  logger = logging.getLogger(__name__)
108
111
 
109
112
 
110
113
  class LaTeXBuilder(Builder):
111
- """
112
- Builds LaTeX output to create PDF.
113
- """
114
+ """Builds LaTeX output to create PDF."""
114
115
 
115
116
  name = 'latex'
116
117
  format = 'latex'
@@ -166,10 +167,7 @@ class LaTeXBuilder(Builder):
166
167
  docname = entry[0]
167
168
  if docname not in self.env.all_docs:
168
169
  logger.warning(
169
- __(
170
- '"latex_documents" config value references unknown '
171
- 'document %s'
172
- ),
170
+ __('"latex_documents" config value references unknown document %s'),
173
171
  docname,
174
172
  )
175
173
  continue
@@ -202,7 +200,7 @@ class LaTeXBuilder(Builder):
202
200
  self.context['date'] = format_date(today_fmt, language=self.config.language)
203
201
 
204
202
  if self.config.latex_logo:
205
- self.context['logofilename'] = path.basename(self.config.latex_logo)
203
+ self.context['logofilename'] = os.path.basename(self.config.latex_logo)
206
204
 
207
205
  # for compatibilities
208
206
  self.context['indexname'] = _('Index')
@@ -213,7 +211,7 @@ class LaTeXBuilder(Builder):
213
211
  def update_context(self) -> None:
214
212
  """Update template variables for .tex file just before writing."""
215
213
  # Apply extension settings to context
216
- registry = self.app.registry
214
+ registry = self.env._registry
217
215
  self.context['packages'] = registry.latex_packages
218
216
  self.context['packages_after_hyperref'] = registry.latex_packages_after_hyperref
219
217
 
@@ -249,7 +247,7 @@ class LaTeXBuilder(Builder):
249
247
  )
250
248
  else:
251
249
  self.context['textgreek'] = ''
252
- if self.context['substitutefont'] == '':
250
+ if not self.context['substitutefont']:
253
251
  self.context['fontsubstitution'] = ''
254
252
 
255
253
  # 'babel' key is public and user setting must be obeyed
@@ -279,7 +277,7 @@ class LaTeXBuilder(Builder):
279
277
 
280
278
  def write_stylesheet(self) -> None:
281
279
  highlighter = highlighting.PygmentsBridge('latex', self.config.pygments_style)
282
- stylesheet = path.join(self.outdir, 'sphinxhighlight.sty')
280
+ stylesheet = self.outdir / 'sphinxhighlight.sty'
283
281
  with open(stylesheet, 'w', encoding='utf-8') as f:
284
282
  f.write('\\NeedsTeXFormat{LaTeX2e}[1995/12/01]\n')
285
283
  f.write(
@@ -320,7 +318,7 @@ class LaTeXBuilder(Builder):
320
318
  if len(entry) > 5:
321
319
  toctree_only = entry[5]
322
320
  destination = SphinxFileOutput(
323
- destination_path=path.join(self.outdir, targetname),
321
+ destination_path=self.outdir / targetname,
324
322
  encoding='utf-8',
325
323
  overwrite_if_changed=True,
326
324
  )
@@ -420,8 +418,6 @@ class LaTeXBuilder(Builder):
420
418
  nodes.Text(')'),
421
419
  ))
422
420
  break
423
- else:
424
- pass
425
421
  pendingnode.replace_self(newnodes)
426
422
  return largetree
427
423
 
@@ -446,11 +442,11 @@ class LaTeXBuilder(Builder):
446
442
  'xindy_lang_option': xindy_lang_option,
447
443
  'xindy_cyrillic': xindy_cyrillic,
448
444
  }
449
- staticdirname = path.join(package_dir, 'texinputs')
450
- for filename in os.listdir(staticdirname):
451
- if not filename.startswith('.'):
445
+ static_dir_name = package_dir / 'texinputs'
446
+ for filename in Path(static_dir_name).iterdir():
447
+ if not filename.name.startswith('.'):
452
448
  copy_asset_file(
453
- path.join(staticdirname, filename),
449
+ static_dir_name / filename,
454
450
  self.outdir,
455
451
  context=context,
456
452
  force=True,
@@ -458,9 +454,9 @@ class LaTeXBuilder(Builder):
458
454
 
459
455
  # use pre-1.6.x Makefile for make latexpdf on Windows
460
456
  if os.name == 'nt':
461
- staticdirname = path.join(package_dir, 'texinputs_win')
457
+ static_dir_name = package_dir / 'texinputs_win'
462
458
  copy_asset_file(
463
- path.join(staticdirname, 'Makefile.jinja'),
459
+ static_dir_name / 'Makefile.jinja',
464
460
  self.outdir,
465
461
  context=context,
466
462
  force=True,
@@ -469,7 +465,7 @@ class LaTeXBuilder(Builder):
469
465
  @progress_message(__('copying additional files'))
470
466
  def copy_latex_additional_files(self) -> None:
471
467
  for filename in self.config.latex_additional_files:
472
- logger.info(' ' + filename, nonl=True)
468
+ logger.info(' %s', filename, nonl=True)
473
469
  source = self.confdir / filename
474
470
  copyfile(
475
471
  source,
@@ -479,7 +475,7 @@ class LaTeXBuilder(Builder):
479
475
 
480
476
  def copy_image_files(self) -> None:
481
477
  if self.images:
482
- stringify_func = ImageAdapter(self.app.env).get_original_image_uri
478
+ stringify_func = ImageAdapter(self.env).get_original_image_uri
483
479
  for src in status_iterator(
484
480
  self.images,
485
481
  __('copying images... '),
@@ -498,15 +494,15 @@ class LaTeXBuilder(Builder):
498
494
  except Exception as err:
499
495
  logger.warning(
500
496
  __('cannot copy image file %r: %s'),
501
- path.join(self.srcdir, src),
497
+ self.srcdir / src,
502
498
  err,
503
499
  )
504
500
  if self.config.latex_logo:
505
- if not path.isfile(path.join(self.confdir, self.config.latex_logo)):
501
+ source = self.confdir / self.config.latex_logo
502
+ if not source.is_file():
506
503
  raise SphinxError(
507
504
  __('logo file %r does not exist') % self.config.latex_logo
508
505
  )
509
- source = self.confdir / self.config.latex_logo
510
506
  copyfile(
511
507
  source,
512
508
  self.outdir / source.name,
@@ -525,11 +521,8 @@ class LaTeXBuilder(Builder):
525
521
  if self.context['babel'] or self.context['polyglossia']:
526
522
  context['addtocaptions'] = r'\addto\captions%s' % self.babel.get_language()
527
523
 
528
- filename = path.join(
529
- package_dir, 'templates', 'latex', 'sphinxmessages.sty.jinja'
530
- )
531
524
  copy_asset_file(
532
- filename,
525
+ package_dir.joinpath('templates', 'latex', 'sphinxmessages.sty.jinja'),
533
526
  self.outdir,
534
527
  context=context,
535
528
  renderer=LaTeXRenderer(),
@@ -555,7 +548,7 @@ def validate_latex_theme_options(app: Sphinx, config: Config) -> None:
555
548
 
556
549
  def install_packages_for_ja(app: Sphinx) -> None:
557
550
  """Install packages for Japanese."""
558
- if app.config.language == 'ja' and app.config.latex_engine in ('platex', 'uplatex'):
551
+ if app.config.language == 'ja' and app.config.latex_engine in {'platex', 'uplatex'}:
559
552
  app.add_latex_package('pxjahyper', after_hyperref=True)
560
553
 
561
554
 
@@ -613,27 +606,44 @@ def setup(app: Sphinx) -> ExtensionMetadata:
613
606
  'latex_engine',
614
607
  default_latex_engine,
615
608
  '',
616
- ENUM('pdflatex', 'xelatex', 'lualatex', 'platex', 'uplatex'),
609
+ types=ENUM('pdflatex', 'xelatex', 'lualatex', 'platex', 'uplatex'),
610
+ )
611
+ app.add_config_value(
612
+ 'latex_documents', default_latex_documents, '', types=frozenset({list, tuple})
613
+ )
614
+ app.add_config_value('latex_logo', None, '', types=frozenset({str}))
615
+ app.add_config_value('latex_appendices', [], '', types=frozenset({list, tuple}))
616
+ app.add_config_value(
617
+ 'latex_use_latex_multicolumn', False, '', types=frozenset({bool})
618
+ )
619
+ app.add_config_value(
620
+ 'latex_use_xindy', default_latex_use_xindy, '', types=frozenset({bool})
621
+ )
622
+ app.add_config_value(
623
+ 'latex_toplevel_sectioning',
624
+ None,
625
+ '',
626
+ types=ENUM(None, 'part', 'chapter', 'section'),
627
+ )
628
+ app.add_config_value(
629
+ 'latex_domain_indices', True, '', types=frozenset({frozenset, list, set, tuple})
617
630
  )
618
- app.add_config_value('latex_documents', default_latex_documents, '')
619
- app.add_config_value('latex_logo', None, '', str)
620
- app.add_config_value('latex_appendices', [], '')
621
- app.add_config_value('latex_use_latex_multicolumn', False, '')
622
- app.add_config_value('latex_use_xindy', default_latex_use_xindy, '', bool)
631
+ app.add_config_value('latex_show_urls', 'no', '', types=frozenset({str}))
632
+ app.add_config_value('latex_show_pagerefs', False, '', types=frozenset({bool}))
633
+ app.add_config_value('latex_elements', {}, '', types=frozenset({dict}))
634
+ app.add_config_value(
635
+ 'latex_additional_files', [], '', types=frozenset({list, tuple})
636
+ )
637
+ app.add_config_value(
638
+ 'latex_table_style', ['booktabs', 'colorrows'], '', types=frozenset({list})
639
+ )
640
+ app.add_config_value('latex_theme', 'manual', '', types=frozenset({str}))
641
+ app.add_config_value('latex_theme_options', {}, '', types=frozenset({dict}))
642
+ app.add_config_value('latex_theme_path', [], '', types=frozenset({list}))
643
+
623
644
  app.add_config_value(
624
- 'latex_toplevel_sectioning', None, '', ENUM(None, 'part', 'chapter', 'section')
645
+ 'latex_docclass', default_latex_docclass, '', types=frozenset({dict})
625
646
  )
626
- app.add_config_value('latex_domain_indices', True, '', types={set, list})
627
- app.add_config_value('latex_show_urls', 'no', '')
628
- app.add_config_value('latex_show_pagerefs', False, '')
629
- app.add_config_value('latex_elements', {}, '')
630
- app.add_config_value('latex_additional_files', [], '')
631
- app.add_config_value('latex_table_style', ['booktabs', 'colorrows'], '', list)
632
- app.add_config_value('latex_theme', 'manual', '', str)
633
- app.add_config_value('latex_theme_options', {}, '')
634
- app.add_config_value('latex_theme_path', [], '', list)
635
-
636
- app.add_config_value('latex_docclass', default_latex_docclass, '')
637
647
 
638
648
  return {
639
649
  'version': 'builtin',
@@ -2,15 +2,18 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Any
5
+ from typing import TYPE_CHECKING
6
6
 
7
- PDFLATEX_DEFAULT_FONTPKG = r'''
7
+ if TYPE_CHECKING:
8
+ from typing import Any
9
+
10
+ PDFLATEX_DEFAULT_FONTPKG = r"""
8
11
  \usepackage{tgtermes}
9
12
  \usepackage{tgheros}
10
13
  \renewcommand{\ttdefault}{txtt}
11
- '''
14
+ """
12
15
 
13
- PDFLATEX_DEFAULT_FONTSUBSTITUTION = r'''
16
+ PDFLATEX_DEFAULT_FONTSUBSTITUTION = r"""
14
17
  \expandafter\ifx\csname T@LGR\endcsname\relax
15
18
  \else
16
19
  % LGR was declared as font encoding
@@ -32,9 +35,9 @@ PDFLATEX_DEFAULT_FONTSUBSTITUTION = r'''
32
35
  \substitutefont{X2}{\sfdefault}{cmss}
33
36
  \substitutefont{X2}{\ttdefault}{cmtt}
34
37
  \fi
35
- '''
38
+ """
36
39
 
37
- XELATEX_DEFAULT_FONTPKG = r'''
40
+ XELATEX_DEFAULT_FONTPKG = r"""
38
41
  \setmainfont{FreeSerif}[
39
42
  Extension = .otf,
40
43
  UprightFont = *,
@@ -56,7 +59,7 @@ XELATEX_DEFAULT_FONTPKG = r'''
56
59
  BoldFont = *Bold,
57
60
  BoldItalicFont = *BoldOblique,
58
61
  ]
59
- '''
62
+ """
60
63
 
61
64
  XELATEX_GREEK_DEFAULT_FONTPKG = (
62
65
  XELATEX_DEFAULT_FONTPKG
@@ -117,7 +120,7 @@ DEFAULT_SETTINGS: dict[str, Any] = {
117
120
  'figure_align': 'htbp',
118
121
  'tocdepth': '',
119
122
  'secnumdepth': '',
120
- }
123
+ } # fmt: skip
121
124
 
122
125
  ADDITIONAL_SETTINGS: dict[Any, dict[str, Any]] = {
123
126
  'pdflatex': {
@@ -204,12 +207,12 @@ ADDITIONAL_SETTINGS: dict[Any, dict[str, Any]] = {
204
207
  ('xelatex', 'el'): {
205
208
  'fontpkg': XELATEX_GREEK_DEFAULT_FONTPKG,
206
209
  },
207
- }
210
+ } # fmt: skip
208
211
 
209
212
 
210
- SHORTHANDOFF = r'''
213
+ SHORTHANDOFF = r"""
211
214
  \ifdefined\shorthandoff
212
215
  \ifnum\catcode`\=\string=\active\shorthandoff{=}\fi
213
216
  \ifnum\catcode`\"=\active\shorthandoff{"}\fi
214
217
  \fi
215
- '''
218
+ """
@@ -1,5 +1,7 @@
1
1
  """Additional nodes for LaTeX writer."""
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  from docutils import nodes
4
6
 
5
7
 
@@ -3,7 +3,6 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import configparser
6
- from os import path
7
6
  from typing import TYPE_CHECKING
8
7
 
9
8
  from sphinx.errors import ThemeError
@@ -11,6 +10,8 @@ from sphinx.locale import __
11
10
  from sphinx.util import logging
12
11
 
13
12
  if TYPE_CHECKING:
13
+ from pathlib import Path
14
+
14
15
  from sphinx.application import Sphinx
15
16
  from sphinx.config import Config
16
17
 
@@ -55,7 +56,7 @@ class BuiltInTheme(Theme):
55
56
  else:
56
57
  self.docclass = config.latex_docclass.get('manual', 'report')
57
58
 
58
- if name in ('manual', 'howto'):
59
+ if name in {'manual', 'howto'}:
59
60
  self.wrapperclass = 'sphinx' + name
60
61
  else:
61
62
  self.wrapperclass = name
@@ -74,10 +75,10 @@ class UserTheme(Theme):
74
75
  REQUIRED_CONFIG_KEYS = ['docclass', 'wrapperclass']
75
76
  OPTIONAL_CONFIG_KEYS = ['papersize', 'pointsize', 'toplevel_sectioning']
76
77
 
77
- def __init__(self, name: str, filename: str) -> None:
78
+ def __init__(self, name: str, filename: Path) -> None:
78
79
  super().__init__(name)
79
80
  self.config = configparser.RawConfigParser()
80
- self.config.read(path.join(filename), encoding='utf-8')
81
+ self.config.read(filename, encoding='utf-8')
81
82
 
82
83
  for key in self.REQUIRED_CONFIG_KEYS:
83
84
  try:
@@ -103,9 +104,7 @@ class ThemeFactory:
103
104
 
104
105
  def __init__(self, app: Sphinx) -> None:
105
106
  self.themes: dict[str, Theme] = {}
106
- self.theme_paths = [
107
- path.join(app.srcdir, p) for p in app.config.latex_theme_path
108
- ]
107
+ self.theme_paths = [app.srcdir / p for p in app.config.latex_theme_path]
109
108
  self.config = app.config
110
109
  self.load_builtin_themes(app.config)
111
110
 
@@ -127,8 +126,8 @@ class ThemeFactory:
127
126
  def find_user_theme(self, name: str) -> Theme | None:
128
127
  """Find a theme named as *name* from latex_theme_path."""
129
128
  for theme_path in self.theme_paths:
130
- config_path = path.join(theme_path, name, 'theme.conf')
131
- if path.isfile(config_path):
129
+ config_path = theme_path / name / 'theme.conf'
130
+ if config_path.is_file():
132
131
  try:
133
132
  return UserTheme(name, config_path)
134
133
  except ThemeError as exc:
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Any, cast
5
+ from typing import TYPE_CHECKING, cast
6
6
 
7
7
  from docutils import nodes
8
8
  from docutils.transforms.references import Substitutions
@@ -21,6 +21,8 @@ from sphinx.transforms.post_transforms import SphinxPostTransform
21
21
  from sphinx.util.nodes import NodeMatcher
22
22
 
23
23
  if TYPE_CHECKING:
24
+ from typing import Any
25
+
24
26
  from docutils.nodes import Element, Node
25
27
 
26
28
  from sphinx.application import Sphinx
@@ -151,7 +153,7 @@ class ShowUrlsTransform(SphinxPostTransform):
151
153
  break
152
154
 
153
155
  # assign new footnote number
154
- old_label = cast(nodes.label, footnote[0])
156
+ old_label = cast('nodes.label', footnote[0])
155
157
  old_label.replace_self(nodes.label('', str(num)))
156
158
  if old_label in footnote['names']:
157
159
  footnote['names'].remove(old_label.astext())
@@ -455,7 +457,7 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
455
457
  number = node.astext().strip()
456
458
  docname = node['docname']
457
459
  if (docname, number) in self.appeared:
458
- footnote = self.appeared[(docname, number)]
460
+ footnote = self.appeared[docname, number]
459
461
  footnote['referred'] = True
460
462
 
461
463
  mark = footnotemark('', number, refid=node['refid'])
@@ -471,7 +473,7 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
471
473
  node.replace_self(footnote)
472
474
  footnote.walkabout(self)
473
475
 
474
- self.appeared[(docname, number)] = footnote
476
+ self.appeared[docname, number] = footnote
475
477
  raise nodes.SkipNode
476
478
 
477
479
  def get_footnote_by_reference(
@@ -566,7 +568,7 @@ class MathReferenceTransform(SphinxPostTransform):
566
568
  def run(self, **kwargs: Any) -> None:
567
569
  equations = self.env.domains.math_domain.data['objects']
568
570
  for node in self.document.findall(addnodes.pending_xref):
569
- if node['refdomain'] == 'math' and node['reftype'] in ('eq', 'numref'):
571
+ if node['refdomain'] == 'math' and node['reftype'] in {'eq', 'numref'}:
570
572
  docname, _ = equations.get(node['reftarget'], (None, None))
571
573
  if docname:
572
574
  refnode = math_reference(