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/domains/std.py
CHANGED
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import re
|
|
6
6
|
from copy import copy
|
|
7
|
-
from typing import TYPE_CHECKING, Any, Callable, Final,
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Callable, Final, cast
|
|
8
8
|
|
|
9
9
|
from docutils import nodes
|
|
10
10
|
from docutils.nodes import Element, Node, system_message
|
|
@@ -20,12 +20,14 @@ from sphinx.roles import EmphasizedLiteral, XRefRole
|
|
|
20
20
|
from sphinx.util import docname_join, logging, ws_re
|
|
21
21
|
from sphinx.util.docutils import SphinxDirective
|
|
22
22
|
from sphinx.util.nodes import clean_astext, make_id, make_refnode
|
|
23
|
-
from sphinx.util.typing import OptionSpec, RoleFunction
|
|
24
23
|
|
|
25
24
|
if TYPE_CHECKING:
|
|
25
|
+
from collections.abc import Iterable, Iterator
|
|
26
|
+
|
|
26
27
|
from sphinx.application import Sphinx
|
|
27
28
|
from sphinx.builders import Builder
|
|
28
29
|
from sphinx.environment import BuildEnvironment
|
|
30
|
+
from sphinx.util.typing import OptionSpec, RoleFunction
|
|
29
31
|
|
|
30
32
|
logger = logging.getLogger(__name__)
|
|
31
33
|
|
|
@@ -214,7 +216,7 @@ class Cmdoption(ObjectDescription[str]):
|
|
|
214
216
|
|
|
215
217
|
self.state.document.note_explicit_target(signode)
|
|
216
218
|
|
|
217
|
-
domain =
|
|
219
|
+
domain = self.env.domains['std']
|
|
218
220
|
for optname in signode.get('allnames', []):
|
|
219
221
|
domain.add_program_option(currprogram, optname,
|
|
220
222
|
self.env.docname, signode['ids'][0])
|
|
@@ -381,10 +383,12 @@ class Glossary(SphinxDirective):
|
|
|
381
383
|
parts = split_term_classifiers(line)
|
|
382
384
|
# parse the term with inline markup
|
|
383
385
|
# classifiers (parts[1:]) will not be shown on doctree
|
|
384
|
-
textnodes, sysmsg = self.state.inline_text(parts[0],
|
|
386
|
+
textnodes, sysmsg = self.state.inline_text(parts[0], # type: ignore[arg-type]
|
|
387
|
+
lineno)
|
|
385
388
|
|
|
386
389
|
# use first classifier as a index key
|
|
387
|
-
term = make_glossary_term(self.env, textnodes,
|
|
390
|
+
term = make_glossary_term(self.env, textnodes,
|
|
391
|
+
parts[1], source, lineno, # type: ignore[arg-type]
|
|
388
392
|
node_id=None, document=self.state.document)
|
|
389
393
|
term.rawsource = line
|
|
390
394
|
system_messages.extend(sysmsg)
|
|
@@ -645,7 +649,7 @@ class StandardDomain(Domain):
|
|
|
645
649
|
self._terms[term.lower()] = (self.env.docname, labelid)
|
|
646
650
|
|
|
647
651
|
@property
|
|
648
|
-
def progoptions(self) -> dict[tuple[str, str], tuple[str, str]]:
|
|
652
|
+
def progoptions(self) -> dict[tuple[str | None, str], tuple[str, str]]:
|
|
649
653
|
return self.data.setdefault('progoptions', {}) # (program, name) -> docname, labelid
|
|
650
654
|
|
|
651
655
|
@property
|
|
@@ -704,7 +708,7 @@ class StandardDomain(Domain):
|
|
|
704
708
|
node = document.ids[labelid]
|
|
705
709
|
if isinstance(node, nodes.target) and 'refid' in node:
|
|
706
710
|
# indirect hyperlink targets
|
|
707
|
-
node = document.ids.get(node['refid'])
|
|
711
|
+
node = document.ids.get(node['refid']) # type: ignore[assignment]
|
|
708
712
|
labelid = node['names'][0]
|
|
709
713
|
if (node.tagname == 'footnote' or
|
|
710
714
|
'refuri' in node or
|
|
@@ -719,11 +723,11 @@ class StandardDomain(Domain):
|
|
|
719
723
|
self.anonlabels[name] = docname, labelid
|
|
720
724
|
if node.tagname == 'section':
|
|
721
725
|
title = cast(nodes.title, node[0])
|
|
722
|
-
sectname
|
|
726
|
+
sectname = clean_astext(title)
|
|
723
727
|
elif node.tagname == 'rubric':
|
|
724
728
|
sectname = clean_astext(node)
|
|
725
729
|
elif self.is_enumerable_node(node):
|
|
726
|
-
sectname = self.get_numfig_title(node)
|
|
730
|
+
sectname = self.get_numfig_title(node) or ''
|
|
727
731
|
if not sectname:
|
|
728
732
|
continue
|
|
729
733
|
else:
|
|
@@ -738,13 +742,14 @@ class StandardDomain(Domain):
|
|
|
738
742
|
else:
|
|
739
743
|
toctree = next(node.findall(addnodes.toctree), None)
|
|
740
744
|
if toctree and toctree.get('caption'):
|
|
741
|
-
sectname = toctree
|
|
745
|
+
sectname = toctree['caption']
|
|
742
746
|
else:
|
|
743
747
|
# anonymous-only labels
|
|
744
748
|
continue
|
|
745
749
|
self.labels[name] = docname, labelid, sectname
|
|
746
750
|
|
|
747
|
-
def add_program_option(self, program: str
|
|
751
|
+
def add_program_option(self, program: str | None, name: str,
|
|
752
|
+
docname: str, labelid: str) -> None:
|
|
748
753
|
# prefer first command option entry
|
|
749
754
|
if (program, name) not in self.progoptions:
|
|
750
755
|
self.progoptions[program, name] = (docname, labelid)
|
|
@@ -825,6 +830,7 @@ class StandardDomain(Domain):
|
|
|
825
830
|
return None
|
|
826
831
|
|
|
827
832
|
target_node = env.get_doctree(docname).ids.get(labelid)
|
|
833
|
+
assert target_node is not None
|
|
828
834
|
figtype = self.get_enumerable_node_type(target_node)
|
|
829
835
|
if figtype is None:
|
|
830
836
|
return None
|
|
@@ -983,9 +989,9 @@ class StandardDomain(Domain):
|
|
|
983
989
|
key = (objtype, ltarget)
|
|
984
990
|
if key in self.objects:
|
|
985
991
|
docname, labelid = self.objects[key]
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
992
|
+
role = 'std:' + self.role_for_objtype(objtype) # type: ignore[operator]
|
|
993
|
+
results.append((role, make_refnode(builder, fromdocname, docname,
|
|
994
|
+
labelid, contnode)))
|
|
989
995
|
return results
|
|
990
996
|
|
|
991
997
|
def get_objects(self) -> Iterator[tuple[str, str, str, str, str, int]]:
|
|
@@ -1096,7 +1102,7 @@ def warn_missing_reference(app: Sphinx, domain: Domain, node: pending_xref,
|
|
|
1096
1102
|
return None
|
|
1097
1103
|
else:
|
|
1098
1104
|
target = node['reftarget']
|
|
1099
|
-
if target not in domain.anonlabels: # type: ignore
|
|
1105
|
+
if target not in domain.anonlabels: # type: ignore[attr-defined]
|
|
1100
1106
|
msg = __('undefined label: %r')
|
|
1101
1107
|
else:
|
|
1102
1108
|
msg = __('Failed to create a cross reference. A title or caption not found: %r')
|
sphinx/environment/__init__.py
CHANGED
|
@@ -5,23 +5,16 @@ from __future__ import annotations
|
|
|
5
5
|
import functools
|
|
6
6
|
import os
|
|
7
7
|
import pickle
|
|
8
|
+
import time
|
|
8
9
|
from collections import defaultdict
|
|
9
10
|
from copy import copy
|
|
10
|
-
from datetime import datetime, timezone
|
|
11
11
|
from os import path
|
|
12
|
-
from typing import TYPE_CHECKING, Any, Callable
|
|
13
|
-
|
|
14
|
-
from docutils import nodes
|
|
15
|
-
from docutils.nodes import Node
|
|
12
|
+
from typing import TYPE_CHECKING, Any, Callable
|
|
16
13
|
|
|
17
14
|
from sphinx import addnodes
|
|
18
|
-
from sphinx.
|
|
19
|
-
from sphinx.domains import Domain
|
|
20
|
-
from sphinx.environment.adapters.toctree import TocTree
|
|
15
|
+
from sphinx.environment.adapters import toctree as toctree_adapters
|
|
21
16
|
from sphinx.errors import BuildEnvironmentError, DocumentError, ExtensionError, SphinxError
|
|
22
|
-
from sphinx.events import EventManager
|
|
23
17
|
from sphinx.locale import __
|
|
24
|
-
from sphinx.project import Project
|
|
25
18
|
from sphinx.transforms import SphinxTransformer
|
|
26
19
|
from sphinx.util import DownloadFiles, FilenameUniqDict, logging
|
|
27
20
|
from sphinx.util.docutils import LoggingReporter
|
|
@@ -30,8 +23,18 @@ from sphinx.util.nodes import is_translatable
|
|
|
30
23
|
from sphinx.util.osutil import canon_path, os_path
|
|
31
24
|
|
|
32
25
|
if TYPE_CHECKING:
|
|
26
|
+
from collections.abc import Generator, Iterator
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
|
|
29
|
+
from docutils import nodes
|
|
30
|
+
from docutils.nodes import Node
|
|
31
|
+
|
|
33
32
|
from sphinx.application import Sphinx
|
|
34
33
|
from sphinx.builders import Builder
|
|
34
|
+
from sphinx.config import Config
|
|
35
|
+
from sphinx.domains import Domain
|
|
36
|
+
from sphinx.events import EventManager
|
|
37
|
+
from sphinx.project import Project
|
|
35
38
|
|
|
36
39
|
logger = logging.getLogger(__name__)
|
|
37
40
|
|
|
@@ -55,9 +58,10 @@ default_settings: dict[str, Any] = {
|
|
|
55
58
|
|
|
56
59
|
# This is increased every time an environment attribute is added
|
|
57
60
|
# or changed to properly invalidate pickle files.
|
|
58
|
-
ENV_VERSION =
|
|
61
|
+
ENV_VERSION = 60
|
|
59
62
|
|
|
60
63
|
# config status
|
|
64
|
+
CONFIG_UNSET = -1
|
|
61
65
|
CONFIG_OK = 1
|
|
62
66
|
CONFIG_NEW = 2
|
|
63
67
|
CONFIG_CHANGED = 3
|
|
@@ -76,7 +80,8 @@ versioning_conditions: dict[str, bool | Callable] = {
|
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
if TYPE_CHECKING:
|
|
79
|
-
from
|
|
83
|
+
from collections.abc import MutableMapping
|
|
84
|
+
from typing import Literal
|
|
80
85
|
|
|
81
86
|
from typing_extensions import overload
|
|
82
87
|
|
|
@@ -142,25 +147,25 @@ class BuildEnvironment:
|
|
|
142
147
|
# --------- ENVIRONMENT INITIALIZATION -------------------------------------
|
|
143
148
|
|
|
144
149
|
def __init__(self, app: Sphinx):
|
|
145
|
-
self.app: Sphinx =
|
|
146
|
-
self.doctreedir:
|
|
147
|
-
self.srcdir:
|
|
148
|
-
self.config: Config = None
|
|
149
|
-
self.config_status: int =
|
|
150
|
-
self.config_status_extra: str =
|
|
151
|
-
self.events: EventManager =
|
|
152
|
-
self.project: Project =
|
|
153
|
-
self.version: dict[str, str] =
|
|
150
|
+
self.app: Sphinx = app
|
|
151
|
+
self.doctreedir: Path = app.doctreedir
|
|
152
|
+
self.srcdir: Path = app.srcdir
|
|
153
|
+
self.config: Config = None # type: ignore[assignment]
|
|
154
|
+
self.config_status: int = CONFIG_UNSET
|
|
155
|
+
self.config_status_extra: str = ''
|
|
156
|
+
self.events: EventManager = app.events
|
|
157
|
+
self.project: Project = app.project
|
|
158
|
+
self.version: dict[str, str] = app.registry.get_envversion(app)
|
|
154
159
|
|
|
155
160
|
# the method of doctree versioning; see set_versioning_method
|
|
156
|
-
self.versioning_condition: bool | Callable = None
|
|
157
|
-
self.versioning_compare: bool = None
|
|
161
|
+
self.versioning_condition: bool | Callable | None = None
|
|
162
|
+
self.versioning_compare: bool | None = None
|
|
158
163
|
|
|
159
164
|
# all the registered domains, set by the application
|
|
160
165
|
self.domains = _DomainsType()
|
|
161
166
|
|
|
162
167
|
# the docutils settings for building
|
|
163
|
-
self.settings = default_settings.copy()
|
|
168
|
+
self.settings: dict[str, Any] = default_settings.copy()
|
|
164
169
|
self.settings['env'] = self
|
|
165
170
|
|
|
166
171
|
# All "docnames" here are /-separated and relative and exclude
|
|
@@ -372,7 +377,7 @@ class BuildEnvironment:
|
|
|
372
377
|
|
|
373
378
|
This possibly comes from a parallel build process.
|
|
374
379
|
"""
|
|
375
|
-
docnames = set(docnames) # type: ignore
|
|
380
|
+
docnames = set(docnames) # type: ignore[assignment]
|
|
376
381
|
for docname in docnames:
|
|
377
382
|
self.all_docs[docname] = other.all_docs[docname]
|
|
378
383
|
self.included[docname] = other.included[docname]
|
|
@@ -383,7 +388,7 @@ class BuildEnvironment:
|
|
|
383
388
|
domain.merge_domaindata(docnames, other.domaindata[domainname])
|
|
384
389
|
self.events.emit('env-merge-info', self, docnames, other)
|
|
385
390
|
|
|
386
|
-
def path2doc(self, filename: str) -> str | None:
|
|
391
|
+
def path2doc(self, filename: str | os.PathLike[str]) -> str | None:
|
|
387
392
|
"""Return the docname for the filename if the file is document.
|
|
388
393
|
|
|
389
394
|
*filename* should be absolute or relative to the source directory.
|
|
@@ -483,12 +488,9 @@ class BuildEnvironment:
|
|
|
483
488
|
mtime = self.all_docs[docname]
|
|
484
489
|
newmtime = _last_modified_time(self.doc2path(docname))
|
|
485
490
|
if newmtime > mtime:
|
|
486
|
-
# convert integer microseconds to floating-point seconds,
|
|
487
|
-
# and then to timezone-aware datetime objects.
|
|
488
|
-
mtime_dt = datetime.fromtimestamp(mtime / 1_000_000, tz=timezone.utc)
|
|
489
|
-
newmtime_dt = datetime.fromtimestamp(mtime / 1_000_000, tz=timezone.utc)
|
|
490
491
|
logger.debug('[build target] outdated %r: %s -> %s',
|
|
491
|
-
docname,
|
|
492
|
+
docname,
|
|
493
|
+
_format_modified_time(mtime), _format_modified_time(newmtime))
|
|
492
494
|
changed.add(docname)
|
|
493
495
|
continue
|
|
494
496
|
# finally, check the mtime of dependencies
|
|
@@ -497,10 +499,19 @@ class BuildEnvironment:
|
|
|
497
499
|
# this will do the right thing when dep is absolute too
|
|
498
500
|
deppath = path.join(self.srcdir, dep)
|
|
499
501
|
if not path.isfile(deppath):
|
|
502
|
+
logger.debug(
|
|
503
|
+
'[build target] changed %r missing dependency %r',
|
|
504
|
+
docname, deppath,
|
|
505
|
+
)
|
|
500
506
|
changed.add(docname)
|
|
501
507
|
break
|
|
502
508
|
depmtime = _last_modified_time(deppath)
|
|
503
509
|
if depmtime > mtime:
|
|
510
|
+
logger.debug(
|
|
511
|
+
'[build target] outdated %r from dependency %r: %s -> %s',
|
|
512
|
+
docname, deppath,
|
|
513
|
+
_format_modified_time(mtime), _format_modified_time(depmtime),
|
|
514
|
+
)
|
|
504
515
|
changed.add(docname)
|
|
505
516
|
break
|
|
506
517
|
except OSError:
|
|
@@ -625,9 +636,11 @@ class BuildEnvironment:
|
|
|
625
636
|
|
|
626
637
|
# now, resolve all toctree nodes
|
|
627
638
|
for toctreenode in doctree.findall(addnodes.toctree):
|
|
628
|
-
result =
|
|
629
|
-
|
|
630
|
-
|
|
639
|
+
result = toctree_adapters._resolve_toctree(
|
|
640
|
+
self, docname, builder, toctreenode,
|
|
641
|
+
prune=prune_toctrees,
|
|
642
|
+
includehidden=includehidden,
|
|
643
|
+
)
|
|
631
644
|
if result is None:
|
|
632
645
|
toctreenode.parent.replace(toctreenode, [])
|
|
633
646
|
else:
|
|
@@ -649,9 +662,14 @@ class BuildEnvironment:
|
|
|
649
662
|
If *collapse* is True, all branches not containing docname will
|
|
650
663
|
be collapsed.
|
|
651
664
|
"""
|
|
652
|
-
return
|
|
653
|
-
|
|
654
|
-
|
|
665
|
+
return toctree_adapters._resolve_toctree(
|
|
666
|
+
self, docname, builder, toctree,
|
|
667
|
+
prune=prune,
|
|
668
|
+
maxdepth=maxdepth,
|
|
669
|
+
titles_only=titles_only,
|
|
670
|
+
collapse=collapse,
|
|
671
|
+
includehidden=includehidden,
|
|
672
|
+
)
|
|
655
673
|
|
|
656
674
|
def resolve_references(self, doctree: nodes.document, fromdocname: str,
|
|
657
675
|
builder: Builder) -> None:
|
|
@@ -675,38 +693,21 @@ class BuildEnvironment:
|
|
|
675
693
|
self.events.emit('doctree-resolved', doctree, docname)
|
|
676
694
|
|
|
677
695
|
def collect_relations(self) -> dict[str, list[str | None]]:
|
|
678
|
-
traversed = set()
|
|
679
|
-
|
|
680
|
-
def traverse_toctree(
|
|
681
|
-
parent: str | None, docname: str,
|
|
682
|
-
) -> Iterator[tuple[str | None, str]]:
|
|
683
|
-
if parent == docname:
|
|
684
|
-
logger.warning(__('self referenced toctree found. Ignored.'),
|
|
685
|
-
location=docname, type='toc',
|
|
686
|
-
subtype='circular')
|
|
687
|
-
return
|
|
688
|
-
|
|
689
|
-
# traverse toctree by pre-order
|
|
690
|
-
yield parent, docname
|
|
691
|
-
traversed.add(docname)
|
|
692
|
-
|
|
693
|
-
for child in (self.toctree_includes.get(docname) or []):
|
|
694
|
-
for subparent, subdocname in traverse_toctree(docname, child):
|
|
695
|
-
if subdocname not in traversed:
|
|
696
|
-
yield subparent, subdocname
|
|
697
|
-
traversed.add(subdocname)
|
|
696
|
+
traversed: set[str] = set()
|
|
698
697
|
|
|
699
698
|
relations = {}
|
|
700
|
-
docnames =
|
|
701
|
-
|
|
699
|
+
docnames = _traverse_toctree(
|
|
700
|
+
traversed, None, self.config.root_doc, self.toctree_includes,
|
|
701
|
+
)
|
|
702
|
+
prev_doc = None
|
|
702
703
|
parent, docname = next(docnames)
|
|
703
|
-
for
|
|
704
|
-
relations[docname] = [parent,
|
|
705
|
-
|
|
706
|
-
docname =
|
|
707
|
-
parent =
|
|
704
|
+
for next_parent, next_doc in docnames:
|
|
705
|
+
relations[docname] = [parent, prev_doc, next_doc]
|
|
706
|
+
prev_doc = docname
|
|
707
|
+
docname = next_doc
|
|
708
|
+
parent = next_parent
|
|
708
709
|
|
|
709
|
-
relations[docname] = [parent,
|
|
710
|
+
relations[docname] = [parent, prev_doc, None]
|
|
710
711
|
|
|
711
712
|
return relations
|
|
712
713
|
|
|
@@ -745,3 +746,34 @@ def _last_modified_time(filename: str | os.PathLike[str]) -> int:
|
|
|
745
746
|
|
|
746
747
|
# upside-down floor division to get the ceiling
|
|
747
748
|
return -(os.stat(filename).st_mtime_ns // -1_000)
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
def _format_modified_time(timestamp: int) -> str:
|
|
752
|
+
"""Return an RFC 3339 formatted string representing the given timestamp."""
|
|
753
|
+
seconds, fraction = divmod(timestamp, 10**6)
|
|
754
|
+
return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(seconds)) + f'.{fraction//1_000}'
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
def _traverse_toctree(
|
|
758
|
+
traversed: set[str],
|
|
759
|
+
parent: str | None,
|
|
760
|
+
docname: str,
|
|
761
|
+
toctree_includes: dict[str, list[str]],
|
|
762
|
+
) -> Iterator[tuple[str | None, str]]:
|
|
763
|
+
if parent == docname:
|
|
764
|
+
logger.warning(__('self referenced toctree found. Ignored.'),
|
|
765
|
+
location=docname, type='toc',
|
|
766
|
+
subtype='circular')
|
|
767
|
+
return
|
|
768
|
+
|
|
769
|
+
# traverse toctree by pre-order
|
|
770
|
+
yield parent, docname
|
|
771
|
+
traversed.add(docname)
|
|
772
|
+
|
|
773
|
+
for child in toctree_includes.get(docname, ()):
|
|
774
|
+
for sub_parent, sub_docname in _traverse_toctree(
|
|
775
|
+
traversed, docname, child, toctree_includes,
|
|
776
|
+
):
|
|
777
|
+
if sub_docname not in traversed:
|
|
778
|
+
yield sub_parent, sub_docname
|
|
779
|
+
traversed.add(sub_docname)
|
|
@@ -5,13 +5,16 @@ from __future__ import annotations
|
|
|
5
5
|
import re
|
|
6
6
|
import unicodedata
|
|
7
7
|
from itertools import groupby
|
|
8
|
-
from typing import Any, Literal
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
9
9
|
|
|
10
|
-
from sphinx.builders import Builder
|
|
11
|
-
from sphinx.environment import BuildEnvironment
|
|
12
10
|
from sphinx.errors import NoUri
|
|
13
11
|
from sphinx.locale import _, __
|
|
14
|
-
from sphinx.util import logging
|
|
12
|
+
from sphinx.util import logging
|
|
13
|
+
from sphinx.util.index_entries import _split_into
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from sphinx.builders import Builder
|
|
17
|
+
from sphinx.environment import BuildEnvironment
|
|
15
18
|
|
|
16
19
|
logger = logging.getLogger(__name__)
|
|
17
20
|
|
|
@@ -41,20 +44,20 @@ class IndexEntries:
|
|
|
41
44
|
try:
|
|
42
45
|
if entry_type == 'single':
|
|
43
46
|
try:
|
|
44
|
-
entry, sub_entry =
|
|
47
|
+
entry, sub_entry = _split_into(2, 'single', value)
|
|
45
48
|
except ValueError:
|
|
46
|
-
entry, =
|
|
49
|
+
entry, = _split_into(1, 'single', value)
|
|
47
50
|
sub_entry = ''
|
|
48
51
|
_add_entry(entry, sub_entry, main,
|
|
49
52
|
dic=new, link=uri, key=category_key)
|
|
50
53
|
elif entry_type == 'pair':
|
|
51
|
-
first, second =
|
|
54
|
+
first, second = _split_into(2, 'pair', value)
|
|
52
55
|
_add_entry(first, second, main,
|
|
53
56
|
dic=new, link=uri, key=category_key)
|
|
54
57
|
_add_entry(second, first, main,
|
|
55
58
|
dic=new, link=uri, key=category_key)
|
|
56
59
|
elif entry_type == 'triple':
|
|
57
|
-
first, second, third =
|
|
60
|
+
first, second, third = _split_into(3, 'triple', value)
|
|
58
61
|
_add_entry(first, second + ' ' + third, main,
|
|
59
62
|
dic=new, link=uri, key=category_key)
|
|
60
63
|
_add_entry(second, third + ', ' + first, main,
|
|
@@ -62,11 +65,11 @@ class IndexEntries:
|
|
|
62
65
|
_add_entry(third, first + ' ' + second, main,
|
|
63
66
|
dic=new, link=uri, key=category_key)
|
|
64
67
|
elif entry_type == 'see':
|
|
65
|
-
first, second =
|
|
68
|
+
first, second = _split_into(2, 'see', value)
|
|
66
69
|
_add_entry(first, _('see %s') % second, None,
|
|
67
70
|
dic=new, link=False, key=category_key)
|
|
68
71
|
elif entry_type == 'seealso':
|
|
69
|
-
first, second =
|
|
72
|
+
first, second = _split_into(2, 'see', value)
|
|
70
73
|
_add_entry(first, _('see also %s') % second, None,
|
|
71
74
|
dic=new, link=False, key=category_key)
|
|
72
75
|
else:
|