Sphinx 7.1.1__py3-none-any.whl → 7.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 +6 -6
- sphinx/__main__.py +3 -1
- sphinx/addnodes.py +35 -22
- sphinx/application.py +40 -38
- sphinx/builders/__init__.py +16 -12
- sphinx/builders/_epub_base.py +15 -11
- sphinx/builders/changes.py +6 -4
- sphinx/builders/dirhtml.py +4 -2
- sphinx/builders/dummy.py +6 -4
- sphinx/builders/epub3.py +16 -8
- sphinx/builders/gettext.py +40 -43
- sphinx/builders/html/__init__.py +166 -196
- sphinx/builders/html/_assets.py +116 -0
- sphinx/builders/html/transforms.py +4 -2
- sphinx/builders/latex/__init__.py +12 -7
- sphinx/builders/latex/theming.py +5 -2
- sphinx/builders/latex/transforms.py +6 -3
- sphinx/builders/linkcheck.py +21 -13
- sphinx/builders/manpage.py +6 -4
- sphinx/builders/singlehtml.py +16 -9
- sphinx/builders/texinfo.py +11 -6
- sphinx/builders/text.py +8 -3
- sphinx/builders/xml.py +9 -4
- sphinx/cmd/build.py +27 -14
- sphinx/cmd/make_mode.py +13 -4
- sphinx/cmd/quickstart.py +13 -4
- sphinx/config.py +17 -14
- sphinx/deprecation.py +4 -2
- sphinx/directives/__init__.py +44 -12
- sphinx/directives/code.py +5 -4
- sphinx/directives/other.py +92 -44
- sphinx/directives/patches.py +1 -1
- sphinx/domains/__init__.py +11 -8
- sphinx/domains/c.py +67 -57
- sphinx/domains/changeset.py +3 -2
- sphinx/domains/citation.py +2 -1
- sphinx/domains/cpp.py +136 -93
- sphinx/domains/index.py +9 -5
- sphinx/domains/javascript.py +32 -19
- sphinx/domains/math.py +5 -3
- sphinx/domains/python.py +69 -57
- sphinx/domains/rst.py +20 -11
- sphinx/domains/std.py +21 -15
- sphinx/environment/__init__.py +97 -65
- sphinx/environment/adapters/indexentries.py +13 -10
- sphinx/environment/adapters/toctree.py +485 -308
- sphinx/environment/collectors/__init__.py +3 -4
- sphinx/environment/collectors/asset.py +10 -4
- sphinx/environment/collectors/dependencies.py +7 -4
- sphinx/environment/collectors/metadata.py +7 -5
- sphinx/environment/collectors/title.py +5 -3
- sphinx/environment/collectors/toctree.py +13 -8
- sphinx/errors.py +1 -1
- sphinx/events.py +5 -5
- sphinx/ext/apidoc.py +49 -27
- sphinx/ext/autodoc/__init__.py +179 -161
- sphinx/ext/autodoc/directive.py +10 -6
- sphinx/ext/autodoc/importer.py +22 -13
- sphinx/ext/autodoc/mock.py +4 -1
- sphinx/ext/autodoc/preserve_defaults.py +80 -12
- sphinx/ext/autodoc/type_comment.py +14 -10
- sphinx/ext/autodoc/typehints.py +7 -3
- sphinx/ext/autosectionlabel.py +6 -3
- sphinx/ext/autosummary/__init__.py +21 -15
- sphinx/ext/autosummary/generate.py +176 -126
- sphinx/ext/coverage.py +93 -8
- sphinx/ext/doctest.py +28 -17
- sphinx/ext/duration.py +19 -17
- sphinx/ext/extlinks.py +11 -6
- sphinx/ext/githubpages.py +8 -7
- sphinx/ext/graphviz.py +61 -17
- sphinx/ext/ifconfig.py +7 -4
- sphinx/ext/imgconverter.py +4 -2
- sphinx/ext/imgmath.py +29 -23
- sphinx/ext/inheritance_diagram.py +41 -27
- sphinx/ext/intersphinx.py +45 -38
- sphinx/ext/linkcode.py +8 -5
- sphinx/ext/mathjax.py +13 -9
- sphinx/ext/napoleon/__init__.py +3 -3
- sphinx/ext/napoleon/docstring.py +40 -31
- sphinx/ext/todo.py +10 -7
- sphinx/ext/viewcode.py +46 -25
- sphinx/extension.py +1 -1
- sphinx/highlighting.py +20 -12
- sphinx/io.py +5 -4
- sphinx/jinja2glue.py +24 -19
- sphinx/locale/__init__.py +8 -2
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +756 -740
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +768 -752
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +758 -742
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +759 -743
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +760 -744
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +759 -743
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +763 -747
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +768 -752
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +767 -751
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +762 -746
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +766 -750
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr/LC_MESSAGES/sphinx.po +768 -752
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/gl/LC_MESSAGES/sphinx.js +60 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +3695 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +763 -747
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +760 -744
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +759 -743
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +765 -749
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +760 -744
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +760 -744
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +767 -751
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +759 -743
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +767 -751
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +760 -744
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +762 -745
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +768 -752
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +759 -743
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +760 -744
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +765 -749
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/sphinx.pot +748 -740
- sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sq/LC_MESSAGES/sphinx.po +768 -752
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/sr@latin/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr@latin/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr_RS/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/ta/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ta/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +763 -747
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +760 -749
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +759 -748
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +768 -752
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +767 -751
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +754 -738
- sphinx/parsers.py +5 -4
- sphinx/project.py +52 -34
- sphinx/pycode/__init__.py +2 -1
- sphinx/pycode/ast.py +7 -13
- sphinx/pycode/parser.py +42 -38
- sphinx/registry.py +35 -29
- sphinx/roles.py +9 -4
- sphinx/search/__init__.py +5 -17
- sphinx/search/da.py +1 -1
- sphinx/search/de.py +1 -1
- sphinx/search/en.py +1 -1
- sphinx/search/es.py +1 -1
- sphinx/search/fi.py +1 -1
- sphinx/search/fr.py +1 -1
- sphinx/search/hu.py +1 -1
- sphinx/search/it.py +1 -1
- sphinx/search/ja.py +1 -1
- sphinx/search/nl.py +1 -1
- sphinx/search/no.py +1 -1
- sphinx/search/pt.py +1 -1
- sphinx/search/ro.py +1 -1
- sphinx/search/ru.py +1 -1
- sphinx/search/sv.py +1 -1
- sphinx/search/tr.py +1 -1
- sphinx/search/zh.py +1 -1
- sphinx/testing/fixtures.py +23 -30
- sphinx/testing/path.py +9 -0
- sphinx/testing/restructuredtext.py +13 -5
- sphinx/testing/util.py +20 -63
- sphinx/texinputs/sphinxlatexobjects.sty +15 -15
- sphinx/themes/agogo/static/agogo.css_t +10 -4
- sphinx/themes/basic/layout.html +1 -1
- sphinx/themes/basic/static/basic.css_t +4 -0
- sphinx/themes/basic/static/documentation_options.js_t +1 -2
- sphinx/themes/basic/static/searchtools.js +17 -9
- sphinx/themes/basic/static/sphinx_highlight.js +13 -3
- sphinx/themes/bizstyle/static/bizstyle.css_t +4 -0
- sphinx/themes/classic/theme.conf +1 -1
- sphinx/themes/epub/static/epub.css_t +6 -1
- sphinx/themes/haiku/theme.conf +1 -1
- sphinx/themes/nature/static/nature.css_t +4 -0
- sphinx/themes/nonav/static/nonav.css_t +6 -1
- sphinx/themes/pyramid/static/pyramid.css_t +4 -0
- sphinx/themes/scrolls/static/scrolls.css_t +4 -0
- sphinx/themes/scrolls/theme.conf +1 -1
- sphinx/themes/sphinxdoc/static/sphinxdoc.css_t +4 -0
- sphinx/theming.py +9 -7
- sphinx/transforms/__init__.py +79 -3
- sphinx/transforms/compact_bullet_list.py +6 -3
- sphinx/transforms/i18n.py +26 -10
- sphinx/transforms/post_transforms/__init__.py +21 -8
- sphinx/transforms/post_transforms/code.py +6 -3
- sphinx/transforms/post_transforms/images.py +13 -9
- sphinx/util/__init__.py +21 -92
- sphinx/util/cfamily.py +7 -4
- sphinx/util/display.py +3 -2
- sphinx/util/docfields.py +7 -6
- sphinx/util/docstrings.py +1 -1
- sphinx/util/docutils.py +41 -31
- sphinx/util/fileutil.py +9 -6
- sphinx/util/i18n.py +21 -18
- sphinx/util/images.py +2 -1
- sphinx/util/index_entries.py +27 -0
- sphinx/util/inspect.py +83 -67
- sphinx/util/inventory.py +4 -2
- sphinx/util/logging.py +9 -6
- sphinx/util/matching.py +5 -2
- sphinx/util/math.py +6 -3
- sphinx/util/nodes.py +70 -31
- sphinx/util/osutil.py +22 -40
- sphinx/util/parallel.py +4 -1
- sphinx/util/rst.py +7 -3
- sphinx/util/tags.py +11 -4
- sphinx/util/template.py +17 -14
- sphinx/util/typing.py +61 -20
- sphinx/versioning.py +6 -4
- sphinx/writers/html.py +1 -1
- sphinx/writers/html5.py +32 -24
- sphinx/writers/latex.py +67 -53
- sphinx/writers/manpage.py +9 -5
- sphinx/writers/texinfo.py +11 -9
- sphinx/writers/text.py +14 -9
- sphinx/writers/xml.py +3 -2
- {sphinx-7.1.1.dist-info → sphinx-7.2.0.dist-info}/METADATA +7 -5
- sphinx-7.2.0.dist-info/RECORD +568 -0
- sphinx/testing/comparer.py +0 -97
- sphinx-7.1.1.dist-info/RECORD +0 -564
- {sphinx-7.1.1.dist-info → sphinx-7.2.0.dist-info}/LICENSE +0 -0
- {sphinx-7.1.1.dist-info → sphinx-7.2.0.dist-info}/WHEEL +0 -0
- {sphinx-7.1.1.dist-info → sphinx-7.2.0.dist-info}/entry_points.txt +0 -0
sphinx/cmd/make_mode.py
CHANGED
|
@@ -13,10 +13,16 @@ import os
|
|
|
13
13
|
import subprocess
|
|
14
14
|
import sys
|
|
15
15
|
from os import path
|
|
16
|
+
from typing import TYPE_CHECKING
|
|
16
17
|
|
|
17
18
|
import sphinx
|
|
18
19
|
from sphinx.cmd.build import build_main
|
|
19
|
-
from sphinx.util.console import
|
|
20
|
+
from sphinx.util.console import ( # type: ignore[attr-defined]
|
|
21
|
+
blue,
|
|
22
|
+
bold,
|
|
23
|
+
color_terminal,
|
|
24
|
+
nocolor,
|
|
25
|
+
)
|
|
20
26
|
from sphinx.util.osutil import rmtree
|
|
21
27
|
|
|
22
28
|
try:
|
|
@@ -24,6 +30,9 @@ try:
|
|
|
24
30
|
except ImportError:
|
|
25
31
|
from sphinx.util.osutil import _chdir as chdir
|
|
26
32
|
|
|
33
|
+
if TYPE_CHECKING:
|
|
34
|
+
from collections.abc import Sequence
|
|
35
|
+
|
|
27
36
|
BUILDERS = [
|
|
28
37
|
("", "html", "to make standalone HTML files"),
|
|
29
38
|
("", "dirhtml", "to make HTML files named index.html in directories"),
|
|
@@ -54,10 +63,10 @@ BUILDERS = [
|
|
|
54
63
|
|
|
55
64
|
|
|
56
65
|
class Make:
|
|
57
|
-
def __init__(self, srcdir: str, builddir: str, opts:
|
|
66
|
+
def __init__(self, srcdir: str, builddir: str, opts: Sequence[str]) -> None:
|
|
58
67
|
self.srcdir = srcdir
|
|
59
68
|
self.builddir = builddir
|
|
60
|
-
self.opts = opts
|
|
69
|
+
self.opts = [*opts]
|
|
61
70
|
self.makecmd = os.environ.get('MAKE', 'make') # refer $MAKE to determine make command
|
|
62
71
|
|
|
63
72
|
def builddir_join(self, *comps: str) -> str:
|
|
@@ -154,7 +163,7 @@ class Make:
|
|
|
154
163
|
return build_main(args + opts)
|
|
155
164
|
|
|
156
165
|
|
|
157
|
-
def run_make_mode(args:
|
|
166
|
+
def run_make_mode(args: Sequence[str]) -> int:
|
|
158
167
|
if len(args) < 3:
|
|
159
168
|
print('Error: at least 3 arguments (builder, source '
|
|
160
169
|
'dir, build dir) are required.', file=sys.stderr)
|
sphinx/cmd/quickstart.py
CHANGED
|
@@ -31,10 +31,19 @@ from docutils.utils import column_width
|
|
|
31
31
|
import sphinx.locale
|
|
32
32
|
from sphinx import __display_version__, package_dir
|
|
33
33
|
from sphinx.locale import __
|
|
34
|
-
from sphinx.util.console import
|
|
34
|
+
from sphinx.util.console import ( # type: ignore[attr-defined]
|
|
35
|
+
bold,
|
|
36
|
+
color_terminal,
|
|
37
|
+
colorize,
|
|
38
|
+
nocolor,
|
|
39
|
+
red,
|
|
40
|
+
)
|
|
35
41
|
from sphinx.util.osutil import ensuredir
|
|
36
42
|
from sphinx.util.template import SphinxRenderer
|
|
37
43
|
|
|
44
|
+
if TYPE_CHECKING:
|
|
45
|
+
from collections.abc import Sequence
|
|
46
|
+
|
|
38
47
|
EXTENSIONS = {
|
|
39
48
|
'autodoc': __('automatically insert docstrings from modules'),
|
|
40
49
|
'doctest': __('automatically test code snippets in doctest blocks'),
|
|
@@ -539,7 +548,7 @@ def get_parser() -> argparse.ArgumentParser:
|
|
|
539
548
|
return parser
|
|
540
549
|
|
|
541
550
|
|
|
542
|
-
def main(argv:
|
|
551
|
+
def main(argv: Sequence[str] = (), /) -> int:
|
|
543
552
|
locale.setlocale(locale.LC_ALL, '')
|
|
544
553
|
sphinx.locale.init_console()
|
|
545
554
|
|
|
@@ -549,7 +558,7 @@ def main(argv: list[str] = sys.argv[1:]) -> int:
|
|
|
549
558
|
# parse options
|
|
550
559
|
parser = get_parser()
|
|
551
560
|
try:
|
|
552
|
-
args = parser.parse_args(argv)
|
|
561
|
+
args = parser.parse_args(argv or sys.argv[1:])
|
|
553
562
|
except SystemExit as err:
|
|
554
563
|
return err.code # type: ignore[return-value]
|
|
555
564
|
|
|
@@ -605,4 +614,4 @@ def main(argv: list[str] = sys.argv[1:]) -> int:
|
|
|
605
614
|
|
|
606
615
|
|
|
607
616
|
if __name__ == '__main__':
|
|
608
|
-
raise SystemExit(main())
|
|
617
|
+
raise SystemExit(main(sys.argv[1:]))
|
sphinx/config.py
CHANGED
|
@@ -6,13 +6,12 @@ import time
|
|
|
6
6
|
import traceback
|
|
7
7
|
import types
|
|
8
8
|
from os import getenv, path
|
|
9
|
-
from typing import TYPE_CHECKING, Any, Callable,
|
|
9
|
+
from typing import TYPE_CHECKING, Any, Callable, NamedTuple
|
|
10
10
|
|
|
11
11
|
from sphinx.errors import ConfigError, ExtensionError
|
|
12
12
|
from sphinx.locale import _, __
|
|
13
13
|
from sphinx.util import logging
|
|
14
14
|
from sphinx.util.osutil import fs_encoding
|
|
15
|
-
from sphinx.util.tags import Tags
|
|
16
15
|
from sphinx.util.typing import NoneType
|
|
17
16
|
|
|
18
17
|
try:
|
|
@@ -21,10 +20,12 @@ except ImportError:
|
|
|
21
20
|
from sphinx.util.osutil import _chdir as chdir
|
|
22
21
|
|
|
23
22
|
if TYPE_CHECKING:
|
|
24
|
-
|
|
23
|
+
import os
|
|
24
|
+
from collections.abc import Generator, Iterator, Sequence
|
|
25
25
|
|
|
26
26
|
from sphinx.application import Sphinx
|
|
27
27
|
from sphinx.environment import BuildEnvironment
|
|
28
|
+
from sphinx.util.tags import Tags
|
|
28
29
|
|
|
29
30
|
logger = logging.getLogger(__name__)
|
|
30
31
|
|
|
@@ -58,7 +59,7 @@ class ENUM:
|
|
|
58
59
|
Example:
|
|
59
60
|
app.add_config_value('latex_show_urls', 'no', None, ENUM('no', 'footnote', 'inline'))
|
|
60
61
|
"""
|
|
61
|
-
def __init__(self, *candidates: str | bool) -> None:
|
|
62
|
+
def __init__(self, *candidates: str | bool | None) -> None:
|
|
62
63
|
self.candidates = candidates
|
|
63
64
|
|
|
64
65
|
def match(self, value: str | list | tuple) -> bool:
|
|
@@ -154,8 +155,10 @@ class Config:
|
|
|
154
155
|
'option_emphasise_placeholders': (False, 'env', []),
|
|
155
156
|
}
|
|
156
157
|
|
|
157
|
-
def __init__(self, config: dict[str, Any]
|
|
158
|
-
|
|
158
|
+
def __init__(self, config: dict[str, Any] | None = None,
|
|
159
|
+
overrides: dict[str, Any] | None = None) -> None:
|
|
160
|
+
config = config or {}
|
|
161
|
+
self.overrides = dict(overrides) if overrides is not None else {}
|
|
159
162
|
self.values = Config.config_values.copy()
|
|
160
163
|
self._raw_config = config
|
|
161
164
|
self.setup: Callable | None = config.get('setup', None)
|
|
@@ -168,9 +171,8 @@ class Config:
|
|
|
168
171
|
self.extensions: list[str] = config.get('extensions', [])
|
|
169
172
|
|
|
170
173
|
@classmethod
|
|
171
|
-
def read(
|
|
172
|
-
|
|
173
|
-
) -> Config:
|
|
174
|
+
def read(cls, confdir: str | os.PathLike[str], overrides: dict | None = None,
|
|
175
|
+
tags: Tags | None = None) -> Config:
|
|
174
176
|
"""Create a Config object from configuration file."""
|
|
175
177
|
filename = path.join(confdir, CONFIG_FILENAME)
|
|
176
178
|
if not path.isfile(filename):
|
|
@@ -310,7 +312,7 @@ class Config:
|
|
|
310
312
|
raise ExtensionError(__('Config value %r already present') % name)
|
|
311
313
|
self.values[name] = (default, rebuild, types)
|
|
312
314
|
|
|
313
|
-
def filter(self, rebuild: str |
|
|
315
|
+
def filter(self, rebuild: str | Sequence[str]) -> Iterator[ConfigValue]:
|
|
314
316
|
if isinstance(rebuild, str):
|
|
315
317
|
rebuild = [rebuild]
|
|
316
318
|
return (value for value in self if value.rebuild in rebuild)
|
|
@@ -402,7 +404,8 @@ def convert_highlight_options(app: Sphinx, config: Config) -> None:
|
|
|
402
404
|
options = config.highlight_options
|
|
403
405
|
if options and not all(isinstance(v, dict) for v in options.values()):
|
|
404
406
|
# old styled option detected because all values are not dictionary.
|
|
405
|
-
config.highlight_options = {config.highlight_language:
|
|
407
|
+
config.highlight_options = {config.highlight_language: # type: ignore[attr-defined]
|
|
408
|
+
options}
|
|
406
409
|
|
|
407
410
|
|
|
408
411
|
def init_numfig_format(app: Sphinx, config: Config) -> None:
|
|
@@ -414,7 +417,7 @@ def init_numfig_format(app: Sphinx, config: Config) -> None:
|
|
|
414
417
|
|
|
415
418
|
# override default labels by configuration
|
|
416
419
|
numfig_format.update(config.numfig_format)
|
|
417
|
-
config.numfig_format = numfig_format # type: ignore
|
|
420
|
+
config.numfig_format = numfig_format # type: ignore[attr-defined]
|
|
418
421
|
|
|
419
422
|
|
|
420
423
|
def correct_copyright_year(_app: Sphinx, config: Config) -> None:
|
|
@@ -523,7 +526,7 @@ def check_primary_domain(app: Sphinx, config: Config) -> None:
|
|
|
523
526
|
primary_domain = config.primary_domain
|
|
524
527
|
if primary_domain and not app.registry.has_domain(primary_domain):
|
|
525
528
|
logger.warning(__('primary_domain %r not found, ignored.'), primary_domain)
|
|
526
|
-
config.primary_domain = None # type: ignore
|
|
529
|
+
config.primary_domain = None # type: ignore[attr-defined]
|
|
527
530
|
|
|
528
531
|
|
|
529
532
|
def check_root_doc(app: Sphinx, env: BuildEnvironment, added: set[str],
|
|
@@ -536,7 +539,7 @@ def check_root_doc(app: Sphinx, env: BuildEnvironment, added: set[str],
|
|
|
536
539
|
'contents' in app.project.docnames):
|
|
537
540
|
logger.warning(__('Since v2.0, Sphinx uses "index" as root_doc by default. '
|
|
538
541
|
'Please add "root_doc = \'contents\'" to your conf.py.'))
|
|
539
|
-
app.config.root_doc = "contents" # type: ignore
|
|
542
|
+
app.config.root_doc = "contents" # type: ignore[attr-defined]
|
|
540
543
|
|
|
541
544
|
return changed
|
|
542
545
|
|
sphinx/deprecation.py
CHANGED
|
@@ -37,7 +37,8 @@ def _deprecation_warning(
|
|
|
37
37
|
|
|
38
38
|
def __getattr__(name):
|
|
39
39
|
if name not in _DEPRECATED_OBJECTS:
|
|
40
|
-
|
|
40
|
+
msg = f'module {__name__!r} has no attribute {name!r}'
|
|
41
|
+
raise AttributeError(msg)
|
|
41
42
|
|
|
42
43
|
from sphinx.deprecation import _deprecation_warning
|
|
43
44
|
|
|
@@ -51,7 +52,8 @@ def _deprecation_warning(
|
|
|
51
52
|
elif remove == (9, 0):
|
|
52
53
|
warning_class = RemovedInSphinx90Warning
|
|
53
54
|
else:
|
|
54
|
-
|
|
55
|
+
msg = f'removal version {remove!r} is invalid!'
|
|
56
|
+
raise RuntimeError(msg)
|
|
55
57
|
|
|
56
58
|
qualified_name = f'{module}.{attribute}'
|
|
57
59
|
if canonical_name:
|
sphinx/directives/__init__.py
CHANGED
|
@@ -3,21 +3,22 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import re
|
|
6
|
-
from typing import TYPE_CHECKING, Any, Generic,
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast
|
|
7
7
|
|
|
8
8
|
from docutils import nodes
|
|
9
|
-
from docutils.nodes import Node
|
|
10
9
|
from docutils.parsers.rst import directives, roles
|
|
11
10
|
|
|
12
11
|
from sphinx import addnodes
|
|
13
|
-
from sphinx.addnodes import desc_signature
|
|
12
|
+
from sphinx.addnodes import desc_signature # NoQA: TCH001
|
|
14
13
|
from sphinx.util import docutils
|
|
15
14
|
from sphinx.util.docfields import DocFieldTransformer, Field, TypedField
|
|
16
15
|
from sphinx.util.docutils import SphinxDirective
|
|
17
16
|
from sphinx.util.nodes import nested_parse_with_titles
|
|
18
|
-
from sphinx.util.typing import OptionSpec
|
|
17
|
+
from sphinx.util.typing import OptionSpec # NoQA: TCH001
|
|
19
18
|
|
|
20
19
|
if TYPE_CHECKING:
|
|
20
|
+
from docutils.nodes import Node
|
|
21
|
+
|
|
21
22
|
from sphinx.application import Sphinx
|
|
22
23
|
|
|
23
24
|
|
|
@@ -35,7 +36,8 @@ def optional_int(argument: str) -> int | None:
|
|
|
35
36
|
else:
|
|
36
37
|
value = int(argument)
|
|
37
38
|
if value < 0:
|
|
38
|
-
|
|
39
|
+
msg = 'negative value; must be positive or zero'
|
|
40
|
+
raise ValueError(msg)
|
|
39
41
|
return value
|
|
40
42
|
|
|
41
43
|
|
|
@@ -54,6 +56,10 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
|
|
|
54
56
|
optional_arguments = 0
|
|
55
57
|
final_argument_whitespace = True
|
|
56
58
|
option_spec: OptionSpec = {
|
|
59
|
+
'no-index': directives.flag,
|
|
60
|
+
'no-index-entry': directives.flag,
|
|
61
|
+
'no-contents-entry': directives.flag,
|
|
62
|
+
'no-typesetting': directives.flag,
|
|
57
63
|
'noindex': directives.flag,
|
|
58
64
|
'noindexentry': directives.flag,
|
|
59
65
|
'nocontentsentry': directives.flag,
|
|
@@ -185,7 +191,7 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
|
|
|
185
191
|
|
|
186
192
|
* find out if called as a domain-specific directive, set self.domain
|
|
187
193
|
* create a `desc` node to fit all description inside
|
|
188
|
-
* parse standard options, currently `
|
|
194
|
+
* parse standard options, currently `no-index`
|
|
189
195
|
* create an index node if needed as self.indexnode
|
|
190
196
|
* parse all given signatures (as returned by self.get_signatures())
|
|
191
197
|
using self.handle_signature(), which should either return a name
|
|
@@ -215,9 +221,22 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
|
|
|
215
221
|
node['domain'] = self.domain
|
|
216
222
|
# 'desctype' is a backwards compatible attribute
|
|
217
223
|
node['objtype'] = node['desctype'] = self.objtype
|
|
218
|
-
node['
|
|
219
|
-
|
|
220
|
-
|
|
224
|
+
node['no-index'] = node['noindex'] = no_index = (
|
|
225
|
+
'no-index' in self.options
|
|
226
|
+
# xref RemovedInSphinx90Warning
|
|
227
|
+
# deprecate noindex in Sphinx 9.0
|
|
228
|
+
or 'noindex' in self.options)
|
|
229
|
+
node['no-index-entry'] = node['noindexentry'] = (
|
|
230
|
+
'no-index-entry' in self.options
|
|
231
|
+
# xref RemovedInSphinx90Warning
|
|
232
|
+
# deprecate noindexentry in Sphinx 9.0
|
|
233
|
+
or 'noindexentry' in self.options)
|
|
234
|
+
node['no-contents-entry'] = node['nocontentsentry'] = (
|
|
235
|
+
'no-contents-entry' in self.options
|
|
236
|
+
# xref RemovedInSphinx90Warning
|
|
237
|
+
# deprecate nocontentsentry in Sphinx 9.0
|
|
238
|
+
or 'nocontentsentry' in self.options)
|
|
239
|
+
node['no-typesetting'] = ('no-typesetting' in self.options)
|
|
221
240
|
if self.domain:
|
|
222
241
|
node['classes'].append(self.domain)
|
|
223
242
|
node['classes'].append(node['objtype'])
|
|
@@ -251,7 +270,7 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
|
|
|
251
270
|
signode['_toc_name'] = ''
|
|
252
271
|
if name not in self.names:
|
|
253
272
|
self.names.append(name)
|
|
254
|
-
if not
|
|
273
|
+
if not no_index:
|
|
255
274
|
# only add target and index entry if this is the first
|
|
256
275
|
# description of the object with this name in this desc block
|
|
257
276
|
self.add_target_and_index(name, sig, signode)
|
|
@@ -270,6 +289,19 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
|
|
|
270
289
|
DocFieldTransformer(self).transform_all(contentnode)
|
|
271
290
|
self.env.temp_data['object'] = None
|
|
272
291
|
self.after_content()
|
|
292
|
+
|
|
293
|
+
if node['no-typesetting']:
|
|
294
|
+
# Attempt to return the index node, and a new target node
|
|
295
|
+
# containing all the ids of this node and its children.
|
|
296
|
+
# If ``:no-index:`` is set, or there are no ids on the node
|
|
297
|
+
# or any of its children, then just return the index node,
|
|
298
|
+
# as Docutils expects a target node to have at least one id.
|
|
299
|
+
if node_ids := [node_id for el in node.findall(nodes.Element)
|
|
300
|
+
for node_id in el.get('ids', ())]:
|
|
301
|
+
target_node = nodes.target(ids=node_ids)
|
|
302
|
+
self.set_source_info(target_node)
|
|
303
|
+
return [self.indexnode, target_node]
|
|
304
|
+
return [self.indexnode]
|
|
273
305
|
return [self.indexnode, node]
|
|
274
306
|
|
|
275
307
|
|
|
@@ -289,7 +321,7 @@ class DefaultRole(SphinxDirective):
|
|
|
289
321
|
role, messages = roles.role(role_name, self.state_machine.language,
|
|
290
322
|
self.lineno, self.state.reporter)
|
|
291
323
|
if role: # type: ignore[truthy-function]
|
|
292
|
-
docutils.register_role('', role)
|
|
324
|
+
docutils.register_role('', role) # type: ignore[arg-type]
|
|
293
325
|
self.env.temp_data['default_role'] = role_name
|
|
294
326
|
else:
|
|
295
327
|
literal_block = nodes.literal_block(self.block_text, self.block_text)
|
|
@@ -298,7 +330,7 @@ class DefaultRole(SphinxDirective):
|
|
|
298
330
|
literal_block, line=self.lineno)
|
|
299
331
|
messages += [error]
|
|
300
332
|
|
|
301
|
-
return cast(
|
|
333
|
+
return cast(list[nodes.Node], messages)
|
|
302
334
|
|
|
303
335
|
|
|
304
336
|
class DefaultDomain(SphinxDirective):
|
sphinx/directives/code.py
CHANGED
|
@@ -6,20 +6,21 @@ from difflib import unified_diff
|
|
|
6
6
|
from typing import TYPE_CHECKING, Any
|
|
7
7
|
|
|
8
8
|
from docutils import nodes
|
|
9
|
-
from docutils.nodes import Element, Node
|
|
10
9
|
from docutils.parsers.rst import directives
|
|
11
10
|
from docutils.statemachine import StringList
|
|
12
11
|
|
|
13
12
|
from sphinx import addnodes
|
|
14
|
-
from sphinx.config import Config
|
|
15
13
|
from sphinx.directives import optional_int
|
|
16
14
|
from sphinx.locale import __
|
|
17
15
|
from sphinx.util import logging, parselinenos
|
|
18
16
|
from sphinx.util.docutils import SphinxDirective
|
|
19
|
-
from sphinx.util.typing import OptionSpec
|
|
20
17
|
|
|
21
18
|
if TYPE_CHECKING:
|
|
19
|
+
from docutils.nodes import Element, Node
|
|
20
|
+
|
|
22
21
|
from sphinx.application import Sphinx
|
|
22
|
+
from sphinx.config import Config
|
|
23
|
+
from sphinx.util.typing import OptionSpec
|
|
23
24
|
|
|
24
25
|
logger = logging.getLogger(__name__)
|
|
25
26
|
|
|
@@ -244,7 +245,7 @@ class LiteralIncludeReader:
|
|
|
244
245
|
new_lines = self.read_file(self.filename)
|
|
245
246
|
old_filename = self.options['diff']
|
|
246
247
|
old_lines = self.read_file(old_filename)
|
|
247
|
-
diff = unified_diff(old_lines, new_lines, old_filename, self.filename)
|
|
248
|
+
diff = unified_diff(old_lines, new_lines, str(old_filename), str(self.filename))
|
|
248
249
|
return list(diff)
|
|
249
250
|
|
|
250
251
|
def pyobject_filter(
|
sphinx/directives/other.py
CHANGED
|
@@ -4,23 +4,27 @@ import re
|
|
|
4
4
|
from typing import TYPE_CHECKING, Any, cast
|
|
5
5
|
|
|
6
6
|
from docutils import nodes
|
|
7
|
-
from docutils.nodes import Element, Node
|
|
8
7
|
from docutils.parsers.rst import directives
|
|
9
8
|
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
|
|
10
9
|
from docutils.parsers.rst.directives.misc import Class
|
|
11
10
|
from docutils.parsers.rst.directives.misc import Include as BaseInclude
|
|
11
|
+
from docutils.statemachine import StateMachine
|
|
12
12
|
|
|
13
13
|
from sphinx import addnodes
|
|
14
14
|
from sphinx.domains.changeset import VersionChange # noqa: F401 # for compatibility
|
|
15
|
+
from sphinx.domains.std import StandardDomain
|
|
15
16
|
from sphinx.locale import _, __
|
|
16
17
|
from sphinx.util import docname_join, logging, url_re
|
|
17
18
|
from sphinx.util.docutils import SphinxDirective
|
|
18
19
|
from sphinx.util.matching import Matcher, patfilter
|
|
19
20
|
from sphinx.util.nodes import explicit_title_re
|
|
20
|
-
from sphinx.util.
|
|
21
|
+
from sphinx.util.osutil import os_path
|
|
21
22
|
|
|
22
23
|
if TYPE_CHECKING:
|
|
24
|
+
from docutils.nodes import Element, Node
|
|
25
|
+
|
|
23
26
|
from sphinx.application import Sphinx
|
|
27
|
+
from sphinx.util.typing import OptionSpec
|
|
24
28
|
|
|
25
29
|
|
|
26
30
|
glob_re = re.compile(r'.*[*?\[].*')
|
|
@@ -79,71 +83,81 @@ class TocTree(SphinxDirective):
|
|
|
79
83
|
return ret
|
|
80
84
|
|
|
81
85
|
def parse_content(self, toctree: addnodes.toctree) -> list[Node]:
|
|
82
|
-
generated_docnames = frozenset(
|
|
86
|
+
generated_docnames = frozenset(StandardDomain._virtual_doc_names)
|
|
83
87
|
suffixes = self.config.source_suffix
|
|
88
|
+
current_docname = self.env.docname
|
|
89
|
+
glob = toctree['glob']
|
|
84
90
|
|
|
85
91
|
# glob target documents
|
|
86
92
|
all_docnames = self.env.found_docs.copy() | generated_docnames
|
|
87
|
-
all_docnames.remove(
|
|
93
|
+
all_docnames.remove(current_docname) # remove current document
|
|
94
|
+
frozen_all_docnames = frozenset(all_docnames)
|
|
88
95
|
|
|
89
96
|
ret: list[Node] = []
|
|
90
97
|
excluded = Matcher(self.config.exclude_patterns)
|
|
91
98
|
for entry in self.content:
|
|
92
99
|
if not entry:
|
|
93
100
|
continue
|
|
101
|
+
|
|
94
102
|
# look for explicit titles ("Some Title <document>")
|
|
95
103
|
explicit = explicit_title_re.match(entry)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
for docname in
|
|
104
|
+
url_match = url_re.match(entry) is not None
|
|
105
|
+
if glob and glob_re.match(entry) and not explicit and not url_match:
|
|
106
|
+
pat_name = docname_join(current_docname, entry)
|
|
107
|
+
doc_names = sorted(patfilter(all_docnames, pat_name))
|
|
108
|
+
for docname in doc_names:
|
|
101
109
|
if docname in generated_docnames:
|
|
102
110
|
# don't include generated documents in globs
|
|
103
111
|
continue
|
|
104
112
|
all_docnames.remove(docname) # don't include it again
|
|
105
113
|
toctree['entries'].append((None, docname))
|
|
106
114
|
toctree['includefiles'].append(docname)
|
|
107
|
-
if not
|
|
115
|
+
if not doc_names:
|
|
108
116
|
logger.warning(__("toctree glob pattern %r didn't match any documents"),
|
|
109
117
|
entry, location=toctree)
|
|
118
|
+
continue
|
|
119
|
+
|
|
120
|
+
if explicit:
|
|
121
|
+
ref = explicit.group(2)
|
|
122
|
+
title = explicit.group(1)
|
|
123
|
+
docname = ref
|
|
110
124
|
else:
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
subtype = 'excluded'
|
|
131
|
-
else:
|
|
132
|
-
message = __('toctree contains reference to nonexisting document %r')
|
|
133
|
-
subtype = 'not_readable'
|
|
134
|
-
|
|
135
|
-
logger.warning(message, docname, type='toc', subtype=subtype,
|
|
136
|
-
location=toctree)
|
|
137
|
-
self.env.note_reread()
|
|
125
|
+
ref = docname = entry
|
|
126
|
+
title = None
|
|
127
|
+
|
|
128
|
+
# remove suffixes (backwards compatibility)
|
|
129
|
+
for suffix in suffixes:
|
|
130
|
+
if docname.endswith(suffix):
|
|
131
|
+
docname = docname.removesuffix(suffix)
|
|
132
|
+
break
|
|
133
|
+
|
|
134
|
+
# absolutise filenames
|
|
135
|
+
docname = docname_join(current_docname, docname)
|
|
136
|
+
if url_match or ref == 'self':
|
|
137
|
+
toctree['entries'].append((title, ref))
|
|
138
|
+
continue
|
|
139
|
+
|
|
140
|
+
if docname not in frozen_all_docnames:
|
|
141
|
+
if excluded(self.env.doc2path(docname, False)):
|
|
142
|
+
message = __('toctree contains reference to excluded document %r')
|
|
143
|
+
subtype = 'excluded'
|
|
138
144
|
else:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
else:
|
|
142
|
-
logger.warning(__('duplicated entry found in toctree: %s'), docname,
|
|
143
|
-
location=toctree)
|
|
145
|
+
message = __('toctree contains reference to nonexisting document %r')
|
|
146
|
+
subtype = 'not_readable'
|
|
144
147
|
|
|
145
|
-
|
|
146
|
-
|
|
148
|
+
logger.warning(message, docname, type='toc', subtype=subtype,
|
|
149
|
+
location=toctree)
|
|
150
|
+
self.env.note_reread()
|
|
151
|
+
continue
|
|
152
|
+
|
|
153
|
+
if docname in all_docnames:
|
|
154
|
+
all_docnames.remove(docname)
|
|
155
|
+
else:
|
|
156
|
+
logger.warning(__('duplicated entry found in toctree: %s'), docname,
|
|
157
|
+
location=toctree)
|
|
158
|
+
|
|
159
|
+
toctree['entries'].append((title, docname))
|
|
160
|
+
toctree['includefiles'].append(docname)
|
|
147
161
|
|
|
148
162
|
# entries contains all entries (self references, external links etc.)
|
|
149
163
|
if 'reversed' in self.options:
|
|
@@ -357,6 +371,40 @@ class Include(BaseInclude, SphinxDirective):
|
|
|
357
371
|
"""
|
|
358
372
|
|
|
359
373
|
def run(self) -> list[Node]:
|
|
374
|
+
|
|
375
|
+
# To properly emit "source-read" events from included RST text,
|
|
376
|
+
# we must patch the ``StateMachine.insert_input()`` method.
|
|
377
|
+
# In the future, docutils will hopefully offer a way for Sphinx
|
|
378
|
+
# to provide the RST parser to use
|
|
379
|
+
# when parsing RST text that comes in via Include directive.
|
|
380
|
+
def _insert_input(include_lines, path):
|
|
381
|
+
# First, we need to combine the lines back into text so that
|
|
382
|
+
# we can send it with the source-read event.
|
|
383
|
+
# In docutils 0.18 and later, there are two lines at the end
|
|
384
|
+
# that act as markers.
|
|
385
|
+
# We must preserve them and leave them out of the source-read event:
|
|
386
|
+
text = "\n".join(include_lines[:-2])
|
|
387
|
+
|
|
388
|
+
# The docname to pass into the source-read event
|
|
389
|
+
docname = self.env.path2doc(os_path(path))
|
|
390
|
+
# Emit the "source-read" event
|
|
391
|
+
arg = [text]
|
|
392
|
+
self.env.app.events.emit("source-read", docname, arg)
|
|
393
|
+
text = arg[0]
|
|
394
|
+
|
|
395
|
+
# Split back into lines and reattach the two marker lines
|
|
396
|
+
include_lines = text.splitlines() + include_lines[-2:]
|
|
397
|
+
|
|
398
|
+
# Call the parent implementation.
|
|
399
|
+
# Note that this snake does not eat its tail because we patch
|
|
400
|
+
# the *Instance* method and this call is to the *Class* method.
|
|
401
|
+
return StateMachine.insert_input(self.state_machine, include_lines, path)
|
|
402
|
+
|
|
403
|
+
# Only enable this patch if there are listeners for 'source-read'.
|
|
404
|
+
if self.env.app.events.listeners.get('source-read'):
|
|
405
|
+
# See https://github.com/python/mypy/issues/2427 for details on the mypy issue
|
|
406
|
+
self.state_machine.insert_input = _insert_input # type: ignore[method-assign]
|
|
407
|
+
|
|
360
408
|
if self.arguments[0].startswith('<') and \
|
|
361
409
|
self.arguments[0].endswith('>'):
|
|
362
410
|
# docutils "standard" includes, do not do path processing
|
sphinx/directives/patches.py
CHANGED
|
@@ -18,10 +18,10 @@ from sphinx.util import logging
|
|
|
18
18
|
from sphinx.util.docutils import SphinxDirective
|
|
19
19
|
from sphinx.util.nodes import set_source_info
|
|
20
20
|
from sphinx.util.osutil import SEP, os_path, relpath
|
|
21
|
-
from sphinx.util.typing import OptionSpec
|
|
22
21
|
|
|
23
22
|
if TYPE_CHECKING:
|
|
24
23
|
from sphinx.application import Sphinx
|
|
24
|
+
from sphinx.util.typing import OptionSpec
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
logger = logging.getLogger(__name__)
|
sphinx/domains/__init__.py
CHANGED
|
@@ -8,23 +8,25 @@ from __future__ import annotations
|
|
|
8
8
|
|
|
9
9
|
import copy
|
|
10
10
|
from abc import ABC, abstractmethod
|
|
11
|
-
from typing import TYPE_CHECKING, Any, Callable,
|
|
11
|
+
from typing import TYPE_CHECKING, Any, Callable, NamedTuple, Optional, cast
|
|
12
12
|
|
|
13
|
-
from docutils import nodes
|
|
14
13
|
from docutils.nodes import Element, Node, system_message
|
|
15
|
-
from docutils.parsers.rst.states import Inliner
|
|
16
14
|
|
|
17
|
-
from sphinx.addnodes import pending_xref
|
|
18
15
|
from sphinx.errors import SphinxError
|
|
19
16
|
from sphinx.locale import _
|
|
20
|
-
from sphinx.roles import XRefRole
|
|
21
|
-
from sphinx.util.typing import RoleFunction
|
|
22
17
|
|
|
23
18
|
if TYPE_CHECKING:
|
|
19
|
+
from collections.abc import Iterable, Sequence
|
|
20
|
+
|
|
21
|
+
from docutils import nodes
|
|
24
22
|
from docutils.parsers.rst import Directive
|
|
23
|
+
from docutils.parsers.rst.states import Inliner
|
|
25
24
|
|
|
25
|
+
from sphinx.addnodes import pending_xref
|
|
26
26
|
from sphinx.builders import Builder
|
|
27
27
|
from sphinx.environment import BuildEnvironment
|
|
28
|
+
from sphinx.roles import XRefRole
|
|
29
|
+
from sphinx.util.typing import RoleFunction
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
class ObjType:
|
|
@@ -262,10 +264,11 @@ class Domain:
|
|
|
262
264
|
fullname = f'{self.name}:{name}'
|
|
263
265
|
|
|
264
266
|
def role_adapter(typ: str, rawtext: str, text: str, lineno: int,
|
|
265
|
-
inliner: Inliner, options: dict
|
|
267
|
+
inliner: Inliner, options: dict | None = None,
|
|
268
|
+
content: Sequence[str] = (),
|
|
266
269
|
) -> tuple[list[Node], list[system_message]]:
|
|
267
270
|
return self.roles[name](fullname, rawtext, text, lineno,
|
|
268
|
-
inliner, options, content)
|
|
271
|
+
inliner, options or {}, content)
|
|
269
272
|
self._role_cache[name] = role_adapter
|
|
270
273
|
return role_adapter
|
|
271
274
|
|