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/util/images.py
CHANGED
|
@@ -13,6 +13,7 @@ if TYPE_CHECKING:
|
|
|
13
13
|
|
|
14
14
|
try:
|
|
15
15
|
from PIL import Image
|
|
16
|
+
|
|
16
17
|
PILLOW_AVAILABLE = True
|
|
17
18
|
except ImportError:
|
|
18
19
|
PILLOW_AVAILABLE = False
|
|
@@ -54,13 +55,13 @@ def get_image_size(filename: str) -> tuple[int, int] | None:
|
|
|
54
55
|
|
|
55
56
|
|
|
56
57
|
@overload
|
|
57
|
-
def guess_mimetype(filename: PathLike[str] | str, default: str) -> str:
|
|
58
|
-
...
|
|
58
|
+
def guess_mimetype(filename: PathLike[str] | str, default: str) -> str: ... # NoQA: E704
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
@overload
|
|
62
|
-
def guess_mimetype(
|
|
63
|
-
|
|
62
|
+
def guess_mimetype( # NoQA: E704
|
|
63
|
+
filename: PathLike[str] | str, default: None = None
|
|
64
|
+
) -> str | None: ...
|
|
64
65
|
|
|
65
66
|
|
|
66
67
|
def guess_mimetype(
|
|
@@ -121,12 +122,12 @@ def _image_type_from_file(filename: PathLike[str] | str) -> str:
|
|
|
121
122
|
|
|
122
123
|
# JPEG data
|
|
123
124
|
# https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format#File_format_structure
|
|
124
|
-
if header.startswith(b'\
|
|
125
|
+
if header.startswith(b'\xff\xd8'):
|
|
125
126
|
return 'jpeg'
|
|
126
127
|
|
|
127
128
|
# Portable Network Graphics
|
|
128
129
|
# https://en.wikipedia.org/wiki/PNG#File_header
|
|
129
|
-
if header.startswith(b'\x89PNG\r\n\
|
|
130
|
+
if header.startswith(b'\x89PNG\r\n\x1a\n'):
|
|
130
131
|
return 'png'
|
|
131
132
|
|
|
132
133
|
# Scalable Vector Graphics
|
sphinx/util/inspect.py
CHANGED
|
@@ -52,11 +52,7 @@ if TYPE_CHECKING:
|
|
|
52
52
|
| types.MethodDescriptorType
|
|
53
53
|
| types.ClassMethodDescriptorType
|
|
54
54
|
)
|
|
55
|
-
_SignatureType: TypeAlias =
|
|
56
|
-
Callable[..., Any]
|
|
57
|
-
| staticmethod
|
|
58
|
-
| classmethod
|
|
59
|
-
)
|
|
55
|
+
_SignatureType: TypeAlias = Callable[..., Any] | staticmethod | classmethod
|
|
60
56
|
|
|
61
57
|
logger = logging.getLogger(__name__)
|
|
62
58
|
|
|
@@ -266,7 +262,8 @@ def isstaticmethod(
|
|
|
266
262
|
def isdescriptor(x: Any) -> TypeIs[_SupportsGet | _SupportsSet | _SupportsDelete]:
|
|
267
263
|
"""Check if the object is a :external+python:term:`descriptor`."""
|
|
268
264
|
return any(
|
|
269
|
-
callable(safe_getattr(x, item, None))
|
|
265
|
+
callable(safe_getattr(x, item, None))
|
|
266
|
+
for item in ('__get__', '__set__', '__delete__')
|
|
270
267
|
)
|
|
271
268
|
|
|
272
269
|
|
|
@@ -392,6 +389,10 @@ def isgenericalias(obj: Any) -> TypeIs[types.GenericAlias]:
|
|
|
392
389
|
|
|
393
390
|
def safe_getattr(obj: Any, name: str, *defargs: Any) -> Any:
|
|
394
391
|
"""A getattr() that turns all exceptions into AttributeErrors."""
|
|
392
|
+
if len(defargs) > 1:
|
|
393
|
+
msg = f'safe_getattr expected at most 3 arguments, got {len(defargs)}'
|
|
394
|
+
raise TypeError(msg)
|
|
395
|
+
|
|
395
396
|
try:
|
|
396
397
|
return getattr(obj, name, *defargs)
|
|
397
398
|
except Exception as exc:
|
|
@@ -429,7 +430,10 @@ def object_description(obj: Any, *, _seen: frozenset[int] = frozenset()) -> str:
|
|
|
429
430
|
sorted_keys = sorted(obj, key=lambda k: object_description(k, _seen=seen))
|
|
430
431
|
|
|
431
432
|
items = (
|
|
432
|
-
(
|
|
433
|
+
(
|
|
434
|
+
object_description(key, _seen=seen),
|
|
435
|
+
object_description(obj[key], _seen=seen),
|
|
436
|
+
)
|
|
433
437
|
for key in sorted_keys
|
|
434
438
|
)
|
|
435
439
|
return '{%s}' % ', '.join(f'{key}: {value}' for (key, value) in items)
|
|
@@ -442,7 +446,9 @@ def object_description(obj: Any, *, _seen: frozenset[int] = frozenset()) -> str:
|
|
|
442
446
|
except TypeError:
|
|
443
447
|
# Cannot sort set values, fall back to using descriptions as a sort key
|
|
444
448
|
sorted_values = sorted(obj, key=lambda x: object_description(x, _seen=seen))
|
|
445
|
-
return '{%s}' % ', '.join(
|
|
449
|
+
return '{%s}' % ', '.join(
|
|
450
|
+
object_description(x, _seen=seen) for x in sorted_values
|
|
451
|
+
)
|
|
446
452
|
elif isinstance(obj, frozenset):
|
|
447
453
|
if id(obj) in seen:
|
|
448
454
|
return 'frozenset(...)'
|
|
@@ -760,7 +766,10 @@ def stringify_signature(
|
|
|
760
766
|
args = []
|
|
761
767
|
last_kind = None
|
|
762
768
|
for param in sig.parameters.values():
|
|
763
|
-
if
|
|
769
|
+
if (
|
|
770
|
+
param.kind != Parameter.POSITIONAL_ONLY
|
|
771
|
+
and last_kind == Parameter.POSITIONAL_ONLY
|
|
772
|
+
):
|
|
764
773
|
# PEP-570: Separator for Positional Only Parameter: /
|
|
765
774
|
args.append('/')
|
|
766
775
|
if param.kind == Parameter.KEYWORD_ONLY and last_kind in (
|
|
@@ -797,7 +806,11 @@ def stringify_signature(
|
|
|
797
806
|
args.append('/')
|
|
798
807
|
|
|
799
808
|
concatenated_args = ', '.join(args)
|
|
800
|
-
if
|
|
809
|
+
if (
|
|
810
|
+
sig.return_annotation is EMPTY
|
|
811
|
+
or not show_annotation
|
|
812
|
+
or not show_return_annotation
|
|
813
|
+
):
|
|
801
814
|
return f'({concatenated_args})'
|
|
802
815
|
else:
|
|
803
816
|
retann = stringify_annotation(sig.return_annotation, mode) # type: ignore[arg-type]
|
|
@@ -842,11 +855,15 @@ def signature_from_ast(node: ast.FunctionDef, code: str = '') -> Signature:
|
|
|
842
855
|
|
|
843
856
|
# normal arguments
|
|
844
857
|
for arg, defexpr in zip(args.args, defaults[pos_only_offset:], strict=False):
|
|
845
|
-
params.append(
|
|
858
|
+
params.append(
|
|
859
|
+
_define(Parameter.POSITIONAL_OR_KEYWORD, arg, code, defexpr=defexpr)
|
|
860
|
+
)
|
|
846
861
|
|
|
847
862
|
# variadic positional argument (no possible default expression)
|
|
848
863
|
if args.vararg:
|
|
849
|
-
params.append(
|
|
864
|
+
params.append(
|
|
865
|
+
_define(Parameter.VAR_POSITIONAL, args.vararg, code, defexpr=None)
|
|
866
|
+
)
|
|
850
867
|
|
|
851
868
|
# keyword-only arguments
|
|
852
869
|
for arg, defexpr in zip(args.kwonlyargs, args.kw_defaults, strict=False):
|
sphinx/util/inventory.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"""Inventory utility functions for Sphinx."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
4
|
|
|
4
5
|
import os
|
|
5
6
|
import re
|
|
6
7
|
import zlib
|
|
7
|
-
from typing import
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
8
9
|
|
|
9
10
|
from sphinx.locale import __
|
|
10
11
|
from sphinx.util import logging
|
|
@@ -17,7 +18,7 @@ if TYPE_CHECKING:
|
|
|
17
18
|
|
|
18
19
|
from sphinx.builders import Builder
|
|
19
20
|
from sphinx.environment import BuildEnvironment
|
|
20
|
-
from sphinx.util.typing import Inventory, InventoryItem
|
|
21
|
+
from sphinx.util.typing import Inventory, InventoryItem, _ReadableStream
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class InventoryFileReader:
|
|
@@ -26,7 +27,7 @@ class InventoryFileReader:
|
|
|
26
27
|
This reader supports mixture of texts and compressed texts.
|
|
27
28
|
"""
|
|
28
29
|
|
|
29
|
-
def __init__(self, stream:
|
|
30
|
+
def __init__(self, stream: _ReadableStream[bytes]) -> None:
|
|
30
31
|
self.stream = stream
|
|
31
32
|
self.buffer = b''
|
|
32
33
|
self.eof = False
|
|
@@ -41,7 +42,7 @@ class InventoryFileReader:
|
|
|
41
42
|
pos = self.buffer.find(b'\n')
|
|
42
43
|
if pos != -1:
|
|
43
44
|
line = self.buffer[:pos].decode()
|
|
44
|
-
self.buffer = self.buffer[pos + 1:]
|
|
45
|
+
self.buffer = self.buffer[pos + 1 :]
|
|
45
46
|
elif self.eof:
|
|
46
47
|
line = self.buffer.decode()
|
|
47
48
|
self.buffer = b''
|
|
@@ -72,7 +73,7 @@ class InventoryFileReader:
|
|
|
72
73
|
pos = buf.find(b'\n')
|
|
73
74
|
while pos != -1:
|
|
74
75
|
yield buf[:pos].decode()
|
|
75
|
-
buf = buf[pos + 1:]
|
|
76
|
+
buf = buf[pos + 1 :]
|
|
76
77
|
pos = buf.find(b'\n')
|
|
77
78
|
|
|
78
79
|
|
|
@@ -80,7 +81,7 @@ class InventoryFile:
|
|
|
80
81
|
@classmethod
|
|
81
82
|
def load(
|
|
82
83
|
cls: type[InventoryFile],
|
|
83
|
-
stream:
|
|
84
|
+
stream: _ReadableStream[bytes],
|
|
84
85
|
uri: str,
|
|
85
86
|
joinfunc: Callable[[str, str], str],
|
|
86
87
|
) -> Inventory:
|
|
@@ -135,8 +136,11 @@ class InventoryFile:
|
|
|
135
136
|
|
|
136
137
|
for line in stream.read_compressed_lines():
|
|
137
138
|
# be careful to handle names with embedded spaces correctly
|
|
138
|
-
m = re.match(
|
|
139
|
-
|
|
139
|
+
m = re.match(
|
|
140
|
+
r'(.+?)\s+(\S+)\s+(-?\d+)\s+?(\S*)\s+(.*)',
|
|
141
|
+
line.rstrip(),
|
|
142
|
+
flags=re.VERBOSE,
|
|
143
|
+
)
|
|
140
144
|
if not m:
|
|
141
145
|
continue
|
|
142
146
|
name, type, prio, location, dispname = m.groups()
|
|
@@ -155,15 +159,20 @@ class InventoryFile:
|
|
|
155
159
|
# Some types require case insensitive matches:
|
|
156
160
|
# * 'term': https://github.com/sphinx-doc/sphinx/issues/9291
|
|
157
161
|
# * 'label': https://github.com/sphinx-doc/sphinx/issues/12008
|
|
158
|
-
definition = f
|
|
162
|
+
definition = f'{type}:{name}'
|
|
159
163
|
content = prio, location, dispname
|
|
160
164
|
lowercase_definition = definition.lower()
|
|
161
165
|
if lowercase_definition in potential_ambiguities:
|
|
162
166
|
if potential_ambiguities[lowercase_definition] != content:
|
|
163
167
|
actual_ambiguities.add(definition)
|
|
164
168
|
else:
|
|
165
|
-
logger.debug(
|
|
166
|
-
|
|
169
|
+
logger.debug(
|
|
170
|
+
__('inventory <%s> contains duplicate definitions of %s'),
|
|
171
|
+
uri,
|
|
172
|
+
definition,
|
|
173
|
+
type='intersphinx',
|
|
174
|
+
subtype='external',
|
|
175
|
+
)
|
|
167
176
|
else:
|
|
168
177
|
potential_ambiguities[lowercase_definition] = content
|
|
169
178
|
if location.endswith('$'):
|
|
@@ -172,40 +181,49 @@ class InventoryFile:
|
|
|
172
181
|
inv_item: InventoryItem = projname, version, location, dispname
|
|
173
182
|
invdata.setdefault(type, {})[name] = inv_item
|
|
174
183
|
for ambiguity in actual_ambiguities:
|
|
175
|
-
logger.info(
|
|
176
|
-
|
|
184
|
+
logger.info(
|
|
185
|
+
__('inventory <%s> contains multiple definitions for %s'),
|
|
186
|
+
uri,
|
|
187
|
+
ambiguity,
|
|
188
|
+
type='intersphinx',
|
|
189
|
+
subtype='external',
|
|
190
|
+
)
|
|
177
191
|
return invdata
|
|
178
192
|
|
|
179
193
|
@classmethod
|
|
180
194
|
def dump(
|
|
181
|
-
cls: type[InventoryFile],
|
|
195
|
+
cls: type[InventoryFile],
|
|
196
|
+
filename: str,
|
|
197
|
+
env: BuildEnvironment,
|
|
198
|
+
builder: Builder,
|
|
182
199
|
) -> None:
|
|
183
200
|
def escape(string: str) -> str:
|
|
184
|
-
return re.sub(
|
|
201
|
+
return re.sub('\\s+', ' ', string)
|
|
185
202
|
|
|
186
203
|
with open(os.path.join(filename), 'wb') as f:
|
|
187
204
|
# header
|
|
188
|
-
f.write(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
205
|
+
f.write(
|
|
206
|
+
(
|
|
207
|
+
'# Sphinx inventory version 2\n'
|
|
208
|
+
f'# Project: {escape(env.config.project)}\n'
|
|
209
|
+
f'# Version: {escape(env.config.version)}\n'
|
|
210
|
+
'# The remainder of this file is compressed using zlib.\n'
|
|
211
|
+
).encode()
|
|
212
|
+
)
|
|
194
213
|
|
|
195
214
|
# body
|
|
196
215
|
compressor = zlib.compressobj(9)
|
|
197
|
-
for
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if anchor.endswith(
|
|
216
|
+
for domain in env.domains.sorted():
|
|
217
|
+
sorted_objects = sorted(domain.get_objects())
|
|
218
|
+
for fullname, dispname, type, docname, anchor, prio in sorted_objects:
|
|
219
|
+
if anchor.endswith(fullname):
|
|
201
220
|
# this can shorten the inventory by as much as 25%
|
|
202
|
-
anchor = anchor
|
|
221
|
+
anchor = anchor.removesuffix(fullname) + '$'
|
|
203
222
|
uri = builder.get_target_uri(docname)
|
|
204
223
|
if anchor:
|
|
205
224
|
uri += '#' + anchor
|
|
206
|
-
if dispname ==
|
|
225
|
+
if dispname == fullname:
|
|
207
226
|
dispname = '-'
|
|
208
|
-
entry =
|
|
209
|
-
(name, domainname, typ, prio, uri, dispname))
|
|
227
|
+
entry = f'{fullname} {domain.name}:{type} {prio} {uri} {dispname}\n'
|
|
210
228
|
f.write(compressor.compress(entry.encode()))
|
|
211
229
|
f.write(compressor.flush())
|
sphinx/util/logging.py
CHANGED
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import logging
|
|
6
6
|
import logging.handlers
|
|
7
7
|
from collections import defaultdict
|
|
8
|
-
from contextlib import contextmanager
|
|
8
|
+
from contextlib import contextmanager, nullcontext
|
|
9
9
|
from typing import IO, TYPE_CHECKING, Any
|
|
10
10
|
|
|
11
11
|
from docutils import nodes
|
|
@@ -17,6 +17,7 @@ from sphinx.util.osutil import abspath
|
|
|
17
17
|
|
|
18
18
|
if TYPE_CHECKING:
|
|
19
19
|
from collections.abc import Iterator, Sequence, Set
|
|
20
|
+
from typing import NoReturn
|
|
20
21
|
|
|
21
22
|
from docutils.nodes import Node
|
|
22
23
|
|
|
@@ -26,27 +27,36 @@ if TYPE_CHECKING:
|
|
|
26
27
|
NAMESPACE = 'sphinx'
|
|
27
28
|
VERBOSE = 15
|
|
28
29
|
|
|
29
|
-
LEVEL_NAMES: defaultdict[str, int] = defaultdict(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
30
|
+
LEVEL_NAMES: defaultdict[str, int] = defaultdict(
|
|
31
|
+
lambda: logging.WARNING,
|
|
32
|
+
{
|
|
33
|
+
'CRITICAL': logging.CRITICAL,
|
|
34
|
+
'SEVERE': logging.CRITICAL,
|
|
35
|
+
'ERROR': logging.ERROR,
|
|
36
|
+
'WARNING': logging.WARNING,
|
|
37
|
+
'INFO': logging.INFO,
|
|
38
|
+
'VERBOSE': VERBOSE,
|
|
39
|
+
'DEBUG': logging.DEBUG,
|
|
40
|
+
},
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
VERBOSITY_MAP: defaultdict[int, int] = defaultdict(
|
|
44
|
+
lambda: logging.NOTSET,
|
|
45
|
+
{
|
|
46
|
+
0: logging.INFO,
|
|
47
|
+
1: VERBOSE,
|
|
48
|
+
2: logging.DEBUG,
|
|
49
|
+
},
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
COLOR_MAP: defaultdict[int, str] = defaultdict(
|
|
53
|
+
lambda: 'blue',
|
|
54
|
+
{
|
|
55
|
+
logging.ERROR: 'darkred',
|
|
56
|
+
logging.WARNING: 'red',
|
|
57
|
+
logging.DEBUG: 'darkgray',
|
|
58
|
+
},
|
|
59
|
+
)
|
|
50
60
|
|
|
51
61
|
|
|
52
62
|
def getLogger(name: str) -> SphinxLoggerAdapter:
|
|
@@ -125,7 +135,7 @@ class SphinxLoggerAdapter(logging.LoggerAdapter):
|
|
|
125
135
|
KEYWORDS = ['type', 'subtype', 'location', 'nonl', 'color', 'once']
|
|
126
136
|
|
|
127
137
|
def log( # type: ignore[override]
|
|
128
|
-
self, level: int | str, msg: str, *args: Any, **kwargs: Any
|
|
138
|
+
self, level: int | str, msg: str, *args: Any, **kwargs: Any
|
|
129
139
|
) -> None:
|
|
130
140
|
if isinstance(level, int):
|
|
131
141
|
super().log(level, msg, *args, **kwargs)
|
|
@@ -322,24 +332,7 @@ def pending_logging() -> Iterator[MemoryHandler]:
|
|
|
322
332
|
memhandler.flushTo(logger)
|
|
323
333
|
|
|
324
334
|
|
|
325
|
-
|
|
326
|
-
def skip_warningiserror(skip: bool = True) -> Iterator[None]:
|
|
327
|
-
"""Context manager to skip WarningIsErrorFilter temporarily."""
|
|
328
|
-
logger = logging.getLogger(NAMESPACE)
|
|
329
|
-
|
|
330
|
-
if skip is False:
|
|
331
|
-
yield
|
|
332
|
-
else:
|
|
333
|
-
try:
|
|
334
|
-
disabler = DisableWarningIsErrorFilter()
|
|
335
|
-
for handler in logger.handlers:
|
|
336
|
-
# use internal method; filters.insert() directly to install disabler
|
|
337
|
-
# before WarningIsErrorFilter
|
|
338
|
-
handler.filters.insert(0, disabler)
|
|
339
|
-
yield
|
|
340
|
-
finally:
|
|
341
|
-
for handler in logger.handlers:
|
|
342
|
-
handler.removeFilter(disabler)
|
|
335
|
+
skip_warningiserror = nullcontext # Deprecate in Sphinx 10
|
|
343
336
|
|
|
344
337
|
|
|
345
338
|
@contextmanager
|
|
@@ -407,8 +400,23 @@ class InfoFilter(logging.Filter):
|
|
|
407
400
|
return record.levelno < logging.WARNING
|
|
408
401
|
|
|
409
402
|
|
|
403
|
+
class _RaiseOnWarningFilter(logging.Filter):
|
|
404
|
+
"""Raise exception if a warning is emitted."""
|
|
405
|
+
|
|
406
|
+
def filter(self, record: logging.LogRecord) -> NoReturn:
|
|
407
|
+
try:
|
|
408
|
+
message = record.msg % record.args
|
|
409
|
+
except (TypeError, ValueError):
|
|
410
|
+
message = record.msg # use record.msg itself
|
|
411
|
+
if location := getattr(record, 'location', ''):
|
|
412
|
+
message = f'{location}:{message}'
|
|
413
|
+
if record.exc_info is not None:
|
|
414
|
+
raise SphinxWarning(message) from record.exc_info[1]
|
|
415
|
+
raise SphinxWarning(message)
|
|
416
|
+
|
|
417
|
+
|
|
410
418
|
def is_suppressed_warning(
|
|
411
|
-
warning_type: str, sub_type: str, suppress_warnings: Set[str] | Sequence[str]
|
|
419
|
+
warning_type: str, sub_type: str, suppress_warnings: Set[str] | Sequence[str]
|
|
412
420
|
) -> bool:
|
|
413
421
|
"""Check whether the warning is suppressed or not."""
|
|
414
422
|
if warning_type is None or len(suppress_warnings) == 0:
|
|
@@ -445,44 +453,6 @@ class WarningSuppressor(logging.Filter):
|
|
|
445
453
|
return True
|
|
446
454
|
|
|
447
455
|
|
|
448
|
-
class WarningIsErrorFilter(logging.Filter):
|
|
449
|
-
"""Raise exception if warning emitted."""
|
|
450
|
-
|
|
451
|
-
def __init__(self, app: Sphinx) -> None:
|
|
452
|
-
self.app = app
|
|
453
|
-
super().__init__()
|
|
454
|
-
|
|
455
|
-
def filter(self, record: logging.LogRecord) -> bool:
|
|
456
|
-
if getattr(record, 'skip_warningsiserror', False):
|
|
457
|
-
# disabled by DisableWarningIsErrorFilter
|
|
458
|
-
return True
|
|
459
|
-
elif self.app.warningiserror:
|
|
460
|
-
location = getattr(record, 'location', '')
|
|
461
|
-
try:
|
|
462
|
-
message = record.msg % record.args
|
|
463
|
-
except (TypeError, ValueError):
|
|
464
|
-
message = record.msg # use record.msg itself
|
|
465
|
-
|
|
466
|
-
if location:
|
|
467
|
-
exc = SphinxWarning(location + ":" + str(message))
|
|
468
|
-
else:
|
|
469
|
-
exc = SphinxWarning(message)
|
|
470
|
-
if record.exc_info is not None:
|
|
471
|
-
raise exc from record.exc_info[1]
|
|
472
|
-
else:
|
|
473
|
-
raise exc
|
|
474
|
-
else:
|
|
475
|
-
return True
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
class DisableWarningIsErrorFilter(logging.Filter):
|
|
479
|
-
"""Disable WarningIsErrorFilter if this filter installed."""
|
|
480
|
-
|
|
481
|
-
def filter(self, record: logging.LogRecord) -> bool:
|
|
482
|
-
record.skip_warningsiserror = True
|
|
483
|
-
return True
|
|
484
|
-
|
|
485
|
-
|
|
486
456
|
class MessagePrefixFilter(logging.Filter):
|
|
487
457
|
"""Prepend prefix to all log records."""
|
|
488
458
|
|
|
@@ -585,11 +555,11 @@ class WarningLogRecordTranslator(SphinxLogRecordTranslator):
|
|
|
585
555
|
def get_node_location(node: Node) -> str | None:
|
|
586
556
|
source, line = get_source_line(node)
|
|
587
557
|
if source and line:
|
|
588
|
-
return f
|
|
558
|
+
return f'{abspath(source)}:{line}'
|
|
589
559
|
if source:
|
|
590
|
-
return f
|
|
560
|
+
return f'{abspath(source)}:'
|
|
591
561
|
if line:
|
|
592
|
-
return f
|
|
562
|
+
return f'<unknown>:{line}'
|
|
593
563
|
return None
|
|
594
564
|
|
|
595
565
|
|
|
@@ -619,7 +589,9 @@ class SafeEncodingWriter:
|
|
|
619
589
|
except UnicodeEncodeError:
|
|
620
590
|
# stream accept only str, not bytes. So, we encode and replace
|
|
621
591
|
# non-encodable characters, then decode them.
|
|
622
|
-
self.stream.write(
|
|
592
|
+
self.stream.write(
|
|
593
|
+
data.encode(self.encoding, 'replace').decode(self.encoding)
|
|
594
|
+
)
|
|
623
595
|
|
|
624
596
|
def flush(self) -> None:
|
|
625
597
|
if hasattr(self.stream, 'flush'):
|
|
@@ -653,9 +625,10 @@ def setup(app: Sphinx, status: IO, warning: IO) -> None:
|
|
|
653
625
|
info_handler.setFormatter(ColorizeFormatter())
|
|
654
626
|
|
|
655
627
|
warning_handler = WarningStreamHandler(SafeEncodingWriter(warning))
|
|
628
|
+
if app._exception_on_warning:
|
|
629
|
+
warning_handler.addFilter(_RaiseOnWarningFilter())
|
|
656
630
|
warning_handler.addFilter(WarningSuppressor(app))
|
|
657
631
|
warning_handler.addFilter(WarningLogRecordTranslator(app))
|
|
658
|
-
warning_handler.addFilter(WarningIsErrorFilter(app))
|
|
659
632
|
warning_handler.addFilter(OnceFilter())
|
|
660
633
|
warning_handler.setLevel(logging.WARNING)
|
|
661
634
|
warning_handler.setFormatter(ColorizeFormatter())
|
sphinx/util/matching.py
CHANGED
|
@@ -112,7 +112,7 @@ def patfilter(names: Iterable[str], pat: str) -> list[str]:
|
|
|
112
112
|
|
|
113
113
|
def get_matching_files(
|
|
114
114
|
dirname: str | os.PathLike[str],
|
|
115
|
-
include_patterns: Iterable[str] = (
|
|
115
|
+
include_patterns: Iterable[str] = ('**',),
|
|
116
116
|
exclude_patterns: Iterable[str] = (),
|
|
117
117
|
) -> Iterator[str]:
|
|
118
118
|
"""Get all file names in a directory, recursively.
|
|
@@ -132,8 +132,8 @@ def get_matching_files(
|
|
|
132
132
|
|
|
133
133
|
for root, dirs, files in os.walk(dirname, followlinks=True):
|
|
134
134
|
relative_root = os.path.relpath(root, dirname)
|
|
135
|
-
if relative_root ==
|
|
136
|
-
relative_root =
|
|
135
|
+
if relative_root == '.':
|
|
136
|
+
relative_root = '' # suppress dirname for files on the target dir
|
|
137
137
|
|
|
138
138
|
# Filter files
|
|
139
139
|
included_files = []
|
sphinx/util/math.py
CHANGED
|
@@ -14,7 +14,7 @@ def get_node_equation_number(writer: HTML5Translator, node: nodes.math_block) ->
|
|
|
14
14
|
if writer.builder.config.math_numfig and writer.builder.config.numfig:
|
|
15
15
|
figtype = 'displaymath'
|
|
16
16
|
if writer.builder.name == 'singlehtml':
|
|
17
|
-
key = f
|
|
17
|
+
key = f'{writer.docnames[-1]}/{figtype}' # type: ignore[has-type]
|
|
18
18
|
else:
|
|
19
19
|
key = figtype
|
|
20
20
|
|