Sphinx 7.2.6__py3-none-any.whl → 7.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of Sphinx might be problematic. Click here for more details.
- sphinx/__init__.py +8 -9
- sphinx/addnodes.py +31 -28
- sphinx/application.py +9 -15
- sphinx/builders/__init__.py +5 -6
- sphinx/builders/_epub_base.py +17 -9
- sphinx/builders/changes.py +10 -5
- sphinx/builders/dirhtml.py +4 -2
- sphinx/builders/dummy.py +3 -2
- sphinx/builders/epub3.py +5 -3
- sphinx/builders/gettext.py +24 -7
- sphinx/builders/html/__init__.py +88 -96
- sphinx/builders/html/_assets.py +16 -16
- sphinx/builders/html/transforms.py +4 -2
- sphinx/builders/latex/__init__.py +40 -33
- sphinx/builders/latex/nodes.py +6 -2
- sphinx/builders/latex/transforms.py +17 -8
- sphinx/builders/latex/util.py +1 -1
- sphinx/builders/linkcheck.py +86 -27
- sphinx/builders/manpage.py +8 -6
- sphinx/builders/singlehtml.py +5 -4
- sphinx/builders/texinfo.py +18 -14
- sphinx/builders/text.py +3 -2
- sphinx/builders/xml.py +5 -2
- sphinx/cmd/build.py +119 -76
- sphinx/cmd/make_mode.py +4 -9
- sphinx/cmd/quickstart.py +13 -16
- sphinx/config.py +432 -250
- sphinx/deprecation.py +23 -13
- sphinx/directives/__init__.py +8 -8
- sphinx/directives/code.py +7 -7
- sphinx/directives/other.py +23 -13
- sphinx/directives/patches.py +7 -6
- sphinx/domains/__init__.py +2 -2
- sphinx/domains/c/__init__.py +796 -0
- sphinx/domains/c/_ast.py +1421 -0
- sphinx/domains/c/_ids.py +65 -0
- sphinx/domains/c/_parser.py +1048 -0
- sphinx/domains/c/_symbol.py +700 -0
- sphinx/domains/changeset.py +11 -7
- sphinx/domains/citation.py +5 -2
- sphinx/domains/cpp/__init__.py +1089 -0
- sphinx/domains/cpp/_ast.py +3635 -0
- sphinx/domains/cpp/_ids.py +537 -0
- sphinx/domains/cpp/_parser.py +2117 -0
- sphinx/domains/cpp/_symbol.py +1092 -0
- sphinx/domains/index.py +6 -4
- sphinx/domains/javascript.py +16 -13
- sphinx/domains/math.py +9 -4
- sphinx/domains/python/__init__.py +890 -0
- sphinx/domains/python/_annotations.py +507 -0
- sphinx/domains/python/_object.py +426 -0
- sphinx/domains/rst.py +12 -7
- sphinx/domains/{std.py → std/__init__.py} +19 -16
- sphinx/environment/__init__.py +21 -19
- sphinx/environment/adapters/indexentries.py +2 -2
- sphinx/environment/adapters/toctree.py +10 -9
- sphinx/environment/collectors/__init__.py +6 -3
- sphinx/environment/collectors/asset.py +4 -3
- sphinx/environment/collectors/dependencies.py +3 -2
- sphinx/environment/collectors/metadata.py +6 -5
- sphinx/environment/collectors/title.py +3 -2
- sphinx/environment/collectors/toctree.py +5 -4
- sphinx/errors.py +13 -2
- sphinx/events.py +14 -9
- sphinx/ext/apidoc.py +9 -11
- sphinx/ext/autodoc/__init__.py +105 -71
- sphinx/ext/autodoc/directive.py +7 -6
- sphinx/ext/autodoc/importer.py +102 -36
- sphinx/ext/autodoc/mock.py +7 -5
- sphinx/ext/autodoc/preserve_defaults.py +4 -3
- sphinx/ext/autodoc/type_comment.py +2 -1
- sphinx/ext/autodoc/typehints.py +5 -4
- sphinx/ext/autosectionlabel.py +3 -2
- sphinx/ext/autosummary/__init__.py +21 -17
- sphinx/ext/autosummary/generate.py +9 -9
- sphinx/ext/coverage.py +26 -20
- sphinx/ext/doctest.py +38 -33
- sphinx/ext/duration.py +1 -0
- sphinx/ext/extlinks.py +4 -3
- sphinx/ext/githubpages.py +3 -2
- sphinx/ext/graphviz.py +10 -7
- sphinx/ext/ifconfig.py +5 -5
- sphinx/ext/imgconverter.py +6 -5
- sphinx/ext/imgmath.py +9 -8
- sphinx/ext/inheritance_diagram.py +31 -31
- sphinx/ext/intersphinx.py +140 -23
- sphinx/ext/linkcode.py +3 -2
- sphinx/ext/mathjax.py +2 -1
- sphinx/ext/napoleon/__init__.py +12 -7
- sphinx/ext/napoleon/docstring.py +34 -32
- sphinx/ext/todo.py +10 -7
- sphinx/ext/viewcode.py +12 -11
- sphinx/extension.py +18 -8
- sphinx/highlighting.py +39 -20
- sphinx/io.py +17 -8
- sphinx/jinja2glue.py +16 -15
- sphinx/locale/__init__.py +30 -23
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +818 -761
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +835 -778
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +864 -807
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +816 -759
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +819 -762
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +838 -781
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +838 -781
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +853 -796
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +856 -799
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +820 -763
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +856 -799
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +845 -788
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +854 -797
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +816 -759
- sphinx/locale/fr/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr/LC_MESSAGES/sphinx.po +904 -847
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/gl/LC_MESSAGES/sphinx.js +54 -54
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +1506 -1449
- sphinx/locale/he/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.po +823 -766
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +853 -796
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +844 -787
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +854 -797
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +853 -796
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +848 -791
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +855 -798
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +825 -768
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js +27 -27
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +876 -818
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +844 -787
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +845 -788
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +908 -851
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +838 -781
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +823 -766
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +854 -797
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +832 -775
- sphinx/locale/sphinx.pot +813 -755
- sphinx/locale/sq/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sq/LC_MESSAGES/sphinx.po +865 -808
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +835 -778
- sphinx/locale/sr@latin/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/ta/LC_MESSAGES/sphinx.js +54 -54
- sphinx/locale/ta/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ta/LC_MESSAGES/sphinx.po +1530 -1473
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +853 -796
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +833 -776
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +855 -798
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +879 -822
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +811 -754
- sphinx/parsers.py +7 -5
- sphinx/project.py +18 -11
- sphinx/pycode/__init__.py +6 -5
- sphinx/pycode/ast.py +23 -8
- sphinx/pycode/parser.py +6 -5
- sphinx/registry.py +12 -6
- sphinx/roles.py +103 -57
- sphinx/search/__init__.py +17 -18
- sphinx/search/da.py +2 -2
- sphinx/search/de.py +2 -2
- sphinx/search/en.py +1 -1
- sphinx/search/es.py +2 -2
- sphinx/search/fi.py +2 -2
- sphinx/search/fr.py +2 -2
- sphinx/search/hu.py +2 -2
- sphinx/search/it.py +2 -2
- sphinx/search/ja.py +13 -22
- sphinx/search/nl.py +2 -2
- sphinx/search/no.py +2 -2
- sphinx/search/pt.py +2 -2
- sphinx/search/ro.py +1 -1
- sphinx/search/ru.py +2 -2
- sphinx/search/sv.py +2 -2
- sphinx/search/tr.py +1 -1
- sphinx/search/zh.py +2 -3
- sphinx/templates/graphviz/graphviz.css +1 -1
- sphinx/testing/fixtures.py +41 -24
- sphinx/testing/path.py +1 -1
- sphinx/testing/util.py +142 -53
- sphinx/texinputs/sphinx.xdy +1 -1
- sphinx/texinputs/sphinxlatextables.sty +1 -1
- sphinx/texinputs/sphinxpackagesubstitutefont.sty +21 -0
- sphinx/themes/agogo/layout.html +4 -4
- sphinx/themes/agogo/static/agogo.css_t +1 -1
- sphinx/themes/agogo/theme.toml +22 -0
- sphinx/themes/basic/defindex.html +1 -1
- sphinx/themes/basic/domainindex.html +1 -1
- sphinx/themes/basic/genindex-single.html +1 -1
- sphinx/themes/basic/genindex-split.html +1 -1
- sphinx/themes/basic/genindex.html +1 -1
- sphinx/themes/basic/globaltoc.html +1 -1
- sphinx/themes/basic/layout.html +1 -1
- sphinx/themes/basic/localtoc.html +1 -1
- sphinx/themes/basic/page.html +1 -1
- sphinx/themes/basic/relations.html +1 -1
- sphinx/themes/basic/search.html +5 -20
- sphinx/themes/basic/searchbox.html +3 -3
- sphinx/themes/basic/searchfield.html +3 -3
- sphinx/themes/basic/sourcelink.html +1 -1
- sphinx/themes/basic/static/basic.css_t +1 -1
- sphinx/themes/basic/static/doctools.js +1 -1
- sphinx/themes/basic/static/language_data.js_t +2 -2
- sphinx/themes/basic/static/searchtools.js +105 -60
- sphinx/themes/basic/theme.toml +23 -0
- sphinx/themes/bizstyle/layout.html +1 -6
- sphinx/themes/bizstyle/static/bizstyle.css_t +1 -1
- sphinx/themes/bizstyle/static/bizstyle.js_t +1 -1
- sphinx/themes/bizstyle/static/css3-mediaqueries_src.js +3 -3
- sphinx/themes/bizstyle/theme.toml +12 -0
- sphinx/themes/classic/layout.html +1 -1
- sphinx/themes/classic/static/classic.css_t +1 -1
- sphinx/themes/classic/static/sidebar.js_t +1 -1
- sphinx/themes/classic/theme.toml +34 -0
- sphinx/themes/default/theme.toml +2 -0
- sphinx/themes/epub/epub-cover.html +1 -1
- sphinx/themes/epub/layout.html +1 -1
- sphinx/themes/epub/static/epub.css_t +1 -1
- sphinx/themes/epub/theme.toml +10 -0
- sphinx/themes/haiku/layout.html +3 -3
- sphinx/themes/haiku/static/haiku.css_t +2 -2
- sphinx/themes/haiku/theme.toml +16 -0
- sphinx/themes/nature/static/nature.css_t +1 -1
- sphinx/themes/nature/theme.toml +6 -0
- sphinx/themes/nonav/layout.html +1 -1
- sphinx/themes/nonav/static/nonav.css_t +1 -1
- sphinx/themes/nonav/theme.toml +10 -0
- sphinx/themes/pyramid/static/epub.css_t +1 -1
- sphinx/themes/pyramid/static/pyramid.css_t +1 -1
- sphinx/themes/pyramid/theme.toml +6 -0
- sphinx/themes/scrolls/artwork/logo.svg +1 -1
- sphinx/themes/scrolls/layout.html +2 -2
- sphinx/themes/scrolls/static/scrolls.css_t +1 -1
- sphinx/themes/scrolls/theme.toml +15 -0
- sphinx/themes/sphinxdoc/static/sphinxdoc.css_t +1 -1
- sphinx/themes/sphinxdoc/theme.toml +6 -0
- sphinx/themes/traditional/static/traditional.css_t +1 -1
- sphinx/themes/traditional/theme.toml +9 -0
- sphinx/theming.py +427 -131
- sphinx/transforms/__init__.py +21 -24
- sphinx/transforms/compact_bullet_list.py +5 -5
- sphinx/transforms/i18n.py +30 -28
- sphinx/transforms/post_transforms/__init__.py +9 -7
- sphinx/transforms/post_transforms/code.py +4 -1
- sphinx/transforms/post_transforms/images.py +17 -13
- sphinx/transforms/references.py +3 -1
- sphinx/util/__init__.py +15 -11
- sphinx/util/_io.py +34 -0
- sphinx/util/_pathlib.py +23 -18
- sphinx/util/build_phase.py +1 -0
- sphinx/util/cfamily.py +19 -11
- sphinx/util/console.py +101 -21
- sphinx/util/display.py +3 -2
- sphinx/util/docfields.py +12 -8
- sphinx/util/docutils.py +21 -35
- sphinx/util/exceptions.py +3 -2
- sphinx/util/fileutil.py +5 -5
- sphinx/util/http_date.py +9 -2
- sphinx/util/i18n.py +40 -9
- sphinx/util/inspect.py +317 -245
- sphinx/util/inventory.py +22 -5
- sphinx/util/logging.py +81 -7
- sphinx/util/matching.py +2 -1
- sphinx/util/math.py +1 -2
- sphinx/util/nodes.py +39 -29
- sphinx/util/osutil.py +25 -6
- sphinx/util/parallel.py +6 -1
- sphinx/util/requests.py +8 -5
- sphinx/util/rst.py +8 -6
- sphinx/util/tags.py +3 -3
- sphinx/util/template.py +8 -3
- sphinx/util/typing.py +76 -42
- sphinx/versioning.py +6 -2
- sphinx/writers/html.py +1 -1
- sphinx/writers/html5.py +17 -13
- sphinx/writers/latex.py +12 -12
- sphinx/writers/manpage.py +13 -7
- sphinx/writers/texinfo.py +13 -10
- sphinx/writers/text.py +13 -23
- sphinx/writers/xml.py +1 -1
- sphinx-7.2.6.dist-info/LICENSE → sphinx-7.3.0.dist-info/LICENSE.rst +1 -1
- {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/METADATA +13 -12
- sphinx-7.3.0.dist-info/RECORD +581 -0
- sphinx/domains/c.py +0 -3906
- sphinx/domains/cpp.py +0 -8233
- sphinx/domains/python.py +0 -1769
- sphinx/themes/agogo/theme.conf +0 -20
- sphinx/themes/basic/theme.conf +0 -16
- sphinx/themes/bizstyle/theme.conf +0 -10
- sphinx/themes/classic/theme.conf +0 -32
- sphinx/themes/default/theme.conf +0 -2
- sphinx/themes/epub/theme.conf +0 -8
- sphinx/themes/haiku/theme.conf +0 -14
- sphinx/themes/nature/theme.conf +0 -4
- sphinx/themes/nonav/theme.conf +0 -8
- sphinx/themes/pyramid/theme.conf +0 -4
- sphinx/themes/scrolls/theme.conf +0 -13
- sphinx/themes/sphinxdoc/theme.conf +0 -4
- sphinx/themes/traditional/theme.conf +0 -7
- sphinx-7.2.6.dist-info/RECORD +0 -569
- {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/WHEEL +0 -0
- {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/entry_points.txt +0 -0
sphinx/util/inventory.py
CHANGED
|
@@ -25,7 +25,7 @@ class InventoryFileReader:
|
|
|
25
25
|
This reader supports mixture of texts and compressed texts.
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
|
-
def __init__(self, stream: IO) -> None:
|
|
28
|
+
def __init__(self, stream: IO[bytes]) -> None:
|
|
29
29
|
self.stream = stream
|
|
30
30
|
self.buffer = b''
|
|
31
31
|
self.eof = False
|
|
@@ -77,7 +77,12 @@ class InventoryFileReader:
|
|
|
77
77
|
|
|
78
78
|
class InventoryFile:
|
|
79
79
|
@classmethod
|
|
80
|
-
def load(
|
|
80
|
+
def load(
|
|
81
|
+
cls: type[InventoryFile],
|
|
82
|
+
stream: IO[bytes],
|
|
83
|
+
uri: str,
|
|
84
|
+
joinfunc: Callable[[str, str], str],
|
|
85
|
+
) -> Inventory:
|
|
81
86
|
reader = InventoryFileReader(stream)
|
|
82
87
|
line = reader.readline().rstrip()
|
|
83
88
|
if line == '# Sphinx inventory version 1':
|
|
@@ -88,7 +93,12 @@ class InventoryFile:
|
|
|
88
93
|
raise ValueError('invalid inventory header: %s' % line)
|
|
89
94
|
|
|
90
95
|
@classmethod
|
|
91
|
-
def load_v1(
|
|
96
|
+
def load_v1(
|
|
97
|
+
cls: type[InventoryFile],
|
|
98
|
+
stream: InventoryFileReader,
|
|
99
|
+
uri: str,
|
|
100
|
+
join: Callable[[str, str], str],
|
|
101
|
+
) -> Inventory:
|
|
92
102
|
invdata: Inventory = {}
|
|
93
103
|
projname = stream.readline().rstrip()[11:]
|
|
94
104
|
version = stream.readline().rstrip()[11:]
|
|
@@ -106,7 +116,12 @@ class InventoryFile:
|
|
|
106
116
|
return invdata
|
|
107
117
|
|
|
108
118
|
@classmethod
|
|
109
|
-
def load_v2(
|
|
119
|
+
def load_v2(
|
|
120
|
+
cls: type[InventoryFile],
|
|
121
|
+
stream: InventoryFileReader,
|
|
122
|
+
uri: str,
|
|
123
|
+
join: Callable[[str, str], str],
|
|
124
|
+
) -> Inventory:
|
|
110
125
|
invdata: Inventory = {}
|
|
111
126
|
projname = stream.readline().rstrip()[11:]
|
|
112
127
|
version = stream.readline().rstrip()[11:]
|
|
@@ -140,7 +155,9 @@ class InventoryFile:
|
|
|
140
155
|
return invdata
|
|
141
156
|
|
|
142
157
|
@classmethod
|
|
143
|
-
def dump(
|
|
158
|
+
def dump(
|
|
159
|
+
cls: type[InventoryFile], filename: str, env: BuildEnvironment, builder: Builder,
|
|
160
|
+
) -> None:
|
|
144
161
|
def escape(string: str) -> str:
|
|
145
162
|
return re.sub("\\s+", " ", string)
|
|
146
163
|
|
sphinx/util/logging.py
CHANGED
|
@@ -16,7 +16,7 @@ from sphinx.util.console import colorize
|
|
|
16
16
|
from sphinx.util.osutil import abspath
|
|
17
17
|
|
|
18
18
|
if TYPE_CHECKING:
|
|
19
|
-
from collections.abc import
|
|
19
|
+
from collections.abc import Iterator
|
|
20
20
|
|
|
21
21
|
from docutils.nodes import Node
|
|
22
22
|
|
|
@@ -85,6 +85,7 @@ def convert_serializable(records: list[logging.LogRecord]) -> None:
|
|
|
85
85
|
|
|
86
86
|
class SphinxLogRecord(logging.LogRecord):
|
|
87
87
|
"""Log record class supporting location"""
|
|
88
|
+
|
|
88
89
|
prefix = ''
|
|
89
90
|
location: Any = None
|
|
90
91
|
|
|
@@ -101,11 +102,13 @@ class SphinxLogRecord(logging.LogRecord):
|
|
|
101
102
|
|
|
102
103
|
class SphinxInfoLogRecord(SphinxLogRecord):
|
|
103
104
|
"""Info log record class supporting location"""
|
|
105
|
+
|
|
104
106
|
prefix = '' # do not show any prefix for INFO messages
|
|
105
107
|
|
|
106
108
|
|
|
107
109
|
class SphinxWarningLogRecord(SphinxLogRecord):
|
|
108
110
|
"""Warning log record class supporting location"""
|
|
111
|
+
|
|
109
112
|
@property
|
|
110
113
|
def prefix(self) -> str: # type: ignore[override]
|
|
111
114
|
if self.levelno >= logging.CRITICAL:
|
|
@@ -118,6 +121,7 @@ class SphinxWarningLogRecord(SphinxLogRecord):
|
|
|
118
121
|
|
|
119
122
|
class SphinxLoggerAdapter(logging.LoggerAdapter):
|
|
120
123
|
"""LoggerAdapter allowing ``type`` and ``subtype`` keywords."""
|
|
124
|
+
|
|
121
125
|
KEYWORDS = ['type', 'subtype', 'location', 'nonl', 'color', 'once']
|
|
122
126
|
|
|
123
127
|
def log( # type: ignore[override]
|
|
@@ -143,9 +147,56 @@ class SphinxLoggerAdapter(logging.LoggerAdapter):
|
|
|
143
147
|
def handle(self, record: logging.LogRecord) -> None:
|
|
144
148
|
self.logger.handle(record)
|
|
145
149
|
|
|
150
|
+
def warning( # type: ignore[override]
|
|
151
|
+
self,
|
|
152
|
+
msg: object,
|
|
153
|
+
*args: object,
|
|
154
|
+
type: None | str = None,
|
|
155
|
+
subtype: None | str = None,
|
|
156
|
+
location: None | str | tuple[str | None, int | None] | Node = None,
|
|
157
|
+
nonl: bool = True,
|
|
158
|
+
color: str | None = None,
|
|
159
|
+
once: bool = False,
|
|
160
|
+
**kwargs: Any,
|
|
161
|
+
) -> None:
|
|
162
|
+
"""Log a sphinx warning.
|
|
163
|
+
|
|
164
|
+
It is recommended to include a ``type`` and ``subtype`` for warnings as
|
|
165
|
+
these can be displayed to the user using :confval:`show_warning_types`
|
|
166
|
+
and used in :confval:`suppress_warnings` to suppress specific warnings.
|
|
167
|
+
|
|
168
|
+
It is also recommended to specify a ``location`` whenever possible
|
|
169
|
+
to help users in correcting the warning.
|
|
170
|
+
|
|
171
|
+
:param msg: The message, which may contain placeholders for ``args``.
|
|
172
|
+
:param args: The arguments to substitute into ``msg``.
|
|
173
|
+
:param type: The type of the warning.
|
|
174
|
+
:param subtype: The subtype of the warning.
|
|
175
|
+
:param location: The source location of the warning's origin,
|
|
176
|
+
which can be a string (the ``docname`` or ``docname:lineno``),
|
|
177
|
+
a tuple of ``(docname, lineno)``,
|
|
178
|
+
or the docutils node object.
|
|
179
|
+
:param nonl: Whether to append a new line terminator to the message.
|
|
180
|
+
:param color: A color code for the message.
|
|
181
|
+
:param once: Do not log this warning,
|
|
182
|
+
if a previous warning already has same ``msg``, ``args`` and ``once=True``.
|
|
183
|
+
"""
|
|
184
|
+
return super().warning(
|
|
185
|
+
msg,
|
|
186
|
+
*args,
|
|
187
|
+
type=type,
|
|
188
|
+
subtype=subtype,
|
|
189
|
+
location=location,
|
|
190
|
+
nonl=nonl,
|
|
191
|
+
color=color,
|
|
192
|
+
once=once,
|
|
193
|
+
**kwargs,
|
|
194
|
+
)
|
|
195
|
+
|
|
146
196
|
|
|
147
197
|
class WarningStreamHandler(logging.StreamHandler):
|
|
148
198
|
"""StreamHandler for warnings."""
|
|
199
|
+
|
|
149
200
|
pass
|
|
150
201
|
|
|
151
202
|
|
|
@@ -195,7 +246,7 @@ class MemoryHandler(logging.handlers.BufferingHandler):
|
|
|
195
246
|
|
|
196
247
|
|
|
197
248
|
@contextmanager
|
|
198
|
-
def pending_warnings() ->
|
|
249
|
+
def pending_warnings() -> Iterator[logging.Handler]:
|
|
199
250
|
"""Context manager to postpone logging warnings temporarily.
|
|
200
251
|
|
|
201
252
|
Similar to :func:`pending_logging`.
|
|
@@ -223,7 +274,7 @@ def pending_warnings() -> Generator[logging.Handler, None, None]:
|
|
|
223
274
|
|
|
224
275
|
|
|
225
276
|
@contextmanager
|
|
226
|
-
def suppress_logging() ->
|
|
277
|
+
def suppress_logging() -> Iterator[MemoryHandler]:
|
|
227
278
|
"""Context manager to suppress logging all logs temporarily.
|
|
228
279
|
|
|
229
280
|
For example::
|
|
@@ -252,7 +303,7 @@ def suppress_logging() -> Generator[MemoryHandler, None, None]:
|
|
|
252
303
|
|
|
253
304
|
|
|
254
305
|
@contextmanager
|
|
255
|
-
def pending_logging() ->
|
|
306
|
+
def pending_logging() -> Iterator[MemoryHandler]:
|
|
256
307
|
"""Context manager to postpone logging all logs temporarily.
|
|
257
308
|
|
|
258
309
|
For example::
|
|
@@ -272,7 +323,7 @@ def pending_logging() -> Generator[MemoryHandler, None, None]:
|
|
|
272
323
|
|
|
273
324
|
|
|
274
325
|
@contextmanager
|
|
275
|
-
def skip_warningiserror(skip: bool = True) ->
|
|
326
|
+
def skip_warningiserror(skip: bool = True) -> Iterator[None]:
|
|
276
327
|
"""Context manager to skip WarningIsErrorFilter temporarily."""
|
|
277
328
|
logger = logging.getLogger(NAMESPACE)
|
|
278
329
|
|
|
@@ -292,7 +343,7 @@ def skip_warningiserror(skip: bool = True) -> Generator[None, None, None]:
|
|
|
292
343
|
|
|
293
344
|
|
|
294
345
|
@contextmanager
|
|
295
|
-
def prefixed_warnings(prefix: str) ->
|
|
346
|
+
def prefixed_warnings(prefix: str) -> Iterator[None]:
|
|
296
347
|
"""Context manager to prepend prefix to all warning log records temporarily.
|
|
297
348
|
|
|
298
349
|
For example::
|
|
@@ -342,7 +393,7 @@ class LogCollector:
|
|
|
342
393
|
self.logs: list[logging.LogRecord] = []
|
|
343
394
|
|
|
344
395
|
@contextmanager
|
|
345
|
-
def collect(self) ->
|
|
396
|
+
def collect(self) -> Iterator[None]:
|
|
346
397
|
with pending_logging() as memhandler:
|
|
347
398
|
yield
|
|
348
399
|
|
|
@@ -475,7 +526,9 @@ class SphinxLogRecordTranslator(logging.Filter):
|
|
|
475
526
|
|
|
476
527
|
* Make a instance of SphinxLogRecord
|
|
477
528
|
* docname to path if location given
|
|
529
|
+
* append warning type/subtype to message if :confval:`show_warning_types` is ``True``
|
|
478
530
|
"""
|
|
531
|
+
|
|
479
532
|
LogRecordClass: type[logging.LogRecord]
|
|
480
533
|
|
|
481
534
|
def __init__(self, app: Sphinx) -> None:
|
|
@@ -507,13 +560,32 @@ class SphinxLogRecordTranslator(logging.Filter):
|
|
|
507
560
|
|
|
508
561
|
class InfoLogRecordTranslator(SphinxLogRecordTranslator):
|
|
509
562
|
"""LogRecordTranslator for INFO level log records."""
|
|
563
|
+
|
|
510
564
|
LogRecordClass = SphinxInfoLogRecord
|
|
511
565
|
|
|
512
566
|
|
|
513
567
|
class WarningLogRecordTranslator(SphinxLogRecordTranslator):
|
|
514
568
|
"""LogRecordTranslator for WARNING level log records."""
|
|
569
|
+
|
|
515
570
|
LogRecordClass = SphinxWarningLogRecord
|
|
516
571
|
|
|
572
|
+
def filter(self, record: SphinxWarningLogRecord) -> bool: # type: ignore[override]
|
|
573
|
+
ret = super().filter(record)
|
|
574
|
+
|
|
575
|
+
try:
|
|
576
|
+
show_warning_types = self.app.config.show_warning_types
|
|
577
|
+
except AttributeError:
|
|
578
|
+
# config is not initialized yet (ex. in conf.py)
|
|
579
|
+
show_warning_types = False
|
|
580
|
+
if show_warning_types:
|
|
581
|
+
if log_type := getattr(record, 'type', ''):
|
|
582
|
+
if log_subtype := getattr(record, 'subtype', ''):
|
|
583
|
+
record.msg += f' [{log_type}.{log_subtype}]'
|
|
584
|
+
else:
|
|
585
|
+
record.msg += f' [{log_type}]'
|
|
586
|
+
|
|
587
|
+
return ret
|
|
588
|
+
|
|
517
589
|
|
|
518
590
|
def get_node_location(node: Node) -> str | None:
|
|
519
591
|
source, line = get_source_line(node)
|
|
@@ -543,6 +615,7 @@ class ColorizeFormatter(logging.Formatter):
|
|
|
543
615
|
|
|
544
616
|
class SafeEncodingWriter:
|
|
545
617
|
"""Stream writer which ignores UnicodeEncodeError silently"""
|
|
618
|
+
|
|
546
619
|
def __init__(self, stream: IO) -> None:
|
|
547
620
|
self.stream = stream
|
|
548
621
|
self.encoding = getattr(stream, 'encoding', 'ascii') or 'ascii'
|
|
@@ -562,6 +635,7 @@ class SafeEncodingWriter:
|
|
|
562
635
|
|
|
563
636
|
class LastMessagesWriter:
|
|
564
637
|
"""Stream writer storing last 10 messages in memory to save trackback"""
|
|
638
|
+
|
|
565
639
|
def __init__(self, app: Sphinx, stream: IO) -> None:
|
|
566
640
|
self.app = app
|
|
567
641
|
|
sphinx/util/matching.py
CHANGED
|
@@ -91,7 +91,8 @@ _pat_cache: dict[str, re.Pattern[str]] = {}
|
|
|
91
91
|
|
|
92
92
|
def patmatch(name: str, pat: str) -> re.Match[str] | None:
|
|
93
93
|
"""Return if name matches the regular expression (pattern)
|
|
94
|
-
``pat```. Adapted from fnmatch module.
|
|
94
|
+
``pat```. Adapted from fnmatch module.
|
|
95
|
+
"""
|
|
95
96
|
if pat not in _pat_cache:
|
|
96
97
|
_pat_cache[pat] = re.compile(_translate_pattern(pat))
|
|
97
98
|
return _pat_cache[pat].match(name)
|
sphinx/util/math.py
CHANGED
|
@@ -54,8 +54,7 @@ def wrap_displaymath(text: str, label: str | None, numbering: bool) -> str:
|
|
|
54
54
|
else:
|
|
55
55
|
begin = r'\begin{align*}%s\!\begin{aligned}' % labeldef
|
|
56
56
|
end = r'\end{aligned}\end{align*}'
|
|
57
|
-
for part in parts
|
|
58
|
-
equations.append('%s\\\\\n' % part.strip())
|
|
57
|
+
equations.extend('%s\\\\\n' % part.strip() for part in parts)
|
|
59
58
|
|
|
60
59
|
concatenated_equations = ''.join(equations)
|
|
61
60
|
return f'{begin}\n{concatenated_equations}{end}'
|
sphinx/util/nodes.py
CHANGED
|
@@ -5,18 +5,19 @@ from __future__ import annotations
|
|
|
5
5
|
import contextlib
|
|
6
6
|
import re
|
|
7
7
|
import unicodedata
|
|
8
|
-
from typing import TYPE_CHECKING, Any, Callable
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar, cast
|
|
9
9
|
|
|
10
10
|
from docutils import nodes
|
|
11
|
+
from docutils.nodes import Node
|
|
11
12
|
|
|
12
13
|
from sphinx import addnodes
|
|
13
14
|
from sphinx.locale import __
|
|
14
15
|
from sphinx.util import logging
|
|
15
16
|
|
|
16
17
|
if TYPE_CHECKING:
|
|
17
|
-
from collections.abc import Iterable
|
|
18
|
+
from collections.abc import Iterable, Iterator
|
|
18
19
|
|
|
19
|
-
from docutils.nodes import Element
|
|
20
|
+
from docutils.nodes import Element
|
|
20
21
|
from docutils.parsers.rst import Directive
|
|
21
22
|
from docutils.parsers.rst.states import Inliner
|
|
22
23
|
from docutils.statemachine import StringList
|
|
@@ -33,7 +34,10 @@ explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<([^<]*?)>$', re.DOTALL)
|
|
|
33
34
|
caption_ref_re = explicit_title_re # b/w compat alias
|
|
34
35
|
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
N = TypeVar("N", bound=Node)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class NodeMatcher(Generic[N]):
|
|
37
41
|
"""A helper class for Node.findall().
|
|
38
42
|
|
|
39
43
|
It checks that the given node is an instance of the specified node-classes and
|
|
@@ -43,20 +47,18 @@ class NodeMatcher:
|
|
|
43
47
|
and ``reftype`` attributes::
|
|
44
48
|
|
|
45
49
|
matcher = NodeMatcher(nodes.reference, refdomain='std', reftype='citation')
|
|
46
|
-
|
|
50
|
+
matcher.findall(doctree)
|
|
47
51
|
# => [<reference ...>, <reference ...>, ...]
|
|
48
52
|
|
|
49
53
|
A special value ``typing.Any`` matches any kind of node-attributes. For example,
|
|
50
54
|
following example searches ``reference`` node having ``refdomain`` attributes::
|
|
51
55
|
|
|
52
|
-
from __future__ import annotations
|
|
53
|
-
from typing import TYPE_CHECKING, Any
|
|
54
56
|
matcher = NodeMatcher(nodes.reference, refdomain=Any)
|
|
55
|
-
|
|
57
|
+
matcher.findall(doctree)
|
|
56
58
|
# => [<reference ...>, <reference ...>, ...]
|
|
57
59
|
"""
|
|
58
60
|
|
|
59
|
-
def __init__(self, *node_classes: type[
|
|
61
|
+
def __init__(self, *node_classes: type[N], **attrs: Any) -> None:
|
|
60
62
|
self.classes = node_classes
|
|
61
63
|
self.attrs = attrs
|
|
62
64
|
|
|
@@ -85,6 +87,15 @@ from typing import TYPE_CHECKING, Any
|
|
|
85
87
|
def __call__(self, node: Node) -> bool:
|
|
86
88
|
return self.match(node)
|
|
87
89
|
|
|
90
|
+
def findall(self, node: Node) -> Iterator[N]:
|
|
91
|
+
"""An alternative to `Node.findall` with improved type safety.
|
|
92
|
+
|
|
93
|
+
While the `NodeMatcher` object can be used as an argument to `Node.findall`, doing so
|
|
94
|
+
confounds type checkers' ability to determine the return type of the iterator.
|
|
95
|
+
"""
|
|
96
|
+
for found in node.findall(self):
|
|
97
|
+
yield cast(N, found)
|
|
98
|
+
|
|
88
99
|
|
|
89
100
|
def get_full_module_name(node: Node) -> str:
|
|
90
101
|
"""
|
|
@@ -99,7 +110,7 @@ def get_full_module_name(node: Node) -> str:
|
|
|
99
110
|
def repr_domxml(node: Node, length: int = 80) -> str:
|
|
100
111
|
"""
|
|
101
112
|
return DOM XML representation of the specified node like:
|
|
102
|
-
'<paragraph translatable="False"><inline classes="
|
|
113
|
+
'<paragraph translatable="False"><inline classes="versionadded">Added in version...'
|
|
103
114
|
|
|
104
115
|
:param nodes.Node node: target node
|
|
105
116
|
:param int length:
|
|
@@ -127,7 +138,7 @@ def apply_source_workaround(node: Element) -> None:
|
|
|
127
138
|
get_full_module_name(node), repr_domxml(node))
|
|
128
139
|
definition_list_item = node.parent
|
|
129
140
|
node.source = definition_list_item.source
|
|
130
|
-
node.line = definition_list_item.line - 1
|
|
141
|
+
node.line = definition_list_item.line - 1 # type: ignore[operator]
|
|
131
142
|
node.rawsource = node.astext() # set 'classifier1' (or 'classifier2')
|
|
132
143
|
elif isinstance(node, nodes.classifier) and not node.source:
|
|
133
144
|
# docutils-0.15 fills in rawsource attribute, but not in source.
|
|
@@ -220,16 +231,13 @@ def is_translatable(node: Node) -> bool:
|
|
|
220
231
|
return False
|
|
221
232
|
# <field_name>orphan</field_name>
|
|
222
233
|
# XXX ignore all metadata (== docinfo)
|
|
223
|
-
if isinstance(node, nodes.field_name) and node.children[0] == 'orphan':
|
|
234
|
+
if isinstance(node, nodes.field_name) and (node.children[0] == 'orphan'):
|
|
224
235
|
logger.debug('[i18n] SKIP %r because orphan node: %s',
|
|
225
236
|
get_full_module_name(node), repr_domxml(node))
|
|
226
237
|
return False
|
|
227
238
|
return True
|
|
228
239
|
|
|
229
|
-
|
|
230
|
-
return True
|
|
231
|
-
|
|
232
|
-
return False
|
|
240
|
+
return isinstance(node, nodes.meta)
|
|
233
241
|
|
|
234
242
|
|
|
235
243
|
LITERAL_TYPE_NODES = (
|
|
@@ -245,10 +253,10 @@ IMAGE_TYPE_NODES = (
|
|
|
245
253
|
|
|
246
254
|
def extract_messages(doctree: Element) -> Iterable[tuple[Element, str]]:
|
|
247
255
|
"""Extract translatable messages from a document tree."""
|
|
248
|
-
for node in doctree.findall(is_translatable):
|
|
256
|
+
for node in doctree.findall(is_translatable):
|
|
249
257
|
if isinstance(node, addnodes.translatable):
|
|
250
258
|
for msg in node.extract_original_messages():
|
|
251
|
-
yield node, msg
|
|
259
|
+
yield node, msg # type: ignore[misc]
|
|
252
260
|
continue
|
|
253
261
|
if isinstance(node, LITERAL_TYPE_NODES):
|
|
254
262
|
msg = node.rawsource
|
|
@@ -262,14 +270,14 @@ def extract_messages(doctree: Element) -> Iterable[tuple[Element, str]]:
|
|
|
262
270
|
msg = f'.. image:: {image_uri}'
|
|
263
271
|
else:
|
|
264
272
|
msg = ''
|
|
265
|
-
elif isinstance(node, nodes.meta):
|
|
273
|
+
elif isinstance(node, nodes.meta):
|
|
266
274
|
msg = node["content"]
|
|
267
275
|
else:
|
|
268
|
-
msg = node.rawsource.replace('\n', ' ').strip()
|
|
276
|
+
msg = node.rawsource.replace('\n', ' ').strip() # type: ignore[attr-defined]
|
|
269
277
|
|
|
270
278
|
# XXX nodes rendering empty are likely a bug in sphinx.addnodes
|
|
271
279
|
if msg:
|
|
272
|
-
yield node, msg
|
|
280
|
+
yield node, msg # type: ignore[misc]
|
|
273
281
|
|
|
274
282
|
|
|
275
283
|
def get_node_source(node: Element) -> str:
|
|
@@ -308,7 +316,7 @@ def traverse_translatable_index(
|
|
|
308
316
|
) -> Iterable[tuple[Element, list[tuple[str, str, str, str, str | None]]]]:
|
|
309
317
|
"""Traverse translatable index node from a document tree."""
|
|
310
318
|
matcher = NodeMatcher(addnodes.index, inline=False)
|
|
311
|
-
for node in
|
|
319
|
+
for node in matcher.findall(doctree):
|
|
312
320
|
if 'raw_entries' in node:
|
|
313
321
|
entries = node['raw_entries']
|
|
314
322
|
else:
|
|
@@ -402,9 +410,14 @@ def process_index_entry(entry: str, targetid: str,
|
|
|
402
410
|
return indexentries
|
|
403
411
|
|
|
404
412
|
|
|
405
|
-
def inline_all_toctrees(
|
|
406
|
-
|
|
407
|
-
|
|
413
|
+
def inline_all_toctrees(
|
|
414
|
+
builder: Builder,
|
|
415
|
+
docnameset: set[str],
|
|
416
|
+
docname: str,
|
|
417
|
+
tree: nodes.document,
|
|
418
|
+
colorfunc: Callable[[str], str],
|
|
419
|
+
traversed: list[str],
|
|
420
|
+
) -> nodes.document:
|
|
408
421
|
"""Inline all toctrees in the *tree*.
|
|
409
422
|
|
|
410
423
|
Record all docnames in *docnameset*, and output docnames with *colorfunc*.
|
|
@@ -599,10 +612,7 @@ def is_smartquotable(node: Node) -> bool:
|
|
|
599
612
|
if pnode.get('support_smartquotes', None) is False:
|
|
600
613
|
return False
|
|
601
614
|
|
|
602
|
-
|
|
603
|
-
return False
|
|
604
|
-
|
|
605
|
-
return True
|
|
615
|
+
return getattr(node, 'support_smartquotes', None) is not False
|
|
606
616
|
|
|
607
617
|
|
|
608
618
|
def process_only_nodes(document: Node, tags: Tags) -> None:
|
sphinx/util/osutil.py
CHANGED
|
@@ -11,12 +11,14 @@ import sys
|
|
|
11
11
|
import unicodedata
|
|
12
12
|
from io import StringIO
|
|
13
13
|
from os import path
|
|
14
|
-
from typing import TYPE_CHECKING
|
|
14
|
+
from typing import TYPE_CHECKING
|
|
15
15
|
|
|
16
16
|
from sphinx.deprecation import _deprecation_warning
|
|
17
17
|
|
|
18
18
|
if TYPE_CHECKING:
|
|
19
19
|
from collections.abc import Iterator
|
|
20
|
+
from types import TracebackType
|
|
21
|
+
from typing import Any
|
|
20
22
|
|
|
21
23
|
# SEP separates path elements in the canonical file names
|
|
22
24
|
#
|
|
@@ -36,7 +38,7 @@ def canon_path(native_path: str | os.PathLike[str], /) -> str:
|
|
|
36
38
|
|
|
37
39
|
|
|
38
40
|
def path_stabilize(filepath: str | os.PathLike[str], /) -> str:
|
|
39
|
-
"Normalize path separator and unicode string"
|
|
41
|
+
"""Normalize path separator and unicode string"""
|
|
40
42
|
new_path = canon_path(filepath)
|
|
41
43
|
return unicodedata.normalize('NFC', new_path)
|
|
42
44
|
|
|
@@ -88,7 +90,16 @@ def copytimes(source: str | os.PathLike[str], dest: str | os.PathLike[str]) -> N
|
|
|
88
90
|
def copyfile(source: str | os.PathLike[str], dest: str | os.PathLike[str]) -> None:
|
|
89
91
|
"""Copy a file and its modification times, if possible.
|
|
90
92
|
|
|
91
|
-
|
|
93
|
+
:param source: An existing source to copy.
|
|
94
|
+
:param dest: The destination path.
|
|
95
|
+
:raise FileNotFoundError: The *source* does not exist.
|
|
96
|
+
|
|
97
|
+
.. note:: :func:`copyfile` is a no-op if *source* and *dest* are identical.
|
|
98
|
+
"""
|
|
99
|
+
if not path.exists(source):
|
|
100
|
+
msg = f'{os.fsdecode(source)} does not exist'
|
|
101
|
+
raise FileNotFoundError(msg)
|
|
102
|
+
|
|
92
103
|
if not path.exists(dest) or not filecmp.cmp(source, dest):
|
|
93
104
|
shutil.copyfile(source, dest)
|
|
94
105
|
with contextlib.suppress(OSError):
|
|
@@ -131,15 +142,22 @@ abspath = path.abspath
|
|
|
131
142
|
|
|
132
143
|
class _chdir:
|
|
133
144
|
"""Remove this fall-back once support for Python 3.10 is removed."""
|
|
134
|
-
|
|
145
|
+
|
|
146
|
+
def __init__(self, target_dir: str, /) -> None:
|
|
135
147
|
self.path = target_dir
|
|
136
148
|
self._dirs: list[str] = []
|
|
137
149
|
|
|
138
|
-
def __enter__(self):
|
|
150
|
+
def __enter__(self) -> None:
|
|
139
151
|
self._dirs.append(os.getcwd())
|
|
140
152
|
os.chdir(self.path)
|
|
141
153
|
|
|
142
|
-
def __exit__(
|
|
154
|
+
def __exit__(
|
|
155
|
+
self,
|
|
156
|
+
type: type[BaseException] | None,
|
|
157
|
+
value: BaseException | None,
|
|
158
|
+
traceback: TracebackType | None,
|
|
159
|
+
/,
|
|
160
|
+
) -> None:
|
|
143
161
|
os.chdir(self._dirs.pop())
|
|
144
162
|
|
|
145
163
|
|
|
@@ -163,6 +181,7 @@ class FileAvoidWrite:
|
|
|
163
181
|
|
|
164
182
|
Objects can be used as context managers.
|
|
165
183
|
"""
|
|
184
|
+
|
|
166
185
|
def __init__(self, path: str) -> None:
|
|
167
186
|
self._path = path
|
|
168
187
|
self._io: StringIO | None = None
|
sphinx/util/parallel.py
CHANGED
|
@@ -94,7 +94,12 @@ class ParallelTasks:
|
|
|
94
94
|
proc = context.Process(target=self._process, args=(psend, task_func, arg))
|
|
95
95
|
self._procs[tid] = proc
|
|
96
96
|
self._precvsWaiting[tid] = precv
|
|
97
|
-
|
|
97
|
+
try:
|
|
98
|
+
self._join_one()
|
|
99
|
+
except Exception:
|
|
100
|
+
# shutdown other child processes on failure
|
|
101
|
+
# (e.g. OSError: Failed to allocate memory)
|
|
102
|
+
self.terminate()
|
|
98
103
|
|
|
99
104
|
def join(self) -> None:
|
|
100
105
|
try:
|
sphinx/util/requests.py
CHANGED
|
@@ -30,17 +30,19 @@ def _get_tls_cacert(url: str, certs: str | dict[str, str] | None) -> str | bool:
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def get(url: str, **kwargs: Any) -> requests.Response:
|
|
33
|
-
"""Sends a GET request like requests.get()
|
|
33
|
+
"""Sends a GET request like ``requests.get()``.
|
|
34
34
|
|
|
35
|
-
This sets up User-Agent header and TLS verification automatically.
|
|
35
|
+
This sets up User-Agent header and TLS verification automatically.
|
|
36
|
+
"""
|
|
36
37
|
with _Session() as session:
|
|
37
38
|
return session.get(url, **kwargs)
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
def head(url: str, **kwargs: Any) -> requests.Response:
|
|
41
|
-
"""Sends a HEAD request like requests.head()
|
|
42
|
+
"""Sends a HEAD request like ``requests.head()``.
|
|
42
43
|
|
|
43
|
-
This sets up User-Agent header and TLS verification automatically.
|
|
44
|
+
This sets up User-Agent header and TLS verification automatically.
|
|
45
|
+
"""
|
|
44
46
|
with _Session() as session:
|
|
45
47
|
return session.head(url, **kwargs)
|
|
46
48
|
|
|
@@ -54,7 +56,8 @@ class _Session(requests.Session):
|
|
|
54
56
|
) -> requests.Response:
|
|
55
57
|
"""Sends a request with an HTTP verb and url.
|
|
56
58
|
|
|
57
|
-
This sets up User-Agent header and TLS verification automatically.
|
|
59
|
+
This sets up User-Agent header and TLS verification automatically.
|
|
60
|
+
"""
|
|
58
61
|
headers = kwargs.setdefault('headers', {})
|
|
59
62
|
headers.setdefault('User-Agent', _user_agent or _USER_AGENT)
|
|
60
63
|
if _tls_info:
|
sphinx/util/rst.py
CHANGED
|
@@ -5,11 +5,11 @@ from __future__ import annotations
|
|
|
5
5
|
import re
|
|
6
6
|
from collections import defaultdict
|
|
7
7
|
from contextlib import contextmanager
|
|
8
|
-
from typing import TYPE_CHECKING
|
|
8
|
+
from typing import TYPE_CHECKING, cast
|
|
9
9
|
from unicodedata import east_asian_width
|
|
10
10
|
|
|
11
11
|
from docutils.parsers.rst import roles
|
|
12
|
-
from docutils.parsers.rst.languages import en as english
|
|
12
|
+
from docutils.parsers.rst.languages import en as english # type: ignore[attr-defined]
|
|
13
13
|
from docutils.parsers.rst.states import Body
|
|
14
14
|
from docutils.utils import Reporter
|
|
15
15
|
from jinja2 import Environment, pass_environment
|
|
@@ -18,7 +18,7 @@ from sphinx.locale import __
|
|
|
18
18
|
from sphinx.util import docutils, logging
|
|
19
19
|
|
|
20
20
|
if TYPE_CHECKING:
|
|
21
|
-
from collections.abc import
|
|
21
|
+
from collections.abc import Iterator
|
|
22
22
|
|
|
23
23
|
from docutils.statemachine import StringList
|
|
24
24
|
|
|
@@ -54,17 +54,18 @@ def textwidth(text: str, widechars: str = 'WF') -> int:
|
|
|
54
54
|
def heading(env: Environment, text: str, level: int = 1) -> str:
|
|
55
55
|
"""Create a heading for *level*."""
|
|
56
56
|
assert level <= 3
|
|
57
|
-
|
|
57
|
+
# ``env.language`` is injected by ``sphinx.util.template.ReSTRenderer``
|
|
58
|
+
width = textwidth(text, WIDECHARS[env.language]) # type: ignore[attr-defined]
|
|
58
59
|
sectioning_char = SECTIONING_CHARS[level - 1]
|
|
59
60
|
return f'{text}\n{sectioning_char * width}'
|
|
60
61
|
|
|
61
62
|
|
|
62
63
|
@contextmanager
|
|
63
|
-
def default_role(docname: str, name: str) ->
|
|
64
|
+
def default_role(docname: str, name: str) -> Iterator[None]:
|
|
64
65
|
if name:
|
|
65
66
|
dummy_reporter = Reporter('', 4, 4)
|
|
66
67
|
role_fn, _ = roles.role(name, english, 0, dummy_reporter)
|
|
67
|
-
if role_fn:
|
|
68
|
+
if role_fn:
|
|
68
69
|
docutils.register_role('', role_fn) # type: ignore[arg-type]
|
|
69
70
|
else:
|
|
70
71
|
logger.warning(__('default role %s not found'), name, location=docname)
|
|
@@ -102,6 +103,7 @@ def append_epilog(content: StringList, epilog: str) -> None:
|
|
|
102
103
|
if epilog:
|
|
103
104
|
if len(content) > 0:
|
|
104
105
|
source, lineno = content.info(-1)
|
|
106
|
+
lineno = cast(int, lineno) # lineno will never be None, since len(content) > 0
|
|
105
107
|
else:
|
|
106
108
|
source = '<generated>'
|
|
107
109
|
lineno = 0
|
sphinx/util/tags.py
CHANGED
|
@@ -20,8 +20,8 @@ class BooleanParser(Parser):
|
|
|
20
20
|
Only allow condition exprs and/or/not operations.
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
|
-
def parse_compare(self) ->
|
|
24
|
-
node:
|
|
23
|
+
def parse_compare(self) -> nodes.Expr:
|
|
24
|
+
node: nodes.Expr
|
|
25
25
|
token = self.stream.current
|
|
26
26
|
if token.type == 'name':
|
|
27
27
|
if token.value in ('true', 'false', 'True', 'False'):
|
|
@@ -67,7 +67,7 @@ class Tags:
|
|
|
67
67
|
msg = 'chunk after expression'
|
|
68
68
|
raise ValueError(msg)
|
|
69
69
|
|
|
70
|
-
def eval_node(node: Node) -> bool:
|
|
70
|
+
def eval_node(node: Node | None) -> bool:
|
|
71
71
|
if isinstance(node, nodes.CondExpr):
|
|
72
72
|
if eval_node(node.test):
|
|
73
73
|
return eval_node(node.expr1)
|