Sphinx 8.1.2__py3-none-any.whl → 8.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of Sphinx might be problematic. Click here for more details.

Files changed (328) hide show
  1. sphinx/__init__.py +8 -4
  2. sphinx/__main__.py +2 -0
  3. sphinx/_cli/__init__.py +2 -5
  4. sphinx/_cli/util/colour.py +34 -11
  5. sphinx/_cli/util/errors.py +128 -61
  6. sphinx/addnodes.py +51 -35
  7. sphinx/application.py +362 -230
  8. sphinx/builders/__init__.py +87 -64
  9. sphinx/builders/_epub_base.py +65 -56
  10. sphinx/builders/changes.py +17 -23
  11. sphinx/builders/dirhtml.py +8 -13
  12. sphinx/builders/epub3.py +70 -38
  13. sphinx/builders/gettext.py +93 -73
  14. sphinx/builders/html/__init__.py +240 -186
  15. sphinx/builders/html/_assets.py +9 -2
  16. sphinx/builders/html/_build_info.py +3 -0
  17. sphinx/builders/latex/__init__.py +64 -54
  18. sphinx/builders/latex/constants.py +14 -11
  19. sphinx/builders/latex/nodes.py +2 -0
  20. sphinx/builders/latex/theming.py +8 -9
  21. sphinx/builders/latex/transforms.py +7 -5
  22. sphinx/builders/linkcheck.py +193 -149
  23. sphinx/builders/manpage.py +17 -17
  24. sphinx/builders/singlehtml.py +28 -16
  25. sphinx/builders/texinfo.py +28 -21
  26. sphinx/builders/text.py +10 -15
  27. sphinx/builders/xml.py +10 -19
  28. sphinx/cmd/build.py +49 -119
  29. sphinx/cmd/make_mode.py +35 -31
  30. sphinx/cmd/quickstart.py +78 -62
  31. sphinx/config.py +265 -163
  32. sphinx/directives/__init__.py +51 -54
  33. sphinx/directives/admonitions.py +107 -0
  34. sphinx/directives/code.py +24 -19
  35. sphinx/directives/other.py +21 -42
  36. sphinx/directives/patches.py +28 -16
  37. sphinx/domains/__init__.py +54 -31
  38. sphinx/domains/_domains_container.py +22 -17
  39. sphinx/domains/_index.py +5 -8
  40. sphinx/domains/c/__init__.py +366 -245
  41. sphinx/domains/c/_ast.py +378 -256
  42. sphinx/domains/c/_ids.py +89 -31
  43. sphinx/domains/c/_parser.py +283 -214
  44. sphinx/domains/c/_symbol.py +269 -198
  45. sphinx/domains/changeset.py +39 -24
  46. sphinx/domains/citation.py +54 -24
  47. sphinx/domains/cpp/__init__.py +517 -362
  48. sphinx/domains/cpp/_ast.py +999 -682
  49. sphinx/domains/cpp/_ids.py +133 -65
  50. sphinx/domains/cpp/_parser.py +746 -588
  51. sphinx/domains/cpp/_symbol.py +692 -489
  52. sphinx/domains/index.py +10 -8
  53. sphinx/domains/javascript.py +152 -74
  54. sphinx/domains/math.py +50 -40
  55. sphinx/domains/python/__init__.py +402 -211
  56. sphinx/domains/python/_annotations.py +134 -61
  57. sphinx/domains/python/_object.py +155 -68
  58. sphinx/domains/rst.py +94 -49
  59. sphinx/domains/std/__init__.py +510 -249
  60. sphinx/environment/__init__.py +345 -61
  61. sphinx/environment/adapters/asset.py +7 -1
  62. sphinx/environment/adapters/indexentries.py +15 -20
  63. sphinx/environment/adapters/toctree.py +19 -9
  64. sphinx/environment/collectors/__init__.py +3 -1
  65. sphinx/environment/collectors/asset.py +18 -15
  66. sphinx/environment/collectors/dependencies.py +8 -10
  67. sphinx/environment/collectors/metadata.py +6 -4
  68. sphinx/environment/collectors/title.py +3 -1
  69. sphinx/environment/collectors/toctree.py +4 -4
  70. sphinx/errors.py +1 -3
  71. sphinx/events.py +4 -4
  72. sphinx/ext/apidoc/__init__.py +66 -0
  73. sphinx/ext/apidoc/__main__.py +9 -0
  74. sphinx/ext/apidoc/_cli.py +356 -0
  75. sphinx/ext/apidoc/_extension.py +262 -0
  76. sphinx/ext/apidoc/_generate.py +356 -0
  77. sphinx/ext/apidoc/_shared.py +99 -0
  78. sphinx/ext/autodoc/__init__.py +837 -483
  79. sphinx/ext/autodoc/directive.py +57 -21
  80. sphinx/ext/autodoc/importer.py +184 -67
  81. sphinx/ext/autodoc/mock.py +25 -10
  82. sphinx/ext/autodoc/preserve_defaults.py +17 -9
  83. sphinx/ext/autodoc/type_comment.py +56 -29
  84. sphinx/ext/autodoc/typehints.py +49 -26
  85. sphinx/ext/autosectionlabel.py +28 -11
  86. sphinx/ext/autosummary/__init__.py +281 -142
  87. sphinx/ext/autosummary/generate.py +121 -51
  88. sphinx/ext/coverage.py +152 -91
  89. sphinx/ext/doctest.py +169 -101
  90. sphinx/ext/duration.py +12 -6
  91. sphinx/ext/extlinks.py +33 -21
  92. sphinx/ext/githubpages.py +8 -8
  93. sphinx/ext/graphviz.py +175 -109
  94. sphinx/ext/ifconfig.py +11 -6
  95. sphinx/ext/imgconverter.py +48 -25
  96. sphinx/ext/imgmath.py +127 -97
  97. sphinx/ext/inheritance_diagram.py +177 -103
  98. sphinx/ext/intersphinx/__init__.py +22 -13
  99. sphinx/ext/intersphinx/__main__.py +3 -1
  100. sphinx/ext/intersphinx/_cli.py +18 -14
  101. sphinx/ext/intersphinx/_load.py +91 -82
  102. sphinx/ext/intersphinx/_resolve.py +108 -74
  103. sphinx/ext/intersphinx/_shared.py +2 -2
  104. sphinx/ext/linkcode.py +28 -12
  105. sphinx/ext/mathjax.py +60 -29
  106. sphinx/ext/napoleon/__init__.py +19 -7
  107. sphinx/ext/napoleon/docstring.py +229 -231
  108. sphinx/ext/todo.py +44 -49
  109. sphinx/ext/viewcode.py +105 -57
  110. sphinx/extension.py +3 -1
  111. sphinx/highlighting.py +13 -7
  112. sphinx/io.py +9 -13
  113. sphinx/jinja2glue.py +29 -26
  114. sphinx/locale/__init__.py +8 -9
  115. sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
  116. sphinx/locale/ar/LC_MESSAGES/sphinx.po +2155 -2050
  117. sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
  118. sphinx/locale/bg/LC_MESSAGES/sphinx.po +2045 -1940
  119. sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
  120. sphinx/locale/bn/LC_MESSAGES/sphinx.po +2175 -2070
  121. sphinx/locale/ca/LC_MESSAGES/sphinx.js +3 -3
  122. sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
  123. sphinx/locale/ca/LC_MESSAGES/sphinx.po +2690 -2585
  124. sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.js +63 -0
  125. sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.mo +0 -0
  126. sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.po +4216 -0
  127. sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
  128. sphinx/locale/cak/LC_MESSAGES/sphinx.po +2096 -1991
  129. sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
  130. sphinx/locale/cs/LC_MESSAGES/sphinx.po +2248 -2143
  131. sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
  132. sphinx/locale/cy/LC_MESSAGES/sphinx.po +2201 -2096
  133. sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
  134. sphinx/locale/da/LC_MESSAGES/sphinx.po +2282 -2177
  135. sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
  136. sphinx/locale/de/LC_MESSAGES/sphinx.po +2261 -2156
  137. sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
  138. sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2045 -1940
  139. sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
  140. sphinx/locale/el/LC_MESSAGES/sphinx.po +2604 -2499
  141. sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
  142. sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2045 -1940
  143. sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
  144. sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2045 -1940
  145. sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
  146. sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2631 -2526
  147. sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
  148. sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2045 -1940
  149. sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
  150. sphinx/locale/eo/LC_MESSAGES/sphinx.po +2078 -1973
  151. sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
  152. sphinx/locale/es/LC_MESSAGES/sphinx.po +2633 -2528
  153. sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
  154. sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2045 -1940
  155. sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
  156. sphinx/locale/et/LC_MESSAGES/sphinx.po +2449 -2344
  157. sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
  158. sphinx/locale/eu/LC_MESSAGES/sphinx.po +2241 -2136
  159. sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
  160. sphinx/locale/fa/LC_MESSAGES/sphinx.po +504 -500
  161. sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
  162. sphinx/locale/fi/LC_MESSAGES/sphinx.po +499 -495
  163. sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
  164. sphinx/locale/fr/LC_MESSAGES/sphinx.po +513 -509
  165. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
  166. sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +499 -495
  167. sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
  168. sphinx/locale/gl/LC_MESSAGES/sphinx.po +2644 -2539
  169. sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
  170. sphinx/locale/he/LC_MESSAGES/sphinx.po +499 -495
  171. sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
  172. sphinx/locale/hi/LC_MESSAGES/sphinx.po +504 -500
  173. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
  174. sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +499 -495
  175. sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
  176. sphinx/locale/hr/LC_MESSAGES/sphinx.po +501 -497
  177. sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
  178. sphinx/locale/hu/LC_MESSAGES/sphinx.po +499 -495
  179. sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
  180. sphinx/locale/id/LC_MESSAGES/sphinx.po +2609 -2504
  181. sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
  182. sphinx/locale/is/LC_MESSAGES/sphinx.po +499 -495
  183. sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
  184. sphinx/locale/it/LC_MESSAGES/sphinx.po +2265 -2160
  185. sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
  186. sphinx/locale/ja/LC_MESSAGES/sphinx.po +2621 -2516
  187. sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
  188. sphinx/locale/ka/LC_MESSAGES/sphinx.po +2567 -2462
  189. sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
  190. sphinx/locale/ko/LC_MESSAGES/sphinx.po +2631 -2526
  191. sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
  192. sphinx/locale/lt/LC_MESSAGES/sphinx.po +2214 -2109
  193. sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
  194. sphinx/locale/lv/LC_MESSAGES/sphinx.po +2218 -2113
  195. sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
  196. sphinx/locale/mk/LC_MESSAGES/sphinx.po +2088 -1983
  197. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
  198. sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2247 -2142
  199. sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
  200. sphinx/locale/ne/LC_MESSAGES/sphinx.po +2227 -2122
  201. sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
  202. sphinx/locale/nl/LC_MESSAGES/sphinx.po +2316 -2211
  203. sphinx/locale/pl/LC_MESSAGES/sphinx.js +2 -2
  204. sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
  205. sphinx/locale/pl/LC_MESSAGES/sphinx.po +2442 -2336
  206. sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
  207. sphinx/locale/pt/LC_MESSAGES/sphinx.po +2045 -1940
  208. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
  209. sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2657 -2552
  210. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
  211. sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2243 -2138
  212. sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
  213. sphinx/locale/ro/LC_MESSAGES/sphinx.po +2244 -2139
  214. sphinx/locale/ru/LC_MESSAGES/sphinx.js +1 -1
  215. sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
  216. sphinx/locale/ru/LC_MESSAGES/sphinx.po +2660 -2555
  217. sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
  218. sphinx/locale/si/LC_MESSAGES/sphinx.po +2134 -2029
  219. sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
  220. sphinx/locale/sk/LC_MESSAGES/sphinx.po +2614 -2509
  221. sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
  222. sphinx/locale/sl/LC_MESSAGES/sphinx.po +2167 -2062
  223. sphinx/locale/sphinx.pot +2069 -1964
  224. sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
  225. sphinx/locale/sq/LC_MESSAGES/sphinx.po +2661 -2556
  226. sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
  227. sphinx/locale/sr/LC_MESSAGES/sphinx.po +2213 -2108
  228. sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
  229. sphinx/locale/sv/LC_MESSAGES/sphinx.po +2229 -2124
  230. sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
  231. sphinx/locale/te/LC_MESSAGES/sphinx.po +2045 -1940
  232. sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
  233. sphinx/locale/tr/LC_MESSAGES/sphinx.po +2608 -2503
  234. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
  235. sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2167 -2062
  236. sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
  237. sphinx/locale/ur/LC_MESSAGES/sphinx.po +2045 -1940
  238. sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
  239. sphinx/locale/vi/LC_MESSAGES/sphinx.po +2204 -2099
  240. sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
  241. sphinx/locale/yue/LC_MESSAGES/sphinx.po +2045 -1940
  242. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
  243. sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2045 -1940
  244. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
  245. sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +2659 -2554
  246. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
  247. sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2045 -1940
  248. sphinx/parsers.py +8 -7
  249. sphinx/project.py +2 -2
  250. sphinx/pycode/__init__.py +31 -21
  251. sphinx/pycode/ast.py +6 -3
  252. sphinx/pycode/parser.py +14 -8
  253. sphinx/pygments_styles.py +4 -5
  254. sphinx/registry.py +192 -92
  255. sphinx/roles.py +58 -7
  256. sphinx/search/__init__.py +75 -54
  257. sphinx/search/en.py +11 -13
  258. sphinx/search/fi.py +1 -1
  259. sphinx/search/ja.py +8 -6
  260. sphinx/search/nl.py +1 -1
  261. sphinx/search/zh.py +19 -21
  262. sphinx/testing/fixtures.py +26 -29
  263. sphinx/testing/path.py +26 -62
  264. sphinx/testing/restructuredtext.py +14 -8
  265. sphinx/testing/util.py +21 -19
  266. sphinx/texinputs/make.bat.jinja +50 -50
  267. sphinx/texinputs/sphinx.sty +4 -3
  268. sphinx/texinputs/sphinxlatexadmonitions.sty +1 -1
  269. sphinx/texinputs/sphinxlatexobjects.sty +29 -10
  270. sphinx/themes/basic/static/searchtools.js +8 -5
  271. sphinx/theming.py +49 -61
  272. sphinx/transforms/__init__.py +17 -38
  273. sphinx/transforms/compact_bullet_list.py +5 -3
  274. sphinx/transforms/i18n.py +8 -21
  275. sphinx/transforms/post_transforms/__init__.py +142 -93
  276. sphinx/transforms/post_transforms/code.py +5 -5
  277. sphinx/transforms/post_transforms/images.py +28 -24
  278. sphinx/transforms/references.py +3 -1
  279. sphinx/util/__init__.py +109 -60
  280. sphinx/util/_files.py +39 -23
  281. sphinx/util/_importer.py +4 -1
  282. sphinx/util/_inventory_file_reader.py +76 -0
  283. sphinx/util/_io.py +2 -2
  284. sphinx/util/_lines.py +6 -3
  285. sphinx/util/_pathlib.py +40 -2
  286. sphinx/util/build_phase.py +2 -0
  287. sphinx/util/cfamily.py +19 -14
  288. sphinx/util/console.py +44 -179
  289. sphinx/util/display.py +9 -10
  290. sphinx/util/docfields.py +140 -122
  291. sphinx/util/docstrings.py +1 -1
  292. sphinx/util/docutils.py +118 -77
  293. sphinx/util/fileutil.py +25 -26
  294. sphinx/util/http_date.py +2 -0
  295. sphinx/util/i18n.py +77 -64
  296. sphinx/util/images.py +8 -6
  297. sphinx/util/inspect.py +147 -38
  298. sphinx/util/inventory.py +215 -116
  299. sphinx/util/logging.py +33 -33
  300. sphinx/util/matching.py +12 -4
  301. sphinx/util/nodes.py +18 -13
  302. sphinx/util/osutil.py +38 -39
  303. sphinx/util/parallel.py +22 -13
  304. sphinx/util/parsing.py +2 -1
  305. sphinx/util/png.py +6 -2
  306. sphinx/util/requests.py +33 -2
  307. sphinx/util/rst.py +3 -2
  308. sphinx/util/tags.py +1 -1
  309. sphinx/util/template.py +18 -10
  310. sphinx/util/texescape.py +8 -6
  311. sphinx/util/typing.py +148 -122
  312. sphinx/versioning.py +3 -3
  313. sphinx/writers/html.py +3 -1
  314. sphinx/writers/html5.py +63 -52
  315. sphinx/writers/latex.py +83 -67
  316. sphinx/writers/manpage.py +19 -38
  317. sphinx/writers/texinfo.py +47 -47
  318. sphinx/writers/text.py +50 -32
  319. sphinx/writers/xml.py +11 -8
  320. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/LICENSE.rst +1 -1
  321. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/METADATA +25 -15
  322. sphinx-8.2.0.dist-info/RECORD +606 -0
  323. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/WHEEL +1 -1
  324. sphinx/builders/html/transforms.py +0 -90
  325. sphinx/ext/apidoc.py +0 -721
  326. sphinx/util/exceptions.py +0 -74
  327. sphinx-8.1.2.dist-info/RECORD +0 -598
  328. {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/entry_points.txt +0 -0
sphinx/parsers.py CHANGED
@@ -6,7 +6,6 @@ from typing import TYPE_CHECKING
6
6
 
7
7
  import docutils.parsers
8
8
  import docutils.parsers.rst
9
- from docutils import nodes
10
9
  from docutils.parsers.rst import states
11
10
  from docutils.statemachine import StringList
12
11
  from docutils.transforms.universal import SmartQuotes
@@ -14,6 +13,7 @@ from docutils.transforms.universal import SmartQuotes
14
13
  from sphinx.util.rst import append_epilog, prepend_prolog
15
14
 
16
15
  if TYPE_CHECKING:
16
+ from docutils import nodes
17
17
  from docutils.transforms import Transform
18
18
 
19
19
  from sphinx.application import Sphinx
@@ -23,10 +23,12 @@ if TYPE_CHECKING:
23
23
 
24
24
 
25
25
  class Parser(docutils.parsers.Parser):
26
- """
27
- A base class of source parsers. The additional parsers should inherit this class instead
28
- of ``docutils.parsers.Parser``. Compared with ``docutils.parsers.Parser``, this class
29
- improves accessibility to Sphinx APIs.
26
+ """A base class of source parsers.
27
+
28
+ The additional parsers should inherit this class
29
+ instead of ``docutils.parsers.Parser``.
30
+ Compared with ``docutils.parsers.Parser``,
31
+ this class improves accessibility to Sphinx APIs.
30
32
 
31
33
  The subclasses can access sphinx core runtime objects (app, config and env).
32
34
  """
@@ -51,8 +53,7 @@ class RSTParser(docutils.parsers.rst.Parser, Parser):
51
53
  """A reST parser for Sphinx."""
52
54
 
53
55
  def get_transforms(self) -> list[type[Transform]]:
54
- """
55
- Sphinx's reST parser replaces a transform class for smart-quotes by its own
56
+ """Sphinx's reST parser replaces a transform class for smart-quotes by its own
56
57
 
57
58
  refs: sphinx.io.SphinxStandaloneReader
58
59
  """
sphinx/project.py CHANGED
@@ -96,10 +96,10 @@ class Project:
96
96
 
97
97
  *filename* should be absolute or relative to the source directory.
98
98
  """
99
+ path = Path(filename)
99
100
  try:
100
- return self._path_to_docname[filename] # type: ignore[index]
101
+ return self._path_to_docname[path]
101
102
  except KeyError:
102
- path = Path(filename)
103
103
  if path.is_absolute():
104
104
  with contextlib.suppress(ValueError):
105
105
  path = path.relative_to(self.srcdir)
sphinx/pycode/__init__.py CHANGED
@@ -4,14 +4,16 @@ from __future__ import annotations
4
4
 
5
5
  import tokenize
6
6
  from importlib import import_module
7
- from os import path
8
- from typing import TYPE_CHECKING, Any
7
+ from typing import TYPE_CHECKING
9
8
 
10
9
  from sphinx.errors import PycodeError
11
10
  from sphinx.pycode.parser import Parser
11
+ from sphinx.util._pathlib import _StrPath
12
12
 
13
13
  if TYPE_CHECKING:
14
+ import os
14
15
  from inspect import Signature
16
+ from typing import Any, Literal
15
17
 
16
18
 
17
19
  class ModuleAnalyzer:
@@ -23,10 +25,10 @@ class ModuleAnalyzer:
23
25
  tags: dict[str, tuple[str, int, int]]
24
26
 
25
27
  # cache for analyzer objects -- caches both by module and file name
26
- cache: dict[tuple[str, str], Any] = {}
28
+ cache: dict[tuple[Literal['file', 'module'], str | _StrPath], Any] = {}
27
29
 
28
30
  @staticmethod
29
- def get_module_source(modname: str) -> tuple[str | None, str | None]:
31
+ def get_module_source(modname: str) -> tuple[_StrPath | None, str | None]:
30
32
  """Try to find the source code for a module.
31
33
 
32
34
  Returns ('filename', 'source'). One of it can be None if
@@ -37,14 +39,15 @@ class ModuleAnalyzer:
37
39
  except Exception as err:
38
40
  raise PycodeError('error importing %r' % modname, err) from err
39
41
  loader = getattr(mod, '__loader__', None)
40
- filename = getattr(mod, '__file__', None)
42
+ filename: str | None = getattr(mod, '__file__', None)
41
43
  if loader and getattr(loader, 'get_source', None):
42
44
  # prefer Native loader, as it respects #coding directive
43
45
  try:
44
46
  source = loader.get_source(modname)
45
47
  if source:
48
+ mod_path = None if filename is None else _StrPath(filename)
46
49
  # no exception and not None - it must be module source
47
- return filename, source
50
+ return mod_path, source
48
51
  except ImportError:
49
52
  pass # Try other "source-mining" methods
50
53
  if filename is None and loader and getattr(loader, 'get_filename', None):
@@ -58,31 +61,36 @@ class ModuleAnalyzer:
58
61
  if filename is None:
59
62
  # all methods for getting filename failed, so raise...
60
63
  raise PycodeError('no source found for module %r' % modname)
61
- filename = path.normpath(path.abspath(filename))
62
- if filename.lower().endswith(('.pyo', '.pyc')):
63
- filename = filename[:-1]
64
- if not path.isfile(filename) and path.isfile(filename + 'w'):
65
- filename += 'w'
66
- elif not filename.lower().endswith(('.py', '.pyw')):
67
- raise PycodeError('source is not a .py file: %r' % filename)
68
-
69
- if not path.isfile(filename):
70
- raise PycodeError('source file is not present: %r' % filename)
71
- return filename, None
64
+ mod_path = _StrPath(filename).resolve()
65
+ if mod_path.suffix in {'.pyo', '.pyc'}:
66
+ mod_path_pyw = mod_path.with_suffix('.pyw')
67
+ if not mod_path.is_file() and mod_path_pyw.is_file():
68
+ mod_path = mod_path_pyw
69
+ else:
70
+ mod_path = mod_path.with_suffix('.py')
71
+ elif mod_path.suffix not in {'.py', '.pyw'}:
72
+ msg = f'source is not a .py file: {mod_path!r}'
73
+ raise PycodeError(msg)
74
+
75
+ if not mod_path.is_file():
76
+ msg = f'source file is not present: {mod_path!r}'
77
+ raise PycodeError(msg)
78
+ return mod_path, None
72
79
 
73
80
  @classmethod
74
81
  def for_string(
75
82
  cls: type[ModuleAnalyzer],
76
83
  string: str,
77
84
  modname: str,
78
- srcname: str = '<string>',
85
+ srcname: str | os.PathLike[str] = '<string>',
79
86
  ) -> ModuleAnalyzer:
80
87
  return cls(string, modname, srcname)
81
88
 
82
89
  @classmethod
83
90
  def for_file(
84
- cls: type[ModuleAnalyzer], filename: str, modname: str
91
+ cls: type[ModuleAnalyzer], filename: str | os.PathLike[str], modname: str
85
92
  ) -> ModuleAnalyzer:
93
+ filename = _StrPath(filename)
86
94
  if ('file', filename) in cls.cache:
87
95
  return cls.cache['file', filename]
88
96
  try:
@@ -114,9 +122,11 @@ class ModuleAnalyzer:
114
122
  cls.cache['module', modname] = obj
115
123
  return obj
116
124
 
117
- def __init__(self, source: str, modname: str, srcname: str) -> None:
125
+ def __init__(
126
+ self, source: str, modname: str, srcname: str | os.PathLike[str]
127
+ ) -> None:
118
128
  self.modname = modname # name of the module
119
- self.srcname = srcname # name of the source file
129
+ self.srcname = str(srcname) # name of the source file
120
130
 
121
131
  # cache the source code as well
122
132
  self.code = source
sphinx/pycode/ast.py CHANGED
@@ -3,7 +3,10 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import ast
6
- from typing import NoReturn, overload
6
+ from typing import TYPE_CHECKING, overload
7
+
8
+ if TYPE_CHECKING:
9
+ from typing import NoReturn
7
10
 
8
11
  OPERATORS: dict[type[ast.AST], str] = {
9
12
  ast.Add: '+',
@@ -29,11 +32,11 @@ OPERATORS: dict[type[ast.AST], str] = {
29
32
 
30
33
 
31
34
  @overload
32
- def unparse(node: None, code: str = '') -> None: ... # NoQA: E704
35
+ def unparse(node: None, code: str = '') -> None: ...
33
36
 
34
37
 
35
38
  @overload
36
- def unparse(node: ast.AST, code: str = '') -> str: ... # NoQA: E704
39
+ def unparse(node: ast.AST, code: str = '') -> str: ...
37
40
 
38
41
 
39
42
  def unparse(node: ast.AST | None, code: str = '') -> str | None:
sphinx/pycode/parser.py CHANGED
@@ -10,13 +10,16 @@ import itertools
10
10
  import operator
11
11
  import re
12
12
  import tokenize
13
- from inspect import Signature
14
13
  from token import DEDENT, INDENT, NAME, NEWLINE, NUMBER, OP, STRING
15
14
  from tokenize import COMMENT, NL
16
- from typing import Any
15
+ from typing import TYPE_CHECKING
17
16
 
18
17
  from sphinx.pycode.ast import unparse as ast_unparse
19
18
 
19
+ if TYPE_CHECKING:
20
+ from inspect import Signature
21
+ from typing import Any
22
+
20
23
  comment_re = re.compile('^\\s*#: ?(.*)\r?\n?$')
21
24
  indent_re = re.compile('^\\s*$')
22
25
  emptyline_re = re.compile('^\\s*(#.*)?$')
@@ -40,21 +43,21 @@ def get_lvar_names(node: ast.AST, self: ast.arg | None = None) -> list[str]:
40
43
  This raises `TypeError` if the assignment does not create new variable::
41
44
 
42
45
  ary[0] = 'foo'
43
- dic["bar"] = 'baz'
46
+ dic['bar'] = 'baz'
44
47
  # => TypeError
45
48
  """
46
49
  if self:
47
50
  self_id = self.arg
48
51
 
49
52
  node_name = node.__class__.__name__
50
- if node_name in ('Constant', 'Index', 'Slice', 'Subscript'):
53
+ if node_name in {'Constant', 'Index', 'Slice', 'Subscript'}:
51
54
  raise TypeError('%r does not create new variable' % node)
52
55
  if node_name == 'Name':
53
56
  if self is None or node.id == self_id: # type: ignore[attr-defined]
54
57
  return [node.id] # type: ignore[attr-defined]
55
58
  else:
56
59
  raise TypeError('The assignment %r is not instance variable' % node)
57
- elif node_name in ('Tuple', 'List'):
60
+ elif node_name in {'Tuple', 'List'}:
58
61
  members = []
59
62
  for elt in node.elts: # type: ignore[attr-defined]
60
63
  with contextlib.suppress(TypeError):
@@ -111,7 +114,7 @@ class Token:
111
114
  self.end = end
112
115
  self.source = source
113
116
 
114
- def __eq__(self, other: Any) -> bool:
117
+ def __eq__(self, other: object) -> bool:
115
118
  if isinstance(other, int):
116
119
  return self.kind == other
117
120
  elif isinstance(other, str):
@@ -123,6 +126,9 @@ class Token:
123
126
  else:
124
127
  raise ValueError('Unknown value: %r' % other)
125
128
 
129
+ def __hash__(self) -> int:
130
+ return hash((self.kind, self.value, self.start, self.end, self.source))
131
+
126
132
  def match(self, *conditions: Any) -> bool:
127
133
  return any(self == candidate for candidate in conditions)
128
134
 
@@ -280,13 +286,13 @@ class VariableCommentPicker(ast.NodeVisitor):
280
286
  qualname = self.get_qualname_for(name)
281
287
  if qualname:
282
288
  basename = '.'.join(qualname[:-1])
283
- self.comments[(basename, name)] = comment
289
+ self.comments[basename, name] = comment
284
290
 
285
291
  def add_variable_annotation(self, name: str, annotation: ast.AST) -> None:
286
292
  qualname = self.get_qualname_for(name)
287
293
  if qualname:
288
294
  basename = '.'.join(qualname[:-1])
289
- self.annotations[(basename, name)] = ast_unparse(annotation)
295
+ self.annotations[basename, name] = ast_unparse(annotation)
290
296
 
291
297
  def is_final(self, decorators: list[ast.expr]) -> bool:
292
298
  final = []
sphinx/pygments_styles.py CHANGED
@@ -1,5 +1,7 @@
1
1
  """Sphinx theme specific highlighting styles."""
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  from pygments.style import Style
4
6
  from pygments.styles.friendly import FriendlyStyle
5
7
  from pygments.token import (
@@ -20,8 +22,7 @@ class NoneStyle(Style):
20
22
 
21
23
 
22
24
  class SphinxStyle(Style):
23
- """
24
- Like friendly, but a bit darker to enhance contrast on the green
25
+ """Like friendly, but a bit darker to enhance contrast on the green
25
26
  background.
26
27
  """
27
28
 
@@ -37,9 +38,7 @@ class SphinxStyle(Style):
37
38
 
38
39
 
39
40
  class PyramidStyle(Style):
40
- """
41
- Pylons/pyramid pygments style based on friendly style, by Blaise Laflamme.
42
- """
41
+ """Pylons/pyramid pygments style based on friendly style, by Blaise Laflamme."""
43
42
 
44
43
  # work in progress...
45
44