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.
- sphinx/__init__.py +8 -4
- sphinx/__main__.py +2 -0
- sphinx/_cli/__init__.py +2 -5
- sphinx/_cli/util/colour.py +34 -11
- sphinx/_cli/util/errors.py +128 -61
- sphinx/addnodes.py +51 -35
- sphinx/application.py +362 -230
- sphinx/builders/__init__.py +87 -64
- sphinx/builders/_epub_base.py +65 -56
- sphinx/builders/changes.py +17 -23
- sphinx/builders/dirhtml.py +8 -13
- sphinx/builders/epub3.py +70 -38
- sphinx/builders/gettext.py +93 -73
- sphinx/builders/html/__init__.py +240 -186
- sphinx/builders/html/_assets.py +9 -2
- sphinx/builders/html/_build_info.py +3 -0
- sphinx/builders/latex/__init__.py +64 -54
- sphinx/builders/latex/constants.py +14 -11
- sphinx/builders/latex/nodes.py +2 -0
- sphinx/builders/latex/theming.py +8 -9
- sphinx/builders/latex/transforms.py +7 -5
- sphinx/builders/linkcheck.py +193 -149
- sphinx/builders/manpage.py +17 -17
- sphinx/builders/singlehtml.py +28 -16
- sphinx/builders/texinfo.py +28 -21
- sphinx/builders/text.py +10 -15
- sphinx/builders/xml.py +10 -19
- sphinx/cmd/build.py +49 -119
- sphinx/cmd/make_mode.py +35 -31
- sphinx/cmd/quickstart.py +78 -62
- sphinx/config.py +265 -163
- sphinx/directives/__init__.py +51 -54
- sphinx/directives/admonitions.py +107 -0
- sphinx/directives/code.py +24 -19
- sphinx/directives/other.py +21 -42
- sphinx/directives/patches.py +28 -16
- sphinx/domains/__init__.py +54 -31
- sphinx/domains/_domains_container.py +22 -17
- sphinx/domains/_index.py +5 -8
- sphinx/domains/c/__init__.py +366 -245
- sphinx/domains/c/_ast.py +378 -256
- sphinx/domains/c/_ids.py +89 -31
- sphinx/domains/c/_parser.py +283 -214
- sphinx/domains/c/_symbol.py +269 -198
- sphinx/domains/changeset.py +39 -24
- sphinx/domains/citation.py +54 -24
- sphinx/domains/cpp/__init__.py +517 -362
- sphinx/domains/cpp/_ast.py +999 -682
- sphinx/domains/cpp/_ids.py +133 -65
- sphinx/domains/cpp/_parser.py +746 -588
- sphinx/domains/cpp/_symbol.py +692 -489
- sphinx/domains/index.py +10 -8
- sphinx/domains/javascript.py +152 -74
- sphinx/domains/math.py +50 -40
- sphinx/domains/python/__init__.py +402 -211
- sphinx/domains/python/_annotations.py +134 -61
- sphinx/domains/python/_object.py +155 -68
- sphinx/domains/rst.py +94 -49
- sphinx/domains/std/__init__.py +510 -249
- sphinx/environment/__init__.py +345 -61
- sphinx/environment/adapters/asset.py +7 -1
- sphinx/environment/adapters/indexentries.py +15 -20
- sphinx/environment/adapters/toctree.py +19 -9
- sphinx/environment/collectors/__init__.py +3 -1
- sphinx/environment/collectors/asset.py +18 -15
- sphinx/environment/collectors/dependencies.py +8 -10
- sphinx/environment/collectors/metadata.py +6 -4
- sphinx/environment/collectors/title.py +3 -1
- sphinx/environment/collectors/toctree.py +4 -4
- sphinx/errors.py +1 -3
- sphinx/events.py +4 -4
- sphinx/ext/apidoc/__init__.py +66 -0
- sphinx/ext/apidoc/__main__.py +9 -0
- sphinx/ext/apidoc/_cli.py +356 -0
- sphinx/ext/apidoc/_extension.py +262 -0
- sphinx/ext/apidoc/_generate.py +356 -0
- sphinx/ext/apidoc/_shared.py +99 -0
- sphinx/ext/autodoc/__init__.py +837 -483
- sphinx/ext/autodoc/directive.py +57 -21
- sphinx/ext/autodoc/importer.py +184 -67
- sphinx/ext/autodoc/mock.py +25 -10
- sphinx/ext/autodoc/preserve_defaults.py +17 -9
- sphinx/ext/autodoc/type_comment.py +56 -29
- sphinx/ext/autodoc/typehints.py +49 -26
- sphinx/ext/autosectionlabel.py +28 -11
- sphinx/ext/autosummary/__init__.py +281 -142
- sphinx/ext/autosummary/generate.py +121 -51
- sphinx/ext/coverage.py +152 -91
- sphinx/ext/doctest.py +169 -101
- sphinx/ext/duration.py +12 -6
- sphinx/ext/extlinks.py +33 -21
- sphinx/ext/githubpages.py +8 -8
- sphinx/ext/graphviz.py +175 -109
- sphinx/ext/ifconfig.py +11 -6
- sphinx/ext/imgconverter.py +48 -25
- sphinx/ext/imgmath.py +127 -97
- sphinx/ext/inheritance_diagram.py +177 -103
- sphinx/ext/intersphinx/__init__.py +22 -13
- sphinx/ext/intersphinx/__main__.py +3 -1
- sphinx/ext/intersphinx/_cli.py +18 -14
- sphinx/ext/intersphinx/_load.py +91 -82
- sphinx/ext/intersphinx/_resolve.py +108 -74
- sphinx/ext/intersphinx/_shared.py +2 -2
- sphinx/ext/linkcode.py +28 -12
- sphinx/ext/mathjax.py +60 -29
- sphinx/ext/napoleon/__init__.py +19 -7
- sphinx/ext/napoleon/docstring.py +229 -231
- sphinx/ext/todo.py +44 -49
- sphinx/ext/viewcode.py +105 -57
- sphinx/extension.py +3 -1
- sphinx/highlighting.py +13 -7
- sphinx/io.py +9 -13
- sphinx/jinja2glue.py +29 -26
- sphinx/locale/__init__.py +8 -9
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +2155 -2050
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +2175 -2070
- sphinx/locale/ca/LC_MESSAGES/sphinx.js +3 -3
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +2690 -2585
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.js +63 -0
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.po +4216 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +2096 -1991
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +2248 -2143
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +2201 -2096
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +2282 -2177
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +2261 -2156
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +2604 -2499
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2631 -2526
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +2078 -1973
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +2633 -2528
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +2449 -2344
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +2241 -2136
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +504 -500
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr/LC_MESSAGES/sphinx.po +513 -509
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +2644 -2539
- sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +504 -500
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +501 -497
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +2609 -2504
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +2265 -2160
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +2621 -2516
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +2567 -2462
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +2631 -2526
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +2214 -2109
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +2218 -2113
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +2088 -1983
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2247 -2142
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +2227 -2122
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +2316 -2211
- sphinx/locale/pl/LC_MESSAGES/sphinx.js +2 -2
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +2442 -2336
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2657 -2552
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2243 -2138
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +2244 -2139
- sphinx/locale/ru/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +2660 -2555
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +2134 -2029
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +2614 -2509
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +2167 -2062
- sphinx/locale/sphinx.pot +2069 -1964
- sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sq/LC_MESSAGES/sphinx.po +2661 -2556
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +2213 -2108
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +2229 -2124
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +2608 -2503
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2167 -2062
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +2204 -2099
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +2659 -2554
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/parsers.py +8 -7
- sphinx/project.py +2 -2
- sphinx/pycode/__init__.py +31 -21
- sphinx/pycode/ast.py +6 -3
- sphinx/pycode/parser.py +14 -8
- sphinx/pygments_styles.py +4 -5
- sphinx/registry.py +192 -92
- sphinx/roles.py +58 -7
- sphinx/search/__init__.py +75 -54
- sphinx/search/en.py +11 -13
- sphinx/search/fi.py +1 -1
- sphinx/search/ja.py +8 -6
- sphinx/search/nl.py +1 -1
- sphinx/search/zh.py +19 -21
- sphinx/testing/fixtures.py +26 -29
- sphinx/testing/path.py +26 -62
- sphinx/testing/restructuredtext.py +14 -8
- sphinx/testing/util.py +21 -19
- sphinx/texinputs/make.bat.jinja +50 -50
- sphinx/texinputs/sphinx.sty +4 -3
- sphinx/texinputs/sphinxlatexadmonitions.sty +1 -1
- sphinx/texinputs/sphinxlatexobjects.sty +29 -10
- sphinx/themes/basic/static/searchtools.js +8 -5
- sphinx/theming.py +49 -61
- sphinx/transforms/__init__.py +17 -38
- sphinx/transforms/compact_bullet_list.py +5 -3
- sphinx/transforms/i18n.py +8 -21
- sphinx/transforms/post_transforms/__init__.py +142 -93
- sphinx/transforms/post_transforms/code.py +5 -5
- sphinx/transforms/post_transforms/images.py +28 -24
- sphinx/transforms/references.py +3 -1
- sphinx/util/__init__.py +109 -60
- sphinx/util/_files.py +39 -23
- sphinx/util/_importer.py +4 -1
- sphinx/util/_inventory_file_reader.py +76 -0
- sphinx/util/_io.py +2 -2
- sphinx/util/_lines.py +6 -3
- sphinx/util/_pathlib.py +40 -2
- sphinx/util/build_phase.py +2 -0
- sphinx/util/cfamily.py +19 -14
- sphinx/util/console.py +44 -179
- sphinx/util/display.py +9 -10
- sphinx/util/docfields.py +140 -122
- sphinx/util/docstrings.py +1 -1
- sphinx/util/docutils.py +118 -77
- sphinx/util/fileutil.py +25 -26
- sphinx/util/http_date.py +2 -0
- sphinx/util/i18n.py +77 -64
- sphinx/util/images.py +8 -6
- sphinx/util/inspect.py +147 -38
- sphinx/util/inventory.py +215 -116
- sphinx/util/logging.py +33 -33
- sphinx/util/matching.py +12 -4
- sphinx/util/nodes.py +18 -13
- sphinx/util/osutil.py +38 -39
- sphinx/util/parallel.py +22 -13
- sphinx/util/parsing.py +2 -1
- sphinx/util/png.py +6 -2
- sphinx/util/requests.py +33 -2
- sphinx/util/rst.py +3 -2
- sphinx/util/tags.py +1 -1
- sphinx/util/template.py +18 -10
- sphinx/util/texescape.py +8 -6
- sphinx/util/typing.py +148 -122
- sphinx/versioning.py +3 -3
- sphinx/writers/html.py +3 -1
- sphinx/writers/html5.py +63 -52
- sphinx/writers/latex.py +83 -67
- sphinx/writers/manpage.py +19 -38
- sphinx/writers/texinfo.py +47 -47
- sphinx/writers/text.py +50 -32
- sphinx/writers/xml.py +11 -8
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/LICENSE.rst +1 -1
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/METADATA +25 -15
- sphinx-8.2.0.dist-info/RECORD +606 -0
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/WHEEL +1 -1
- sphinx/builders/html/transforms.py +0 -90
- sphinx/ext/apidoc.py +0 -721
- sphinx/util/exceptions.py +0 -74
- sphinx-8.1.2.dist-info/RECORD +0 -598
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/entry_points.txt +0 -0
sphinx/ext/todo.py
CHANGED
|
@@ -9,14 +9,13 @@ from __future__ import annotations
|
|
|
9
9
|
|
|
10
10
|
import functools
|
|
11
11
|
import operator
|
|
12
|
-
from typing import TYPE_CHECKING,
|
|
12
|
+
from typing import TYPE_CHECKING, cast
|
|
13
13
|
|
|
14
14
|
from docutils import nodes
|
|
15
|
-
from docutils.parsers.rst import directives
|
|
16
|
-
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
|
|
17
15
|
|
|
18
16
|
import sphinx
|
|
19
17
|
from sphinx import addnodes
|
|
18
|
+
from sphinx.directives.admonitions import SphinxAdmonition
|
|
20
19
|
from sphinx.domains import Domain
|
|
21
20
|
from sphinx.errors import NoUri
|
|
22
21
|
from sphinx.locale import _, __
|
|
@@ -25,6 +24,7 @@ from sphinx.util.docutils import SphinxDirective, new_document
|
|
|
25
24
|
|
|
26
25
|
if TYPE_CHECKING:
|
|
27
26
|
from collections.abc import Set
|
|
27
|
+
from typing import Any, ClassVar
|
|
28
28
|
|
|
29
29
|
from docutils.nodes import Element, Node
|
|
30
30
|
|
|
@@ -45,37 +45,25 @@ class todolist(nodes.General, nodes.Element):
|
|
|
45
45
|
pass
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
class Todo(
|
|
49
|
-
"""
|
|
50
|
-
A todo entry, displayed (if configured) in the form of an admonition.
|
|
51
|
-
"""
|
|
48
|
+
class Todo(SphinxAdmonition):
|
|
49
|
+
"""A todo entry, displayed (if configured) in the form of an admonition."""
|
|
52
50
|
|
|
53
51
|
node_class = todo_node
|
|
54
|
-
has_content = True
|
|
55
|
-
required_arguments = 0
|
|
56
|
-
optional_arguments = 0
|
|
57
|
-
final_argument_whitespace = False
|
|
58
|
-
option_spec: ClassVar[OptionSpec] = {
|
|
59
|
-
'class': directives.class_option,
|
|
60
|
-
'name': directives.unchanged,
|
|
61
|
-
}
|
|
62
52
|
|
|
63
53
|
def run(self) -> list[Node]:
|
|
64
54
|
if not self.options.get('class'):
|
|
65
55
|
self.options['class'] = ['admonition-todo']
|
|
66
56
|
|
|
67
57
|
(todo,) = super().run()
|
|
68
|
-
if isinstance(todo,
|
|
58
|
+
if not isinstance(todo, todo_node):
|
|
69
59
|
return [todo]
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
else:
|
|
78
|
-
raise RuntimeError # never reached here
|
|
60
|
+
|
|
61
|
+
todo.insert(0, nodes.title(text=_('Todo')))
|
|
62
|
+
todo['docname'] = self.env.docname
|
|
63
|
+
self.add_name(todo)
|
|
64
|
+
self.set_source_info(todo)
|
|
65
|
+
self.state.document.note_explicit_target(todo)
|
|
66
|
+
return [todo]
|
|
79
67
|
|
|
80
68
|
|
|
81
69
|
class TodoDomain(Domain):
|
|
@@ -93,22 +81,22 @@ class TodoDomain(Domain):
|
|
|
93
81
|
for docname in docnames:
|
|
94
82
|
self.todos[docname] = otherdata['todos'][docname]
|
|
95
83
|
|
|
96
|
-
def process_doc(
|
|
97
|
-
|
|
84
|
+
def process_doc(
|
|
85
|
+
self, env: BuildEnvironment, docname: str, document: nodes.document
|
|
86
|
+
) -> None:
|
|
98
87
|
todos = self.todos.setdefault(docname, [])
|
|
99
88
|
for todo in document.findall(todo_node):
|
|
100
|
-
env.
|
|
89
|
+
env.events.emit('todo-defined', todo)
|
|
101
90
|
todos.append(todo)
|
|
102
91
|
|
|
103
92
|
if env.config.todo_emit_warnings:
|
|
104
|
-
logger.warning(
|
|
105
|
-
|
|
93
|
+
logger.warning(
|
|
94
|
+
__('TODO entry found: %s'), todo[1].astext(), location=todo
|
|
95
|
+
)
|
|
106
96
|
|
|
107
97
|
|
|
108
98
|
class TodoList(SphinxDirective):
|
|
109
|
-
"""
|
|
110
|
-
A list of all todo entries.
|
|
111
|
-
"""
|
|
99
|
+
"""A list of all todo entries."""
|
|
112
100
|
|
|
113
101
|
has_content = False
|
|
114
102
|
required_arguments = 0
|
|
@@ -134,7 +122,8 @@ class TodoListProcessor:
|
|
|
134
122
|
|
|
135
123
|
def process(self, doctree: nodes.document, docname: str) -> None:
|
|
136
124
|
todos: list[todo_node] = functools.reduce(
|
|
137
|
-
operator.iadd, self.domain.todos.values(), []
|
|
125
|
+
operator.iadd, self.domain.todos.values(), []
|
|
126
|
+
)
|
|
138
127
|
for node in list(doctree.findall(todolist)):
|
|
139
128
|
if not self.config.todo_include_todos:
|
|
140
129
|
node.parent.remove(node)
|
|
@@ -162,11 +151,13 @@ class TodoListProcessor:
|
|
|
162
151
|
if self.config.todo_link_only:
|
|
163
152
|
description = _('<<original entry>>')
|
|
164
153
|
else:
|
|
165
|
-
description =
|
|
166
|
-
|
|
154
|
+
description = _('(The <<original entry>> is located in %s, line %d.)') % (
|
|
155
|
+
todo.source,
|
|
156
|
+
todo.line,
|
|
157
|
+
)
|
|
167
158
|
|
|
168
|
-
prefix = description[:description.find('<<')]
|
|
169
|
-
suffix = description[description.find('>>') + 2:]
|
|
159
|
+
prefix = description[: description.find('<<')]
|
|
160
|
+
suffix = description[description.find('>>') + 2 :]
|
|
170
161
|
|
|
171
162
|
para = nodes.paragraph(classes=['todo-source'])
|
|
172
163
|
para += nodes.Text(prefix)
|
|
@@ -175,7 +166,9 @@ class TodoListProcessor:
|
|
|
175
166
|
linktext = nodes.emphasis(_('original entry'), _('original entry'))
|
|
176
167
|
reference = nodes.reference('', '', linktext, internal=True)
|
|
177
168
|
try:
|
|
178
|
-
reference['refuri'] = self.builder.get_relative_uri(
|
|
169
|
+
reference['refuri'] = self.builder.get_relative_uri(
|
|
170
|
+
docname, todo['docname']
|
|
171
|
+
)
|
|
179
172
|
reference['refuri'] += '#' + todo['ids'][0]
|
|
180
173
|
except NoUri:
|
|
181
174
|
# ignore if no URI can be determined, e.g. for LaTeX output
|
|
@@ -214,7 +207,7 @@ def latex_visit_todo_node(self: LaTeXTranslator, node: todo_node) -> None:
|
|
|
214
207
|
self.body.append('\n\\begin{sphinxtodo}{')
|
|
215
208
|
self.body.append(self.hypertarget_to(node))
|
|
216
209
|
|
|
217
|
-
title_node = cast(nodes.title, node[0])
|
|
210
|
+
title_node = cast('nodes.title', node[0])
|
|
218
211
|
title = texescape.escape(title_node.astext(), self.config.latex_engine)
|
|
219
212
|
self.body.append('%s:}' % title)
|
|
220
213
|
self.no_latex_floats += 1
|
|
@@ -232,17 +225,19 @@ def latex_depart_todo_node(self: LaTeXTranslator, node: todo_node) -> None:
|
|
|
232
225
|
|
|
233
226
|
def setup(app: Sphinx) -> ExtensionMetadata:
|
|
234
227
|
app.add_event('todo-defined')
|
|
235
|
-
app.add_config_value('todo_include_todos', False, 'html')
|
|
236
|
-
app.add_config_value('todo_link_only', False, 'html')
|
|
237
|
-
app.add_config_value('todo_emit_warnings', False, 'html')
|
|
228
|
+
app.add_config_value('todo_include_todos', False, 'html', types=frozenset({bool}))
|
|
229
|
+
app.add_config_value('todo_link_only', False, 'html', types=frozenset({bool}))
|
|
230
|
+
app.add_config_value('todo_emit_warnings', False, 'html', types=frozenset({bool}))
|
|
238
231
|
|
|
239
232
|
app.add_node(todolist)
|
|
240
|
-
app.add_node(
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
233
|
+
app.add_node(
|
|
234
|
+
todo_node,
|
|
235
|
+
html=(visit_todo_node, depart_todo_node),
|
|
236
|
+
latex=(latex_visit_todo_node, latex_depart_todo_node),
|
|
237
|
+
text=(visit_todo_node, depart_todo_node),
|
|
238
|
+
man=(visit_todo_node, depart_todo_node),
|
|
239
|
+
texinfo=(visit_todo_node, depart_todo_node),
|
|
240
|
+
)
|
|
246
241
|
|
|
247
242
|
app.add_directive('todo', Todo)
|
|
248
243
|
app.add_directive('todolist', TodoList)
|
sphinx/ext/viewcode.py
CHANGED
|
@@ -2,19 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import importlib.util
|
|
5
6
|
import operator
|
|
6
7
|
import posixpath
|
|
7
8
|
import traceback
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
from typing import TYPE_CHECKING, Any, cast
|
|
9
|
+
from types import NoneType
|
|
10
|
+
from typing import TYPE_CHECKING, cast
|
|
11
11
|
|
|
12
12
|
from docutils import nodes
|
|
13
|
-
from docutils.nodes import Element
|
|
13
|
+
from docutils.nodes import Element
|
|
14
14
|
|
|
15
15
|
import sphinx
|
|
16
16
|
from sphinx import addnodes
|
|
17
|
-
from sphinx.builders.html import StandaloneHTMLBuilder
|
|
18
17
|
from sphinx.locale import _, __
|
|
19
18
|
from sphinx.pycode import ModuleAnalyzer
|
|
20
19
|
from sphinx.transforms.post_transforms import SphinxPostTransform
|
|
@@ -24,11 +23,16 @@ from sphinx.util.nodes import make_refnode
|
|
|
24
23
|
from sphinx.util.osutil import _last_modified_time
|
|
25
24
|
|
|
26
25
|
if TYPE_CHECKING:
|
|
27
|
-
from collections.abc import
|
|
26
|
+
from collections.abc import Iterator, Set
|
|
27
|
+
from typing import Any
|
|
28
|
+
|
|
29
|
+
from docutils.nodes import Node
|
|
28
30
|
|
|
29
31
|
from sphinx.application import Sphinx
|
|
30
32
|
from sphinx.builders import Builder
|
|
33
|
+
from sphinx.builders.html import StandaloneHTMLBuilder
|
|
31
34
|
from sphinx.environment import BuildEnvironment
|
|
35
|
+
from sphinx.util._pathlib import _StrPath
|
|
32
36
|
from sphinx.util.typing import ExtensionMetadata
|
|
33
37
|
|
|
34
38
|
logger = logging.getLogger(__name__)
|
|
@@ -47,12 +51,30 @@ class viewcode_anchor(Element):
|
|
|
47
51
|
|
|
48
52
|
|
|
49
53
|
def _get_full_modname(modname: str, attribute: str) -> str | None:
|
|
54
|
+
if modname is None:
|
|
55
|
+
# Prevents a TypeError: if the last getattr() call will return None
|
|
56
|
+
# then it's better to return it directly
|
|
57
|
+
return None
|
|
58
|
+
|
|
50
59
|
try:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
60
|
+
# Attempt to find full path of module
|
|
61
|
+
module_path = modname.split('.')
|
|
62
|
+
num_parts = len(module_path)
|
|
63
|
+
for i in range(num_parts, 0, -1):
|
|
64
|
+
mod_root = '.'.join(module_path[:i])
|
|
65
|
+
module_spec = importlib.util.find_spec(mod_root)
|
|
66
|
+
if module_spec is not None:
|
|
67
|
+
break
|
|
68
|
+
else:
|
|
54
69
|
return None
|
|
55
|
-
|
|
70
|
+
# Load and execute the module
|
|
71
|
+
module = importlib.util.module_from_spec(module_spec)
|
|
72
|
+
if module_spec.loader is None:
|
|
73
|
+
return None
|
|
74
|
+
module_spec.loader.exec_module(module)
|
|
75
|
+
if i != num_parts:
|
|
76
|
+
for mod in module_path[i:]:
|
|
77
|
+
module = getattr(module, mod)
|
|
56
78
|
|
|
57
79
|
# Allow an attribute to have multiple parts and incidentally allow
|
|
58
80
|
# repeated .s in the attribute.
|
|
@@ -64,8 +86,8 @@ def _get_full_modname(modname: str, attribute: str) -> str | None:
|
|
|
64
86
|
return getattr(value, '__module__', None)
|
|
65
87
|
except AttributeError:
|
|
66
88
|
# sphinx.ext.viewcode can't follow class instance attribute
|
|
67
|
-
# then AttributeError logging output only
|
|
68
|
-
logger.
|
|
89
|
+
# then AttributeError logging output only debug mode.
|
|
90
|
+
logger.debug("Didn't find %s in %s", attribute, modname)
|
|
69
91
|
return None
|
|
70
92
|
except Exception as e:
|
|
71
93
|
# sphinx.ext.viewcode follow python domain directives.
|
|
@@ -78,15 +100,16 @@ def _get_full_modname(modname: str, attribute: str) -> str | None:
|
|
|
78
100
|
|
|
79
101
|
|
|
80
102
|
def is_supported_builder(builder: Builder) -> bool:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
103
|
+
return (
|
|
104
|
+
builder.format == 'html'
|
|
105
|
+
and builder.name != 'singlehtml'
|
|
106
|
+
and (not builder.name.startswith('epub') or builder.config.viewcode_enable_epub)
|
|
107
|
+
)
|
|
86
108
|
|
|
87
109
|
|
|
88
110
|
def doctree_read(app: Sphinx, doctree: Node) -> None:
|
|
89
|
-
env = app.
|
|
111
|
+
env = app.env
|
|
112
|
+
events = app.events
|
|
90
113
|
if not hasattr(env, '_viewcode_modules'):
|
|
91
114
|
env._viewcode_modules = {} # type: ignore[attr-defined]
|
|
92
115
|
|
|
@@ -95,7 +118,7 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
|
|
|
95
118
|
if entry is False:
|
|
96
119
|
return False
|
|
97
120
|
|
|
98
|
-
code_tags =
|
|
121
|
+
code_tags = events.emit_firstresult('viewcode-find-source', modname)
|
|
99
122
|
if code_tags is None:
|
|
100
123
|
try:
|
|
101
124
|
analyzer = ModuleAnalyzer.for_module(modname)
|
|
@@ -130,8 +153,8 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
|
|
|
130
153
|
fullname = signode.get('fullname')
|
|
131
154
|
refname = modname
|
|
132
155
|
if env.config.viewcode_follow_imported_members:
|
|
133
|
-
new_modname =
|
|
134
|
-
'viewcode-follow-imported', modname, fullname
|
|
156
|
+
new_modname = events.emit_firstresult(
|
|
157
|
+
'viewcode-follow-imported', modname, fullname
|
|
135
158
|
)
|
|
136
159
|
if not new_modname:
|
|
137
160
|
new_modname = _get_full_modname(modname, fullname)
|
|
@@ -146,11 +169,14 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
|
|
|
146
169
|
continue
|
|
147
170
|
names.add(fullname)
|
|
148
171
|
pagename = posixpath.join(OUTPUT_DIRNAME, modname.replace('.', '/'))
|
|
149
|
-
signode += viewcode_anchor(
|
|
172
|
+
signode += viewcode_anchor(
|
|
173
|
+
reftarget=pagename, refid=fullname, refdoc=env.docname
|
|
174
|
+
)
|
|
150
175
|
|
|
151
176
|
|
|
152
|
-
def env_merge_info(
|
|
153
|
-
|
|
177
|
+
def env_merge_info(
|
|
178
|
+
app: Sphinx, env: BuildEnvironment, docnames: Set[str], other: BuildEnvironment
|
|
179
|
+
) -> None:
|
|
154
180
|
if not hasattr(other, '_viewcode_modules'):
|
|
155
181
|
return
|
|
156
182
|
# create a _viewcode_modules dict on the main environment
|
|
@@ -198,8 +224,13 @@ class ViewcodeAnchorTransform(SphinxPostTransform):
|
|
|
198
224
|
def convert_viewcode_anchors(self) -> None:
|
|
199
225
|
for node in self.document.findall(viewcode_anchor):
|
|
200
226
|
anchor = nodes.inline('', _('[source]'), classes=['viewcode-link'])
|
|
201
|
-
refnode = make_refnode(
|
|
202
|
-
|
|
227
|
+
refnode = make_refnode(
|
|
228
|
+
self.app.builder,
|
|
229
|
+
node['refdoc'],
|
|
230
|
+
node['reftarget'],
|
|
231
|
+
node['refid'],
|
|
232
|
+
anchor,
|
|
233
|
+
)
|
|
203
234
|
node.replace_self(refnode)
|
|
204
235
|
|
|
205
236
|
def remove_viewcode_anchors(self) -> None:
|
|
@@ -207,9 +238,10 @@ class ViewcodeAnchorTransform(SphinxPostTransform):
|
|
|
207
238
|
node.parent.remove(node)
|
|
208
239
|
|
|
209
240
|
|
|
210
|
-
def get_module_filename(app: Sphinx, modname: str) ->
|
|
241
|
+
def get_module_filename(app: Sphinx, modname: str) -> _StrPath | None:
|
|
211
242
|
"""Get module filename for *modname*."""
|
|
212
|
-
|
|
243
|
+
events = app.events
|
|
244
|
+
source_info = events.emit_firstresult('viewcode-find-source', modname)
|
|
213
245
|
if source_info:
|
|
214
246
|
return None
|
|
215
247
|
else:
|
|
@@ -227,9 +259,9 @@ def should_generate_module_page(app: Sphinx, modname: str) -> bool:
|
|
|
227
259
|
# Always (re-)generate module page when module filename is not found.
|
|
228
260
|
return True
|
|
229
261
|
|
|
230
|
-
builder = cast(StandaloneHTMLBuilder, app.builder)
|
|
262
|
+
builder = cast('StandaloneHTMLBuilder', app.builder)
|
|
231
263
|
basename = modname.replace('.', '/') + builder.out_suffix
|
|
232
|
-
page_filename =
|
|
264
|
+
page_filename = app.outdir / '_modules' / basename
|
|
233
265
|
|
|
234
266
|
try:
|
|
235
267
|
if _last_modified_time(module_filename) <= _last_modified_time(page_filename):
|
|
@@ -242,7 +274,7 @@ def should_generate_module_page(app: Sphinx, modname: str) -> bool:
|
|
|
242
274
|
|
|
243
275
|
|
|
244
276
|
def collect_pages(app: Sphinx) -> Iterator[tuple[str, dict[str, Any], str]]:
|
|
245
|
-
env = app.
|
|
277
|
+
env = app.env
|
|
246
278
|
if not hasattr(env, '_viewcode_modules'):
|
|
247
279
|
return
|
|
248
280
|
if not is_supported_builder(app.builder):
|
|
@@ -253,10 +285,13 @@ def collect_pages(app: Sphinx) -> Iterator[tuple[str, dict[str, Any], str]]:
|
|
|
253
285
|
modnames = set(env._viewcode_modules)
|
|
254
286
|
|
|
255
287
|
for modname, entry in status_iterator(
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
288
|
+
sorted(env._viewcode_modules.items()),
|
|
289
|
+
__('highlighting module code... '),
|
|
290
|
+
'blue',
|
|
291
|
+
len(env._viewcode_modules),
|
|
292
|
+
app.verbosity,
|
|
293
|
+
operator.itemgetter(0),
|
|
294
|
+
):
|
|
260
295
|
if not entry:
|
|
261
296
|
continue
|
|
262
297
|
if not should_generate_module_page(app, modname):
|
|
@@ -286,9 +321,11 @@ def collect_pages(app: Sphinx) -> Iterator[tuple[str, dict[str, Any], str]]:
|
|
|
286
321
|
for name, docname in used.items():
|
|
287
322
|
type, start, end = tags[name]
|
|
288
323
|
backlink = urito(pagename, docname) + '#' + refname + '.' + name
|
|
289
|
-
lines[start] = (
|
|
290
|
-
|
|
291
|
-
|
|
324
|
+
lines[start] = (
|
|
325
|
+
f'<div class="viewcode-block" id="{name}">\n'
|
|
326
|
+
f'<a class="viewcode-back" href="{backlink}">{link_text}</a>\n'
|
|
327
|
+
+ lines[start]
|
|
328
|
+
)
|
|
292
329
|
lines[min(end, max_index)] += '</div>\n'
|
|
293
330
|
|
|
294
331
|
# try to find parents (for submodules)
|
|
@@ -298,20 +335,24 @@ def collect_pages(app: Sphinx) -> Iterator[tuple[str, dict[str, Any], str]]:
|
|
|
298
335
|
parent = parent.rsplit('.', 1)[0]
|
|
299
336
|
if parent in modnames:
|
|
300
337
|
parents.append({
|
|
301
|
-
'link': urito(
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
338
|
+
'link': urito(
|
|
339
|
+
pagename,
|
|
340
|
+
posixpath.join(OUTPUT_DIRNAME, parent.replace('.', '/')),
|
|
341
|
+
),
|
|
342
|
+
'title': parent,
|
|
343
|
+
})
|
|
344
|
+
parents.append({
|
|
345
|
+
'link': urito(pagename, posixpath.join(OUTPUT_DIRNAME, 'index')),
|
|
346
|
+
'title': _('Module code'),
|
|
347
|
+
})
|
|
306
348
|
parents.reverse()
|
|
307
349
|
# putting it all together
|
|
308
350
|
context = {
|
|
309
351
|
'parents': parents,
|
|
310
352
|
'title': modname,
|
|
311
|
-
'body': (_('<h1>Source code for %s</h1>') % modname +
|
|
312
|
-
'\n'.join(lines)),
|
|
353
|
+
'body': (_('<h1>Source code for %s</h1>') % modname + '\n'.join(lines)),
|
|
313
354
|
}
|
|
314
|
-
yield
|
|
355
|
+
yield pagename, context, 'page.html'
|
|
315
356
|
|
|
316
357
|
if not modnames:
|
|
317
358
|
return
|
|
@@ -329,30 +370,37 @@ def collect_pages(app: Sphinx) -> Iterator[tuple[str, dict[str, Any], str]]:
|
|
|
329
370
|
stack.pop()
|
|
330
371
|
html.append('</ul>')
|
|
331
372
|
stack.append(modname + '.')
|
|
332
|
-
relative_uri = urito(
|
|
333
|
-
|
|
373
|
+
relative_uri = urito(
|
|
374
|
+
posixpath.join(OUTPUT_DIRNAME, 'index'),
|
|
375
|
+
posixpath.join(OUTPUT_DIRNAME, modname.replace('.', '/')),
|
|
376
|
+
)
|
|
334
377
|
html.append(f'<li><a href="{relative_uri}">{modname}</a></li>\n')
|
|
335
378
|
html.append('</ul>' * (len(stack) - 1))
|
|
336
379
|
context = {
|
|
337
380
|
'title': _('Overview: module code'),
|
|
338
|
-
'body': (_('<h1>All modules for which code is available</h1>') +
|
|
339
|
-
''.join(html)),
|
|
381
|
+
'body': (_('<h1>All modules for which code is available</h1>') + ''.join(html)),
|
|
340
382
|
}
|
|
341
383
|
|
|
342
|
-
yield
|
|
384
|
+
yield posixpath.join(OUTPUT_DIRNAME, 'index'), context, 'page.html'
|
|
343
385
|
|
|
344
386
|
|
|
345
387
|
def setup(app: Sphinx) -> ExtensionMetadata:
|
|
346
|
-
app.add_config_value('viewcode_import', None, '')
|
|
347
|
-
app.add_config_value('viewcode_enable_epub', False, '')
|
|
348
|
-
app.add_config_value(
|
|
349
|
-
|
|
388
|
+
app.add_config_value('viewcode_import', None, '', types=frozenset({NoneType}))
|
|
389
|
+
app.add_config_value('viewcode_enable_epub', False, '', types=frozenset({bool}))
|
|
390
|
+
app.add_config_value(
|
|
391
|
+
'viewcode_follow_imported_members', True, '', types=frozenset({bool})
|
|
392
|
+
)
|
|
393
|
+
app.add_config_value('viewcode_line_numbers', False, 'env', types=frozenset({bool}))
|
|
350
394
|
app.connect('doctree-read', doctree_read)
|
|
351
395
|
app.connect('env-merge-info', env_merge_info)
|
|
352
396
|
app.connect('env-purge-doc', env_purge_doc)
|
|
353
397
|
app.connect('html-collect-pages', collect_pages)
|
|
354
|
-
# app.add_config_value(
|
|
355
|
-
#
|
|
398
|
+
# app.add_config_value(
|
|
399
|
+
# 'viewcode_include_modules', [], 'env', types=frozenset({list, tuple})
|
|
400
|
+
# )
|
|
401
|
+
# app.add_config_value(
|
|
402
|
+
# 'viewcode_exclude_modules', [], 'env', types=frozenset({list, tuple})
|
|
403
|
+
# )
|
|
356
404
|
app.add_event('viewcode-find-source')
|
|
357
405
|
app.add_event('viewcode-follow-imported')
|
|
358
406
|
app.add_post_transform(ViewcodeAnchorTransform)
|
sphinx/extension.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
7
|
from packaging.version import InvalidVersion, Version
|
|
8
8
|
|
|
@@ -11,6 +11,8 @@ from sphinx.locale import __
|
|
|
11
11
|
from sphinx.util import logging
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
14
16
|
from sphinx.application import Sphinx
|
|
15
17
|
from sphinx.config import Config
|
|
16
18
|
from sphinx.util.typing import ExtensionMetadata
|
sphinx/highlighting.py
CHANGED
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from functools import partial
|
|
6
6
|
from importlib import import_module
|
|
7
|
-
from typing import TYPE_CHECKING
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
8
|
|
|
9
9
|
import pygments
|
|
10
10
|
from pygments import highlight
|
|
@@ -27,12 +27,14 @@ from sphinx.pygments_styles import NoneStyle, SphinxStyle
|
|
|
27
27
|
from sphinx.util import logging, texescape
|
|
28
28
|
|
|
29
29
|
if TYPE_CHECKING:
|
|
30
|
+
from typing import Any
|
|
31
|
+
|
|
30
32
|
from pygments.formatter import Formatter
|
|
31
33
|
from pygments.lexer import Lexer
|
|
32
34
|
from pygments.style import Style
|
|
33
35
|
|
|
34
|
-
if tuple(map(int, pygments.__version__.split('.')
|
|
35
|
-
from pygments.formatter import Formatter
|
|
36
|
+
if tuple(map(int, pygments.__version__.split('.')[:2])) < (2, 18):
|
|
37
|
+
from pygments.formatter import Formatter
|
|
36
38
|
|
|
37
39
|
Formatter.__class_getitem__ = classmethod(lambda cls, name: cls) # type: ignore[attr-defined]
|
|
38
40
|
|
|
@@ -127,7 +129,7 @@ class PygmentsBridge:
|
|
|
127
129
|
else:
|
|
128
130
|
return get_style_by_name(stylename)
|
|
129
131
|
|
|
130
|
-
def get_formatter(self, **kwargs: Any) -> Formatter:
|
|
132
|
+
def get_formatter(self, **kwargs: Any) -> Formatter[str]:
|
|
131
133
|
kwargs.update(self.formatter_args)
|
|
132
134
|
return self.formatter(**kwargs)
|
|
133
135
|
|
|
@@ -135,7 +137,7 @@ class PygmentsBridge:
|
|
|
135
137
|
self,
|
|
136
138
|
source: str,
|
|
137
139
|
lang: str,
|
|
138
|
-
opts: dict | None = None,
|
|
140
|
+
opts: dict[str, Any] | None = None,
|
|
139
141
|
force: bool = False,
|
|
140
142
|
location: Any = None,
|
|
141
143
|
) -> Lexer:
|
|
@@ -165,7 +167,11 @@ class PygmentsBridge:
|
|
|
165
167
|
lexer = get_lexer_by_name(lang, **opts)
|
|
166
168
|
except ClassNotFound:
|
|
167
169
|
logger.warning(
|
|
168
|
-
__('Pygments lexer name %r is not known'),
|
|
170
|
+
__('Pygments lexer name %r is not known'),
|
|
171
|
+
lang,
|
|
172
|
+
location=location,
|
|
173
|
+
type='misc',
|
|
174
|
+
subtype='higlighting_failure',
|
|
169
175
|
)
|
|
170
176
|
lexer = lexer_classes['none'](**opts)
|
|
171
177
|
|
|
@@ -178,7 +184,7 @@ class PygmentsBridge:
|
|
|
178
184
|
self,
|
|
179
185
|
source: str,
|
|
180
186
|
lang: str,
|
|
181
|
-
opts: dict | None = None,
|
|
187
|
+
opts: dict[str, Any] | None = None,
|
|
182
188
|
force: bool = False,
|
|
183
189
|
location: Any = None,
|
|
184
190
|
**kwargs: Any,
|
sphinx/io.py
CHANGED
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
7
|
from docutils.core import Publisher
|
|
8
|
-
from docutils.io import FileInput,
|
|
8
|
+
from docutils.io import FileInput, NullOutput
|
|
9
9
|
from docutils.readers import standalone
|
|
10
10
|
from docutils.transforms.references import DanglingReferences
|
|
11
11
|
from docutils.writers import UnfilteredWriter
|
|
12
12
|
|
|
13
|
-
from sphinx import addnodes
|
|
14
13
|
from sphinx.transforms import AutoIndexUpgrader, DoctreeReadEvent, SphinxTransformer
|
|
15
14
|
from sphinx.transforms.i18n import (
|
|
16
15
|
Locale,
|
|
@@ -23,8 +22,11 @@ from sphinx.util.docutils import LoggingReporter
|
|
|
23
22
|
from sphinx.versioning import UIDTransform
|
|
24
23
|
|
|
25
24
|
if TYPE_CHECKING:
|
|
25
|
+
from typing import Any
|
|
26
|
+
|
|
26
27
|
from docutils import nodes
|
|
27
28
|
from docutils.frontend import Values
|
|
29
|
+
from docutils.io import Input
|
|
28
30
|
from docutils.parsers import Parser
|
|
29
31
|
from docutils.transforms import Transform
|
|
30
32
|
|
|
@@ -36,8 +38,7 @@ logger = logging.getLogger(__name__)
|
|
|
36
38
|
|
|
37
39
|
|
|
38
40
|
class SphinxBaseReader(standalone.Reader): # type: ignore[misc]
|
|
39
|
-
"""
|
|
40
|
-
A base class of readers for Sphinx.
|
|
41
|
+
"""A base class of readers for Sphinx.
|
|
41
42
|
|
|
42
43
|
This replaces reporter by Sphinx's on generating document.
|
|
43
44
|
"""
|
|
@@ -70,12 +71,10 @@ class SphinxBaseReader(standalone.Reader): # type: ignore[misc]
|
|
|
70
71
|
return transforms
|
|
71
72
|
|
|
72
73
|
def new_document(self) -> nodes.document:
|
|
73
|
-
"""
|
|
74
|
-
Creates a new document object which has a special reporter object good
|
|
74
|
+
"""Creates a new document object which has a special reporter object good
|
|
75
75
|
for logging.
|
|
76
76
|
"""
|
|
77
77
|
document = super().new_document()
|
|
78
|
-
document.__class__ = addnodes.document # replace the class with patched version
|
|
79
78
|
|
|
80
79
|
# substitute transformer
|
|
81
80
|
document.transformer = SphinxTransformer(document)
|
|
@@ -89,9 +88,7 @@ class SphinxBaseReader(standalone.Reader): # type: ignore[misc]
|
|
|
89
88
|
|
|
90
89
|
|
|
91
90
|
class SphinxStandaloneReader(SphinxBaseReader):
|
|
92
|
-
"""
|
|
93
|
-
A basic document reader for Sphinx.
|
|
94
|
-
"""
|
|
91
|
+
"""A basic document reader for Sphinx."""
|
|
95
92
|
|
|
96
93
|
def setup(self, app: Sphinx) -> None:
|
|
97
94
|
self.transforms = self.transforms + app.registry.get_transforms()
|
|
@@ -117,8 +114,7 @@ class SphinxStandaloneReader(SphinxBaseReader):
|
|
|
117
114
|
|
|
118
115
|
|
|
119
116
|
class SphinxI18nReader(SphinxBaseReader):
|
|
120
|
-
"""
|
|
121
|
-
A document reader for i18n.
|
|
117
|
+
"""A document reader for i18n.
|
|
122
118
|
|
|
123
119
|
This returns the source line number of original text as current source line number
|
|
124
120
|
to let users know where the error happened.
|