Sphinx 8.0.1__py3-none-any.whl → 8.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of Sphinx might be problematic. Click here for more details.
- sphinx/__init__.py +6 -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 +206 -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 +10 -3
- 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 +133 -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 +107 -39
- sphinx/texinputs/sphinxlatexadmonitions.sty +51 -35
- 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.0.dist-info/LICENSE.rst +31 -0
- {sphinx-8.0.1.dist-info → sphinx-8.1.0.dist-info}/METADATA +13 -11
- sphinx-8.1.0.dist-info/RECORD +598 -0
- sphinx-8.0.1.dist-info/LICENSE.rst +0 -67
- sphinx-8.0.1.dist-info/RECORD +0 -590
- {sphinx-8.0.1.dist-info → sphinx-8.1.0.dist-info}/WHEEL +0 -0
- {sphinx-8.0.1.dist-info → sphinx-8.1.0.dist-info}/entry_points.txt +0 -0
|
@@ -66,7 +66,7 @@ class ReferencesResolver(SphinxPostTransform):
|
|
|
66
66
|
|
|
67
67
|
def run(self, **kwargs: Any) -> None:
|
|
68
68
|
for node in self.document.findall(addnodes.pending_xref):
|
|
69
|
-
content = self.find_pending_xref_condition(node, (
|
|
69
|
+
content = self.find_pending_xref_condition(node, ('resolved', '*'))
|
|
70
70
|
if content:
|
|
71
71
|
contnode = cast(Element, content[0].deepcopy())
|
|
72
72
|
else:
|
|
@@ -87,16 +87,21 @@ class ReferencesResolver(SphinxPostTransform):
|
|
|
87
87
|
domain = self.env.domains[node['refdomain']]
|
|
88
88
|
except KeyError as exc:
|
|
89
89
|
raise NoUri(target, typ) from exc
|
|
90
|
-
newnode = domain.resolve_xref(
|
|
91
|
-
|
|
90
|
+
newnode = domain.resolve_xref(
|
|
91
|
+
self.env, refdoc, self.app.builder, typ, target, node, contnode
|
|
92
|
+
)
|
|
92
93
|
# really hardwired reference types
|
|
93
94
|
elif typ == 'any':
|
|
94
95
|
newnode = self.resolve_anyref(refdoc, node, contnode)
|
|
95
96
|
# no new node found? try the missing-reference event
|
|
96
97
|
if newnode is None:
|
|
97
|
-
newnode = self.app.emit_firstresult(
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
newnode = self.app.emit_firstresult(
|
|
99
|
+
'missing-reference',
|
|
100
|
+
self.env,
|
|
101
|
+
node,
|
|
102
|
+
contnode,
|
|
103
|
+
allowed_exceptions=(NoUri,),
|
|
104
|
+
)
|
|
100
105
|
# still not found? warn if node wishes to be warned about or
|
|
101
106
|
# we are in nitpicky mode
|
|
102
107
|
if newnode is None:
|
|
@@ -108,69 +113,103 @@ class ReferencesResolver(SphinxPostTransform):
|
|
|
108
113
|
newnodes: list[Node] = [newnode]
|
|
109
114
|
else:
|
|
110
115
|
newnodes = [contnode]
|
|
111
|
-
if newnode is None and isinstance(
|
|
112
|
-
|
|
116
|
+
if newnode is None and isinstance(
|
|
117
|
+
node[0], addnodes.pending_xref_condition
|
|
118
|
+
):
|
|
119
|
+
matched = self.find_pending_xref_condition(node, ('*',))
|
|
113
120
|
if matched:
|
|
114
121
|
newnodes = matched
|
|
115
122
|
else:
|
|
116
|
-
logger.warning(
|
|
117
|
-
|
|
123
|
+
logger.warning(
|
|
124
|
+
__(
|
|
125
|
+
'Could not determine the fallback text for the '
|
|
126
|
+
'cross-reference. Might be a bug.'
|
|
127
|
+
),
|
|
128
|
+
location=node,
|
|
129
|
+
)
|
|
118
130
|
|
|
119
131
|
node.replace_self(newnodes)
|
|
120
132
|
|
|
121
133
|
def resolve_anyref(
|
|
122
|
-
self,
|
|
134
|
+
self,
|
|
135
|
+
refdoc: str,
|
|
136
|
+
node: pending_xref,
|
|
137
|
+
contnode: Element,
|
|
123
138
|
) -> Element | None:
|
|
124
139
|
"""Resolve reference generated by the "any" role."""
|
|
125
|
-
stddomain = self.env.
|
|
140
|
+
stddomain = self.env.domains.standard_domain
|
|
126
141
|
target = node['reftarget']
|
|
127
142
|
results: list[tuple[str, Element]] = []
|
|
128
143
|
# first, try resolving as :doc:
|
|
129
|
-
doc_ref = stddomain.resolve_xref(
|
|
130
|
-
|
|
144
|
+
doc_ref = stddomain.resolve_xref(
|
|
145
|
+
self.env, refdoc, self.app.builder, 'doc', target, node, contnode
|
|
146
|
+
)
|
|
131
147
|
if doc_ref:
|
|
132
148
|
results.append(('doc', doc_ref))
|
|
133
149
|
# next, do the standard domain (makes this a priority)
|
|
134
|
-
results.extend(
|
|
135
|
-
|
|
136
|
-
|
|
150
|
+
results.extend(
|
|
151
|
+
stddomain.resolve_any_xref(
|
|
152
|
+
self.env, refdoc, self.app.builder, target, node, contnode
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
for domain in self.env.domains.sorted():
|
|
137
156
|
if domain.name == 'std':
|
|
138
157
|
continue # we did this one already
|
|
139
158
|
try:
|
|
140
|
-
results.extend(
|
|
141
|
-
|
|
159
|
+
results.extend(
|
|
160
|
+
domain.resolve_any_xref(
|
|
161
|
+
self.env, refdoc, self.app.builder, target, node, contnode
|
|
162
|
+
)
|
|
163
|
+
)
|
|
142
164
|
except NotImplementedError:
|
|
143
165
|
# the domain doesn't yet support the new interface
|
|
144
166
|
# we have to manually collect possible references (SLOW)
|
|
145
167
|
for role in domain.roles:
|
|
146
|
-
res = domain.resolve_xref(
|
|
147
|
-
|
|
168
|
+
res = domain.resolve_xref(
|
|
169
|
+
self.env, refdoc, self.app.builder, role, target, node, contnode
|
|
170
|
+
)
|
|
148
171
|
if res and len(res) > 0 and isinstance(res[0], nodes.Element):
|
|
149
172
|
results.append((f'{domain.name}:{role}', res))
|
|
150
173
|
# now, see how many matches we got...
|
|
151
174
|
if not results:
|
|
152
175
|
return None
|
|
153
176
|
if len(results) > 1:
|
|
177
|
+
|
|
154
178
|
def stringify(name: str, node: Element) -> str:
|
|
155
179
|
reftitle = node.get('reftitle', node.astext())
|
|
156
180
|
return f':{name}:`{reftitle}`'
|
|
181
|
+
|
|
157
182
|
candidates = ' or '.join(starmap(stringify, results))
|
|
158
|
-
logger.warning(
|
|
159
|
-
|
|
160
|
-
|
|
183
|
+
logger.warning(
|
|
184
|
+
__(
|
|
185
|
+
"more than one target found for 'any' cross-"
|
|
186
|
+
'reference %r: could be %s'
|
|
187
|
+
),
|
|
188
|
+
target,
|
|
189
|
+
candidates,
|
|
190
|
+
location=node,
|
|
191
|
+
)
|
|
161
192
|
res_role, newnode = results[0]
|
|
162
193
|
# Override "any" class with the actual role type to get the styling
|
|
163
194
|
# approximately correct.
|
|
164
195
|
res_domain = res_role.split(':')[0]
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
|
|
196
|
+
if (
|
|
197
|
+
len(newnode) > 0
|
|
198
|
+
and isinstance(newnode[0], nodes.Element)
|
|
199
|
+
and newnode[0].get('classes')
|
|
200
|
+
):
|
|
168
201
|
newnode[0]['classes'].append(res_domain)
|
|
169
202
|
newnode[0]['classes'].append(res_role.replace(':', '-'))
|
|
170
203
|
return newnode
|
|
171
204
|
|
|
172
|
-
def warn_missing_reference(
|
|
173
|
-
|
|
205
|
+
def warn_missing_reference(
|
|
206
|
+
self,
|
|
207
|
+
refdoc: str,
|
|
208
|
+
typ: str,
|
|
209
|
+
target: str,
|
|
210
|
+
node: pending_xref,
|
|
211
|
+
domain: Domain | None,
|
|
212
|
+
) -> None:
|
|
174
213
|
warn = node.get('refwarn')
|
|
175
214
|
if self.config.nitpicky:
|
|
176
215
|
warn = True
|
|
@@ -179,24 +218,26 @@ class ReferencesResolver(SphinxPostTransform):
|
|
|
179
218
|
if (dtype, target) in self.config.nitpick_ignore:
|
|
180
219
|
warn = False
|
|
181
220
|
# for "std" types also try without domain name
|
|
182
|
-
if (
|
|
183
|
-
|
|
221
|
+
if (
|
|
222
|
+
(not domain or domain.name == 'std')
|
|
223
|
+
and (typ, target) in self.config.nitpick_ignore
|
|
224
|
+
): # fmt: skip
|
|
184
225
|
warn = False
|
|
185
226
|
if self.config.nitpick_ignore_regex:
|
|
227
|
+
|
|
186
228
|
def matches_ignore(entry_type: str, entry_target: str) -> bool:
|
|
187
229
|
return any(
|
|
188
230
|
(
|
|
189
231
|
re.fullmatch(ignore_type, entry_type)
|
|
190
232
|
and re.fullmatch(ignore_target, entry_target)
|
|
191
233
|
)
|
|
192
|
-
for ignore_type, ignore_target
|
|
193
|
-
in self.config.nitpick_ignore_regex
|
|
234
|
+
for ignore_type, ignore_target in self.config.nitpick_ignore_regex
|
|
194
235
|
)
|
|
236
|
+
|
|
195
237
|
if matches_ignore(dtype, target):
|
|
196
238
|
warn = False
|
|
197
239
|
# for "std" types also try without domain name
|
|
198
|
-
if (not domain or domain.name == 'std') and
|
|
199
|
-
matches_ignore(typ, target):
|
|
240
|
+
if (not domain or domain.name == 'std') and matches_ignore(typ, target):
|
|
200
241
|
warn = False
|
|
201
242
|
if not warn:
|
|
202
243
|
return
|
|
@@ -206,14 +247,20 @@ class ReferencesResolver(SphinxPostTransform):
|
|
|
206
247
|
elif domain and typ in domain.dangling_warnings:
|
|
207
248
|
msg = domain.dangling_warnings[typ] % {'target': target}
|
|
208
249
|
elif node.get('refdomain', 'std') not in ('', 'std'):
|
|
209
|
-
msg =
|
|
210
|
-
|
|
250
|
+
msg = __('%s:%s reference target not found: %s') % (
|
|
251
|
+
node['refdomain'],
|
|
252
|
+
typ,
|
|
253
|
+
target,
|
|
254
|
+
)
|
|
211
255
|
else:
|
|
212
256
|
msg = __('%r reference target not found: %s') % (typ, target)
|
|
213
257
|
logger.warning(msg, location=node, type='ref', subtype=typ)
|
|
214
258
|
|
|
215
|
-
def find_pending_xref_condition(
|
|
216
|
-
|
|
259
|
+
def find_pending_xref_condition(
|
|
260
|
+
self,
|
|
261
|
+
node: pending_xref,
|
|
262
|
+
conditions: Sequence[str],
|
|
263
|
+
) -> list[Node] | None:
|
|
217
264
|
for condition in conditions:
|
|
218
265
|
matched = find_pending_xref_condition(node, condition)
|
|
219
266
|
if matched:
|
|
@@ -238,8 +285,10 @@ class SigElementFallbackTransform(SphinxPostTransform):
|
|
|
238
285
|
default_priority = 200
|
|
239
286
|
|
|
240
287
|
def run(self, **kwargs: Any) -> None:
|
|
241
|
-
def has_visitor(
|
|
242
|
-
|
|
288
|
+
def has_visitor(
|
|
289
|
+
translator: type[nodes.NodeVisitor], node: type[Element]
|
|
290
|
+
) -> bool:
|
|
291
|
+
return hasattr(translator, 'visit_%s' % node.__name__)
|
|
243
292
|
|
|
244
293
|
try:
|
|
245
294
|
translator = self.app.builder.get_translator_class()
|
|
@@ -253,8 +302,10 @@ class SigElementFallbackTransform(SphinxPostTransform):
|
|
|
253
302
|
|
|
254
303
|
# for the leaf elements (desc_sig_element), the translator should support _all_,
|
|
255
304
|
# unless there exists a generic visit_desc_sig_element default visitor
|
|
256
|
-
if (
|
|
257
|
-
|
|
305
|
+
if (
|
|
306
|
+
not all(has_visitor(translator, node) for node in addnodes.SIG_ELEMENTS)
|
|
307
|
+
and not has_visitor(translator, addnodes.desc_sig_element)
|
|
308
|
+
): # fmt: skip
|
|
258
309
|
self.fallback(addnodes.desc_sig_element)
|
|
259
310
|
|
|
260
311
|
if not has_visitor(translator, addnodes.desc_inline):
|
|
@@ -37,8 +37,9 @@ class HighlightLanguageTransform(SphinxTransform):
|
|
|
37
37
|
default_priority = 400
|
|
38
38
|
|
|
39
39
|
def apply(self, **kwargs: Any) -> None:
|
|
40
|
-
visitor = HighlightLanguageVisitor(
|
|
41
|
-
|
|
40
|
+
visitor = HighlightLanguageVisitor(
|
|
41
|
+
self.document, self.config.highlight_language
|
|
42
|
+
)
|
|
42
43
|
self.document.walkabout(visitor)
|
|
43
44
|
|
|
44
45
|
for node in list(self.document.findall(addnodes.highlightlang)):
|
|
@@ -70,9 +71,9 @@ class HighlightLanguageVisitor(nodes.NodeVisitor):
|
|
|
70
71
|
self.settings.pop()
|
|
71
72
|
|
|
72
73
|
def visit_highlightlang(self, node: addnodes.highlightlang) -> None:
|
|
73
|
-
self.settings[-1] = HighlightSetting(
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
self.settings[-1] = HighlightSetting(
|
|
75
|
+
node['lang'], node['force'], node['linenothreshold']
|
|
76
|
+
)
|
|
76
77
|
|
|
77
78
|
def visit_literal_block(self, node: nodes.literal_block) -> None:
|
|
78
79
|
setting = self.settings[-1]
|
|
@@ -81,7 +82,7 @@ class HighlightLanguageVisitor(nodes.NodeVisitor):
|
|
|
81
82
|
node['force'] = setting.force
|
|
82
83
|
if 'linenos' not in node:
|
|
83
84
|
lines = node.astext().count('\n')
|
|
84
|
-
node['linenos'] =
|
|
85
|
+
node['linenos'] = lines >= setting.lineno_threshold - 1
|
|
85
86
|
|
|
86
87
|
|
|
87
88
|
class TrimDoctestFlagsTransform(SphinxTransform):
|
|
@@ -6,6 +6,7 @@ import os
|
|
|
6
6
|
import re
|
|
7
7
|
from hashlib import sha1
|
|
8
8
|
from math import ceil
|
|
9
|
+
from pathlib import Path
|
|
9
10
|
from typing import TYPE_CHECKING, Any
|
|
10
11
|
|
|
11
12
|
from docutils import nodes
|
|
@@ -13,6 +14,7 @@ from docutils import nodes
|
|
|
13
14
|
from sphinx.locale import __
|
|
14
15
|
from sphinx.transforms import SphinxTransform
|
|
15
16
|
from sphinx.util import logging, requests
|
|
17
|
+
from sphinx.util._pathlib import _StrPath
|
|
16
18
|
from sphinx.util.http_date import epoch_to_rfc1123, rfc1123_to_epoch
|
|
17
19
|
from sphinx.util.images import get_image_extension, guess_mimetype, parse_data_uri
|
|
18
20
|
from sphinx.util.osutil import ensuredir
|
|
@@ -61,54 +63,65 @@ class ImageDownloader(BaseImageConverter):
|
|
|
61
63
|
basename = basename.split('?')[0]
|
|
62
64
|
if basename == '' or len(basename) > MAX_FILENAME_LEN:
|
|
63
65
|
filename, ext = os.path.splitext(node['uri'])
|
|
64
|
-
basename =
|
|
65
|
-
|
|
66
|
+
basename = (
|
|
67
|
+
sha1(filename.encode(), usedforsecurity=False).hexdigest() + ext
|
|
68
|
+
)
|
|
69
|
+
basename = CRITICAL_PATH_CHAR_RE.sub('_', basename)
|
|
66
70
|
|
|
67
71
|
uri_hash = sha1(node['uri'].encode(), usedforsecurity=False).hexdigest()
|
|
68
|
-
|
|
69
|
-
path
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if os.path.exists(path):
|
|
73
|
-
timestamp: float = ceil(os.stat(path).st_mtime)
|
|
74
|
-
headers['If-Modified-Since'] = epoch_to_rfc1123(timestamp)
|
|
75
|
-
|
|
76
|
-
config = self.app.config
|
|
77
|
-
r = requests.get(
|
|
78
|
-
node['uri'], headers=headers,
|
|
79
|
-
_user_agent=config.user_agent,
|
|
80
|
-
_tls_info=(config.tls_verify, config.tls_cacerts),
|
|
81
|
-
)
|
|
82
|
-
if r.status_code >= 400:
|
|
83
|
-
logger.warning(__('Could not fetch remote image: %s [%d]'),
|
|
84
|
-
node['uri'], r.status_code)
|
|
85
|
-
else:
|
|
86
|
-
self.app.env.original_image_uri[path] = node['uri']
|
|
87
|
-
|
|
88
|
-
if r.status_code == 200:
|
|
89
|
-
with open(path, 'wb') as f:
|
|
90
|
-
f.write(r.content)
|
|
91
|
-
|
|
92
|
-
last_modified = r.headers.get('last-modified')
|
|
93
|
-
if last_modified:
|
|
94
|
-
timestamp = rfc1123_to_epoch(last_modified)
|
|
95
|
-
os.utime(path, (timestamp, timestamp))
|
|
96
|
-
|
|
97
|
-
mimetype = guess_mimetype(path, default='*')
|
|
98
|
-
if mimetype != '*' and os.path.splitext(basename)[1] == '':
|
|
99
|
-
# append a suffix if URI does not contain suffix
|
|
100
|
-
ext = get_image_extension(mimetype)
|
|
101
|
-
newpath = os.path.join(self.imagedir, uri_hash, basename + ext)
|
|
102
|
-
os.replace(path, newpath)
|
|
103
|
-
self.app.env.original_image_uri.pop(path)
|
|
104
|
-
self.app.env.original_image_uri[newpath] = node['uri']
|
|
105
|
-
path = newpath
|
|
106
|
-
node['candidates'].pop('?')
|
|
107
|
-
node['candidates'][mimetype] = path
|
|
108
|
-
node['uri'] = path
|
|
109
|
-
self.app.env.images.add_file(self.env.docname, path)
|
|
72
|
+
path = Path(self.imagedir, uri_hash, basename)
|
|
73
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
74
|
+
self._download_image(node, path)
|
|
75
|
+
|
|
110
76
|
except Exception as exc:
|
|
111
|
-
|
|
77
|
+
msg = __('Could not fetch remote image: %s [%s]')
|
|
78
|
+
logger.warning(msg, node['uri'], exc)
|
|
79
|
+
|
|
80
|
+
def _download_image(self, node: nodes.image, path: Path) -> None:
|
|
81
|
+
headers = {}
|
|
82
|
+
if path.exists():
|
|
83
|
+
timestamp: float = ceil(path.stat().st_mtime)
|
|
84
|
+
headers['If-Modified-Since'] = epoch_to_rfc1123(timestamp)
|
|
85
|
+
|
|
86
|
+
config = self.app.config
|
|
87
|
+
r = requests.get(
|
|
88
|
+
node['uri'],
|
|
89
|
+
headers=headers,
|
|
90
|
+
_user_agent=config.user_agent,
|
|
91
|
+
_tls_info=(config.tls_verify, config.tls_cacerts),
|
|
92
|
+
)
|
|
93
|
+
if r.status_code >= 400:
|
|
94
|
+
msg = __('Could not fetch remote image: %s [%d]')
|
|
95
|
+
logger.warning(msg, node['uri'], r.status_code)
|
|
96
|
+
else:
|
|
97
|
+
self.app.env.original_image_uri[_StrPath(path)] = node['uri']
|
|
98
|
+
|
|
99
|
+
if r.status_code == 200:
|
|
100
|
+
path.write_bytes(r.content)
|
|
101
|
+
if last_modified := r.headers.get('Last-Modified'):
|
|
102
|
+
timestamp = rfc1123_to_epoch(last_modified)
|
|
103
|
+
os.utime(path, (timestamp, timestamp))
|
|
104
|
+
|
|
105
|
+
self._process_image(node, path)
|
|
106
|
+
|
|
107
|
+
def _process_image(self, node: nodes.image, path: Path) -> None:
|
|
108
|
+
str_path = _StrPath(path)
|
|
109
|
+
self.app.env.original_image_uri[str_path] = node['uri']
|
|
110
|
+
|
|
111
|
+
mimetype = guess_mimetype(path, default='*')
|
|
112
|
+
if mimetype != '*' and path.suffix == '':
|
|
113
|
+
# append a suffix if URI does not contain suffix
|
|
114
|
+
ext = get_image_extension(mimetype) or ''
|
|
115
|
+
with_ext = path.with_name(path.name + ext)
|
|
116
|
+
os.replace(path, with_ext)
|
|
117
|
+
self.app.env.original_image_uri.pop(str_path)
|
|
118
|
+
self.app.env.original_image_uri[_StrPath(with_ext)] = node['uri']
|
|
119
|
+
path = with_ext
|
|
120
|
+
path_str = str(path)
|
|
121
|
+
node['candidates'].pop('?')
|
|
122
|
+
node['candidates'][mimetype] = path_str
|
|
123
|
+
node['uri'] = path_str
|
|
124
|
+
self.app.env.images.add_file(self.env.docname, path_str)
|
|
112
125
|
|
|
113
126
|
|
|
114
127
|
class DataURIExtractor(BaseImageConverter):
|
|
@@ -124,27 +137,29 @@ class DataURIExtractor(BaseImageConverter):
|
|
|
124
137
|
assert image is not None
|
|
125
138
|
ext = get_image_extension(image.mimetype)
|
|
126
139
|
if ext is None:
|
|
127
|
-
logger.warning(
|
|
128
|
-
|
|
140
|
+
logger.warning(
|
|
141
|
+
__('Unknown image format: %s...'), node['uri'][:32], location=node
|
|
142
|
+
)
|
|
129
143
|
return
|
|
130
144
|
|
|
131
145
|
ensuredir(os.path.join(self.imagedir, 'embeded'))
|
|
132
146
|
digest = sha1(image.data, usedforsecurity=False).hexdigest()
|
|
133
|
-
path =
|
|
147
|
+
path = _StrPath(self.imagedir, 'embeded', digest + ext)
|
|
134
148
|
self.app.env.original_image_uri[path] = node['uri']
|
|
135
149
|
|
|
136
150
|
with open(path, 'wb') as f:
|
|
137
151
|
f.write(image.data)
|
|
138
152
|
|
|
153
|
+
path_str = str(path)
|
|
139
154
|
node['candidates'].pop('?')
|
|
140
|
-
node['candidates'][image.mimetype] =
|
|
141
|
-
node['uri'] =
|
|
142
|
-
self.app.env.images.add_file(self.env.docname,
|
|
155
|
+
node['candidates'][image.mimetype] = path_str
|
|
156
|
+
node['uri'] = path_str
|
|
157
|
+
self.app.env.images.add_file(self.env.docname, path_str)
|
|
143
158
|
|
|
144
159
|
|
|
145
160
|
def get_filename_for(filename: str, mimetype: str) -> str:
|
|
146
161
|
basename = os.path.basename(filename)
|
|
147
|
-
basename = CRITICAL_PATH_CHAR_RE.sub(
|
|
162
|
+
basename = CRITICAL_PATH_CHAR_RE.sub('_', basename)
|
|
148
163
|
return os.path.splitext(basename)[0] + (get_image_extension(mimetype) or '')
|
|
149
164
|
|
|
150
165
|
|
|
@@ -195,7 +210,9 @@ class ImageConverter(BaseImageConverter):
|
|
|
195
210
|
return False
|
|
196
211
|
if '?' in node['candidates']:
|
|
197
212
|
return False
|
|
198
|
-
|
|
213
|
+
node_mime_types = set(self.guess_mimetypes(node))
|
|
214
|
+
supported_image_types = set(self.app.builder.supported_image_types)
|
|
215
|
+
if node_mime_types & supported_image_types:
|
|
199
216
|
# builder supports the image; no need to convert
|
|
200
217
|
return False
|
|
201
218
|
if self.available is None:
|
|
@@ -258,7 +275,7 @@ class ImageConverter(BaseImageConverter):
|
|
|
258
275
|
node['candidates'][_to] = destpath
|
|
259
276
|
node['uri'] = destpath
|
|
260
277
|
|
|
261
|
-
self.env.original_image_uri[destpath] = srcpath
|
|
278
|
+
self.env.original_image_uri[_StrPath(destpath)] = srcpath
|
|
262
279
|
self.env.images.add_file(self.env.docname, destpath)
|
|
263
280
|
|
|
264
281
|
def convert(self, _from: str, _to: str) -> bool:
|
sphinx/transforms/references.py
CHANGED
|
@@ -34,8 +34,7 @@ class SphinxDomains(SphinxTransform):
|
|
|
34
34
|
default_priority = 850
|
|
35
35
|
|
|
36
36
|
def apply(self, **kwargs: Any) -> None:
|
|
37
|
-
|
|
38
|
-
domain.process_doc(self.env, self.env.docname, self.document)
|
|
37
|
+
self.env.domains._process_doc(self.env, self.env.docname, self.document)
|
|
39
38
|
|
|
40
39
|
|
|
41
40
|
def setup(app: Sphinx) -> ExtensionMetadata:
|