Sphinx 8.0.2__py3-none-any.whl → 8.1.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 +6 -3
- sphinx/_cli/__init__.py +40 -20
- sphinx/_cli/util/colour.py +5 -4
- sphinx/_cli/util/errors.py +28 -11
- sphinx/application.py +361 -38
- sphinx/builders/__init__.py +229 -83
- sphinx/builders/_epub_base.py +118 -71
- sphinx/builders/changes.py +39 -21
- sphinx/builders/dirhtml.py +4 -4
- sphinx/builders/dummy.py +2 -5
- sphinx/builders/epub3.py +43 -22
- sphinx/builders/gettext.py +43 -25
- sphinx/builders/html/__init__.py +284 -218
- sphinx/builders/html/_assets.py +62 -26
- sphinx/builders/html/_build_info.py +76 -0
- sphinx/builders/html/transforms.py +11 -9
- sphinx/builders/latex/__init__.py +139 -81
- sphinx/builders/latex/constants.py +7 -7
- sphinx/builders/latex/nodes.py +3 -2
- sphinx/builders/latex/theming.py +7 -5
- sphinx/builders/latex/transforms.py +27 -19
- sphinx/builders/linkcheck.py +146 -72
- sphinx/builders/manpage.py +30 -13
- sphinx/builders/singlehtml.py +22 -14
- sphinx/builders/texinfo.py +67 -37
- sphinx/builders/text.py +5 -5
- sphinx/builders/xml.py +6 -9
- sphinx/cmd/build.py +282 -103
- sphinx/cmd/make_mode.py +106 -63
- sphinx/cmd/quickstart.py +341 -145
- sphinx/config.py +45 -12
- sphinx/deprecation.py +8 -2
- sphinx/directives/__init__.py +28 -19
- sphinx/directives/code.py +86 -56
- sphinx/directives/other.py +50 -36
- sphinx/directives/patches.py +29 -19
- sphinx/domains/__init__.py +20 -120
- sphinx/domains/_domains_container.py +281 -0
- sphinx/domains/_index.py +110 -0
- sphinx/domains/c/__init__.py +3 -3
- sphinx/domains/c/_parser.py +10 -6
- sphinx/domains/changeset.py +5 -3
- sphinx/domains/citation.py +5 -3
- sphinx/domains/cpp/__init__.py +9 -11
- sphinx/domains/cpp/_parser.py +8 -7
- sphinx/domains/index.py +3 -3
- sphinx/domains/javascript.py +12 -7
- sphinx/domains/math.py +2 -2
- sphinx/domains/python/__init__.py +10 -5
- sphinx/domains/python/_object.py +1 -1
- sphinx/domains/rst.py +5 -5
- sphinx/domains/std/__init__.py +16 -11
- sphinx/environment/__init__.py +202 -146
- sphinx/environment/adapters/asset.py +3 -2
- sphinx/environment/adapters/indexentries.py +74 -33
- sphinx/environment/adapters/toctree.py +100 -43
- sphinx/environment/collectors/__init__.py +19 -8
- sphinx/environment/collectors/asset.py +47 -15
- sphinx/environment/collectors/dependencies.py +8 -4
- sphinx/environment/collectors/metadata.py +7 -2
- sphinx/environment/collectors/title.py +7 -2
- sphinx/environment/collectors/toctree.py +54 -22
- sphinx/errors.py +4 -1
- sphinx/events.py +314 -7
- sphinx/ext/apidoc.py +42 -18
- sphinx/ext/autodoc/__init__.py +52 -24
- sphinx/ext/autodoc/importer.py +6 -9
- sphinx/ext/autosectionlabel.py +1 -2
- sphinx/ext/autosummary/__init__.py +3 -1
- sphinx/ext/autosummary/generate.py +28 -14
- sphinx/ext/coverage.py +7 -7
- sphinx/ext/doctest.py +4 -8
- sphinx/ext/duration.py +6 -5
- sphinx/ext/inheritance_diagram.py +1 -1
- sphinx/ext/intersphinx/_cli.py +6 -4
- sphinx/ext/intersphinx/_load.py +77 -32
- sphinx/ext/intersphinx/_resolve.py +173 -79
- sphinx/ext/intersphinx/_shared.py +7 -5
- sphinx/ext/linkcode.py +7 -1
- sphinx/ext/mathjax.py +1 -2
- sphinx/ext/napoleon/__init__.py +37 -24
- sphinx/ext/napoleon/docstring.py +202 -134
- sphinx/ext/todo.py +5 -3
- sphinx/highlighting.py +9 -2
- sphinx/io.py +1 -1
- sphinx/jinja2glue.py +27 -6
- sphinx/locale/__init__.py +6 -2
- sphinx/locale/ar/LC_MESSAGES/sphinx.js +8 -1
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +2246 -2288
- sphinx/locale/bg/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/bn/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +2349 -2395
- sphinx/locale/ca/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +2846 -2892
- sphinx/locale/cak/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +2213 -2259
- sphinx/locale/cs/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +2225 -2269
- sphinx/locale/cy/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +2403 -2447
- sphinx/locale/da/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +2214 -2260
- sphinx/locale/de/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +2230 -2276
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/el/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +2619 -2665
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2519 -2565
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/eo/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +2232 -2278
- sphinx/locale/es/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +2516 -2561
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2114 -2159
- sphinx/locale/et/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +2317 -2363
- sphinx/locale/eu/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +2218 -2264
- sphinx/locale/fa/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +2505 -2551
- sphinx/locale/fi/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +2303 -2349
- sphinx/locale/fr/LC_MESSAGES/sphinx.js +6 -2
- sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr/LC_MESSAGES/sphinx.po +2863 -2908
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +2114 -2159
- sphinx/locale/gl/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +2571 -2617
- sphinx/locale/he/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.po +2307 -2352
- sphinx/locale/hi/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +2580 -2626
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/hr/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +2238 -2283
- sphinx/locale/hu/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +2228 -2274
- sphinx/locale/id/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +2787 -2834
- sphinx/locale/is/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +2224 -2270
- sphinx/locale/it/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +2231 -2276
- sphinx/locale/ja/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +2507 -2554
- sphinx/locale/ka/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +2428 -2474
- sphinx/locale/ko/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +2516 -2563
- sphinx/locale/lt/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +2425 -2469
- sphinx/locale/lv/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +2362 -2407
- sphinx/locale/mk/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +2121 -2167
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2220 -2266
- sphinx/locale/ne/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +2221 -2267
- sphinx/locale/nl/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +2240 -2286
- sphinx/locale/pl/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +2319 -2363
- sphinx/locale/pt/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +2114 -2159
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2854 -2899
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2224 -2269
- sphinx/locale/ro/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +2226 -2271
- sphinx/locale/ru/LC_MESSAGES/sphinx.js +8 -3
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +2841 -2885
- sphinx/locale/si/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +2294 -2340
- sphinx/locale/sk/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +2497 -2541
- sphinx/locale/sl/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +2331 -2375
- sphinx/locale/sphinx.pot +2121 -2167
- sphinx/locale/sq/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sq/LC_MESSAGES/sphinx.po +2855 -2901
- sphinx/locale/sr/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +2203 -2248
- 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 +4 -1
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +2423 -2469
- sphinx/locale/te/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/tr/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +2443 -2489
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2329 -2373
- sphinx/locale/ur/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/vi/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +2199 -2246
- sphinx/locale/yue/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +2112 -2159
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2112 -2159
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +2845 -2892
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2112 -2159
- sphinx/parsers.py +3 -1
- sphinx/project.py +6 -2
- sphinx/pycode/__init__.py +11 -4
- sphinx/pycode/ast.py +58 -58
- sphinx/pycode/parser.py +49 -28
- sphinx/pygments_styles.py +49 -49
- sphinx/registry.py +8 -3
- sphinx/roles.py +136 -13
- sphinx/search/__init__.py +146 -87
- sphinx/search/da.py +2 -4
- sphinx/search/de.py +2 -4
- sphinx/search/en.py +4 -4
- sphinx/search/es.py +2 -4
- sphinx/search/fi.py +2 -4
- sphinx/search/fr.py +2 -4
- sphinx/search/hu.py +2 -4
- sphinx/search/it.py +2 -4
- sphinx/search/ja.py +55 -32
- sphinx/search/nl.py +2 -4
- sphinx/search/no.py +2 -4
- sphinx/search/pt.py +2 -4
- sphinx/search/ro.py +0 -2
- sphinx/search/ru.py +2 -4
- sphinx/search/sv.py +2 -4
- sphinx/search/tr.py +0 -2
- sphinx/search/zh.py +18 -13
- sphinx/templates/graphviz/graphviz.css +0 -7
- sphinx/testing/fixtures.py +6 -5
- sphinx/testing/path.py +7 -5
- sphinx/testing/util.py +63 -29
- sphinx/texinputs/sphinx.sty +115 -50
- sphinx/texinputs/sphinxlatexadmonitions.sty +56 -38
- sphinx/texinputs/sphinxlatexcontainers.sty +1 -1
- sphinx/texinputs/sphinxlatexgraphics.sty +3 -2
- sphinx/texinputs/sphinxlatexindbibtoc.sty +1 -1
- sphinx/texinputs/sphinxlatexlists.sty +1 -1
- sphinx/texinputs/sphinxlatexliterals.sty +4 -1
- sphinx/texinputs/sphinxlatexnumfig.sty +22 -9
- sphinx/texinputs/sphinxlatexobjects.sty +1 -1
- sphinx/texinputs/sphinxlatexshadowbox.sty +72 -10
- sphinx/texinputs/sphinxlatexstyleheadings.sty +7 -2
- sphinx/texinputs/sphinxlatexstylepage.sty +2 -8
- sphinx/texinputs/sphinxlatexstyletext.sty +2 -4
- sphinx/texinputs/sphinxlatextables.sty +1 -1
- sphinx/texinputs/sphinxoptionsgeometry.sty +1 -1
- sphinx/texinputs/sphinxoptionshyperref.sty +1 -1
- sphinx/themes/agogo/layout.html +1 -10
- sphinx/themes/agogo/static/agogo.css.jinja +0 -7
- sphinx/themes/basic/defindex.html +1 -8
- sphinx/themes/basic/domainindex.html +1 -9
- sphinx/themes/basic/genindex-single.html +1 -9
- sphinx/themes/basic/genindex-split.html +1 -9
- sphinx/themes/basic/genindex.html +1 -9
- sphinx/themes/basic/globaltoc.html +1 -9
- sphinx/themes/basic/layout.html +1 -9
- sphinx/themes/basic/localtoc.html +1 -9
- sphinx/themes/basic/page.html +1 -9
- sphinx/themes/basic/relations.html +1 -9
- sphinx/themes/basic/search.html +1 -9
- sphinx/themes/basic/searchbox.html +1 -9
- sphinx/themes/basic/searchfield.html +4 -10
- sphinx/themes/basic/sourcelink.html +1 -9
- sphinx/themes/basic/static/basic.css.jinja +2 -13
- sphinx/themes/basic/static/doctools.js +0 -7
- sphinx/themes/basic/static/language_data.js.jinja +0 -7
- sphinx/themes/basic/static/searchtools.js +25 -13
- sphinx/themes/bizstyle/layout.html +1 -9
- sphinx/themes/bizstyle/static/bizstyle.css.jinja +0 -7
- sphinx/themes/bizstyle/static/bizstyle.js.jinja +5 -11
- sphinx/themes/classic/layout.html +1 -9
- sphinx/themes/classic/static/classic.css.jinja +0 -7
- sphinx/themes/classic/static/sidebar.js.jinja +0 -6
- sphinx/themes/epub/epub-cover.html +1 -9
- sphinx/themes/epub/layout.html +1 -9
- sphinx/themes/epub/static/epub.css.jinja +0 -7
- sphinx/themes/haiku/layout.html +1 -9
- sphinx/themes/haiku/static/haiku.css.jinja +0 -6
- sphinx/themes/nature/static/nature.css.jinja +0 -7
- sphinx/themes/nonav/layout.html +1 -9
- sphinx/themes/nonav/static/nonav.css.jinja +0 -7
- sphinx/themes/pyramid/static/epub.css.jinja +0 -7
- sphinx/themes/pyramid/static/pyramid.css.jinja +0 -7
- sphinx/themes/scrolls/layout.html +1 -10
- sphinx/themes/scrolls/static/scrolls.css.jinja +0 -7
- sphinx/themes/sphinxdoc/static/sphinxdoc.css.jinja +2 -7
- sphinx/themes/traditional/static/traditional.css.jinja +0 -7
- sphinx/theming.py +18 -6
- sphinx/transforms/__init__.py +56 -35
- sphinx/transforms/compact_bullet_list.py +3 -2
- sphinx/transforms/i18n.py +132 -50
- sphinx/transforms/post_transforms/__init__.py +94 -43
- sphinx/transforms/post_transforms/code.py +7 -6
- sphinx/transforms/post_transforms/images.py +71 -54
- sphinx/transforms/references.py +1 -2
- sphinx/util/__init__.py +23 -194
- sphinx/util/_files.py +80 -0
- sphinx/util/_importer.py +27 -0
- sphinx/util/_io.py +1 -2
- sphinx/util/_lines.py +26 -0
- sphinx/util/_pathlib.py +5 -2
- sphinx/util/_serialise.py +53 -0
- sphinx/util/_timestamps.py +2 -1
- sphinx/util/_uri.py +16 -0
- sphinx/util/cfamily.py +48 -25
- sphinx/util/console.py +1 -0
- sphinx/util/display.py +1 -1
- sphinx/util/docfields.py +125 -45
- sphinx/util/docstrings.py +1 -1
- sphinx/util/docutils.py +118 -44
- sphinx/util/exceptions.py +11 -5
- sphinx/util/fileutil.py +53 -32
- sphinx/util/http_date.py +9 -7
- sphinx/util/i18n.py +49 -16
- sphinx/util/images.py +7 -6
- sphinx/util/inspect.py +29 -12
- sphinx/util/inventory.py +47 -29
- sphinx/util/logging.py +58 -85
- sphinx/util/matching.py +3 -3
- sphinx/util/math.py +1 -1
- sphinx/util/nodes.py +176 -108
- sphinx/util/osutil.py +13 -10
- sphinx/util/parallel.py +5 -4
- sphinx/util/parsing.py +5 -3
- sphinx/util/png.py +3 -3
- sphinx/util/requests.py +8 -4
- sphinx/util/rst.py +5 -3
- sphinx/util/tags.py +5 -2
- sphinx/util/template.py +26 -11
- sphinx/util/texescape.py +2 -2
- sphinx/util/typing.py +89 -38
- sphinx/versioning.py +3 -1
- sphinx/writers/html.py +22 -7
- sphinx/writers/html5.py +113 -64
- sphinx/writers/latex.py +408 -221
- sphinx/writers/manpage.py +25 -15
- sphinx/writers/texinfo.py +94 -82
- sphinx/writers/text.py +87 -53
- sphinx/writers/xml.py +5 -4
- sphinx-8.1.1.dist-info/LICENSE.rst +31 -0
- {sphinx-8.0.2.dist-info → sphinx-8.1.1.dist-info}/METADATA +13 -11
- sphinx-8.1.1.dist-info/RECORD +598 -0
- sphinx-8.0.2.dist-info/LICENSE.rst +0 -67
- sphinx-8.0.2.dist-info/RECORD +0 -590
- {sphinx-8.0.2.dist-info → sphinx-8.1.1.dist-info}/WHEEL +0 -0
- {sphinx-8.0.2.dist-info → sphinx-8.1.1.dist-info}/entry_points.txt +0 -0
sphinx/ext/intersphinx/_load.py
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import concurrent.futures
|
|
6
|
-
import functools
|
|
7
6
|
import posixpath
|
|
8
7
|
import time
|
|
9
8
|
from operator import itemgetter
|
|
@@ -20,7 +19,8 @@ from sphinx.util.inventory import InventoryFile
|
|
|
20
19
|
|
|
21
20
|
if TYPE_CHECKING:
|
|
22
21
|
from pathlib import Path
|
|
23
|
-
|
|
22
|
+
|
|
23
|
+
from urllib3.response import HTTPResponse
|
|
24
24
|
|
|
25
25
|
from sphinx.application import Sphinx
|
|
26
26
|
from sphinx.config import Config
|
|
@@ -31,7 +31,7 @@ if TYPE_CHECKING:
|
|
|
31
31
|
InventoryName,
|
|
32
32
|
InventoryURI,
|
|
33
33
|
)
|
|
34
|
-
from sphinx.util.typing import Inventory
|
|
34
|
+
from sphinx.util.typing import Inventory, _ReadableStream
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
def validate_intersphinx_mapping(app: Sphinx, config: Config) -> None:
|
|
@@ -89,8 +89,10 @@ def validate_intersphinx_mapping(app: Sphinx, config: Config) -> None:
|
|
|
89
89
|
# ensure target URIs are non-empty and unique
|
|
90
90
|
if not uri or not isinstance(uri, str):
|
|
91
91
|
errors += 1
|
|
92
|
-
msg = __(
|
|
93
|
-
|
|
92
|
+
msg = __(
|
|
93
|
+
'Invalid target URI value `%r` in intersphinx_mapping[%r][0]. '
|
|
94
|
+
'Target URIs must be unique non-empty strings.'
|
|
95
|
+
)
|
|
94
96
|
LOGGER.error(msg, uri, name)
|
|
95
97
|
del config.intersphinx_mapping[name]
|
|
96
98
|
continue
|
|
@@ -105,9 +107,12 @@ def validate_intersphinx_mapping(app: Sphinx, config: Config) -> None:
|
|
|
105
107
|
continue
|
|
106
108
|
seen[uri] = name
|
|
107
109
|
|
|
110
|
+
if not isinstance(inv, tuple | list):
|
|
111
|
+
inv = (inv,)
|
|
112
|
+
|
|
108
113
|
# ensure inventory locations are None or non-empty
|
|
109
114
|
targets: list[InventoryLocation] = []
|
|
110
|
-
for target in
|
|
115
|
+
for target in inv:
|
|
111
116
|
if target is None or target and isinstance(target, str):
|
|
112
117
|
targets.append(target)
|
|
113
118
|
else:
|
|
@@ -143,9 +148,13 @@ def load_mappings(app: Sphinx) -> None:
|
|
|
143
148
|
projects = []
|
|
144
149
|
for name, (uri, locations) in intersphinx_mapping.values():
|
|
145
150
|
try:
|
|
146
|
-
project = _IntersphinxProject(
|
|
151
|
+
project = _IntersphinxProject(
|
|
152
|
+
name=name, target_uri=uri, locations=locations
|
|
153
|
+
)
|
|
147
154
|
except ValueError as err:
|
|
148
|
-
msg = __(
|
|
155
|
+
msg = __(
|
|
156
|
+
'An invalid intersphinx_mapping entry was added after normalisation.'
|
|
157
|
+
)
|
|
149
158
|
raise ConfigError(msg) from err
|
|
150
159
|
else:
|
|
151
160
|
projects.append(project)
|
|
@@ -201,14 +210,24 @@ def _fetch_inventory_group(
|
|
|
201
210
|
config: Config,
|
|
202
211
|
srcdir: Path,
|
|
203
212
|
) -> bool:
|
|
204
|
-
|
|
213
|
+
if config.intersphinx_cache_limit >= 0:
|
|
214
|
+
# Positive value: cache is expired if its timestamp is below
|
|
215
|
+
# `now - X days`.
|
|
216
|
+
cache_time = now - config.intersphinx_cache_limit * 86400
|
|
217
|
+
else:
|
|
218
|
+
# Negative value: cache is expired if its timestamp is below
|
|
219
|
+
# zero, which is impossible.
|
|
220
|
+
cache_time = 0
|
|
205
221
|
|
|
206
222
|
updated = False
|
|
207
223
|
failures = []
|
|
208
224
|
|
|
209
225
|
for location in project.locations:
|
|
210
226
|
# location is either None or a non-empty string
|
|
211
|
-
|
|
227
|
+
if location is None:
|
|
228
|
+
inv = posixpath.join(project.target_uri, INVENTORY_FILENAME)
|
|
229
|
+
else:
|
|
230
|
+
inv = location
|
|
212
231
|
|
|
213
232
|
# decide whether the inventory must be read: always read local
|
|
214
233
|
# files; remote ones only if the cache time is expired
|
|
@@ -217,8 +236,11 @@ def _fetch_inventory_group(
|
|
|
217
236
|
or project.target_uri not in cache
|
|
218
237
|
or cache[project.target_uri][1] < cache_time
|
|
219
238
|
):
|
|
220
|
-
LOGGER.info(
|
|
221
|
-
|
|
239
|
+
LOGGER.info(
|
|
240
|
+
__("loading intersphinx inventory '%s' from %s ..."),
|
|
241
|
+
project.name,
|
|
242
|
+
_get_safe_url(inv),
|
|
243
|
+
)
|
|
222
244
|
|
|
223
245
|
try:
|
|
224
246
|
invdata = _fetch_inventory(
|
|
@@ -239,14 +261,21 @@ def _fetch_inventory_group(
|
|
|
239
261
|
if not failures:
|
|
240
262
|
pass
|
|
241
263
|
elif len(failures) < len(project.locations):
|
|
242
|
-
LOGGER.info(
|
|
243
|
-
|
|
264
|
+
LOGGER.info(
|
|
265
|
+
__(
|
|
266
|
+
'encountered some issues with some of the inventories,'
|
|
267
|
+
' but they had working alternatives:'
|
|
268
|
+
)
|
|
269
|
+
)
|
|
244
270
|
for fail in failures:
|
|
245
271
|
LOGGER.info(*fail)
|
|
246
272
|
else:
|
|
247
273
|
issues = '\n'.join(f[0] % f[1:] for f in failures)
|
|
248
|
-
LOGGER.warning(
|
|
249
|
-
|
|
274
|
+
LOGGER.warning(
|
|
275
|
+
__('failed to reach any of the inventories ' 'with the following issues:')
|
|
276
|
+
+ '\n'
|
|
277
|
+
+ issues
|
|
278
|
+
)
|
|
250
279
|
return updated
|
|
251
280
|
|
|
252
281
|
|
|
@@ -261,7 +290,7 @@ def fetch_inventory(app: Sphinx, uri: InventoryURI, inv: str) -> Inventory:
|
|
|
261
290
|
|
|
262
291
|
|
|
263
292
|
def _fetch_inventory(
|
|
264
|
-
*, target_uri: InventoryURI, inv_location: str, config: Config, srcdir: Path
|
|
293
|
+
*, target_uri: InventoryURI, inv_location: str, config: Config, srcdir: Path
|
|
265
294
|
) -> Inventory:
|
|
266
295
|
"""Fetch, parse and return an intersphinx inventory file."""
|
|
267
296
|
# both *target_uri* (base URI of the links to generate)
|
|
@@ -272,12 +301,16 @@ def _fetch_inventory(
|
|
|
272
301
|
target_uri = _strip_basic_auth(target_uri)
|
|
273
302
|
try:
|
|
274
303
|
if '://' in inv_location:
|
|
275
|
-
f = _read_from_url(inv_location, config=config)
|
|
304
|
+
f: _ReadableStream[bytes] = _read_from_url(inv_location, config=config)
|
|
276
305
|
else:
|
|
277
306
|
f = open(path.join(srcdir, inv_location), 'rb') # NoQA: SIM115
|
|
278
307
|
except Exception as err:
|
|
279
|
-
err.args = (
|
|
280
|
-
|
|
308
|
+
err.args = (
|
|
309
|
+
'intersphinx inventory %r not fetchable due to %s: %s',
|
|
310
|
+
inv_location,
|
|
311
|
+
err.__class__,
|
|
312
|
+
str(err),
|
|
313
|
+
)
|
|
281
314
|
raise
|
|
282
315
|
try:
|
|
283
316
|
if hasattr(f, 'url'):
|
|
@@ -289,17 +322,22 @@ def _fetch_inventory(
|
|
|
289
322
|
if target_uri in {
|
|
290
323
|
inv_location,
|
|
291
324
|
path.dirname(inv_location),
|
|
292
|
-
path.dirname(inv_location) + '/'
|
|
325
|
+
path.dirname(inv_location) + '/',
|
|
293
326
|
}:
|
|
294
327
|
target_uri = path.dirname(new_inv_location)
|
|
295
328
|
with f:
|
|
296
329
|
try:
|
|
297
330
|
invdata = InventoryFile.load(f, target_uri, posixpath.join)
|
|
298
331
|
except ValueError as exc:
|
|
299
|
-
|
|
332
|
+
msg = f'unknown or unsupported inventory version: {exc!r}'
|
|
333
|
+
raise ValueError(msg) from exc
|
|
300
334
|
except Exception as err:
|
|
301
|
-
err.args = (
|
|
302
|
-
|
|
335
|
+
err.args = (
|
|
336
|
+
'intersphinx inventory %r not readable due to %s: %s',
|
|
337
|
+
inv_location,
|
|
338
|
+
err.__class__.__name__,
|
|
339
|
+
str(err),
|
|
340
|
+
)
|
|
303
341
|
raise
|
|
304
342
|
else:
|
|
305
343
|
return invdata
|
|
@@ -351,7 +389,7 @@ def _strip_basic_auth(url: str) -> str:
|
|
|
351
389
|
return urlunsplit(frags)
|
|
352
390
|
|
|
353
391
|
|
|
354
|
-
def _read_from_url(url: str, *, config: Config) ->
|
|
392
|
+
def _read_from_url(url: str, *, config: Config) -> HTTPResponse:
|
|
355
393
|
"""Reads data from *url* with an HTTP *GET*.
|
|
356
394
|
|
|
357
395
|
This function supports fetching from resources which use basic HTTP auth as
|
|
@@ -367,12 +405,19 @@ def _read_from_url(url: str, *, config: Config) -> IO:
|
|
|
367
405
|
:return: data read from resource described by *url*
|
|
368
406
|
:rtype: ``file``-like object
|
|
369
407
|
"""
|
|
370
|
-
r = requests.get(
|
|
371
|
-
|
|
372
|
-
|
|
408
|
+
r = requests.get(
|
|
409
|
+
url,
|
|
410
|
+
stream=True,
|
|
411
|
+
timeout=config.intersphinx_timeout,
|
|
412
|
+
_user_agent=config.user_agent,
|
|
413
|
+
_tls_info=(config.tls_verify, config.tls_cacerts),
|
|
414
|
+
)
|
|
373
415
|
r.raise_for_status()
|
|
374
|
-
|
|
375
|
-
#
|
|
376
|
-
#
|
|
377
|
-
|
|
416
|
+
|
|
417
|
+
# For inv_location / new_inv_location
|
|
418
|
+
r.raw.url = r.url # type: ignore[union-attr]
|
|
419
|
+
|
|
420
|
+
# Decode content-body based on the header.
|
|
421
|
+
# xref: https://github.com/psf/requests/issues/2155
|
|
422
|
+
r.raw.decode_content = True
|
|
378
423
|
return r.raw
|
|
@@ -32,9 +32,13 @@ if TYPE_CHECKING:
|
|
|
32
32
|
from sphinx.util.typing import Inventory, InventoryItem, RoleFunction
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
def _create_element_from_result(
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
def _create_element_from_result(
|
|
36
|
+
domain: Domain,
|
|
37
|
+
inv_name: InventoryName | None,
|
|
38
|
+
data: InventoryItem,
|
|
39
|
+
node: pending_xref,
|
|
40
|
+
contnode: TextElement,
|
|
41
|
+
) -> nodes.reference:
|
|
38
42
|
proj, version, uri, dispname = data
|
|
39
43
|
if '://' not in uri and node.get('refdoc'):
|
|
40
44
|
# get correct path in case of subdirectories
|
|
@@ -51,8 +55,11 @@ def _create_element_from_result(domain: Domain, inv_name: InventoryName | None,
|
|
|
51
55
|
# use whatever title was given, but strip prefix
|
|
52
56
|
title = contnode.astext()
|
|
53
57
|
if inv_name is not None and title.startswith(inv_name + ':'):
|
|
54
|
-
newnode.append(
|
|
55
|
-
|
|
58
|
+
newnode.append(
|
|
59
|
+
contnode.__class__(
|
|
60
|
+
title[len(inv_name) + 1 :], title[len(inv_name) + 1 :]
|
|
61
|
+
)
|
|
62
|
+
)
|
|
56
63
|
else:
|
|
57
64
|
newnode.append(contnode)
|
|
58
65
|
else:
|
|
@@ -62,10 +69,14 @@ def _create_element_from_result(domain: Domain, inv_name: InventoryName | None,
|
|
|
62
69
|
|
|
63
70
|
|
|
64
71
|
def _resolve_reference_in_domain_by_target(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
inv_name: InventoryName | None,
|
|
73
|
+
inventory: Inventory,
|
|
74
|
+
domain: Domain,
|
|
75
|
+
objtypes: Iterable[str],
|
|
76
|
+
target: str,
|
|
77
|
+
node: pending_xref,
|
|
78
|
+
contnode: TextElement,
|
|
79
|
+
) -> nodes.reference | None:
|
|
69
80
|
for objtype in objtypes:
|
|
70
81
|
if objtype not in inventory:
|
|
71
82
|
# Continue if there's nothing of this kind in the inventory
|
|
@@ -79,13 +90,34 @@ def _resolve_reference_in_domain_by_target(
|
|
|
79
90
|
# * 'term': https://github.com/sphinx-doc/sphinx/issues/9291
|
|
80
91
|
# * 'label': https://github.com/sphinx-doc/sphinx/issues/12008
|
|
81
92
|
target_lower = target.lower()
|
|
82
|
-
insensitive_matches = list(
|
|
83
|
-
|
|
93
|
+
insensitive_matches = list(
|
|
94
|
+
filter(lambda k: k.lower() == target_lower, inventory[objtype].keys())
|
|
95
|
+
)
|
|
84
96
|
if len(insensitive_matches) > 1:
|
|
97
|
+
data_items = {
|
|
98
|
+
inventory[objtype][match] for match in insensitive_matches
|
|
99
|
+
}
|
|
85
100
|
inv_descriptor = inv_name or 'main_inventory'
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
101
|
+
if len(data_items) == 1: # these are duplicates; relatively innocuous
|
|
102
|
+
LOGGER.debug(
|
|
103
|
+
__("inventory '%s': duplicate matches found for %s:%s"),
|
|
104
|
+
inv_descriptor,
|
|
105
|
+
objtype,
|
|
106
|
+
target,
|
|
107
|
+
type='intersphinx',
|
|
108
|
+
subtype='external',
|
|
109
|
+
location=node,
|
|
110
|
+
)
|
|
111
|
+
else:
|
|
112
|
+
LOGGER.warning(
|
|
113
|
+
__("inventory '%s': multiple matches found for %s:%s"),
|
|
114
|
+
inv_descriptor,
|
|
115
|
+
objtype,
|
|
116
|
+
target,
|
|
117
|
+
type='intersphinx',
|
|
118
|
+
subtype='external',
|
|
119
|
+
location=node,
|
|
120
|
+
)
|
|
89
121
|
if insensitive_matches:
|
|
90
122
|
data = inventory[objtype][insensitive_matches[0]]
|
|
91
123
|
else:
|
|
@@ -100,12 +132,16 @@ def _resolve_reference_in_domain_by_target(
|
|
|
100
132
|
return None
|
|
101
133
|
|
|
102
134
|
|
|
103
|
-
def _resolve_reference_in_domain(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
135
|
+
def _resolve_reference_in_domain(
|
|
136
|
+
env: BuildEnvironment,
|
|
137
|
+
inv_name: InventoryName | None,
|
|
138
|
+
inventory: Inventory,
|
|
139
|
+
honor_disabled_refs: bool,
|
|
140
|
+
domain: Domain,
|
|
141
|
+
objtypes: Iterable[str],
|
|
142
|
+
node: pending_xref,
|
|
143
|
+
contnode: TextElement,
|
|
144
|
+
) -> nodes.reference | None:
|
|
109
145
|
obj_types: dict[str, None] = {}.fromkeys(objtypes)
|
|
110
146
|
|
|
111
147
|
# we adjust the object types for backwards compatibility
|
|
@@ -123,15 +159,16 @@ def _resolve_reference_in_domain(env: BuildEnvironment,
|
|
|
123
159
|
# now that the objtypes list is complete we can remove the disabled ones
|
|
124
160
|
if honor_disabled_refs:
|
|
125
161
|
disabled = set(env.config.intersphinx_disabled_reftypes)
|
|
126
|
-
obj_types = {
|
|
127
|
-
|
|
128
|
-
|
|
162
|
+
obj_types = {
|
|
163
|
+
obj_type: None for obj_type in obj_types if obj_type not in disabled
|
|
164
|
+
}
|
|
129
165
|
|
|
130
166
|
objtypes = [*obj_types.keys()]
|
|
131
167
|
|
|
132
168
|
# without qualification
|
|
133
|
-
res = _resolve_reference_in_domain_by_target(
|
|
134
|
-
|
|
169
|
+
res = _resolve_reference_in_domain_by_target(
|
|
170
|
+
inv_name, inventory, domain, objtypes, node['reftarget'], node, contnode
|
|
171
|
+
)
|
|
135
172
|
if res is not None:
|
|
136
173
|
return res
|
|
137
174
|
|
|
@@ -139,14 +176,19 @@ def _resolve_reference_in_domain(env: BuildEnvironment,
|
|
|
139
176
|
full_qualified_name = domain.get_full_qualified_name(node)
|
|
140
177
|
if full_qualified_name is None:
|
|
141
178
|
return None
|
|
142
|
-
return _resolve_reference_in_domain_by_target(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
179
|
+
return _resolve_reference_in_domain_by_target(
|
|
180
|
+
inv_name, inventory, domain, objtypes, full_qualified_name, node, contnode
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _resolve_reference(
|
|
185
|
+
env: BuildEnvironment,
|
|
186
|
+
inv_name: InventoryName | None,
|
|
187
|
+
inventory: Inventory,
|
|
188
|
+
honor_disabled_refs: bool,
|
|
189
|
+
node: pending_xref,
|
|
190
|
+
contnode: TextElement,
|
|
191
|
+
) -> nodes.reference | None:
|
|
150
192
|
# disabling should only be done if no inventory is given
|
|
151
193
|
honor_disabled_refs = honor_disabled_refs and inv_name is None
|
|
152
194
|
intersphinx_disabled_reftypes = env.config.intersphinx_disabled_reftypes
|
|
@@ -156,14 +198,23 @@ def _resolve_reference(env: BuildEnvironment,
|
|
|
156
198
|
|
|
157
199
|
typ = node['reftype']
|
|
158
200
|
if typ == 'any':
|
|
159
|
-
for
|
|
160
|
-
if
|
|
201
|
+
for domain in env.domains.sorted():
|
|
202
|
+
if (
|
|
203
|
+
honor_disabled_refs
|
|
204
|
+
and f'{domain.name}:*' in intersphinx_disabled_reftypes
|
|
205
|
+
):
|
|
161
206
|
continue
|
|
162
207
|
objtypes: Iterable[str] = domain.object_types.keys()
|
|
163
|
-
res = _resolve_reference_in_domain(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
208
|
+
res = _resolve_reference_in_domain(
|
|
209
|
+
env,
|
|
210
|
+
inv_name,
|
|
211
|
+
inventory,
|
|
212
|
+
honor_disabled_refs,
|
|
213
|
+
domain,
|
|
214
|
+
objtypes,
|
|
215
|
+
node,
|
|
216
|
+
contnode,
|
|
217
|
+
)
|
|
167
218
|
if res is not None:
|
|
168
219
|
return res
|
|
169
220
|
return None
|
|
@@ -178,20 +229,28 @@ def _resolve_reference(env: BuildEnvironment,
|
|
|
178
229
|
objtypes = domain.objtypes_for_role(typ) or ()
|
|
179
230
|
if not objtypes:
|
|
180
231
|
return None
|
|
181
|
-
return _resolve_reference_in_domain(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
232
|
+
return _resolve_reference_in_domain(
|
|
233
|
+
env,
|
|
234
|
+
inv_name,
|
|
235
|
+
inventory,
|
|
236
|
+
honor_disabled_refs,
|
|
237
|
+
domain,
|
|
238
|
+
objtypes,
|
|
239
|
+
node,
|
|
240
|
+
contnode,
|
|
241
|
+
)
|
|
185
242
|
|
|
186
243
|
|
|
187
244
|
def inventory_exists(env: BuildEnvironment, inv_name: InventoryName) -> bool:
|
|
188
245
|
return inv_name in InventoryAdapter(env).named_inventory
|
|
189
246
|
|
|
190
247
|
|
|
191
|
-
def resolve_reference_in_inventory(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
248
|
+
def resolve_reference_in_inventory(
|
|
249
|
+
env: BuildEnvironment,
|
|
250
|
+
inv_name: InventoryName,
|
|
251
|
+
node: pending_xref,
|
|
252
|
+
contnode: TextElement,
|
|
253
|
+
) -> nodes.reference | None:
|
|
195
254
|
"""Attempt to resolve a missing reference via intersphinx references.
|
|
196
255
|
|
|
197
256
|
Resolution is tried in the given inventory with the target as is.
|
|
@@ -199,26 +258,39 @@ def resolve_reference_in_inventory(env: BuildEnvironment,
|
|
|
199
258
|
Requires ``inventory_exists(env, inv_name)``.
|
|
200
259
|
"""
|
|
201
260
|
assert inventory_exists(env, inv_name)
|
|
202
|
-
return _resolve_reference(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
261
|
+
return _resolve_reference(
|
|
262
|
+
env,
|
|
263
|
+
inv_name,
|
|
264
|
+
InventoryAdapter(env).named_inventory[inv_name],
|
|
265
|
+
False,
|
|
266
|
+
node,
|
|
267
|
+
contnode,
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def resolve_reference_any_inventory(
|
|
272
|
+
env: BuildEnvironment,
|
|
273
|
+
honor_disabled_refs: bool,
|
|
274
|
+
node: pending_xref,
|
|
275
|
+
contnode: TextElement,
|
|
276
|
+
) -> nodes.reference | None:
|
|
210
277
|
"""Attempt to resolve a missing reference via intersphinx references.
|
|
211
278
|
|
|
212
279
|
Resolution is tried with the target as is in any inventory.
|
|
213
280
|
"""
|
|
214
|
-
return _resolve_reference(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
281
|
+
return _resolve_reference(
|
|
282
|
+
env,
|
|
283
|
+
None,
|
|
284
|
+
InventoryAdapter(env).main_inventory,
|
|
285
|
+
honor_disabled_refs,
|
|
286
|
+
node,
|
|
287
|
+
contnode,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def resolve_reference_detect_inventory(
|
|
292
|
+
env: BuildEnvironment, node: pending_xref, contnode: TextElement
|
|
293
|
+
) -> nodes.reference | None:
|
|
222
294
|
"""Attempt to resolve a missing reference via intersphinx references.
|
|
223
295
|
|
|
224
296
|
Resolution is tried first with the target as is in any inventory.
|
|
@@ -244,8 +316,9 @@ def resolve_reference_detect_inventory(env: BuildEnvironment,
|
|
|
244
316
|
return res_inv
|
|
245
317
|
|
|
246
318
|
|
|
247
|
-
def missing_reference(
|
|
248
|
-
|
|
319
|
+
def missing_reference(
|
|
320
|
+
app: Sphinx, env: BuildEnvironment, node: pending_xref, contnode: TextElement
|
|
321
|
+
) -> nodes.reference | None:
|
|
249
322
|
"""Attempt to resolve a missing reference via intersphinx references."""
|
|
250
323
|
return resolve_reference_detect_inventory(env, node, contnode)
|
|
251
324
|
|
|
@@ -257,7 +330,11 @@ class IntersphinxDispatcher(CustomReSTDispatcher):
|
|
|
257
330
|
"""
|
|
258
331
|
|
|
259
332
|
def role(
|
|
260
|
-
self,
|
|
333
|
+
self,
|
|
334
|
+
role_name: str,
|
|
335
|
+
language_module: ModuleType,
|
|
336
|
+
lineno: int,
|
|
337
|
+
reporter: Reporter,
|
|
261
338
|
) -> tuple[RoleFunction, list[system_message]]:
|
|
262
339
|
if len(role_name) > 9 and role_name.startswith(('external:', 'external+')):
|
|
263
340
|
return IntersphinxRole(role_name), []
|
|
@@ -296,16 +373,17 @@ class IntersphinxRole(SphinxRole):
|
|
|
296
373
|
|
|
297
374
|
if domain_name is not None:
|
|
298
375
|
# the user specified a domain, so we only check that
|
|
299
|
-
if
|
|
376
|
+
if domain_name not in self.env.domains:
|
|
300
377
|
self._emit_warning(
|
|
301
378
|
__('domain for external cross-reference not found: %r'), domain_name
|
|
302
379
|
)
|
|
303
380
|
return [], []
|
|
304
|
-
|
|
381
|
+
domain = self.env.domains[domain_name]
|
|
382
|
+
role_func = domain.roles.get(role_name)
|
|
383
|
+
if role_func is None:
|
|
305
384
|
msg = 'role for external cross-reference not found in domain %r: %r'
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
) is not None and object_types.roles:
|
|
385
|
+
object_types = domain.object_types.get(role_name)
|
|
386
|
+
if object_types is not None and object_types.roles:
|
|
309
387
|
self._emit_warning(
|
|
310
388
|
__(f'{msg} (perhaps you meant one of: %s)'),
|
|
311
389
|
domain_name,
|
|
@@ -323,7 +401,7 @@ class IntersphinxRole(SphinxRole):
|
|
|
323
401
|
if default_domain := self.env.temp_data.get('default_domain'):
|
|
324
402
|
domains.append(default_domain)
|
|
325
403
|
if (
|
|
326
|
-
std_domain := self.env.domains.
|
|
404
|
+
std_domain := self.env.domains.standard_domain
|
|
327
405
|
) is not None and std_domain not in domains:
|
|
328
406
|
domains.append(std_domain)
|
|
329
407
|
|
|
@@ -454,7 +532,9 @@ class IntersphinxRole(SphinxRole):
|
|
|
454
532
|
except ExtensionError:
|
|
455
533
|
return False
|
|
456
534
|
|
|
457
|
-
def invoke_role(
|
|
535
|
+
def invoke_role(
|
|
536
|
+
self, role: tuple[str, str]
|
|
537
|
+
) -> tuple[list[Node], list[system_message]]:
|
|
458
538
|
"""Invoke the role described by a ``(domain, role name)`` pair."""
|
|
459
539
|
_deprecation_warning(
|
|
460
540
|
__name__, f'{self.__class__.__name__}.invoke_role', '', remove=(9, 0)
|
|
@@ -464,8 +544,15 @@ class IntersphinxRole(SphinxRole):
|
|
|
464
544
|
role_func = domain.role(role[1])
|
|
465
545
|
assert role_func is not None
|
|
466
546
|
|
|
467
|
-
return role_func(
|
|
468
|
-
|
|
547
|
+
return role_func(
|
|
548
|
+
':'.join(role),
|
|
549
|
+
self.rawtext,
|
|
550
|
+
self.text,
|
|
551
|
+
self.lineno,
|
|
552
|
+
self.inliner,
|
|
553
|
+
self.options,
|
|
554
|
+
self.content,
|
|
555
|
+
)
|
|
469
556
|
else:
|
|
470
557
|
return [], []
|
|
471
558
|
|
|
@@ -486,13 +573,20 @@ class IntersphinxRoleResolver(ReferencesResolver):
|
|
|
486
573
|
inv_name = node['inventory']
|
|
487
574
|
if inv_name is not None:
|
|
488
575
|
assert inventory_exists(self.env, inv_name)
|
|
489
|
-
newnode = resolve_reference_in_inventory(
|
|
576
|
+
newnode = resolve_reference_in_inventory(
|
|
577
|
+
self.env, inv_name, node, contnode
|
|
578
|
+
)
|
|
490
579
|
else:
|
|
491
|
-
newnode = resolve_reference_any_inventory(
|
|
580
|
+
newnode = resolve_reference_any_inventory(
|
|
581
|
+
self.env, False, node, contnode
|
|
582
|
+
)
|
|
492
583
|
if newnode is None:
|
|
493
584
|
typ = node['reftype']
|
|
494
|
-
msg =
|
|
495
|
-
|
|
585
|
+
msg = __('external %s:%s reference target not found: %s') % (
|
|
586
|
+
node['refdomain'],
|
|
587
|
+
typ,
|
|
588
|
+
node['reftarget'],
|
|
589
|
+
)
|
|
496
590
|
LOGGER.warning(msg, location=node, type='ref', subtype=typ)
|
|
497
591
|
node.replace_self(contnode)
|
|
498
592
|
else:
|
|
@@ -54,7 +54,7 @@ class _IntersphinxProject:
|
|
|
54
54
|
'locations': 'A tuple of local or remote targets containing '
|
|
55
55
|
'the inventory data to fetch. '
|
|
56
56
|
'None indicates the default inventory file name.',
|
|
57
|
-
}
|
|
57
|
+
} # fmt: skip
|
|
58
58
|
|
|
59
59
|
def __init__(
|
|
60
60
|
self,
|
|
@@ -83,10 +83,12 @@ class _IntersphinxProject:
|
|
|
83
83
|
object.__setattr__(self, 'locations', tuple(locations))
|
|
84
84
|
|
|
85
85
|
def __repr__(self) -> str:
|
|
86
|
-
return (
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
return (
|
|
87
|
+
f'{self.__class__.__name__}('
|
|
88
|
+
f'name={self.name!r}, '
|
|
89
|
+
f'target_uri={self.target_uri!r}, '
|
|
90
|
+
f'locations={self.locations!r})'
|
|
91
|
+
)
|
|
90
92
|
|
|
91
93
|
def __eq__(self, other: object) -> bool:
|
|
92
94
|
if not isinstance(other, _IntersphinxProject):
|
sphinx/ext/linkcode.py
CHANGED
|
@@ -31,6 +31,12 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
|
|
|
31
31
|
raise LinkcodeError(msg)
|
|
32
32
|
assert resolve_target is not None # for mypy
|
|
33
33
|
|
|
34
|
+
# By default, the linkcode extension will only inject references
|
|
35
|
+
# for an ``html`` builder. If a builder wishes to support managing
|
|
36
|
+
# references generated by linkcode as well, it can define the
|
|
37
|
+
# ``supported_linkcode`` attribute.
|
|
38
|
+
node_only_expr = getattr(app.builder, 'supported_linkcode', 'html')
|
|
39
|
+
|
|
34
40
|
domain_keys = {
|
|
35
41
|
'py': ['module', 'fullname'],
|
|
36
42
|
'c': ['names'],
|
|
@@ -67,7 +73,7 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
|
|
|
67
73
|
uris.add(uri)
|
|
68
74
|
|
|
69
75
|
inline = nodes.inline('', _('[source]'), classes=['viewcode-link'])
|
|
70
|
-
onlynode = addnodes.only(expr=
|
|
76
|
+
onlynode = addnodes.only(expr=node_only_expr)
|
|
71
77
|
onlynode += nodes.reference('', '', inline, internal=False, refuri=uri)
|
|
72
78
|
signode += onlynode
|
|
73
79
|
|