Sphinx 7.3.7__py3-none-any.whl → 7.4.1__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 +5 -6
- sphinx/_cli/__init__.py +296 -0
- sphinx/_cli/util/__init__.py +0 -0
- sphinx/_cli/util/colour.py +103 -0
- sphinx/_cli/util/errors.py +165 -0
- sphinx/application.py +78 -43
- sphinx/builders/__init__.py +59 -15
- sphinx/builders/_epub_base.py +11 -5
- sphinx/builders/changes.py +2 -2
- sphinx/builders/epub3.py +2 -2
- sphinx/builders/gettext.py +10 -10
- sphinx/builders/html/__init__.py +56 -54
- sphinx/builders/latex/__init__.py +5 -5
- sphinx/builders/latex/constants.py +5 -0
- sphinx/builders/linkcheck.py +73 -38
- sphinx/builders/texinfo.py +1 -1
- sphinx/cmd/build.py +1 -1
- sphinx/cmd/quickstart.py +11 -11
- sphinx/config.py +57 -38
- sphinx/directives/__init__.py +7 -9
- sphinx/directives/code.py +12 -15
- sphinx/directives/other.py +12 -15
- sphinx/directives/patches.py +26 -0
- sphinx/domains/__init__.py +1 -1
- sphinx/domains/c/__init__.py +5 -5
- sphinx/domains/c/_ast.py +436 -12
- sphinx/domains/c/_symbol.py +89 -134
- sphinx/domains/changeset.py +3 -4
- sphinx/domains/cpp/__init__.py +5 -6
- sphinx/domains/cpp/_ast.py +822 -25
- sphinx/domains/cpp/_symbol.py +3 -0
- sphinx/domains/javascript.py +3 -6
- sphinx/domains/math.py +3 -2
- sphinx/domains/python/__init__.py +44 -6
- sphinx/domains/python/_object.py +7 -5
- sphinx/domains/rst.py +2 -2
- sphinx/domains/std/__init__.py +95 -14
- sphinx/environment/__init__.py +35 -15
- sphinx/environment/adapters/indexentries.py +71 -24
- sphinx/environment/adapters/toctree.py +1 -1
- sphinx/environment/collectors/__init__.py +18 -4
- sphinx/environment/collectors/asset.py +4 -4
- sphinx/environment/collectors/toctree.py +27 -14
- sphinx/events.py +7 -6
- sphinx/ext/apidoc.py +377 -170
- sphinx/ext/autodoc/__init__.py +13 -13
- sphinx/ext/autodoc/directive.py +10 -13
- sphinx/ext/autodoc/mock.py +10 -7
- sphinx/ext/autodoc/preserve_defaults.py +1 -1
- sphinx/ext/autodoc/typehints.py +2 -2
- sphinx/ext/autosummary/__init__.py +15 -9
- sphinx/ext/autosummary/generate.py +270 -154
- sphinx/ext/coverage.py +108 -18
- sphinx/ext/duration.py +10 -3
- sphinx/ext/extlinks.py +3 -2
- sphinx/ext/graphviz.py +3 -3
- sphinx/ext/ifconfig.py +1 -2
- sphinx/ext/imgconverter.py +1 -0
- sphinx/ext/imgmath.py +7 -6
- sphinx/ext/inheritance_diagram.py +3 -3
- sphinx/ext/intersphinx/__init__.py +81 -0
- sphinx/ext/intersphinx/__main__.py +10 -0
- sphinx/ext/intersphinx/_cli.py +44 -0
- sphinx/ext/intersphinx/_load.py +253 -0
- sphinx/ext/{intersphinx.py → intersphinx/_resolve.py} +17 -368
- sphinx/ext/intersphinx/_shared.py +53 -0
- sphinx/ext/mathjax.py +1 -1
- sphinx/ext/todo.py +2 -2
- sphinx/io.py +2 -6
- sphinx/locale/__init__.py +1 -5
- sphinx/locale/ar/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +678 -471
- sphinx/locale/bg/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +684 -476
- sphinx/locale/bn/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +679 -472
- sphinx/locale/ca/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +681 -474
- sphinx/locale/cak/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +678 -471
- sphinx/locale/cs/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +679 -472
- sphinx/locale/cy/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +679 -472
- sphinx/locale/da/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +679 -472
- sphinx/locale/de/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +679 -472
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +678 -471
- sphinx/locale/el/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/eo/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/es/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/et/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/eu/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/fa/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/fi/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +700 -493
- 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 +725 -518
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/gl/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +701 -494
- 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 +700 -493
- sphinx/locale/hi/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/hr/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/hu/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/id/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/is/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/it/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +708 -500
- sphinx/locale/ja/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/ka/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/ko/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/lt/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/lv/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/mk/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/ne/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/nl/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/pl/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/pt/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +705 -498
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/ro/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/ru/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +890 -680
- sphinx/locale/si/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/sk/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/sl/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/sphinx.pot +702 -494
- 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 +704 -497
- sphinx/locale/sr/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +700 -493
- 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.js +1 -1
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/ta/LC_MESSAGES/sphinx.po +1016 -808
- sphinx/locale/te/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/tr/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/ur/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/vi/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/yue/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +704 -496
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +700 -493
- 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 +729 -522
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +700 -493
- sphinx/roles.py +1 -1
- sphinx/search/__init__.py +17 -9
- sphinx/templates/quickstart/{root_doc.rst_t → root_doc.rst.jinja} +7 -10
- sphinx/testing/fixtures.py +22 -20
- sphinx/testing/path.py +6 -2
- sphinx/testing/util.py +8 -13
- sphinx/texinputs/sphinx.sty +449 -332
- sphinx/texinputs/sphinxlatexadmonitions.sty +209 -66
- sphinx/texinputs/sphinxlatexliterals.sty +9 -16
- sphinx/texinputs/sphinxlatexstyletext.sty +4 -38
- sphinx/texinputs/sphinxlatextables.sty +6 -14
- sphinx/texinputs/sphinxpackageboxes.sty +15 -42
- sphinx/texinputs/sphinxpackagefootnote.sty +4 -3
- sphinx/themes/agogo/layout.html +3 -3
- sphinx/themes/basic/genindex-single.html +2 -1
- sphinx/themes/basic/layout.html +3 -6
- sphinx/themes/basic/static/searchtools.js +4 -3
- sphinx/themes/haiku/layout.html +4 -4
- sphinx/themes/pyramid/layout.html +1 -1
- sphinx/themes/scrolls/layout.html +2 -2
- sphinx/theming.py +3 -3
- sphinx/transforms/__init__.py +34 -20
- sphinx/transforms/i18n.py +8 -7
- sphinx/transforms/post_transforms/__init__.py +1 -1
- sphinx/transforms/post_transforms/images.py +7 -10
- sphinx/util/_pathlib.py +2 -2
- sphinx/util/cfamily.py +52 -30
- sphinx/util/console.py +1 -1
- sphinx/util/display.py +16 -11
- sphinx/util/docutils.py +88 -40
- sphinx/util/fileutil.py +15 -3
- sphinx/util/images.py +1 -0
- sphinx/util/inspect.py +66 -22
- sphinx/util/inventory.py +15 -0
- sphinx/util/logging.py +14 -21
- sphinx/util/math.py +3 -1
- sphinx/util/nodes.py +9 -12
- sphinx/util/osutil.py +5 -5
- sphinx/util/parsing.py +93 -0
- sphinx/util/tags.py +71 -47
- sphinx/util/typing.py +265 -143
- sphinx/versioning.py +17 -17
- sphinx/writers/html5.py +26 -19
- sphinx/writers/latex.py +60 -30
- sphinx/writers/manpage.py +4 -3
- sphinx/writers/texinfo.py +19 -14
- {sphinx-7.3.7.dist-info → sphinx-7.4.1.dist-info}/METADATA +21 -20
- sphinx-7.4.1.dist-info/RECORD +591 -0
- sphinx-7.3.7.dist-info/RECORD +0 -581
- /sphinx/templates/apidoc/{module.rst_t → module.rst.jinja} +0 -0
- /sphinx/templates/apidoc/{package.rst_t → package.rst.jinja} +0 -0
- /sphinx/templates/apidoc/{toc.rst_t → toc.rst.jinja} +0 -0
- /sphinx/templates/epub3/{content.opf_t → content.opf.jinja} +0 -0
- /sphinx/templates/epub3/{nav.xhtml_t → nav.xhtml.jinja} +0 -0
- /sphinx/templates/epub3/{toc.ncx_t → toc.ncx.jinja} +0 -0
- /sphinx/templates/gettext/{message.pot_t → message.pot.jinja} +0 -0
- /sphinx/templates/imgmath/{preview.tex_t → preview.tex.jinja} +0 -0
- /sphinx/templates/imgmath/{template.tex_t → template.tex.jinja} +0 -0
- /sphinx/templates/latex/{latex.tex_t → latex.tex.jinja} +0 -0
- /sphinx/templates/latex/{longtable.tex_t → longtable.tex.jinja} +0 -0
- /sphinx/templates/latex/{sphinxmessages.sty_t → sphinxmessages.sty.jinja} +0 -0
- /sphinx/templates/latex/{tabular.tex_t → tabular.tex.jinja} +0 -0
- /sphinx/templates/latex/{tabulary.tex_t → tabulary.tex.jinja} +0 -0
- /sphinx/templates/quickstart/{Makefile_t → Makefile.jinja} +0 -0
- /sphinx/templates/quickstart/{Makefile.new_t → Makefile.new.jinja} +0 -0
- /sphinx/templates/quickstart/{conf.py_t → conf.py.jinja} +0 -0
- /sphinx/templates/quickstart/{make.bat_t → make.bat.jinja} +0 -0
- /sphinx/templates/quickstart/{make.bat.new_t → make.bat.new.jinja} +0 -0
- /sphinx/texinputs/{Makefile_t → Makefile.jinja} +0 -0
- /sphinx/texinputs/{latexmkjarc_t → latexmkjarc.jinja} +0 -0
- /sphinx/texinputs/{latexmkrc_t → latexmkrc.jinja} +0 -0
- /sphinx/texinputs/{make.bat_t → make.bat.jinja} +0 -0
- /sphinx/texinputs_win/{Makefile_t → Makefile.jinja} +0 -0
- /sphinx/themes/agogo/static/{agogo.css_t → agogo.css.jinja} +0 -0
- /sphinx/themes/basic/static/{basic.css_t → basic.css.jinja} +0 -0
- /sphinx/themes/basic/static/{documentation_options.js_t → documentation_options.js.jinja} +0 -0
- /sphinx/themes/basic/static/{language_data.js_t → language_data.js.jinja} +0 -0
- /sphinx/themes/bizstyle/static/{bizstyle.css_t → bizstyle.css.jinja} +0 -0
- /sphinx/themes/bizstyle/static/{bizstyle.js_t → bizstyle.js.jinja} +0 -0
- /sphinx/themes/classic/static/{classic.css_t → classic.css.jinja} +0 -0
- /sphinx/themes/classic/static/{sidebar.js_t → sidebar.js.jinja} +0 -0
- /sphinx/themes/epub/static/{epub.css_t → epub.css.jinja} +0 -0
- /sphinx/themes/haiku/static/{haiku.css_t → haiku.css.jinja} +0 -0
- /sphinx/themes/nature/static/{nature.css_t → nature.css.jinja} +0 -0
- /sphinx/themes/nonav/static/{nonav.css_t → nonav.css.jinja} +0 -0
- /sphinx/themes/pyramid/static/{epub.css_t → epub.css.jinja} +0 -0
- /sphinx/themes/pyramid/static/{pyramid.css_t → pyramid.css.jinja} +0 -0
- /sphinx/themes/scrolls/static/{scrolls.css_t → scrolls.css.jinja} +0 -0
- /sphinx/themes/sphinxdoc/static/{sphinxdoc.css_t → sphinxdoc.css.jinja} +0 -0
- /sphinx/themes/traditional/static/{traditional.css_t → traditional.css.jinja} +0 -0
- {sphinx-7.3.7.dist-info → sphinx-7.4.1.dist-info}/LICENSE.rst +0 -0
- {sphinx-7.3.7.dist-info → sphinx-7.4.1.dist-info}/WHEEL +0 -0
- {sphinx-7.3.7.dist-info → sphinx-7.4.1.dist-info}/entry_points.txt +0 -0
sphinx/builders/html/__init__.py
CHANGED
|
@@ -115,7 +115,7 @@ class BuildInfo:
|
|
|
115
115
|
"""
|
|
116
116
|
|
|
117
117
|
@classmethod
|
|
118
|
-
def load(cls: type[BuildInfo], f: IO) -> BuildInfo:
|
|
118
|
+
def load(cls: type[BuildInfo], f: IO[str]) -> BuildInfo:
|
|
119
119
|
try:
|
|
120
120
|
lines = f.readlines()
|
|
121
121
|
assert lines[0].rstrip() == '# Sphinx build info version 1'
|
|
@@ -149,7 +149,7 @@ class BuildInfo:
|
|
|
149
149
|
return (self.config_hash == other.config_hash and
|
|
150
150
|
self.tags_hash == other.tags_hash)
|
|
151
151
|
|
|
152
|
-
def dump(self, f: IO) -> None:
|
|
152
|
+
def dump(self, f: IO[str]) -> None:
|
|
153
153
|
f.write('# Sphinx build info version 1\n'
|
|
154
154
|
'# This file hashes the configuration used when building these files.'
|
|
155
155
|
' When it is not found, a full rebuild will be done.\n'
|
|
@@ -201,7 +201,9 @@ class StandaloneHTMLBuilder(Builder):
|
|
|
201
201
|
self._js_files: list[_JavaScript] = []
|
|
202
202
|
|
|
203
203
|
# Cached Publisher for writing doctrees to HTML
|
|
204
|
-
reader: Reader = docutils.readers.doctree.Reader(
|
|
204
|
+
reader: Reader[DocTreeInput] = docutils.readers.doctree.Reader(
|
|
205
|
+
parser_name='restructuredtext'
|
|
206
|
+
)
|
|
205
207
|
pub = Publisher(
|
|
206
208
|
reader=reader,
|
|
207
209
|
parser=reader.parser,
|
|
@@ -209,11 +211,7 @@ class StandaloneHTMLBuilder(Builder):
|
|
|
209
211
|
source_class=DocTreeInput,
|
|
210
212
|
destination=StringOutput(encoding='unicode'),
|
|
211
213
|
)
|
|
212
|
-
|
|
213
|
-
pub.get_settings(output_encoding='unicode', traceback=True)
|
|
214
|
-
else:
|
|
215
|
-
op = pub.setup_option_parser(output_encoding='unicode', traceback=True)
|
|
216
|
-
pub.settings = op.get_default_values()
|
|
214
|
+
pub.get_settings(output_encoding='unicode', traceback=True)
|
|
217
215
|
self._publisher = pub
|
|
218
216
|
|
|
219
217
|
def init(self) -> None:
|
|
@@ -269,7 +267,7 @@ class StandaloneHTMLBuilder(Builder):
|
|
|
269
267
|
else:
|
|
270
268
|
yield 'default.css'
|
|
271
269
|
|
|
272
|
-
def get_theme_config(self) -> tuple[str, dict]:
|
|
270
|
+
def get_theme_config(self) -> tuple[str, dict[str, str | int | bool]]:
|
|
273
271
|
return self.config.html_theme, self.config.html_theme_options
|
|
274
272
|
|
|
275
273
|
def init_templates(self) -> None:
|
|
@@ -465,29 +463,31 @@ class StandaloneHTMLBuilder(Builder):
|
|
|
465
463
|
# determine the additional indices to include
|
|
466
464
|
self.domain_indices = []
|
|
467
465
|
# html_domain_indices can be False/True or a list of index names
|
|
468
|
-
indices_config
|
|
469
|
-
|
|
466
|
+
if indices_config := self.config.html_domain_indices:
|
|
467
|
+
if not isinstance(indices_config, bool):
|
|
468
|
+
check_names = True
|
|
469
|
+
indices_config = frozenset(indices_config)
|
|
470
|
+
else:
|
|
471
|
+
check_names = False
|
|
470
472
|
for domain_name in sorted(self.env.domains):
|
|
471
473
|
domain: Domain = self.env.domains[domain_name]
|
|
472
|
-
for
|
|
473
|
-
|
|
474
|
-
if
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
content, collapse = indexcls(domain).generate()
|
|
474
|
+
for index_cls in domain.indices:
|
|
475
|
+
index_name = f'{domain.name}-{index_cls.name}'
|
|
476
|
+
if check_names and index_name not in indices_config:
|
|
477
|
+
continue
|
|
478
|
+
content, collapse = index_cls(domain).generate()
|
|
478
479
|
if content:
|
|
479
480
|
self.domain_indices.append(
|
|
480
|
-
(
|
|
481
|
+
(index_name, index_cls, content, collapse))
|
|
481
482
|
|
|
482
483
|
# format the "last updated on" string, only once is enough since it
|
|
483
484
|
# typically doesn't include the time of day
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
language=self.config.language)
|
|
485
|
+
last_updated: str | None
|
|
486
|
+
if (lu_fmt := self.config.html_last_updated_fmt) is not None:
|
|
487
|
+
lu_fmt = lu_fmt or _('%b %d, %Y')
|
|
488
|
+
last_updated = format_date(lu_fmt, language=self.config.language)
|
|
489
489
|
else:
|
|
490
|
-
|
|
490
|
+
last_updated = None
|
|
491
491
|
|
|
492
492
|
# If the logo or favicon are urls, keep them as-is, otherwise
|
|
493
493
|
# strip the relative path as the files will be copied into _static.
|
|
@@ -526,7 +526,7 @@ class StandaloneHTMLBuilder(Builder):
|
|
|
526
526
|
'project': self.config.project,
|
|
527
527
|
'release': return_codes_re.sub('', self.config.release),
|
|
528
528
|
'version': self.config.version,
|
|
529
|
-
'last_updated':
|
|
529
|
+
'last_updated': last_updated,
|
|
530
530
|
'copyright': self.config.copyright,
|
|
531
531
|
'master_doc': self.config.root_doc,
|
|
532
532
|
'root_doc': self.config.root_doc,
|
|
@@ -552,6 +552,7 @@ class StandaloneHTMLBuilder(Builder):
|
|
|
552
552
|
'builder': self.name,
|
|
553
553
|
'parents': [],
|
|
554
554
|
'logo_url': logo,
|
|
555
|
+
'logo_alt': _('Logo of %s') % self.config.project,
|
|
555
556
|
'favicon_url': favicon,
|
|
556
557
|
'html5_doctype': True,
|
|
557
558
|
}
|
|
@@ -824,7 +825,7 @@ class StandaloneHTMLBuilder(Builder):
|
|
|
824
825
|
excluded=DOTFILES, context=context,
|
|
825
826
|
renderer=self.templates, onerror=onerror)
|
|
826
827
|
|
|
827
|
-
def copy_html_static_files(self, context: dict) -> None:
|
|
828
|
+
def copy_html_static_files(self, context: dict[str, Any]) -> None:
|
|
828
829
|
def onerror(filename: str, error: Exception) -> None:
|
|
829
830
|
logger.warning(__('Failed to copy a file in html_static_file: %s: %r'),
|
|
830
831
|
filename, error)
|
|
@@ -890,7 +891,7 @@ class StandaloneHTMLBuilder(Builder):
|
|
|
890
891
|
|
|
891
892
|
def post_process_images(self, doctree: Node) -> None:
|
|
892
893
|
"""Pick the best candidate for an image and link down-scaled images to
|
|
893
|
-
their high
|
|
894
|
+
their high resolution version.
|
|
894
895
|
"""
|
|
895
896
|
super().post_process_images(doctree)
|
|
896
897
|
|
|
@@ -957,47 +958,48 @@ class StandaloneHTMLBuilder(Builder):
|
|
|
957
958
|
def get_outfilename(self, pagename: str) -> str:
|
|
958
959
|
return path.join(self.outdir, os_path(pagename) + self.out_suffix)
|
|
959
960
|
|
|
960
|
-
def add_sidebars(self, pagename: str, ctx: dict) -> None:
|
|
961
|
+
def add_sidebars(self, pagename: str, ctx: dict[str, Any]) -> None:
|
|
961
962
|
def has_wildcard(pattern: str) -> bool:
|
|
962
963
|
return any(char in pattern for char in '*?[')
|
|
963
964
|
|
|
964
965
|
matched = None
|
|
965
|
-
customsidebar = None
|
|
966
966
|
|
|
967
967
|
# default sidebars settings for selected theme
|
|
968
968
|
sidebars = list(self.theme.sidebar_templates)
|
|
969
969
|
|
|
970
970
|
# user sidebar settings
|
|
971
971
|
html_sidebars = self.get_builder_config('sidebars', 'html')
|
|
972
|
-
|
|
972
|
+
msg = __('page %s matches two patterns in html_sidebars: %r and %r')
|
|
973
|
+
for pattern, pat_sidebars in html_sidebars.items():
|
|
973
974
|
if patmatch(pagename, pattern):
|
|
974
|
-
if matched:
|
|
975
|
-
if
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
# else the already matched pattern is more specific
|
|
982
|
-
# than the present one, because it contains no wildcard
|
|
983
|
-
continue
|
|
975
|
+
if matched and has_wildcard(pattern):
|
|
976
|
+
# warn if both patterns contain wildcards
|
|
977
|
+
if has_wildcard(matched):
|
|
978
|
+
logger.warning(msg, pagename, matched)
|
|
979
|
+
# else the already matched pattern is more specific
|
|
980
|
+
# than the present one, because it contains no wildcard
|
|
981
|
+
continue
|
|
984
982
|
matched = pattern
|
|
985
|
-
sidebars =
|
|
983
|
+
sidebars = pat_sidebars
|
|
986
984
|
|
|
987
985
|
if len(sidebars) == 0:
|
|
988
986
|
# keep defaults
|
|
989
987
|
pass
|
|
990
988
|
|
|
991
|
-
ctx['sidebars'] = sidebars
|
|
992
|
-
ctx['customsidebar'] = customsidebar
|
|
989
|
+
ctx['sidebars'] = list(sidebars)
|
|
993
990
|
|
|
994
991
|
# --------- these are overwritten by the serialization builder
|
|
995
992
|
|
|
996
993
|
def get_target_uri(self, docname: str, typ: str | None = None) -> str:
|
|
997
994
|
return quote(docname) + self.link_suffix
|
|
998
995
|
|
|
999
|
-
def handle_page(
|
|
1000
|
-
|
|
996
|
+
def handle_page(
|
|
997
|
+
self, pagename: str,
|
|
998
|
+
addctx: dict[str, Any],
|
|
999
|
+
templatename: str = 'page.html',
|
|
1000
|
+
outfilename: str | None = None,
|
|
1001
|
+
event_arg: Any = None,
|
|
1002
|
+
) -> None:
|
|
1001
1003
|
ctx = self.globalcontext.copy()
|
|
1002
1004
|
# current_page_name is backwards compatibility
|
|
1003
1005
|
ctx['pagename'] = ctx['current_page_name'] = pagename
|
|
@@ -1144,7 +1146,7 @@ class StandaloneHTMLBuilder(Builder):
|
|
|
1144
1146
|
copyfile(self.env.doc2path(pagename), source_name)
|
|
1145
1147
|
|
|
1146
1148
|
def update_page_context(self, pagename: str, templatename: str,
|
|
1147
|
-
ctx: dict, event_arg: Any) -> None:
|
|
1149
|
+
ctx: dict[str, Any], event_arg: Any) -> None:
|
|
1148
1150
|
pass
|
|
1149
1151
|
|
|
1150
1152
|
def handle_finish(self) -> None:
|
|
@@ -1175,7 +1177,7 @@ class StandaloneHTMLBuilder(Builder):
|
|
|
1175
1177
|
|
|
1176
1178
|
def convert_html_css_files(app: Sphinx, config: Config) -> None:
|
|
1177
1179
|
"""Convert string styled html_css_files to tuple styled one."""
|
|
1178
|
-
html_css_files: list[tuple[str, dict]] = []
|
|
1180
|
+
html_css_files: list[tuple[str, dict[str, str]]] = []
|
|
1179
1181
|
for entry in config.html_css_files:
|
|
1180
1182
|
if isinstance(entry, str):
|
|
1181
1183
|
html_css_files.append((entry, {}))
|
|
@@ -1187,7 +1189,7 @@ def convert_html_css_files(app: Sphinx, config: Config) -> None:
|
|
|
1187
1189
|
logger.warning(__('invalid css_file: %r, ignored'), entry)
|
|
1188
1190
|
continue
|
|
1189
1191
|
|
|
1190
|
-
config.html_css_files = html_css_files
|
|
1192
|
+
config.html_css_files = html_css_files
|
|
1191
1193
|
|
|
1192
1194
|
|
|
1193
1195
|
def _format_modified_time(timestamp: float) -> str:
|
|
@@ -1198,7 +1200,7 @@ def _format_modified_time(timestamp: float) -> str:
|
|
|
1198
1200
|
|
|
1199
1201
|
def convert_html_js_files(app: Sphinx, config: Config) -> None:
|
|
1200
1202
|
"""Convert string styled html_js_files to tuple styled one."""
|
|
1201
|
-
html_js_files: list[tuple[str, dict]] = []
|
|
1203
|
+
html_js_files: list[tuple[str, dict[str, str]]] = []
|
|
1202
1204
|
for entry in config.html_js_files:
|
|
1203
1205
|
if isinstance(entry, str):
|
|
1204
1206
|
html_js_files.append((entry, {}))
|
|
@@ -1210,11 +1212,11 @@ def convert_html_js_files(app: Sphinx, config: Config) -> None:
|
|
|
1210
1212
|
logger.warning(__('invalid js_file: %r, ignored'), entry)
|
|
1211
1213
|
continue
|
|
1212
1214
|
|
|
1213
|
-
config.html_js_files = html_js_files
|
|
1215
|
+
config.html_js_files = html_js_files
|
|
1214
1216
|
|
|
1215
1217
|
|
|
1216
1218
|
def setup_resource_paths(app: Sphinx, pagename: str, templatename: str,
|
|
1217
|
-
context: dict, doctree: Node) -> None:
|
|
1219
|
+
context: dict[str, Any], doctree: Node) -> None:
|
|
1218
1220
|
"""Set up relative resource paths."""
|
|
1219
1221
|
pathto = context['pathto']
|
|
1220
1222
|
|
|
@@ -1273,7 +1275,7 @@ def validate_html_logo(app: Sphinx, config: Config) -> None:
|
|
|
1273
1275
|
not path.isfile(path.join(app.confdir, config.html_logo)) and
|
|
1274
1276
|
not isurl(config.html_logo)):
|
|
1275
1277
|
logger.warning(__('logo file %r does not exist'), config.html_logo)
|
|
1276
|
-
config.html_logo = None
|
|
1278
|
+
config.html_logo = None
|
|
1277
1279
|
|
|
1278
1280
|
|
|
1279
1281
|
def validate_html_favicon(app: Sphinx, config: Config) -> None:
|
|
@@ -1282,7 +1284,7 @@ def validate_html_favicon(app: Sphinx, config: Config) -> None:
|
|
|
1282
1284
|
not path.isfile(path.join(app.confdir, config.html_favicon)) and
|
|
1283
1285
|
not isurl(config.html_favicon)):
|
|
1284
1286
|
logger.warning(__('favicon file %r does not exist'), config.html_favicon)
|
|
1285
|
-
config.html_favicon = None
|
|
1287
|
+
config.html_favicon = None
|
|
1286
1288
|
|
|
1287
1289
|
|
|
1288
1290
|
def error_on_html_4(_app: Sphinx, config: Config) -> None:
|
|
@@ -1315,7 +1317,7 @@ def setup(app: Sphinx) -> ExtensionMetadata:
|
|
|
1315
1317
|
app.add_config_value('html_last_updated_fmt', None, 'html', str)
|
|
1316
1318
|
app.add_config_value('html_sidebars', {}, 'html')
|
|
1317
1319
|
app.add_config_value('html_additional_pages', {}, 'html')
|
|
1318
|
-
app.add_config_value('html_domain_indices', True, 'html', list)
|
|
1320
|
+
app.add_config_value('html_domain_indices', True, 'html', types={set, list})
|
|
1319
1321
|
app.add_config_value('html_permalinks', True, 'html')
|
|
1320
1322
|
app.add_config_value('html_permalinks_icon', '¶', 'html')
|
|
1321
1323
|
app.add_config_value('html_use_index', True, 'html')
|
|
@@ -417,7 +417,7 @@ class LaTeXBuilder(Builder):
|
|
|
417
417
|
# use pre-1.6.x Makefile for make latexpdf on Windows
|
|
418
418
|
if os.name == 'nt':
|
|
419
419
|
staticdirname = path.join(package_dir, 'texinputs_win')
|
|
420
|
-
copy_asset_file(path.join(staticdirname, '
|
|
420
|
+
copy_asset_file(path.join(staticdirname, 'Makefile.jinja'),
|
|
421
421
|
self.outdir, context=context)
|
|
422
422
|
|
|
423
423
|
@progress_message(__('copying additional files'))
|
|
@@ -456,7 +456,7 @@ class LaTeXBuilder(Builder):
|
|
|
456
456
|
if self.context['babel'] or self.context['polyglossia']:
|
|
457
457
|
context['addtocaptions'] = r'\addto\captions%s' % self.babel.get_language()
|
|
458
458
|
|
|
459
|
-
filename = path.join(package_dir, 'templates', 'latex', 'sphinxmessages.
|
|
459
|
+
filename = path.join(package_dir, 'templates', 'latex', 'sphinxmessages.sty.jinja')
|
|
460
460
|
copy_asset_file(filename, self.outdir, context=context, renderer=LaTeXRenderer())
|
|
461
461
|
|
|
462
462
|
|
|
@@ -464,7 +464,7 @@ def validate_config_values(app: Sphinx, config: Config) -> None:
|
|
|
464
464
|
for key in list(config.latex_elements):
|
|
465
465
|
if key not in DEFAULT_SETTINGS:
|
|
466
466
|
msg = __("Unknown configure key: latex_elements[%r], ignored.")
|
|
467
|
-
logger.warning(msg
|
|
467
|
+
logger.warning(msg, key)
|
|
468
468
|
config.latex_elements.pop(key)
|
|
469
469
|
|
|
470
470
|
|
|
@@ -472,7 +472,7 @@ def validate_latex_theme_options(app: Sphinx, config: Config) -> None:
|
|
|
472
472
|
for key in list(config.latex_theme_options):
|
|
473
473
|
if key not in Theme.UPDATABLE_KEYS:
|
|
474
474
|
msg = __("Unknown theme option: latex_theme_options[%r], ignored.")
|
|
475
|
-
logger.warning(msg
|
|
475
|
+
logger.warning(msg, key)
|
|
476
476
|
config.latex_theme_options.pop(key)
|
|
477
477
|
|
|
478
478
|
|
|
@@ -539,7 +539,7 @@ def setup(app: Sphinx) -> ExtensionMetadata:
|
|
|
539
539
|
app.add_config_value('latex_use_xindy', default_latex_use_xindy, '', bool)
|
|
540
540
|
app.add_config_value('latex_toplevel_sectioning', None, '',
|
|
541
541
|
ENUM(None, 'part', 'chapter', 'section'))
|
|
542
|
-
app.add_config_value('latex_domain_indices', True, '', list)
|
|
542
|
+
app.add_config_value('latex_domain_indices', True, '', types={set, list})
|
|
543
543
|
app.add_config_value('latex_show_urls', 'no', '')
|
|
544
544
|
app.add_config_value('latex_show_pagerefs', False, '')
|
|
545
545
|
app.add_config_value('latex_elements', {}, '')
|
|
@@ -183,6 +183,11 @@ ADDITIONAL_SETTINGS: dict[Any, dict[str, Any]] = {
|
|
|
183
183
|
},
|
|
184
184
|
|
|
185
185
|
# special settings for latex_engine + language_code
|
|
186
|
+
('lualatex', 'fr'): {
|
|
187
|
+
# use babel instead of polyglossia by default
|
|
188
|
+
'polyglossia': '',
|
|
189
|
+
'babel': '\\usepackage{babel}',
|
|
190
|
+
},
|
|
186
191
|
('xelatex', 'fr'): {
|
|
187
192
|
# use babel instead of polyglossia by default
|
|
188
193
|
'polyglossia': '',
|
sphinx/builders/linkcheck.py
CHANGED
|
@@ -13,7 +13,7 @@ from os import path
|
|
|
13
13
|
from queue import PriorityQueue, Queue
|
|
14
14
|
from threading import Thread
|
|
15
15
|
from typing import TYPE_CHECKING, NamedTuple, cast
|
|
16
|
-
from urllib.parse import unquote, urlparse, urlsplit, urlunparse
|
|
16
|
+
from urllib.parse import quote, unquote, urlparse, urlsplit, urlunparse
|
|
17
17
|
|
|
18
18
|
from docutils import nodes
|
|
19
19
|
from requests.exceptions import ConnectionError, HTTPError, SSLError, TooManyRedirects
|
|
@@ -102,9 +102,11 @@ class CheckExternalLinksBuilder(DummyBuilder):
|
|
|
102
102
|
def process_result(self, result: CheckResult) -> None:
|
|
103
103
|
filename = self.env.doc2path(result.docname, False)
|
|
104
104
|
|
|
105
|
-
linkstat
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
linkstat: dict[str, str | int] = {
|
|
106
|
+
'filename': filename, 'lineno': result.lineno,
|
|
107
|
+
'status': result.status, 'code': result.code,
|
|
108
|
+
'uri': result.uri, 'info': result.message,
|
|
109
|
+
}
|
|
108
110
|
self.write_linkstat(linkstat)
|
|
109
111
|
|
|
110
112
|
if result.status == 'unchecked':
|
|
@@ -164,7 +166,7 @@ class CheckExternalLinksBuilder(DummyBuilder):
|
|
|
164
166
|
else:
|
|
165
167
|
raise ValueError('Unknown status %s.' % result.status)
|
|
166
168
|
|
|
167
|
-
def write_linkstat(self, data: dict) -> None:
|
|
169
|
+
def write_linkstat(self, data: dict[str, str | int]) -> None:
|
|
168
170
|
self.json_outfile.write(json.dumps(data))
|
|
169
171
|
self.json_outfile.write('\n')
|
|
170
172
|
|
|
@@ -178,41 +180,67 @@ class HyperlinkCollector(SphinxPostTransform):
|
|
|
178
180
|
default_priority = 800
|
|
179
181
|
|
|
180
182
|
def run(self, **kwargs: Any) -> None:
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
183
|
+
for node in self.document.findall():
|
|
184
|
+
if uri := self.find_uri(node):
|
|
185
|
+
self._add_uri(uri, node)
|
|
186
|
+
|
|
187
|
+
def find_uri(self, node: nodes.Element) -> str | None:
|
|
188
|
+
"""Find a URI for a given node.
|
|
184
189
|
|
|
190
|
+
This call can be used to retrieve a URI from a provided node. If no
|
|
191
|
+
URI exists for a provided node, this call will return ``None``.
|
|
192
|
+
|
|
193
|
+
This method can be useful for extension developers who wish to
|
|
194
|
+
easily inject hyperlinks into a builder by only needing to override
|
|
195
|
+
this method.
|
|
196
|
+
|
|
197
|
+
:param node: A node class
|
|
198
|
+
:returns: URI of the node
|
|
199
|
+
"""
|
|
185
200
|
# reference nodes
|
|
186
|
-
|
|
187
|
-
if 'refuri' in
|
|
188
|
-
|
|
189
|
-
_add_uri(self.app, uri, refnode, hyperlinks, docname)
|
|
201
|
+
if isinstance(node, nodes.reference):
|
|
202
|
+
if 'refuri' in node:
|
|
203
|
+
return node['refuri']
|
|
190
204
|
|
|
191
205
|
# image nodes
|
|
192
|
-
|
|
193
|
-
uri =
|
|
206
|
+
if isinstance(node, nodes.image):
|
|
207
|
+
uri = node['candidates'].get('?')
|
|
194
208
|
if uri and '://' in uri:
|
|
195
|
-
|
|
209
|
+
return uri
|
|
196
210
|
|
|
197
211
|
# raw nodes
|
|
198
|
-
|
|
199
|
-
uri =
|
|
212
|
+
if isinstance(node, nodes.raw):
|
|
213
|
+
uri = node.get('source')
|
|
200
214
|
if uri and '://' in uri:
|
|
201
|
-
|
|
215
|
+
return uri
|
|
216
|
+
|
|
217
|
+
return None
|
|
202
218
|
|
|
219
|
+
def _add_uri(self, uri: str, node: nodes.Element) -> None:
|
|
220
|
+
"""Registers a node's URI into a builder's collection of hyperlinks.
|
|
203
221
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
222
|
+
Provides the ability to register a URI value determined from a node
|
|
223
|
+
into the linkcheck's builder. URI's processed through this call can
|
|
224
|
+
be manipulated through a ``linkcheck-process-uri`` event before the
|
|
225
|
+
builder attempts to validate.
|
|
208
226
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
227
|
+
:param uri: URI to add
|
|
228
|
+
:param node: A node class where the URI was found
|
|
229
|
+
"""
|
|
230
|
+
builder = cast(CheckExternalLinksBuilder, self.app.builder)
|
|
231
|
+
hyperlinks = builder.hyperlinks
|
|
232
|
+
docname = self.env.docname
|
|
233
|
+
|
|
234
|
+
if newuri := self.app.emit_firstresult('linkcheck-process-uri', uri):
|
|
235
|
+
uri = newuri
|
|
236
|
+
|
|
237
|
+
try:
|
|
238
|
+
lineno = get_node_line(node)
|
|
239
|
+
except ValueError:
|
|
240
|
+
lineno = -1
|
|
213
241
|
|
|
214
|
-
|
|
215
|
-
|
|
242
|
+
if uri not in hyperlinks:
|
|
243
|
+
hyperlinks[uri] = Hyperlink(uri, docname, self.env.doc2path(docname), lineno)
|
|
216
244
|
|
|
217
245
|
|
|
218
246
|
class Hyperlink(NamedTuple):
|
|
@@ -390,9 +418,11 @@ class HyperlinkAvailabilityCheckWorker(Thread):
|
|
|
390
418
|
|
|
391
419
|
return status, info, code
|
|
392
420
|
|
|
393
|
-
def _retrieval_methods(
|
|
394
|
-
|
|
395
|
-
|
|
421
|
+
def _retrieval_methods(
|
|
422
|
+
self,
|
|
423
|
+
check_anchors: bool,
|
|
424
|
+
anchor: str,
|
|
425
|
+
) -> Iterator[tuple[Callable[..., Response], dict[str, bool]]]:
|
|
396
426
|
if not check_anchors or not anchor:
|
|
397
427
|
yield self._session.head, {'allow_redirects': True}
|
|
398
428
|
yield self._session.get, {'stream': True}
|
|
@@ -409,6 +439,7 @@ class HyperlinkAvailabilityCheckWorker(Thread):
|
|
|
409
439
|
if rex.match(req_url):
|
|
410
440
|
anchor = ''
|
|
411
441
|
break
|
|
442
|
+
anchor = unquote(anchor)
|
|
412
443
|
|
|
413
444
|
# handle non-ASCII URIs
|
|
414
445
|
try:
|
|
@@ -444,14 +475,18 @@ class HyperlinkAvailabilityCheckWorker(Thread):
|
|
|
444
475
|
_user_agent=self.user_agent,
|
|
445
476
|
_tls_info=(self.tls_verify, self.tls_cacerts),
|
|
446
477
|
) as response:
|
|
447
|
-
if
|
|
448
|
-
|
|
449
|
-
|
|
478
|
+
if anchor and self.check_anchors and response.ok:
|
|
479
|
+
try:
|
|
480
|
+
found = contains_anchor(response, anchor)
|
|
481
|
+
except UnicodeDecodeError:
|
|
482
|
+
return 'ignored', 'unable to decode response content', 0
|
|
483
|
+
if not found:
|
|
484
|
+
return 'broken', __("Anchor '%s' not found") % quote(anchor), 0
|
|
450
485
|
|
|
451
486
|
# Copy data we need from the (closed) response
|
|
452
487
|
status_code = response.status_code
|
|
453
488
|
redirect_status_code = response.history[-1].status_code if response.history else None # NoQA: E501
|
|
454
|
-
retry_after = response.headers.get('Retry-After')
|
|
489
|
+
retry_after = response.headers.get('Retry-After', '')
|
|
455
490
|
response_url = f'{response.url}'
|
|
456
491
|
response.raise_for_status()
|
|
457
492
|
del response
|
|
@@ -536,7 +571,7 @@ class HyperlinkAvailabilityCheckWorker(Thread):
|
|
|
536
571
|
else:
|
|
537
572
|
return 'redirected', response_url, 0
|
|
538
573
|
|
|
539
|
-
def limit_rate(self, response_url: str, retry_after: str) -> float | None:
|
|
574
|
+
def limit_rate(self, response_url: str, retry_after: str | None) -> float | None:
|
|
540
575
|
delay = DEFAULT_DELAY
|
|
541
576
|
next_check = None
|
|
542
577
|
if retry_after:
|
|
@@ -592,7 +627,7 @@ def _get_request_headers(
|
|
|
592
627
|
|
|
593
628
|
def contains_anchor(response: Response, anchor: str) -> bool:
|
|
594
629
|
"""Determine if an anchor is contained within an HTTP response."""
|
|
595
|
-
parser = AnchorCheckParser(
|
|
630
|
+
parser = AnchorCheckParser(anchor)
|
|
596
631
|
# Read file in chunks. If we find a matching anchor, we break
|
|
597
632
|
# the loop early in hopes not to have to download the whole thing.
|
|
598
633
|
for chunk in response.iter_content(chunk_size=4096, decode_unicode=True):
|
|
@@ -681,7 +716,7 @@ def setup(app: Sphinx) -> ExtensionMetadata:
|
|
|
681
716
|
# commonly used for dynamic pages
|
|
682
717
|
app.add_config_value('linkcheck_anchors_ignore', ['^!'], '')
|
|
683
718
|
app.add_config_value('linkcheck_anchors_ignore_for_url', (), '', (tuple, list))
|
|
684
|
-
app.add_config_value('linkcheck_rate_limit_timeout', 300.0, '')
|
|
719
|
+
app.add_config_value('linkcheck_rate_limit_timeout', 300.0, '', (int, float))
|
|
685
720
|
app.add_config_value('linkcheck_allow_unauthorized', True, '')
|
|
686
721
|
app.add_config_value('linkcheck_report_timeouts_as_broken', True, '', bool)
|
|
687
722
|
|
sphinx/builders/texinfo.py
CHANGED
|
@@ -221,7 +221,7 @@ def setup(app: Sphinx) -> ExtensionMetadata:
|
|
|
221
221
|
app.add_config_value('texinfo_documents', default_texinfo_documents, '')
|
|
222
222
|
app.add_config_value('texinfo_appendices', [], '')
|
|
223
223
|
app.add_config_value('texinfo_elements', {}, '')
|
|
224
|
-
app.add_config_value('texinfo_domain_indices', True, '', list)
|
|
224
|
+
app.add_config_value('texinfo_domain_indices', True, '', types={set, list})
|
|
225
225
|
app.add_config_value('texinfo_show_urls', 'footnote', '')
|
|
226
226
|
app.add_config_value('texinfo_no_detailmenu', False, '')
|
|
227
227
|
app.add_config_value('texinfo_cross_references', True, '')
|
sphinx/cmd/build.py
CHANGED
|
@@ -179,7 +179,7 @@ files can be built by specifying individual filenames.
|
|
|
179
179
|
dest='tags', default=[],
|
|
180
180
|
help=__('define tag: include "only" blocks with TAG'))
|
|
181
181
|
group.add_argument('--nitpicky', '-n', action='store_true', dest='nitpicky',
|
|
182
|
-
help=__('
|
|
182
|
+
help=__('nitpicky mode: warn about all missing references'))
|
|
183
183
|
|
|
184
184
|
group = parser.add_argument_group(__('console output options'))
|
|
185
185
|
group.add_argument('--verbose', '-v', action='count', dest='verbosity',
|
sphinx/cmd/quickstart.py
CHANGED
|
@@ -372,32 +372,32 @@ def generate(
|
|
|
372
372
|
if 'quiet' not in d:
|
|
373
373
|
print(__('File %s already exists, skipping.') % fpath)
|
|
374
374
|
|
|
375
|
-
conf_path = os.path.join(templatedir, 'conf.
|
|
375
|
+
conf_path = os.path.join(templatedir, 'conf.py.jinja') if templatedir else None
|
|
376
376
|
if not conf_path or not path.isfile(conf_path):
|
|
377
|
-
conf_path = os.path.join(package_dir, 'templates', 'quickstart', 'conf.
|
|
377
|
+
conf_path = os.path.join(package_dir, 'templates', 'quickstart', 'conf.py.jinja')
|
|
378
378
|
with open(conf_path, encoding="utf-8") as f:
|
|
379
379
|
conf_text = f.read()
|
|
380
380
|
|
|
381
381
|
write_file(path.join(srcdir, 'conf.py'), template.render_string(conf_text, d))
|
|
382
382
|
|
|
383
383
|
masterfile = path.join(srcdir, d['master'] + d['suffix'])
|
|
384
|
-
if template._has_custom_template('quickstart/master_doc.
|
|
385
|
-
msg = ('A custom template `master_doc.
|
|
386
|
-
'`root_doc.
|
|
384
|
+
if template._has_custom_template('quickstart/master_doc.rst.jinja'):
|
|
385
|
+
msg = ('A custom template `master_doc.rst.jinja` found. It has been renamed to '
|
|
386
|
+
'`root_doc.rst.jinja`. Please rename it on your project too.')
|
|
387
387
|
print(colorize('red', msg))
|
|
388
|
-
write_file(masterfile, template.render('quickstart/master_doc.
|
|
388
|
+
write_file(masterfile, template.render('quickstart/master_doc.rst.jinja', d))
|
|
389
389
|
else:
|
|
390
|
-
write_file(masterfile, template.render('quickstart/root_doc.
|
|
390
|
+
write_file(masterfile, template.render('quickstart/root_doc.rst.jinja', d))
|
|
391
391
|
|
|
392
392
|
if d.get('make_mode'):
|
|
393
|
-
makefile_template = 'quickstart/Makefile.
|
|
394
|
-
batchfile_template = 'quickstart/make.bat.
|
|
393
|
+
makefile_template = 'quickstart/Makefile.new.jinja'
|
|
394
|
+
batchfile_template = 'quickstart/make.bat.new.jinja'
|
|
395
395
|
else:
|
|
396
396
|
# xref RemovedInSphinx80Warning
|
|
397
397
|
msg = "Support for '--no-use-make-mode' will be removed in Sphinx 8."
|
|
398
398
|
print(colorize('red', msg))
|
|
399
|
-
makefile_template = 'quickstart/
|
|
400
|
-
batchfile_template = 'quickstart/make.
|
|
399
|
+
makefile_template = 'quickstart/Makefile.jinja'
|
|
400
|
+
batchfile_template = 'quickstart/make.bat.jinja'
|
|
401
401
|
|
|
402
402
|
if d['makefile'] is True:
|
|
403
403
|
d['rsrcdir'] = 'source' if d['sep'] else '.'
|