Sphinx 8.1.3__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 +829 -480
  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.3.dist-info → sphinx-8.2.0.dist-info}/LICENSE.rst +1 -1
  321. {sphinx-8.1.3.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.3.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.3.dist-info/RECORD +0 -598
  328. {sphinx-8.1.3.dist-info → sphinx-8.2.0.dist-info}/entry_points.txt +0 -0
sphinx/writers/latex.py CHANGED
@@ -8,11 +8,11 @@ from __future__ import annotations
8
8
 
9
9
  import re
10
10
  from collections import defaultdict
11
- from collections.abc import Iterable
12
- from os import path
13
- from typing import TYPE_CHECKING, Any, ClassVar, cast
11
+ from pathlib import Path
12
+ from typing import TYPE_CHECKING, cast
14
13
 
15
14
  from docutils import nodes, writers
15
+ from roman_numerals import RomanNumeral
16
16
 
17
17
  from sphinx import addnodes, highlighting
18
18
  from sphinx.errors import SphinxError
@@ -24,13 +24,10 @@ from sphinx.util.nodes import clean_astext, get_prev_node
24
24
  from sphinx.util.template import LaTeXRenderer
25
25
  from sphinx.util.texescape import tex_replace_map
26
26
 
27
- try:
28
- from docutils.utils.roman import toRoman
29
- except ImportError:
30
- # In Debian/Ubuntu, roman package is provided as roman, not as docutils.utils.roman
31
- from roman import toRoman # type: ignore[no-redef, import-not-found]
32
-
33
27
  if TYPE_CHECKING:
28
+ from collections.abc import Iterable
29
+ from typing import Any, ClassVar
30
+
34
31
  from docutils.nodes import Element, Node, Text
35
32
 
36
33
  from sphinx.builders.latex import LaTeXBuilder
@@ -100,7 +97,7 @@ class LaTeXWriter(writers.Writer): # type: ignore[type-arg]
100
97
  self.document, self.builder, self.theme
101
98
  )
102
99
  self.document.walkabout(visitor)
103
- self.output = cast(LaTeXTranslator, visitor).astext()
100
+ self.output = cast('LaTeXTranslator', visitor).astext()
104
101
 
105
102
 
106
103
  # Helper classes
@@ -219,8 +216,8 @@ class Table:
219
216
  self.cell_id += 1
220
217
  for col in range(width):
221
218
  for row in range(height):
222
- assert self.cells[(self.row + row, self.col + col)] == 0
223
- self.cells[(self.row + row, self.col + col)] = self.cell_id
219
+ assert self.cells[self.row + row, self.col + col] == 0
220
+ self.cells[self.row + row, self.col + col] = self.cell_id
224
221
 
225
222
  def cell(
226
223
  self,
@@ -246,25 +243,25 @@ class TableCell:
246
243
  """Data of a cell in a table."""
247
244
 
248
245
  def __init__(self, table: Table, row: int, col: int) -> None:
249
- if table.cells[(row, col)] == 0:
246
+ if table.cells[row, col] == 0:
250
247
  raise IndexError
251
248
 
252
249
  self.table = table
253
- self.cell_id = table.cells[(row, col)]
250
+ self.cell_id = table.cells[row, col]
254
251
  self.row = row
255
252
  self.col = col
256
253
 
257
254
  # adjust position for multirow/multicol cell
258
- while table.cells[(self.row - 1, self.col)] == self.cell_id:
255
+ while table.cells[self.row - 1, self.col] == self.cell_id:
259
256
  self.row -= 1
260
- while table.cells[(self.row, self.col - 1)] == self.cell_id:
257
+ while table.cells[self.row, self.col - 1] == self.cell_id:
261
258
  self.col -= 1
262
259
 
263
260
  @property
264
261
  def width(self) -> int:
265
262
  """Returns the cell width."""
266
263
  width = 0
267
- while self.table.cells[(self.row, self.col + width)] == self.cell_id:
264
+ while self.table.cells[self.row, self.col + width] == self.cell_id:
268
265
  width += 1
269
266
  return width
270
267
 
@@ -272,7 +269,7 @@ class TableCell:
272
269
  def height(self) -> int:
273
270
  """Returns the cell height."""
274
271
  height = 0
275
- while self.table.cells[(self.row + height, self.col)] == self.cell_id:
272
+ while self.table.cells[self.row + height, self.col] == self.cell_id:
276
273
  height += 1
277
274
  return height
278
275
 
@@ -291,7 +288,7 @@ def rstdim_to_latexdim(width_str: str, scale: int = 100) -> str:
291
288
  amount, unit = match.groups()[:2]
292
289
  if scale == 100:
293
290
  float(amount) # validate amount is float
294
- if unit in ('', 'px'):
291
+ if unit in {'', 'px'}:
295
292
  res = r'%s\sphinxpxdimen' % amount
296
293
  elif unit == 'pt':
297
294
  res = '%sbp' % amount # convert to 'bp'
@@ -299,7 +296,7 @@ def rstdim_to_latexdim(width_str: str, scale: int = 100) -> str:
299
296
  res = r'%.3f\linewidth' % (float(amount) / 100.0)
300
297
  else:
301
298
  amount_float = float(amount) * scale / 100.0
302
- if unit in ('', 'px'):
299
+ if unit in {'', 'px'}:
303
300
  res = r'%.5f\sphinxpxdimen' % amount_float
304
301
  elif unit == 'pt':
305
302
  res = '%.5fbp' % amount_float
@@ -326,7 +323,7 @@ class LaTeXTranslator(SphinxTranslator):
326
323
 
327
324
  # flags
328
325
  self.in_title = 0
329
- self.in_production_list = 0
326
+ self.in_production_list = False
330
327
  self.in_footnote = 0
331
328
  self.in_caption = 0
332
329
  self.in_term = 0
@@ -564,7 +561,7 @@ class LaTeXTranslator(SphinxTranslator):
564
561
  indices_config = frozenset(indices_config)
565
562
  else:
566
563
  check_names = False
567
- for domain in self.builder.env.domains.sorted():
564
+ for domain in self._domains.sorted():
568
565
  for index_cls in domain.indices:
569
566
  index_name = f'{domain.name}-{index_cls.name}'
570
567
  if check_names and index_name not in indices_config:
@@ -583,18 +580,19 @@ class LaTeXTranslator(SphinxTranslator):
583
580
  def render(self, template_name: str, variables: dict[str, Any]) -> str:
584
581
  renderer = LaTeXRenderer(latex_engine=self.config.latex_engine)
585
582
  for template_dir in self.config.templates_path:
586
- template = path.join(self.builder.confdir, template_dir, template_name)
587
- if path.exists(template):
588
- return renderer.render(template, variables)
589
- elif template.endswith('.jinja'):
590
- legacy_template = template.removesuffix('.jinja') + '_t'
591
- if path.exists(legacy_template):
583
+ template = self.builder.confdir / template_dir / template_name
584
+ if template.exists():
585
+ return renderer.render(str(template), variables)
586
+ elif template.suffix == '.jinja':
587
+ legacy_template_name = template.name.removesuffix('.jinja') + '_t'
588
+ legacy_template = template.with_name(legacy_template_name)
589
+ if legacy_template.exists():
592
590
  logger.warning(
593
591
  __('template %s not found; loading from legacy %s instead'),
594
592
  template_name,
595
593
  legacy_template,
596
594
  )
597
- return renderer.render(legacy_template, variables)
595
+ return renderer.render(str(legacy_template), variables)
598
596
 
599
597
  return renderer.render(template_name, variables)
600
598
 
@@ -673,22 +671,20 @@ class LaTeXTranslator(SphinxTranslator):
673
671
  def visit_productionlist(self, node: Element) -> None:
674
672
  self.body.append(BLANKLINE)
675
673
  self.body.append(r'\begin{productionlist}' + CR)
676
- self.in_production_list = 1
674
+ self.in_production_list = True
677
675
 
678
676
  def depart_productionlist(self, node: Element) -> None:
677
+ self.in_production_list = False
679
678
  self.body.append(r'\end{productionlist}' + BLANKLINE)
680
- self.in_production_list = 0
681
679
 
682
680
  def visit_production(self, node: Element) -> None:
683
- if node['tokenname']:
684
- tn = node['tokenname']
685
- self.body.append(self.hypertarget('grammar-token-' + tn))
686
- self.body.append(r'\production{%s}{' % self.encode(tn))
687
- else:
688
- self.body.append(r'\productioncont{')
681
+ # Nothing to do, the productionlist LaTeX environment
682
+ # is configured to render the nodes line-by-line
683
+ # But see also visit_literal_strong special clause.
684
+ pass
689
685
 
690
686
  def depart_production(self, node: Element) -> None:
691
- self.body.append('}' + CR)
687
+ pass
692
688
 
693
689
  def visit_transition(self, node: Element) -> None:
694
690
  self.body.append(self.elements['transition'])
@@ -956,6 +952,7 @@ class LaTeXTranslator(SphinxTranslator):
956
952
  self.required_params_left = sum(self.list_is_required_param)
957
953
  self.param_separator = r'\sphinxparamcomma '
958
954
  self.multi_line_parameter_list = node.get('multi_line_parameter_list', False)
955
+ self.trailing_comma = node.get('multi_line_trailing_comma', False)
959
956
 
960
957
  def visit_desc_parameterlist(self, node: Element) -> None:
961
958
  if self.has_tp_list:
@@ -1015,7 +1012,7 @@ class LaTeXTranslator(SphinxTranslator):
1015
1012
  if (
1016
1013
  opt_param_left_at_level
1017
1014
  or is_required
1018
- and (is_last_group or next_is_required)
1015
+ and (next_is_required or self.trailing_comma)
1019
1016
  ):
1020
1017
  self.body.append(self.param_separator)
1021
1018
 
@@ -1057,13 +1054,20 @@ class LaTeXTranslator(SphinxTranslator):
1057
1054
 
1058
1055
  def depart_desc_optional(self, node: Element) -> None:
1059
1056
  self.optional_param_level -= 1
1057
+ level = self.optional_param_level
1060
1058
  if self.multi_line_parameter_list:
1059
+ max_level = self.max_optional_param_level
1060
+ len_lirp = len(self.list_is_required_param)
1061
+ is_last_group = self.param_group_index + 1 == len_lirp
1061
1062
  # If it's the first time we go down one level, add the separator before the
1062
- # bracket.
1063
- if self.optional_param_level == self.max_optional_param_level - 1:
1063
+ # bracket, except if this is the last parameter and the parameter list
1064
+ # should not feature a trailing comma.
1065
+ if level == max_level - 1 and (
1066
+ not is_last_group or level > 0 or self.trailing_comma
1067
+ ):
1064
1068
  self.body.append(self.param_separator)
1065
1069
  self.body.append('}')
1066
- if self.optional_param_level == 0:
1070
+ if level == 0:
1067
1071
  self.param_group_index += 1
1068
1072
 
1069
1073
  def visit_desc_annotation(self, node: Element) -> None:
@@ -1090,7 +1094,7 @@ class LaTeXTranslator(SphinxTranslator):
1090
1094
  self.no_latex_floats -= 1
1091
1095
 
1092
1096
  def visit_rubric(self, node: nodes.rubric) -> None:
1093
- if len(node) == 1 and node.astext() in ('Footnotes', _('Footnotes')):
1097
+ if len(node) == 1 and node.astext() in {'Footnotes', _('Footnotes')}:
1094
1098
  raise nodes.SkipNode
1095
1099
  tag = 'subsubsection'
1096
1100
  if 'heading-level' in node:
@@ -1115,7 +1119,7 @@ class LaTeXTranslator(SphinxTranslator):
1115
1119
 
1116
1120
  def visit_footnote(self, node: Element) -> None:
1117
1121
  self.in_footnote += 1
1118
- label = cast(nodes.label, node[0])
1122
+ label = cast('nodes.label', node[0])
1119
1123
  if self.in_parsed_literal:
1120
1124
  self.body.append(r'\begin{footnote}[%s]' % label.astext())
1121
1125
  else:
@@ -1337,7 +1341,7 @@ class LaTeXTranslator(SphinxTranslator):
1337
1341
  if (
1338
1342
  len(node) == 1
1339
1343
  and isinstance(node[0], nodes.paragraph)
1340
- and node.astext() == ''
1344
+ and not node.astext()
1341
1345
  ):
1342
1346
  pass
1343
1347
  else:
@@ -1386,8 +1390,8 @@ class LaTeXTranslator(SphinxTranslator):
1386
1390
  def visit_acks(self, node: Element) -> None:
1387
1391
  # this is a list in the source, but should be rendered as a
1388
1392
  # comma-separated list here
1389
- bullet_list = cast(nodes.bullet_list, node[0])
1390
- list_items = cast(Iterable[nodes.list_item], bullet_list)
1393
+ bullet_list = cast('nodes.bullet_list', node[0])
1394
+ list_items = cast('Iterable[nodes.list_item]', bullet_list)
1391
1395
  self.body.append(BLANKLINE)
1392
1396
  self.body.append(', '.join(n.astext() for n in list_items) + '.')
1393
1397
  self.body.append(BLANKLINE)
@@ -1420,8 +1424,9 @@ class LaTeXTranslator(SphinxTranslator):
1420
1424
  else:
1421
1425
  return get_nested_level(node.parent)
1422
1426
 
1423
- enum = 'enum%s' % toRoman(get_nested_level(node)).lower()
1424
- enumnext = 'enum%s' % toRoman(get_nested_level(node) + 1).lower()
1427
+ nested_level = get_nested_level(node)
1428
+ enum = f'enum{RomanNumeral(nested_level).to_lowercase()}'
1429
+ enumnext = f'enum{RomanNumeral(nested_level + 1).to_lowercase()}'
1425
1430
  style = ENUMERATE_LIST_STYLE.get(get_enumtype(node))
1426
1431
  prefix = node.get('prefix', '')
1427
1432
  suffix = node.get('suffix', '.')
@@ -1648,7 +1653,9 @@ class LaTeXTranslator(SphinxTranslator):
1648
1653
  options = ''
1649
1654
  if include_graphics_options:
1650
1655
  options = '[%s]' % ','.join(include_graphics_options)
1651
- base, ext = path.splitext(uri)
1656
+ img_path = Path(uri)
1657
+ base = img_path.with_suffix('')
1658
+ ext = img_path.suffix
1652
1659
 
1653
1660
  if self.in_title and base:
1654
1661
  # Lowercase tokens forcely because some fncychap themes capitalize
@@ -1657,8 +1664,8 @@ class LaTeXTranslator(SphinxTranslator):
1657
1664
  else:
1658
1665
  cmd = rf'\sphinxincludegraphics{options}{{{{{base}}}{ext}}}'
1659
1666
  # escape filepath for includegraphics, https://tex.stackexchange.com/a/202714/41112
1660
- if '#' in base:
1661
- cmd = r'{\catcode`\#=12' + cmd + '}'
1667
+ if '#' in str(base):
1668
+ cmd = rf'{{\catcode`\#=12{cmd}}}'
1662
1669
  self.body.append(cmd)
1663
1670
  self.body.extend(post)
1664
1671
 
@@ -1684,7 +1691,7 @@ class LaTeXTranslator(SphinxTranslator):
1684
1691
  if any(isinstance(child, nodes.caption) for child in node):
1685
1692
  self.body.append(r'\capstart')
1686
1693
  self.context.append(r'\end{sphinxfigure-in-table}\relax' + CR)
1687
- elif node.get('align', '') in ('left', 'right'):
1694
+ elif node.get('align', '') in {'left', 'right'}:
1688
1695
  length = None
1689
1696
  if 'width' in node:
1690
1697
  length = self.latex_image_length(node['width'])
@@ -1816,7 +1823,7 @@ class LaTeXTranslator(SphinxTranslator):
1816
1823
  while isinstance(next_node, nodes.target):
1817
1824
  next_node = next_node.next_node(ascend=True)
1818
1825
 
1819
- domain = self.builder.env.domains.standard_domain
1826
+ domain = self._domains.standard_domain
1820
1827
  if isinstance(next_node, HYPERLINK_SUPPORT_NODES):
1821
1828
  return
1822
1829
  if (
@@ -1840,7 +1847,8 @@ class LaTeXTranslator(SphinxTranslator):
1840
1847
  else:
1841
1848
  add_target(node['refid'])
1842
1849
  # Temporary fix for https://github.com/sphinx-doc/sphinx/issues/11093
1843
- # TODO: investigate if a more elegant solution exists (see comments of #11093)
1850
+ # TODO: investigate if a more elegant solution exists
1851
+ # (see comments of https://github.com/sphinx-doc/sphinx/issues/11093)
1844
1852
  if node.get('ismod', False):
1845
1853
  # Detect if the previous nodes are label targets. If so, remove
1846
1854
  # the refid thereof from node['ids'] to avoid duplicated ids.
@@ -2061,17 +2069,25 @@ class LaTeXTranslator(SphinxTranslator):
2061
2069
  self.body.append('}')
2062
2070
 
2063
2071
  def visit_literal_strong(self, node: Element) -> None:
2072
+ if self.in_production_list:
2073
+ ctx = [r'\phantomsection']
2074
+ ctx += [self.hypertarget(id_, anchor=False) for id_ in node['ids']]
2075
+ self.body.append(''.join(ctx))
2076
+ return
2064
2077
  self.body.append(r'\sphinxstyleliteralstrong{\sphinxupquote{')
2065
2078
 
2066
2079
  def depart_literal_strong(self, node: Element) -> None:
2080
+ if self.in_production_list:
2081
+ return
2067
2082
  self.body.append('}}')
2068
2083
 
2069
2084
  def visit_abbreviation(self, node: Element) -> None:
2085
+ explanation = node.get('explanation', '')
2070
2086
  abbr = node.astext()
2071
2087
  self.body.append(r'\sphinxstyleabbreviation{')
2072
2088
  # spell out the explanation once
2073
- if node.hasattr('explanation') and abbr not in self.handled_abbrs:
2074
- self.context.append('} (%s)' % self.encode(node['explanation']))
2089
+ if explanation and abbr not in self.handled_abbrs:
2090
+ self.context.append('} (%s)' % self.encode(explanation))
2075
2091
  self.handled_abbrs.add(abbr)
2076
2092
  else:
2077
2093
  self.context.append('}')
@@ -2092,8 +2108,8 @@ class LaTeXTranslator(SphinxTranslator):
2092
2108
  self.body.append('}')
2093
2109
 
2094
2110
  def visit_thebibliography(self, node: Element) -> None:
2095
- citations = cast(Iterable[nodes.citation], node)
2096
- labels = (cast(nodes.label, citation[0]) for citation in citations)
2111
+ citations = cast('Iterable[nodes.citation]', node)
2112
+ labels = (cast('nodes.label', citation[0]) for citation in citations)
2097
2113
  longest_label = max((label.astext() for label in labels), key=len)
2098
2114
  if len(longest_label) > MAX_CITATION_LABEL_LENGTH:
2099
2115
  # adjust max width of citation labels not to break the layout
@@ -2107,7 +2123,7 @@ class LaTeXTranslator(SphinxTranslator):
2107
2123
  self.body.append(r'\end{sphinxthebibliography}' + CR)
2108
2124
 
2109
2125
  def visit_citation(self, node: Element) -> None:
2110
- label = cast(nodes.label, node[0])
2126
+ label = cast('nodes.label', node[0])
2111
2127
  self.body.append(
2112
2128
  rf'\bibitem[{self.encode(label.astext())}]'
2113
2129
  rf'{{{node["docname"]}:{node["ids"][0]}}}'
@@ -2160,7 +2176,7 @@ class LaTeXTranslator(SphinxTranslator):
2160
2176
  self.body.append(']')
2161
2177
 
2162
2178
  def visit_footnotetext(self, node: Element) -> None:
2163
- label = cast(nodes.label, node[0])
2179
+ label = cast('nodes.label', node[0])
2164
2180
  self.body.append('%' + CR)
2165
2181
  self.body.append(r'\begin{footnotetext}[%s]' % label.astext())
2166
2182
  self.body.append(r'\sphinxAtStartFootnote' + CR)
@@ -2443,20 +2459,20 @@ class LaTeXTranslator(SphinxTranslator):
2443
2459
  def depart_system_message(self, node: Element) -> None:
2444
2460
  self.body.append(CR)
2445
2461
 
2446
- def visit_math(self, node: Element) -> None:
2462
+ def visit_math(self, node: nodes.math) -> None:
2447
2463
  if self.in_title:
2448
2464
  self.body.append(r'\protect\(%s\protect\)' % node.astext())
2449
2465
  else:
2450
2466
  self.body.append(r'\(%s\)' % node.astext())
2451
2467
  raise nodes.SkipNode
2452
2468
 
2453
- def visit_math_block(self, node: Element) -> None:
2469
+ def visit_math_block(self, node: nodes.math_block) -> None:
2454
2470
  if node.get('label'):
2455
- label = f"equation:{node['docname']}:{node['label']}"
2471
+ label = f'equation:{node["docname"]}:{node["label"]}'
2456
2472
  else:
2457
2473
  label = None
2458
2474
 
2459
- if node.get('nowrap'):
2475
+ if node.get('no-wrap', node.get('nowrap', False)):
2460
2476
  if label:
2461
2477
  self.body.append(r'\label{%s}' % label)
2462
2478
  self.body.append(node.astext())
@@ -2469,7 +2485,7 @@ class LaTeXTranslator(SphinxTranslator):
2469
2485
  raise nodes.SkipNode
2470
2486
 
2471
2487
  def visit_math_reference(self, node: Element) -> None:
2472
- label = f"equation:{node['docname']}:{node['target']}"
2488
+ label = f'equation:{node["docname"]}:{node["target"]}'
2473
2489
  eqref_format = self.config.math_eqref_format
2474
2490
  if eqref_format:
2475
2491
  try:
@@ -2486,7 +2502,7 @@ class LaTeXTranslator(SphinxTranslator):
2486
2502
 
2487
2503
 
2488
2504
  # FIXME: Workaround to avoid circular import
2489
- # refs: https://github.com/sphinx-doc/sphinx/issues/5433
2505
+ # See: https://github.com/sphinx-doc/sphinx/issues/5433
2490
2506
  from sphinx.builders.latex.nodes import ( # NoQA: E402 # isort:skip
2491
2507
  HYPERLINK_SUPPORT_NODES,
2492
2508
  captioned_literal_block,
sphinx/writers/manpage.py CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from collections.abc import Iterable
6
- from typing import TYPE_CHECKING, Any, cast
5
+ from typing import TYPE_CHECKING, cast
7
6
 
8
7
  from docutils import nodes
9
8
  from docutils.writers.manpage import Translator as BaseTranslator
@@ -17,6 +16,9 @@ from sphinx.util.i18n import format_date
17
16
  from sphinx.util.nodes import NodeMatcher
18
17
 
19
18
  if TYPE_CHECKING:
19
+ from collections.abc import Iterable
20
+ from typing import Any
21
+
20
22
  from docutils.nodes import Element
21
23
 
22
24
  from sphinx.builders import Builder
@@ -33,14 +35,13 @@ class ManualPageWriter(Writer): # type: ignore[misc]
33
35
  transform = NestedInlineTransform(self.document)
34
36
  transform.apply()
35
37
  visitor = self.builder.create_translator(self.document, self.builder)
36
- self.visitor = cast(ManualPageTranslator, visitor)
38
+ self.visitor = cast('ManualPageTranslator', visitor)
37
39
  self.document.walkabout(visitor)
38
40
  self.output = self.visitor.astext()
39
41
 
40
42
 
41
43
  class NestedInlineTransform:
42
- """
43
- Flatten nested inline nodes:
44
+ """Flatten nested inline nodes:
44
45
 
45
46
  Before:
46
47
  <strong>foo=<emphasis>1</emphasis>
@@ -71,17 +72,13 @@ class NestedInlineTransform:
71
72
 
72
73
 
73
74
  class ManualPageTranslator(SphinxTranslator, BaseTranslator): # type: ignore[misc]
74
- """
75
- Custom man page translator.
76
- """
75
+ """Custom man page translator."""
77
76
 
78
77
  _docinfo: dict[str, Any] = {}
79
78
 
80
79
  def __init__(self, document: nodes.document, builder: Builder) -> None:
81
80
  super().__init__(document, builder)
82
81
 
83
- self.in_productionlist = 0
84
-
85
82
  # first title is the manpage title
86
83
  self.section_level = -1
87
84
 
@@ -117,7 +114,7 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): # type: ignore[mi
117
114
  ' "%(date)s" "%(version)s" "%(manual_group)s"\n'
118
115
  )
119
116
  if self._docinfo['subtitle']:
120
- tmpl += '.SH NAME\n' '%(title)s \\- %(subtitle)s\n'
117
+ tmpl += '.SH NAME\n%(title)s \\- %(subtitle)s\n'
121
118
  return tmpl % self._docinfo
122
119
 
123
120
  def visit_start_of_file(self, node: Element) -> None:
@@ -259,7 +256,7 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): # type: ignore[mi
259
256
  # overwritten -- handle footnotes rubric
260
257
  def visit_rubric(self, node: Element) -> None:
261
258
  self.ensure_eol()
262
- if len(node) == 1 and node.astext() in ('Footnotes', _('Footnotes')):
259
+ if len(node) == 1 and node.astext() in {'Footnotes', _('Footnotes')}:
263
260
  self.body.append('.SH ' + self.deunicode(node.astext()).upper() + '\n')
264
261
  raise nodes.SkipNode
265
262
  self.body.append('.sp\n')
@@ -275,26 +272,10 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): # type: ignore[mi
275
272
 
276
273
  def visit_productionlist(self, node: Element) -> None:
277
274
  self.ensure_eol()
278
- self.in_productionlist += 1
279
275
  self.body.append('.sp\n.nf\n')
280
- productionlist = cast(Iterable[addnodes.production], node)
281
- names = (production['tokenname'] for production in productionlist)
282
- maxlen = max(len(name) for name in names)
283
- lastname = None
284
- for production in productionlist:
285
- if production['tokenname']:
286
- lastname = production['tokenname'].ljust(maxlen)
287
- self.body.append(self.defs['strong'][0])
288
- self.body.append(self.deunicode(lastname))
289
- self.body.append(self.defs['strong'][1])
290
- self.body.append(' ::= ')
291
- elif lastname is not None:
292
- self.body.append('%s ' % (' ' * len(lastname)))
293
- production.walkabout(self)
294
- self.body.append('\n')
276
+
277
+ def depart_productionlist(self, node: Element) -> None:
295
278
  self.body.append('\n.fi\n')
296
- self.in_productionlist -= 1
297
- raise nodes.SkipNode
298
279
 
299
280
  def visit_production(self, node: Element) -> None:
300
281
  pass
@@ -379,11 +360,11 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): # type: ignore[mi
379
360
  pass
380
361
 
381
362
  def visit_acks(self, node: Element) -> None:
382
- bullet_list = cast(nodes.bullet_list, node[0])
383
- list_items = cast(Iterable[nodes.list_item], bullet_list)
363
+ bullet_list = cast('nodes.bullet_list', node[0])
364
+ list_items = cast('Iterable[nodes.list_item]', bullet_list)
384
365
  self.ensure_eol()
385
- bullet_list = cast(nodes.bullet_list, node[0])
386
- list_items = cast(Iterable[nodes.list_item], bullet_list)
366
+ bullet_list = cast('nodes.bullet_list', node[0])
367
+ list_items = cast('Iterable[nodes.list_item]', bullet_list)
387
368
  self.body.append(', '.join(n.astext() for n in list_items) + '.')
388
369
  self.body.append('\n')
389
370
  raise nodes.SkipNode
@@ -477,14 +458,14 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): # type: ignore[mi
477
458
  def depart_inline(self, node: Element) -> None:
478
459
  pass
479
460
 
480
- def visit_math(self, node: Element) -> None:
461
+ def visit_math(self, node: nodes.math) -> None:
481
462
  pass
482
463
 
483
- def depart_math(self, node: Element) -> None:
464
+ def depart_math(self, node: nodes.math) -> None:
484
465
  pass
485
466
 
486
- def visit_math_block(self, node: Element) -> None:
467
+ def visit_math_block(self, node: nodes.math_block) -> None:
487
468
  self.visit_centered(node)
488
469
 
489
- def depart_math_block(self, node: Element) -> None:
470
+ def depart_math_block(self, node: nodes.math_block) -> None:
490
471
  self.depart_centered(node)