Sphinx 7.1.2__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 +18 -11
- 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.2.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.2.dist-info/RECORD +0 -564
- {sphinx-7.1.2.dist-info → sphinx-7.2.0.dist-info}/LICENSE +0 -0
- {sphinx-7.1.2.dist-info → sphinx-7.2.0.dist-info}/WHEEL +0 -0
- {sphinx-7.1.2.dist-info → sphinx-7.2.0.dist-info}/entry_points.txt +0 -0
sphinx/parsers.py
CHANGED
|
@@ -9,15 +9,16 @@ import docutils.parsers.rst
|
|
|
9
9
|
from docutils import nodes
|
|
10
10
|
from docutils.parsers.rst import states
|
|
11
11
|
from docutils.statemachine import StringList
|
|
12
|
-
from docutils.transforms import Transform
|
|
13
12
|
from docutils.transforms.universal import SmartQuotes
|
|
14
13
|
|
|
15
|
-
from sphinx.config import Config
|
|
16
|
-
from sphinx.environment import BuildEnvironment
|
|
17
14
|
from sphinx.util.rst import append_epilog, prepend_prolog
|
|
18
15
|
|
|
19
16
|
if TYPE_CHECKING:
|
|
17
|
+
from docutils.transforms import Transform
|
|
18
|
+
|
|
20
19
|
from sphinx.application import Sphinx
|
|
20
|
+
from sphinx.config import Config
|
|
21
|
+
from sphinx.environment import BuildEnvironment
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class Parser(docutils.parsers.Parser):
|
|
@@ -60,7 +61,7 @@ class RSTParser(docutils.parsers.rst.Parser, Parser):
|
|
|
60
61
|
|
|
61
62
|
def parse(self, inputstring: str | StringList, document: nodes.document) -> None:
|
|
62
63
|
"""Parse text and generate a document tree."""
|
|
63
|
-
self.setup_parse(inputstring, document) # type: ignore
|
|
64
|
+
self.setup_parse(inputstring, document) # type: ignore[arg-type]
|
|
64
65
|
self.statemachine = states.RSTStateMachine(
|
|
65
66
|
state_classes=self.state_classes,
|
|
66
67
|
initial_state=self.initial_state,
|
sphinx/project.py
CHANGED
|
@@ -2,14 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import contextlib
|
|
5
6
|
import os
|
|
6
7
|
from glob import glob
|
|
7
|
-
from typing import
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
8
9
|
|
|
9
10
|
from sphinx.locale import __
|
|
10
11
|
from sphinx.util import logging
|
|
11
12
|
from sphinx.util.matching import get_matching_files
|
|
12
|
-
from sphinx.util.osutil import
|
|
13
|
+
from sphinx.util.osutil import path_stabilize, relpath
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from collections.abc import Iterable
|
|
13
17
|
|
|
14
18
|
logger = logging.getLogger(__name__)
|
|
15
19
|
EXCLUDE_PATHS = ['**/_sources', '.#*', '**/.#*', '*.lproj/**']
|
|
@@ -18,77 +22,91 @@ EXCLUDE_PATHS = ['**/_sources', '.#*', '**/.#*', '*.lproj/**']
|
|
|
18
22
|
class Project:
|
|
19
23
|
"""A project is the source code set of the Sphinx document(s)."""
|
|
20
24
|
|
|
21
|
-
def __init__(self, srcdir: str, source_suffix:
|
|
25
|
+
def __init__(self, srcdir: str | os.PathLike[str], source_suffix: Iterable[str]) -> None:
|
|
22
26
|
#: Source directory.
|
|
23
27
|
self.srcdir = srcdir
|
|
24
28
|
|
|
25
29
|
#: source_suffix. Same as :confval:`source_suffix`.
|
|
26
|
-
self.source_suffix = source_suffix
|
|
30
|
+
self.source_suffix = tuple(source_suffix)
|
|
31
|
+
self._first_source_suffix = next(iter(self.source_suffix), "")
|
|
27
32
|
|
|
28
|
-
#: The name of documents
|
|
33
|
+
#: The name of documents belonging to this project.
|
|
29
34
|
self.docnames: set[str] = set()
|
|
30
35
|
|
|
36
|
+
# Bijective mapping between docnames and (srcdir relative) paths.
|
|
37
|
+
self._path_to_docname: dict[str, str] = {}
|
|
38
|
+
self._docname_to_path: dict[str, str] = {}
|
|
39
|
+
|
|
31
40
|
def restore(self, other: Project) -> None:
|
|
32
41
|
"""Take over a result of last build."""
|
|
33
42
|
self.docnames = other.docnames
|
|
43
|
+
self._path_to_docname = other._path_to_docname
|
|
44
|
+
self._docname_to_path = other._docname_to_path
|
|
34
45
|
|
|
35
46
|
def discover(self, exclude_paths: Iterable[str] = (),
|
|
36
47
|
include_paths: Iterable[str] = ("**",)) -> set[str]:
|
|
37
48
|
"""Find all document files in the source directory and put them in
|
|
38
49
|
:attr:`docnames`.
|
|
39
50
|
"""
|
|
40
|
-
|
|
51
|
+
|
|
52
|
+
self.docnames.clear()
|
|
53
|
+
self._path_to_docname.clear()
|
|
54
|
+
self._docname_to_path.clear()
|
|
55
|
+
|
|
41
56
|
for filename in get_matching_files(
|
|
42
57
|
self.srcdir,
|
|
43
58
|
include_paths,
|
|
44
59
|
[*exclude_paths] + EXCLUDE_PATHS,
|
|
45
60
|
):
|
|
46
|
-
docname
|
|
47
|
-
if docname:
|
|
61
|
+
if docname := self.path2doc(filename):
|
|
48
62
|
if docname in self.docnames:
|
|
49
63
|
pattern = os.path.join(self.srcdir, docname) + '.*'
|
|
50
64
|
files = [relpath(f, self.srcdir) for f in glob(pattern)]
|
|
51
65
|
logger.warning(__('multiple files found for the document "%s": %r\n'
|
|
52
66
|
'Use %r for the build.'),
|
|
53
|
-
docname, files, self.doc2path(docname
|
|
67
|
+
docname, files, self.doc2path(docname, absolute=True),
|
|
68
|
+
once=True)
|
|
54
69
|
elif os.access(os.path.join(self.srcdir, filename), os.R_OK):
|
|
55
70
|
self.docnames.add(docname)
|
|
71
|
+
self._path_to_docname[filename] = docname
|
|
72
|
+
self._docname_to_path[docname] = filename
|
|
56
73
|
else:
|
|
57
|
-
logger.warning(__("
|
|
74
|
+
logger.warning(__("Ignored unreadable document %r."),
|
|
75
|
+
filename, location=docname)
|
|
58
76
|
|
|
59
77
|
return self.docnames
|
|
60
78
|
|
|
61
|
-
def path2doc(self, filename: str) -> str | None:
|
|
79
|
+
def path2doc(self, filename: str | os.PathLike[str]) -> str | None:
|
|
62
80
|
"""Return the docname for the filename if the file is a document.
|
|
63
81
|
|
|
64
82
|
*filename* should be absolute or relative to the source directory.
|
|
65
83
|
"""
|
|
66
|
-
|
|
67
|
-
filename
|
|
68
|
-
|
|
69
|
-
if
|
|
70
|
-
|
|
71
|
-
|
|
84
|
+
try:
|
|
85
|
+
return self._path_to_docname[filename] # type: ignore[index]
|
|
86
|
+
except KeyError:
|
|
87
|
+
if os.path.isabs(filename):
|
|
88
|
+
with contextlib.suppress(ValueError):
|
|
89
|
+
filename = os.path.relpath(filename, self.srcdir)
|
|
90
|
+
|
|
91
|
+
for suffix in self.source_suffix:
|
|
92
|
+
if os.path.basename(filename).endswith(suffix):
|
|
93
|
+
return path_stabilize(filename).removesuffix(suffix)
|
|
72
94
|
|
|
73
|
-
|
|
74
|
-
|
|
95
|
+
# the file does not have a docname
|
|
96
|
+
return None
|
|
75
97
|
|
|
76
|
-
def doc2path(self, docname: str,
|
|
98
|
+
def doc2path(self, docname: str, absolute: bool) -> str:
|
|
77
99
|
"""Return the filename for the document name.
|
|
78
100
|
|
|
79
|
-
If *
|
|
101
|
+
If *absolute* is True, return as an absolute path.
|
|
80
102
|
Else, return as a relative path to the source directory.
|
|
81
103
|
"""
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if basedir:
|
|
92
|
-
return basename + suffix
|
|
93
|
-
else:
|
|
94
|
-
return docname + suffix
|
|
104
|
+
try:
|
|
105
|
+
filename = self._docname_to_path[docname]
|
|
106
|
+
except KeyError:
|
|
107
|
+
# Backwards compatibility: the document does not exist
|
|
108
|
+
filename = docname + self._first_source_suffix
|
|
109
|
+
|
|
110
|
+
if absolute:
|
|
111
|
+
return os.path.join(self.srcdir, filename)
|
|
112
|
+
return filename
|
sphinx/pycode/__init__.py
CHANGED
|
@@ -138,7 +138,8 @@ class ModuleAnalyzer:
|
|
|
138
138
|
self.tagorder = parser.deforders
|
|
139
139
|
self._analyzed = True
|
|
140
140
|
except Exception as exc:
|
|
141
|
-
|
|
141
|
+
msg = f'parsing {self.srcname!r} failed: {exc!r}'
|
|
142
|
+
raise PycodeError(msg) from exc
|
|
142
143
|
|
|
143
144
|
def find_attr_docs(self) -> dict[tuple[str, str], list[str]]:
|
|
144
145
|
"""Find class and module-level attributes and their documentation."""
|
sphinx/pycode/ast.py
CHANGED
|
@@ -143,9 +143,6 @@ class _UnparseVisitor(ast.NodeVisitor):
|
|
|
143
143
|
items = (k + ": " + v for k, v in zip(keys, values))
|
|
144
144
|
return "{" + ", ".join(items) + "}"
|
|
145
145
|
|
|
146
|
-
def visit_Index(self, node: ast.Index) -> str:
|
|
147
|
-
return self.visit(node.value)
|
|
148
|
-
|
|
149
146
|
def visit_Lambda(self, node: ast.Lambda) -> str:
|
|
150
147
|
return "lambda %s: ..." % self.visit(node.args)
|
|
151
148
|
|
|
@@ -159,21 +156,18 @@ class _UnparseVisitor(ast.NodeVisitor):
|
|
|
159
156
|
return "{" + ", ".join(self.visit(e) for e in node.elts) + "}"
|
|
160
157
|
|
|
161
158
|
def visit_Subscript(self, node: ast.Subscript) -> str:
|
|
162
|
-
def is_simple_tuple(value: ast.
|
|
159
|
+
def is_simple_tuple(value: ast.expr) -> bool:
|
|
163
160
|
return (
|
|
164
|
-
isinstance(value, ast.Tuple)
|
|
165
|
-
bool(value.elts)
|
|
166
|
-
not any(isinstance(elt, ast.Starred) for elt in value.elts)
|
|
161
|
+
isinstance(value, ast.Tuple)
|
|
162
|
+
and bool(value.elts)
|
|
163
|
+
and not any(isinstance(elt, ast.Starred) for elt in value.elts)
|
|
167
164
|
)
|
|
168
165
|
|
|
169
166
|
if is_simple_tuple(node.slice):
|
|
170
|
-
elts = ", ".join(self.visit(e)
|
|
171
|
-
|
|
172
|
-
elif isinstance(node.slice, ast.Index) and is_simple_tuple(node.slice.value):
|
|
173
|
-
elts = ", ".join(self.visit(e) for e in node.slice.value.elts) # type: ignore
|
|
167
|
+
elts = ", ".join(self.visit(e)
|
|
168
|
+
for e in node.slice.elts) # type: ignore[attr-defined]
|
|
174
169
|
return f"{self.visit(node.value)}[{elts}]"
|
|
175
|
-
|
|
176
|
-
return f"{self.visit(node.value)}[{self.visit(node.slice)}]"
|
|
170
|
+
return f"{self.visit(node.value)}[{self.visit(node.slice)}]"
|
|
177
171
|
|
|
178
172
|
def visit_UnaryOp(self, node: ast.UnaryOp) -> str:
|
|
179
173
|
# UnaryOp is one of {UAdd, USub, Invert, Not}, which refer to ``+x``,
|
sphinx/pycode/parser.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import ast
|
|
6
|
+
import contextlib
|
|
6
7
|
import inspect
|
|
7
8
|
import itertools
|
|
8
9
|
import re
|
|
@@ -28,7 +29,7 @@ def get_assign_targets(node: ast.AST) -> list[ast.expr]:
|
|
|
28
29
|
if isinstance(node, ast.Assign):
|
|
29
30
|
return node.targets
|
|
30
31
|
else:
|
|
31
|
-
return [node.target] # type: ignore
|
|
32
|
+
return [node.target] # type: ignore[attr-defined]
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
def get_lvar_names(node: ast.AST, self: ast.arg | None = None) -> list[str]:
|
|
@@ -44,20 +45,19 @@ def get_lvar_names(node: ast.AST, self: ast.arg | None = None) -> list[str]:
|
|
|
44
45
|
self_id = self.arg
|
|
45
46
|
|
|
46
47
|
node_name = node.__class__.__name__
|
|
47
|
-
if node_name in ('
|
|
48
|
+
if node_name in ('Constant', 'Index', 'Slice', 'Subscript'):
|
|
48
49
|
raise TypeError('%r does not create new variable' % node)
|
|
49
50
|
if node_name == 'Name':
|
|
50
|
-
if self is None or node.id == self_id: # type: ignore
|
|
51
|
-
return [node.id] # type: ignore
|
|
51
|
+
if self is None or node.id == self_id: # type: ignore[attr-defined]
|
|
52
|
+
return [node.id] # type: ignore[attr-defined]
|
|
52
53
|
else:
|
|
53
54
|
raise TypeError('The assignment %r is not instance variable' % node)
|
|
54
55
|
elif node_name in ('Tuple', 'List'):
|
|
55
56
|
members = []
|
|
56
|
-
for elt in node.elts: # type: ignore
|
|
57
|
-
|
|
57
|
+
for elt in node.elts: # type: ignore[attr-defined]
|
|
58
|
+
with contextlib.suppress(TypeError):
|
|
58
59
|
members.extend(get_lvar_names(elt, self))
|
|
59
|
-
|
|
60
|
-
pass
|
|
60
|
+
|
|
61
61
|
return members
|
|
62
62
|
elif node_name == 'Attribute':
|
|
63
63
|
if (
|
|
@@ -65,13 +65,13 @@ def get_lvar_names(node: ast.AST, self: ast.arg | None = None) -> list[str]:
|
|
|
65
65
|
self and node.value.id == self_id # type: ignore[attr-defined]
|
|
66
66
|
):
|
|
67
67
|
# instance variable
|
|
68
|
-
return ["%s" % get_lvar_names(node.attr, self)[0]] # type: ignore
|
|
68
|
+
return ["%s" % get_lvar_names(node.attr, self)[0]] # type: ignore[attr-defined]
|
|
69
69
|
else:
|
|
70
70
|
raise TypeError('The assignment %r is not instance variable' % node)
|
|
71
71
|
elif node_name == 'str':
|
|
72
|
-
return [node] # type: ignore
|
|
72
|
+
return [node] # type: ignore[list-item]
|
|
73
73
|
elif node_name == 'Starred':
|
|
74
|
-
return get_lvar_names(node.value, self) # type: ignore
|
|
74
|
+
return get_lvar_names(node.value, self) # type: ignore[attr-defined]
|
|
75
75
|
else:
|
|
76
76
|
raise NotImplementedError('Unexpected node name %r' % node_name)
|
|
77
77
|
|
|
@@ -145,21 +145,21 @@ class TokenProcessor:
|
|
|
145
145
|
|
|
146
146
|
return self.current
|
|
147
147
|
|
|
148
|
-
def fetch_until(self, condition: Any) -> list[Token
|
|
148
|
+
def fetch_until(self, condition: Any) -> list[Token]:
|
|
149
149
|
"""Fetch tokens until specified token appeared.
|
|
150
150
|
|
|
151
151
|
.. note:: This also handles parenthesis well.
|
|
152
152
|
"""
|
|
153
153
|
tokens = []
|
|
154
|
-
while self.fetch_token():
|
|
155
|
-
tokens.append(
|
|
156
|
-
if
|
|
154
|
+
while current := self.fetch_token():
|
|
155
|
+
tokens.append(current)
|
|
156
|
+
if current == condition:
|
|
157
157
|
break
|
|
158
|
-
if
|
|
158
|
+
if current == [OP, '(']:
|
|
159
159
|
tokens += self.fetch_until([OP, ')'])
|
|
160
|
-
elif
|
|
160
|
+
elif current == [OP, '{']:
|
|
161
161
|
tokens += self.fetch_until([OP, '}'])
|
|
162
|
-
elif
|
|
162
|
+
elif current == [OP, '[']:
|
|
163
163
|
tokens += self.fetch_until([OP, ']'])
|
|
164
164
|
|
|
165
165
|
return tokens
|
|
@@ -176,22 +176,22 @@ class AfterCommentParser(TokenProcessor):
|
|
|
176
176
|
super().__init__(lines)
|
|
177
177
|
self.comment: str | None = None
|
|
178
178
|
|
|
179
|
-
def fetch_rvalue(self) -> list[Token
|
|
179
|
+
def fetch_rvalue(self) -> list[Token]:
|
|
180
180
|
"""Fetch right-hand value of assignment."""
|
|
181
181
|
tokens = []
|
|
182
|
-
while self.fetch_token():
|
|
183
|
-
tokens.append(
|
|
184
|
-
if
|
|
182
|
+
while current := self.fetch_token():
|
|
183
|
+
tokens.append(current)
|
|
184
|
+
if current == [OP, '(']:
|
|
185
185
|
tokens += self.fetch_until([OP, ')'])
|
|
186
|
-
elif
|
|
186
|
+
elif current == [OP, '{']:
|
|
187
187
|
tokens += self.fetch_until([OP, '}'])
|
|
188
|
-
elif
|
|
188
|
+
elif current == [OP, '[']:
|
|
189
189
|
tokens += self.fetch_until([OP, ']'])
|
|
190
|
-
elif
|
|
190
|
+
elif current == INDENT:
|
|
191
191
|
tokens += self.fetch_until(DEDENT)
|
|
192
|
-
elif
|
|
192
|
+
elif current == [OP, ';']: # NoQA: SIM114
|
|
193
193
|
break
|
|
194
|
-
elif
|
|
194
|
+
elif current and current.kind not in {OP, NAME, NUMBER, STRING}:
|
|
195
195
|
break
|
|
196
196
|
|
|
197
197
|
return tokens
|
|
@@ -200,14 +200,17 @@ class AfterCommentParser(TokenProcessor):
|
|
|
200
200
|
"""Parse the code and obtain comment after assignment."""
|
|
201
201
|
# skip lvalue (or whole of AnnAssign)
|
|
202
202
|
while (tok := self.fetch_token()) and not tok.match([OP, '='], NEWLINE, COMMENT):
|
|
203
|
-
assert
|
|
203
|
+
assert tok
|
|
204
|
+
assert tok is not None
|
|
204
205
|
|
|
205
206
|
# skip rvalue (if exists)
|
|
206
|
-
if
|
|
207
|
+
if tok == [OP, '=']:
|
|
207
208
|
self.fetch_rvalue()
|
|
209
|
+
tok = self.current
|
|
210
|
+
assert tok is not None
|
|
208
211
|
|
|
209
|
-
if
|
|
210
|
-
self.comment =
|
|
212
|
+
if tok == COMMENT:
|
|
213
|
+
self.comment = tok.value
|
|
211
214
|
|
|
212
215
|
|
|
213
216
|
class VariableCommentPicker(ast.NodeVisitor):
|
|
@@ -360,7 +363,8 @@ class VariableCommentPicker(ast.NodeVisitor):
|
|
|
360
363
|
self.add_variable_annotation(varname, node.annotation)
|
|
361
364
|
elif hasattr(node, 'type_comment') and node.type_comment:
|
|
362
365
|
for varname in varnames:
|
|
363
|
-
self.add_variable_annotation(
|
|
366
|
+
self.add_variable_annotation(
|
|
367
|
+
varname, node.type_comment) # type: ignore[arg-type]
|
|
364
368
|
|
|
365
369
|
# check comments after assignment
|
|
366
370
|
parser = AfterCommentParser([current_line[node.col_offset:]] +
|
|
@@ -395,20 +399,20 @@ class VariableCommentPicker(ast.NodeVisitor):
|
|
|
395
399
|
|
|
396
400
|
def visit_AnnAssign(self, node: ast.AnnAssign) -> None:
|
|
397
401
|
"""Handles AnnAssign node and pick up a variable comment."""
|
|
398
|
-
self.visit_Assign(node) # type: ignore
|
|
402
|
+
self.visit_Assign(node) # type: ignore[arg-type]
|
|
399
403
|
|
|
400
404
|
def visit_Expr(self, node: ast.Expr) -> None:
|
|
401
405
|
"""Handles Expr node and pick up a comment if string."""
|
|
402
406
|
if (isinstance(self.previous, (ast.Assign, ast.AnnAssign)) and
|
|
403
|
-
isinstance(node.value, ast.
|
|
407
|
+
isinstance(node.value, ast.Constant) and isinstance(node.value.value, str)):
|
|
404
408
|
try:
|
|
405
409
|
targets = get_assign_targets(self.previous)
|
|
406
410
|
varnames = get_lvar_names(targets[0], self.get_self())
|
|
407
411
|
for varname in varnames:
|
|
408
|
-
if isinstance(node.value.
|
|
409
|
-
docstring = node.value.
|
|
412
|
+
if isinstance(node.value.value, str):
|
|
413
|
+
docstring = node.value.value
|
|
410
414
|
else:
|
|
411
|
-
docstring = node.value.
|
|
415
|
+
docstring = node.value.value.decode(self.encoding or 'utf-8')
|
|
412
416
|
|
|
413
417
|
self.add_variable_comment(varname, dedent_docstring(docstring))
|
|
414
418
|
self.add_entry(varname)
|
|
@@ -455,7 +459,7 @@ class VariableCommentPicker(ast.NodeVisitor):
|
|
|
455
459
|
|
|
456
460
|
def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
|
|
457
461
|
"""Handles AsyncFunctionDef node and set context."""
|
|
458
|
-
self.visit_FunctionDef(node) # type: ignore
|
|
462
|
+
self.visit_FunctionDef(node) # type: ignore[arg-type]
|
|
459
463
|
|
|
460
464
|
|
|
461
465
|
class DefinitionFinder(TokenProcessor):
|
sphinx/registry.py
CHANGED
|
@@ -6,25 +6,15 @@ import sys
|
|
|
6
6
|
import traceback
|
|
7
7
|
from importlib import import_module
|
|
8
8
|
from types import MethodType
|
|
9
|
-
from typing import TYPE_CHECKING, Any, Callable
|
|
10
|
-
|
|
11
|
-
from docutils import nodes
|
|
12
|
-
from docutils.core import Publisher
|
|
13
|
-
from docutils.nodes import Element, Node, TextElement
|
|
14
|
-
from docutils.parsers import Parser
|
|
15
|
-
from docutils.parsers.rst import Directive
|
|
16
|
-
from docutils.transforms import Transform
|
|
9
|
+
from typing import TYPE_CHECKING, Any, Callable
|
|
17
10
|
|
|
18
11
|
if sys.version_info >= (3, 10):
|
|
19
12
|
from importlib.metadata import entry_points
|
|
20
13
|
else:
|
|
21
14
|
from importlib_metadata import entry_points
|
|
22
15
|
|
|
23
|
-
from sphinx.builders import Builder
|
|
24
|
-
from sphinx.config import Config
|
|
25
16
|
from sphinx.domains import Domain, Index, ObjType
|
|
26
17
|
from sphinx.domains.std import GenericObject, Target
|
|
27
|
-
from sphinx.environment import BuildEnvironment
|
|
28
18
|
from sphinx.errors import ExtensionError, SphinxError, VersionRequirementError
|
|
29
19
|
from sphinx.extension import Extension
|
|
30
20
|
from sphinx.io import create_publisher
|
|
@@ -33,11 +23,23 @@ from sphinx.parsers import Parser as SphinxParser
|
|
|
33
23
|
from sphinx.roles import XRefRole
|
|
34
24
|
from sphinx.util import logging
|
|
35
25
|
from sphinx.util.logging import prefixed_warnings
|
|
36
|
-
from sphinx.util.typing import RoleFunction, TitleGetter
|
|
37
26
|
|
|
38
27
|
if TYPE_CHECKING:
|
|
28
|
+
from collections.abc import Iterator, Sequence
|
|
29
|
+
|
|
30
|
+
from docutils import nodes
|
|
31
|
+
from docutils.core import Publisher
|
|
32
|
+
from docutils.nodes import Element, Node, TextElement
|
|
33
|
+
from docutils.parsers import Parser
|
|
34
|
+
from docutils.parsers.rst import Directive
|
|
35
|
+
from docutils.transforms import Transform
|
|
36
|
+
|
|
39
37
|
from sphinx.application import Sphinx
|
|
38
|
+
from sphinx.builders import Builder
|
|
39
|
+
from sphinx.config import Config
|
|
40
|
+
from sphinx.environment import BuildEnvironment
|
|
40
41
|
from sphinx.ext.autodoc import Documenter
|
|
42
|
+
from sphinx.util.typing import RoleFunction, TitleGetter
|
|
41
43
|
|
|
42
44
|
logger = logging.getLogger(__name__)
|
|
43
45
|
|
|
@@ -83,12 +85,14 @@ class SphinxComponentRegistry:
|
|
|
83
85
|
|
|
84
86
|
#: additional enumerable nodes
|
|
85
87
|
#: a dict of node class -> tuple of figtype and title_getter function
|
|
86
|
-
self.enumerable_nodes: dict[type[Node], tuple[str, TitleGetter]] = {}
|
|
88
|
+
self.enumerable_nodes: dict[type[Node], tuple[str, TitleGetter | None]] = {}
|
|
87
89
|
|
|
88
90
|
#: HTML inline and block math renderers
|
|
89
91
|
#: a dict of name -> tuple of visit function and depart function
|
|
90
|
-
self.html_inline_math_renderers: dict[str,
|
|
91
|
-
|
|
92
|
+
self.html_inline_math_renderers: dict[str,
|
|
93
|
+
tuple[Callable, Callable | None]] = {}
|
|
94
|
+
self.html_block_math_renderers: dict[str,
|
|
95
|
+
tuple[Callable, Callable | None]] = {}
|
|
92
96
|
|
|
93
97
|
#: HTML assets
|
|
94
98
|
self.html_assets_policy: str = 'per_page'
|
|
@@ -97,12 +101,12 @@ class SphinxComponentRegistry:
|
|
|
97
101
|
self.html_themes: dict[str, str] = {}
|
|
98
102
|
|
|
99
103
|
#: js_files; list of JS paths or URLs
|
|
100
|
-
self.js_files: list[tuple[str, dict[str, Any]]] = []
|
|
104
|
+
self.js_files: list[tuple[str | None, dict[str, Any]]] = []
|
|
101
105
|
|
|
102
106
|
#: LaTeX packages; list of package names and its options
|
|
103
|
-
self.latex_packages: list[tuple[str, str]] = []
|
|
107
|
+
self.latex_packages: list[tuple[str, str | None]] = []
|
|
104
108
|
|
|
105
|
-
self.latex_packages_after_hyperref: list[tuple[str, str]] = []
|
|
109
|
+
self.latex_packages_after_hyperref: list[tuple[str, str | None]] = []
|
|
106
110
|
|
|
107
111
|
#: post transforms; list of transforms
|
|
108
112
|
self.post_transforms: list[type[Transform]] = []
|
|
@@ -118,7 +122,7 @@ class SphinxComponentRegistry:
|
|
|
118
122
|
|
|
119
123
|
#: custom handlers for translators
|
|
120
124
|
#: a dict of builder name -> dict of node name -> visitor and departure functions
|
|
121
|
-
self.translation_handlers: dict[str, dict[str, tuple[Callable, Callable]]] = {}
|
|
125
|
+
self.translation_handlers: dict[str, dict[str, tuple[Callable, Callable | None]]] = {}
|
|
122
126
|
|
|
123
127
|
#: additional transforms; list of transforms
|
|
124
128
|
self.transforms: list[type[Transform]] = []
|
|
@@ -149,8 +153,7 @@ class SphinxComponentRegistry:
|
|
|
149
153
|
|
|
150
154
|
self.load_extension(app, entry_point.module)
|
|
151
155
|
|
|
152
|
-
def create_builder(self, app: Sphinx, name: str,
|
|
153
|
-
env: BuildEnvironment | None = None) -> Builder:
|
|
156
|
+
def create_builder(self, app: Sphinx, name: str, env: BuildEnvironment) -> Builder:
|
|
154
157
|
if name not in self.builders:
|
|
155
158
|
raise SphinxError(__('Builder name %s not registered') % name)
|
|
156
159
|
|
|
@@ -221,7 +224,7 @@ class SphinxComponentRegistry:
|
|
|
221
224
|
parse_node: Callable | None = None,
|
|
222
225
|
ref_nodeclass: type[TextElement] | None = None,
|
|
223
226
|
objname: str = '',
|
|
224
|
-
doc_field_types:
|
|
227
|
+
doc_field_types: Sequence = (),
|
|
225
228
|
override: bool = False,
|
|
226
229
|
) -> None:
|
|
227
230
|
logger.debug('[app] adding object type: %r',
|
|
@@ -232,7 +235,7 @@ class SphinxComponentRegistry:
|
|
|
232
235
|
directive = type(directivename,
|
|
233
236
|
(GenericObject, object),
|
|
234
237
|
{'indextemplate': indextemplate,
|
|
235
|
-
'parse_node': staticmethod(parse_node),
|
|
238
|
+
'parse_node': parse_node and staticmethod(parse_node),
|
|
236
239
|
'doc_field_types': doc_field_types})
|
|
237
240
|
|
|
238
241
|
self.add_directive_to_domain('std', directivename, directive)
|
|
@@ -312,7 +315,7 @@ class SphinxComponentRegistry:
|
|
|
312
315
|
def add_translation_handlers(
|
|
313
316
|
self,
|
|
314
317
|
node: type[Element],
|
|
315
|
-
**kwargs: tuple[Callable
|
|
318
|
+
**kwargs: tuple[Callable, Callable | None],
|
|
316
319
|
) -> None:
|
|
317
320
|
logger.debug('[app] adding translation_handlers: %r, %r', node, kwargs)
|
|
318
321
|
for builder_name, handlers in kwargs.items():
|
|
@@ -333,7 +336,8 @@ class SphinxComponentRegistry:
|
|
|
333
336
|
try:
|
|
334
337
|
return builder.default_translator_class
|
|
335
338
|
except AttributeError as err:
|
|
336
|
-
|
|
339
|
+
msg = f'translator not found for {builder.name}'
|
|
340
|
+
raise AttributeError(msg) from err
|
|
337
341
|
|
|
338
342
|
def create_translator(self, builder: Builder, *args: Any) -> nodes.NodeVisitor:
|
|
339
343
|
translator_class = self.get_translator_class(builder)
|
|
@@ -410,16 +414,18 @@ class SphinxComponentRegistry:
|
|
|
410
414
|
def add_html_math_renderer(
|
|
411
415
|
self,
|
|
412
416
|
name: str,
|
|
413
|
-
inline_renderers: tuple[Callable
|
|
414
|
-
block_renderers: tuple[Callable
|
|
417
|
+
inline_renderers: tuple[Callable, Callable | None] | None,
|
|
418
|
+
block_renderers: tuple[Callable, Callable | None] | None,
|
|
415
419
|
) -> None:
|
|
416
420
|
logger.debug('[app] adding html_math_renderer: %s, %r, %r',
|
|
417
421
|
name, inline_renderers, block_renderers)
|
|
418
422
|
if name in self.html_inline_math_renderers:
|
|
419
423
|
raise ExtensionError(__('math renderer %s is already registered') % name)
|
|
420
424
|
|
|
421
|
-
|
|
422
|
-
|
|
425
|
+
if inline_renderers is not None:
|
|
426
|
+
self.html_inline_math_renderers[name] = inline_renderers
|
|
427
|
+
if block_renderers is not None:
|
|
428
|
+
self.html_block_math_renderers[name] = block_renderers
|
|
423
429
|
|
|
424
430
|
def add_html_theme(self, name: str, theme_path: str) -> None:
|
|
425
431
|
self.html_themes[name] = theme_path
|
sphinx/roles.py
CHANGED
|
@@ -9,17 +9,20 @@ import docutils.parsers.rst.directives
|
|
|
9
9
|
import docutils.parsers.rst.roles
|
|
10
10
|
import docutils.parsers.rst.states
|
|
11
11
|
from docutils import nodes, utils
|
|
12
|
-
from docutils.nodes import Element, Node, TextElement, system_message
|
|
13
12
|
|
|
14
13
|
from sphinx import addnodes
|
|
15
14
|
from sphinx.locale import _, __
|
|
16
15
|
from sphinx.util import ws_re
|
|
17
16
|
from sphinx.util.docutils import ReferenceRole, SphinxRole
|
|
18
|
-
from sphinx.util.typing import RoleFunction
|
|
19
17
|
|
|
20
18
|
if TYPE_CHECKING:
|
|
19
|
+
from collections.abc import Sequence
|
|
20
|
+
|
|
21
|
+
from docutils.nodes import Element, Node, TextElement, system_message
|
|
22
|
+
|
|
21
23
|
from sphinx.application import Sphinx
|
|
22
24
|
from sphinx.environment import BuildEnvironment
|
|
25
|
+
from sphinx.util.typing import RoleFunction
|
|
23
26
|
|
|
24
27
|
|
|
25
28
|
generic_docroles = {
|
|
@@ -365,8 +368,10 @@ class Abbreviation(SphinxRole):
|
|
|
365
368
|
# TODO: Change to use `SphinxRole` once SphinxRole is fixed to support options.
|
|
366
369
|
def code_role(name: str, rawtext: str, text: str, lineno: int,
|
|
367
370
|
inliner: docutils.parsers.rst.states.Inliner,
|
|
368
|
-
options: dict =
|
|
371
|
+
options: dict | None = None, content: Sequence[str] = (),
|
|
369
372
|
) -> tuple[list[Node], list[system_message]]:
|
|
373
|
+
if options is None:
|
|
374
|
+
options = {}
|
|
370
375
|
options = options.copy()
|
|
371
376
|
docutils.parsers.rst.roles.set_classes(options)
|
|
372
377
|
language = options.get('language', '')
|
|
@@ -384,7 +389,7 @@ def code_role(name: str, rawtext: str, text: str, lineno: int,
|
|
|
384
389
|
return [node], []
|
|
385
390
|
|
|
386
391
|
|
|
387
|
-
code_role.options = { # type: ignore
|
|
392
|
+
code_role.options = { # type: ignore[attr-defined]
|
|
388
393
|
'class': docutils.parsers.rst.directives.class_option,
|
|
389
394
|
'language': docutils.parsers.rst.directives.unchanged,
|
|
390
395
|
}
|
sphinx/search/__init__.py
CHANGED
|
@@ -9,29 +9,17 @@ import pickle
|
|
|
9
9
|
import re
|
|
10
10
|
from importlib import import_module
|
|
11
11
|
from os import path
|
|
12
|
-
from typing import
|
|
13
|
-
IO,
|
|
14
|
-
Any,
|
|
15
|
-
Callable,
|
|
16
|
-
Dict,
|
|
17
|
-
Generator,
|
|
18
|
-
Iterable,
|
|
19
|
-
Iterator,
|
|
20
|
-
List,
|
|
21
|
-
Optional,
|
|
22
|
-
Sequence,
|
|
23
|
-
Set,
|
|
24
|
-
Tuple,
|
|
25
|
-
Type,
|
|
26
|
-
Union,
|
|
27
|
-
)
|
|
12
|
+
from typing import IO, TYPE_CHECKING, Any
|
|
28
13
|
|
|
29
14
|
from docutils import nodes
|
|
30
15
|
from docutils.nodes import Element, Node
|
|
31
16
|
|
|
32
17
|
from sphinx import addnodes, package_dir
|
|
33
18
|
from sphinx.environment import BuildEnvironment
|
|
34
|
-
from sphinx.util import split_index_msg
|
|
19
|
+
from sphinx.util.index_entries import split_index_msg
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from collections.abc import Iterable
|
|
35
23
|
|
|
36
24
|
|
|
37
25
|
class SearchLanguage:
|