Sphinx 8.0.2__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 +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 +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.2.dist-info → sphinx-8.1.0.dist-info}/METADATA +13 -11
- sphinx-8.1.0.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.0.dist-info}/WHEEL +0 -0
- {sphinx-8.0.2.dist-info → sphinx-8.1.0.dist-info}/entry_points.txt +0 -0
sphinx/config.py
CHANGED
|
@@ -23,7 +23,7 @@ else:
|
|
|
23
23
|
|
|
24
24
|
if TYPE_CHECKING:
|
|
25
25
|
import os
|
|
26
|
-
from collections.abc import Collection, Iterator, Sequence, Set
|
|
26
|
+
from collections.abc import Collection, Iterable, Iterator, Sequence, Set
|
|
27
27
|
from typing import TypeAlias
|
|
28
28
|
|
|
29
29
|
from sphinx.application import Sphinx
|
|
@@ -271,7 +271,7 @@ class Config:
|
|
|
271
271
|
'smartquotes': _Opt(True, 'env', ()),
|
|
272
272
|
'smartquotes_action': _Opt('qDe', 'env', ()),
|
|
273
273
|
'smartquotes_excludes': _Opt(
|
|
274
|
-
{'languages': ['ja'], 'builders': ['man', 'text']}, 'env', ()),
|
|
274
|
+
{'languages': ['ja', 'zh_CN', 'zh_TW'], 'builders': ['man', 'text']}, 'env', ()),
|
|
275
275
|
'option_emphasise_placeholders': _Opt(False, 'env', ()),
|
|
276
276
|
}
|
|
277
277
|
|
|
@@ -619,28 +619,55 @@ def init_numfig_format(app: Sphinx, config: Config) -> None:
|
|
|
619
619
|
config.numfig_format = numfig_format
|
|
620
620
|
|
|
621
621
|
|
|
622
|
+
def evaluate_copyright_placeholders(_app: Sphinx, config: Config) -> None:
|
|
623
|
+
"""Replace copyright year placeholders (%Y) with the current year."""
|
|
624
|
+
replace_yr = str(time.localtime().tm_year)
|
|
625
|
+
for k in ('copyright', 'epub_copyright'):
|
|
626
|
+
if k in config:
|
|
627
|
+
value: str | Sequence[str] = config[k]
|
|
628
|
+
if isinstance(value, str):
|
|
629
|
+
if '%Y' in value:
|
|
630
|
+
config[k] = value.replace('%Y', replace_yr)
|
|
631
|
+
else:
|
|
632
|
+
if any('%Y' in line for line in value):
|
|
633
|
+
items = (line.replace('%Y', replace_yr) for line in value)
|
|
634
|
+
config[k] = type(value)(items) # type: ignore[call-arg]
|
|
635
|
+
|
|
636
|
+
|
|
622
637
|
def correct_copyright_year(_app: Sphinx, config: Config) -> None:
|
|
623
638
|
"""Correct values of copyright year that are not coherent with
|
|
624
639
|
the SOURCE_DATE_EPOCH environment variable (if set)
|
|
625
640
|
|
|
626
641
|
See https://reproducible-builds.org/specs/source-date-epoch/
|
|
627
642
|
"""
|
|
628
|
-
if
|
|
643
|
+
if source_date_epoch := int(getenv('SOURCE_DATE_EPOCH', '0')):
|
|
644
|
+
source_date_epoch_year = time.gmtime(source_date_epoch).tm_year
|
|
645
|
+
else:
|
|
629
646
|
return
|
|
630
647
|
|
|
631
|
-
|
|
648
|
+
# If the current year is the replacement year, there's no work to do.
|
|
649
|
+
# We also skip replacement years that are in the future.
|
|
650
|
+
current_year = time.localtime().tm_year
|
|
651
|
+
if current_year <= source_date_epoch_year:
|
|
652
|
+
return
|
|
632
653
|
|
|
654
|
+
current_yr = str(current_year)
|
|
655
|
+
replace_yr = str(source_date_epoch_year)
|
|
633
656
|
for k in ('copyright', 'epub_copyright'):
|
|
634
657
|
if k in config:
|
|
635
658
|
value: str | Sequence[str] = config[k]
|
|
636
659
|
if isinstance(value, str):
|
|
637
|
-
config[k] = _substitute_copyright_year(value,
|
|
660
|
+
config[k] = _substitute_copyright_year(value, current_yr, replace_yr)
|
|
638
661
|
else:
|
|
639
|
-
items = (
|
|
662
|
+
items = (
|
|
663
|
+
_substitute_copyright_year(x, current_yr, replace_yr) for x in value
|
|
664
|
+
)
|
|
640
665
|
config[k] = type(value)(items) # type: ignore[call-arg]
|
|
641
666
|
|
|
642
667
|
|
|
643
|
-
def _substitute_copyright_year(
|
|
668
|
+
def _substitute_copyright_year(
|
|
669
|
+
copyright_line: str, current_year: str, replace_year: str
|
|
670
|
+
) -> str:
|
|
644
671
|
"""Replace the year in a single copyright line.
|
|
645
672
|
|
|
646
673
|
Legal formats are:
|
|
@@ -648,6 +675,7 @@ def _substitute_copyright_year(copyright_line: str, replace_year: str) -> str:
|
|
|
648
675
|
* ``YYYY``
|
|
649
676
|
* ``YYYY,``
|
|
650
677
|
* ``YYYY ``
|
|
678
|
+
* ``YYYY-YYYY``
|
|
651
679
|
* ``YYYY-YYYY,``
|
|
652
680
|
* ``YYYY-YYYY ``
|
|
653
681
|
|
|
@@ -656,13 +684,17 @@ def _substitute_copyright_year(copyright_line: str, replace_year: str) -> str:
|
|
|
656
684
|
if len(copyright_line) < 4 or not copyright_line[:4].isdigit():
|
|
657
685
|
return copyright_line
|
|
658
686
|
|
|
659
|
-
if copyright_line[4:5] in {'', ' ', ','}:
|
|
687
|
+
if copyright_line[:4] == current_year and copyright_line[4:5] in {'', ' ', ','}:
|
|
660
688
|
return replace_year + copyright_line[4:]
|
|
661
689
|
|
|
662
|
-
if copyright_line[4] != '-':
|
|
690
|
+
if copyright_line[4:5] != '-':
|
|
663
691
|
return copyright_line
|
|
664
692
|
|
|
665
|
-
if
|
|
693
|
+
if (
|
|
694
|
+
copyright_line[5:9].isdigit()
|
|
695
|
+
and copyright_line[5:9] == current_year
|
|
696
|
+
and copyright_line[9:10] in {'', ' ', ','}
|
|
697
|
+
):
|
|
666
698
|
return copyright_line[:5] + replace_year + copyright_line[9:]
|
|
667
699
|
|
|
668
700
|
return copyright_line
|
|
@@ -739,8 +771,8 @@ def check_primary_domain(app: Sphinx, config: Config) -> None:
|
|
|
739
771
|
config.primary_domain = None
|
|
740
772
|
|
|
741
773
|
|
|
742
|
-
def check_root_doc(app: Sphinx, env: BuildEnvironment, added:
|
|
743
|
-
changed:
|
|
774
|
+
def check_root_doc(app: Sphinx, env: BuildEnvironment, added: Set[str],
|
|
775
|
+
changed: Set[str], removed: Set[str]) -> Iterable[str]:
|
|
744
776
|
"""Adjust root_doc to 'contents' to support an old project which does not have
|
|
745
777
|
any root_doc setting.
|
|
746
778
|
"""
|
|
@@ -758,6 +790,7 @@ def setup(app: Sphinx) -> ExtensionMetadata:
|
|
|
758
790
|
app.connect('config-inited', convert_source_suffix, priority=800)
|
|
759
791
|
app.connect('config-inited', convert_highlight_options, priority=800)
|
|
760
792
|
app.connect('config-inited', init_numfig_format, priority=800)
|
|
793
|
+
app.connect('config-inited', evaluate_copyright_placeholders, priority=795)
|
|
761
794
|
app.connect('config-inited', correct_copyright_year, priority=800)
|
|
762
795
|
app.connect('config-inited', check_confval_types, priority=800)
|
|
763
796
|
app.connect('config-inited', check_primary_domain, priority=800)
|
sphinx/deprecation.py
CHANGED
|
@@ -40,7 +40,11 @@ def _deprecation_warning(
|
|
|
40
40
|
|
|
41
41
|
# deprecated name -> (object to return, canonical path or empty string, removal version)
|
|
42
42
|
_DEPRECATED_OBJECTS = {
|
|
43
|
-
'deprecated_name': (
|
|
43
|
+
'deprecated_name': (
|
|
44
|
+
object_to_return,
|
|
45
|
+
'fully_qualified_replacement_name',
|
|
46
|
+
(9, 0),
|
|
47
|
+
),
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
|
|
@@ -65,7 +69,9 @@ def _deprecation_warning(
|
|
|
65
69
|
|
|
66
70
|
qualname = f'{module}.{attribute}'
|
|
67
71
|
if canonical_name:
|
|
68
|
-
message =
|
|
72
|
+
message = (
|
|
73
|
+
f'The alias {qualname!r} is deprecated, use {canonical_name!r} instead.'
|
|
74
|
+
)
|
|
69
75
|
else:
|
|
70
76
|
message = f'{qualname!r} is deprecated.'
|
|
71
77
|
|
sphinx/directives/__init__.py
CHANGED
|
@@ -111,7 +111,9 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
|
|
|
111
111
|
"""
|
|
112
112
|
raise ValueError
|
|
113
113
|
|
|
114
|
-
def add_target_and_index(
|
|
114
|
+
def add_target_and_index(
|
|
115
|
+
self, name: ObjDescT, sig: str, signode: desc_signature
|
|
116
|
+
) -> None:
|
|
115
117
|
"""
|
|
116
118
|
Add cross-reference IDs and entries to self.indexnode, if applicable.
|
|
117
119
|
|
|
@@ -228,19 +230,18 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
|
|
|
228
230
|
self.options['no-index'] = self.options['noindex']
|
|
229
231
|
if 'no-index-entry' not in self.options and 'noindexentry' in self.options:
|
|
230
232
|
self.options['no-index-entry'] = self.options['noindexentry']
|
|
231
|
-
if
|
|
233
|
+
if (
|
|
234
|
+
'no-contents-entry' not in self.options
|
|
235
|
+
and 'nocontentsentry' in self.options
|
|
236
|
+
):
|
|
232
237
|
self.options['no-contents-entry'] = self.options['nocontentsentry']
|
|
233
238
|
|
|
234
|
-
node['no-index'] = node['noindex'] = no_index =
|
|
235
|
-
|
|
236
|
-
)
|
|
237
|
-
node['no-index-entry'] = node['noindexentry'] = (
|
|
238
|
-
'no-index-entry' in self.options
|
|
239
|
-
)
|
|
239
|
+
node['no-index'] = node['noindex'] = no_index = 'no-index' in self.options
|
|
240
|
+
node['no-index-entry'] = node['noindexentry'] = 'no-index-entry' in self.options
|
|
240
241
|
node['no-contents-entry'] = node['nocontentsentry'] = (
|
|
241
242
|
'no-contents-entry' in self.options
|
|
242
243
|
)
|
|
243
|
-
node['no-typesetting'] =
|
|
244
|
+
node['no-typesetting'] = 'no-typesetting' in self.options
|
|
244
245
|
if self.domain:
|
|
245
246
|
node['classes'].append(self.domain)
|
|
246
247
|
node['classes'].append(node['objtype'])
|
|
@@ -287,8 +288,9 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
|
|
|
287
288
|
content_node = addnodes.desc_content('', *content_children)
|
|
288
289
|
node.append(content_node)
|
|
289
290
|
self.transform_content(content_node)
|
|
290
|
-
self.env.app.emit(
|
|
291
|
-
|
|
291
|
+
self.env.app.emit(
|
|
292
|
+
'object-description-transform', self.domain, self.objtype, content_node
|
|
293
|
+
)
|
|
292
294
|
DocFieldTransformer(self).transform_all(content_node)
|
|
293
295
|
self.env.temp_data['object'] = None
|
|
294
296
|
self.after_content()
|
|
@@ -299,8 +301,11 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
|
|
|
299
301
|
# If ``:no-index:`` is set, or there are no ids on the node
|
|
300
302
|
# or any of its children, then just return the index node,
|
|
301
303
|
# as Docutils expects a target node to have at least one id.
|
|
302
|
-
if node_ids := [
|
|
303
|
-
|
|
304
|
+
if node_ids := [ # type: ignore[var-annotated]
|
|
305
|
+
node_id
|
|
306
|
+
for el in node.findall(nodes.Element)
|
|
307
|
+
for node_id in el.get('ids', ())
|
|
308
|
+
]:
|
|
304
309
|
target_node = nodes.target(ids=node_ids)
|
|
305
310
|
self.set_source_info(target_node)
|
|
306
311
|
return [self.indexnode, target_node]
|
|
@@ -321,16 +326,20 @@ class DefaultRole(SphinxDirective):
|
|
|
321
326
|
docutils.unregister_role('')
|
|
322
327
|
return []
|
|
323
328
|
role_name = self.arguments[0]
|
|
324
|
-
role, messages = roles.role(
|
|
325
|
-
|
|
329
|
+
role, messages = roles.role(
|
|
330
|
+
role_name, self.state_machine.language, self.lineno, self.state.reporter
|
|
331
|
+
)
|
|
326
332
|
if role:
|
|
327
333
|
docutils.register_role('', role) # type: ignore[arg-type]
|
|
328
334
|
self.env.temp_data['default_role'] = role_name
|
|
329
335
|
else:
|
|
330
336
|
literal_block = nodes.literal_block(self.block_text, self.block_text)
|
|
331
337
|
reporter = self.state.reporter
|
|
332
|
-
error = reporter.error(
|
|
333
|
-
|
|
338
|
+
error = reporter.error(
|
|
339
|
+
'Unknown interpreted text role "%s".' % role_name,
|
|
340
|
+
literal_block,
|
|
341
|
+
line=self.lineno,
|
|
342
|
+
)
|
|
334
343
|
messages += [error]
|
|
335
344
|
|
|
336
345
|
return cast(list[nodes.Node], messages)
|
|
@@ -351,7 +360,7 @@ class DefaultDomain(SphinxDirective):
|
|
|
351
360
|
domain_name = self.arguments[0].lower()
|
|
352
361
|
# if domain_name not in env.domains:
|
|
353
362
|
# # try searching by label
|
|
354
|
-
# for domain in env.domains.
|
|
363
|
+
# for domain in env.domains.sorted():
|
|
355
364
|
# if domain.label.lower() == domain_name:
|
|
356
365
|
# domain_name = domain.name
|
|
357
366
|
# break
|
|
@@ -360,7 +369,7 @@ class DefaultDomain(SphinxDirective):
|
|
|
360
369
|
|
|
361
370
|
|
|
362
371
|
def setup(app: Sphinx) -> ExtensionMetadata:
|
|
363
|
-
app.add_config_value(
|
|
372
|
+
app.add_config_value('strip_signature_backslash', False, 'env')
|
|
364
373
|
directives.register_directive('default-role', DefaultRole)
|
|
365
374
|
directives.register_directive('default-domain', DefaultDomain)
|
|
366
375
|
directives.register_directive('describe', ObjectDescription)
|
sphinx/directives/code.py
CHANGED
|
@@ -11,7 +11,8 @@ from docutils.parsers.rst import directives
|
|
|
11
11
|
from sphinx import addnodes
|
|
12
12
|
from sphinx.directives import optional_int
|
|
13
13
|
from sphinx.locale import __
|
|
14
|
-
from sphinx.util import logging
|
|
14
|
+
from sphinx.util import logging
|
|
15
|
+
from sphinx.util._lines import parse_line_num_spec
|
|
15
16
|
from sphinx.util.docutils import SphinxDirective
|
|
16
17
|
|
|
17
18
|
if TYPE_CHECKING:
|
|
@@ -45,13 +46,15 @@ class Highlight(SphinxDirective):
|
|
|
45
46
|
force = 'force' in self.options
|
|
46
47
|
|
|
47
48
|
self.env.temp_data['highlight_language'] = language
|
|
48
|
-
return [
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
return [
|
|
50
|
+
addnodes.highlightlang(
|
|
51
|
+
lang=language, force=force, linenothreshold=linenothreshold
|
|
52
|
+
)
|
|
53
|
+
]
|
|
51
54
|
|
|
52
55
|
|
|
53
56
|
def dedent_lines(
|
|
54
|
-
lines: list[str], dedent: int | None, location: tuple[str, int] | None = None
|
|
57
|
+
lines: list[str], dedent: int | None, location: tuple[str, int] | None = None
|
|
55
58
|
) -> list[str]:
|
|
56
59
|
if dedent is None:
|
|
57
60
|
return textwrap.dedent(''.join(lines)).splitlines(True)
|
|
@@ -70,10 +73,11 @@ def dedent_lines(
|
|
|
70
73
|
|
|
71
74
|
|
|
72
75
|
def container_wrapper(
|
|
73
|
-
directive: SphinxDirective, literal_node: Node, caption: str
|
|
76
|
+
directive: SphinxDirective, literal_node: Node, caption: str
|
|
74
77
|
) -> nodes.container:
|
|
75
|
-
container_node = nodes.container(
|
|
76
|
-
|
|
78
|
+
container_node = nodes.container(
|
|
79
|
+
'', literal_block=True, classes=['literal-block-wrapper']
|
|
80
|
+
)
|
|
77
81
|
parsed = directive.parse_text_to_nodes(caption, offset=directive.content_offset)
|
|
78
82
|
node = parsed[0]
|
|
79
83
|
if isinstance(node, nodes.system_message):
|
|
@@ -119,11 +123,14 @@ class CodeBlock(SphinxDirective):
|
|
|
119
123
|
if linespec:
|
|
120
124
|
try:
|
|
121
125
|
nlines = len(self.content)
|
|
122
|
-
hl_lines =
|
|
126
|
+
hl_lines = parse_line_num_spec(linespec, nlines)
|
|
123
127
|
if any(i >= nlines for i in hl_lines):
|
|
124
|
-
logger.warning(
|
|
125
|
-
|
|
126
|
-
|
|
128
|
+
logger.warning(
|
|
129
|
+
__('line number spec is out of range(1-%d): %r'),
|
|
130
|
+
nlines,
|
|
131
|
+
self.options['emphasize-lines'],
|
|
132
|
+
location=location,
|
|
133
|
+
)
|
|
127
134
|
|
|
128
135
|
hl_lines = [x + 1 for x in hl_lines if x < nlines]
|
|
129
136
|
except ValueError as err:
|
|
@@ -149,8 +156,9 @@ class CodeBlock(SphinxDirective):
|
|
|
149
156
|
# no highlight language specified. Then this directive refers the current
|
|
150
157
|
# highlight setting via ``highlight`` directive or ``highlight_language``
|
|
151
158
|
# configuration.
|
|
152
|
-
literal['language'] = self.env.temp_data.get(
|
|
153
|
-
|
|
159
|
+
literal['language'] = self.env.temp_data.get(
|
|
160
|
+
'highlight_language', self.config.highlight_language
|
|
161
|
+
)
|
|
154
162
|
extra_args = literal['highlight_args'] = {}
|
|
155
163
|
if hl_lines is not None:
|
|
156
164
|
extra_args['hl_lines'] = hl_lines
|
|
@@ -200,11 +208,11 @@ class LiteralIncludeReader:
|
|
|
200
208
|
def parse_options(self) -> None:
|
|
201
209
|
for option1, option2 in self.INVALID_OPTIONS_PAIR:
|
|
202
210
|
if option1 in self.options and option2 in self.options:
|
|
203
|
-
|
|
204
|
-
|
|
211
|
+
msg = __('Cannot use both "%s" and "%s" options') % (option1, option2)
|
|
212
|
+
raise ValueError(msg)
|
|
205
213
|
|
|
206
214
|
def read_file(
|
|
207
|
-
self, filename: str, location: tuple[str, int] | None = None
|
|
215
|
+
self, filename: str, location: tuple[str, int] | None = None
|
|
208
216
|
) -> list[str]:
|
|
209
217
|
try:
|
|
210
218
|
with open(filename, encoding=self.encoding, errors='strict') as f:
|
|
@@ -214,24 +222,28 @@ class LiteralIncludeReader:
|
|
|
214
222
|
|
|
215
223
|
return text.splitlines(True)
|
|
216
224
|
except OSError as exc:
|
|
217
|
-
|
|
218
|
-
|
|
225
|
+
msg = __('Include file %r not found or reading it failed') % filename
|
|
226
|
+
raise OSError(msg) from exc
|
|
219
227
|
except UnicodeError as exc:
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
228
|
+
msg = __(
|
|
229
|
+
'Encoding %r used for reading included file %r seems to '
|
|
230
|
+
'be wrong, try giving an :encoding: option'
|
|
231
|
+
) % (self.encoding, filename)
|
|
232
|
+
raise UnicodeError(msg) from exc
|
|
223
233
|
|
|
224
234
|
def read(self, location: tuple[str, int] | None = None) -> tuple[str, int]:
|
|
225
235
|
if 'diff' in self.options:
|
|
226
236
|
lines = self.show_diff()
|
|
227
237
|
else:
|
|
228
|
-
filters = [
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
238
|
+
filters = [
|
|
239
|
+
self.pyobject_filter,
|
|
240
|
+
self.start_filter,
|
|
241
|
+
self.end_filter,
|
|
242
|
+
self.lines_filter,
|
|
243
|
+
self.dedent_filter,
|
|
244
|
+
self.prepend_filter,
|
|
245
|
+
self.append_filter,
|
|
246
|
+
]
|
|
235
247
|
lines = self.read_file(self.filename, location=location)
|
|
236
248
|
for func in filters:
|
|
237
249
|
lines = func(lines, location=location)
|
|
@@ -246,33 +258,41 @@ class LiteralIncludeReader:
|
|
|
246
258
|
return list(diff)
|
|
247
259
|
|
|
248
260
|
def pyobject_filter(
|
|
249
|
-
self, lines: list[str], location: tuple[str, int] | None = None
|
|
261
|
+
self, lines: list[str], location: tuple[str, int] | None = None
|
|
250
262
|
) -> list[str]:
|
|
251
263
|
pyobject = self.options.get('pyobject')
|
|
252
264
|
if pyobject:
|
|
253
265
|
from sphinx.pycode import ModuleAnalyzer
|
|
266
|
+
|
|
254
267
|
analyzer = ModuleAnalyzer.for_file(self.filename, '')
|
|
255
268
|
tags = analyzer.find_tags()
|
|
256
269
|
if pyobject not in tags:
|
|
257
|
-
|
|
258
|
-
|
|
270
|
+
msg = __('Object named %r not found in include file %r') % (
|
|
271
|
+
pyobject,
|
|
272
|
+
self.filename,
|
|
273
|
+
)
|
|
274
|
+
raise ValueError(msg)
|
|
259
275
|
start = tags[pyobject][1]
|
|
260
276
|
end = tags[pyobject][2]
|
|
261
|
-
lines = lines[start - 1:end]
|
|
277
|
+
lines = lines[start - 1 : end]
|
|
262
278
|
if 'lineno-match' in self.options:
|
|
263
279
|
self.lineno_start = start
|
|
264
280
|
|
|
265
281
|
return lines
|
|
266
282
|
|
|
267
283
|
def lines_filter(
|
|
268
|
-
self, lines: list[str], location: tuple[str, int] | None = None
|
|
284
|
+
self, lines: list[str], location: tuple[str, int] | None = None
|
|
269
285
|
) -> list[str]:
|
|
270
286
|
linespec = self.options.get('lines')
|
|
271
287
|
if linespec:
|
|
272
|
-
linelist =
|
|
288
|
+
linelist = parse_line_num_spec(linespec, len(lines))
|
|
273
289
|
if any(i >= len(lines) for i in linelist):
|
|
274
|
-
logger.warning(
|
|
275
|
-
|
|
290
|
+
logger.warning(
|
|
291
|
+
__('line number spec is out of range(1-%d): %r'),
|
|
292
|
+
len(lines),
|
|
293
|
+
linespec,
|
|
294
|
+
location=location,
|
|
295
|
+
)
|
|
276
296
|
|
|
277
297
|
if 'lineno-match' in self.options:
|
|
278
298
|
# make sure the line list is not "disjoint".
|
|
@@ -280,18 +300,21 @@ class LiteralIncludeReader:
|
|
|
280
300
|
if all(first + i == n for i, n in enumerate(linelist)):
|
|
281
301
|
self.lineno_start += linelist[0]
|
|
282
302
|
else:
|
|
283
|
-
|
|
284
|
-
|
|
303
|
+
msg = __('Cannot use "lineno-match" with a disjoint set of "lines"')
|
|
304
|
+
raise ValueError(msg)
|
|
285
305
|
|
|
286
306
|
lines = [lines[n] for n in linelist if n < len(lines)]
|
|
287
307
|
if not lines:
|
|
288
|
-
|
|
289
|
-
|
|
308
|
+
msg = __('Line spec %r: no lines pulled from include file %r') % (
|
|
309
|
+
linespec,
|
|
310
|
+
self.filename,
|
|
311
|
+
)
|
|
312
|
+
raise ValueError(msg)
|
|
290
313
|
|
|
291
314
|
return lines
|
|
292
315
|
|
|
293
316
|
def start_filter(
|
|
294
|
-
self, lines: list[str], location: tuple[str, int] | None = None
|
|
317
|
+
self, lines: list[str], location: tuple[str, int] | None = None
|
|
295
318
|
) -> list[str]:
|
|
296
319
|
if 'start-at' in self.options:
|
|
297
320
|
start = self.options.get('start-at')
|
|
@@ -309,7 +332,7 @@ class LiteralIncludeReader:
|
|
|
309
332
|
if 'lineno-match' in self.options:
|
|
310
333
|
self.lineno_start += lineno + 1
|
|
311
334
|
|
|
312
|
-
return lines[lineno + 1:]
|
|
335
|
+
return lines[lineno + 1 :]
|
|
313
336
|
else:
|
|
314
337
|
if 'lineno-match' in self.options:
|
|
315
338
|
self.lineno_start += lineno
|
|
@@ -324,7 +347,7 @@ class LiteralIncludeReader:
|
|
|
324
347
|
return lines
|
|
325
348
|
|
|
326
349
|
def end_filter(
|
|
327
|
-
self, lines: list[str], location: tuple[str, int] | None = None
|
|
350
|
+
self, lines: list[str], location: tuple[str, int] | None = None
|
|
328
351
|
) -> list[str]:
|
|
329
352
|
if 'end-at' in self.options:
|
|
330
353
|
end = self.options.get('end-at')
|
|
@@ -339,7 +362,7 @@ class LiteralIncludeReader:
|
|
|
339
362
|
for lineno, line in enumerate(lines):
|
|
340
363
|
if end in line:
|
|
341
364
|
if inclusive:
|
|
342
|
-
return lines[:lineno + 1]
|
|
365
|
+
return lines[: lineno + 1]
|
|
343
366
|
else:
|
|
344
367
|
if lineno == 0:
|
|
345
368
|
pass # end-before ignores first line
|
|
@@ -353,7 +376,7 @@ class LiteralIncludeReader:
|
|
|
353
376
|
return lines
|
|
354
377
|
|
|
355
378
|
def prepend_filter(
|
|
356
|
-
self, lines: list[str], location: tuple[str, int] | None = None
|
|
379
|
+
self, lines: list[str], location: tuple[str, int] | None = None
|
|
357
380
|
) -> list[str]:
|
|
358
381
|
prepend = self.options.get('prepend')
|
|
359
382
|
if prepend:
|
|
@@ -362,7 +385,7 @@ class LiteralIncludeReader:
|
|
|
362
385
|
return lines
|
|
363
386
|
|
|
364
387
|
def append_filter(
|
|
365
|
-
self, lines: list[str], location: tuple[str, int] | None = None
|
|
388
|
+
self, lines: list[str], location: tuple[str, int] | None = None
|
|
366
389
|
) -> list[str]:
|
|
367
390
|
append = self.options.get('append')
|
|
368
391
|
if append:
|
|
@@ -371,7 +394,7 @@ class LiteralIncludeReader:
|
|
|
371
394
|
return lines
|
|
372
395
|
|
|
373
396
|
def dedent_filter(
|
|
374
|
-
self, lines: list[str], location: tuple[str, int] | None = None
|
|
397
|
+
self, lines: list[str], location: tuple[str, int] | None = None
|
|
375
398
|
) -> list[str]:
|
|
376
399
|
if 'dedent' in self.options:
|
|
377
400
|
return dedent_lines(lines, self.options.get('dedent'), location=location)
|
|
@@ -417,8 +440,9 @@ class LiteralInclude(SphinxDirective):
|
|
|
417
440
|
def run(self) -> list[Node]:
|
|
418
441
|
document = self.state.document
|
|
419
442
|
if not document.settings.file_insertion_enabled:
|
|
420
|
-
return [
|
|
421
|
-
|
|
443
|
+
return [
|
|
444
|
+
document.reporter.warning('File insertion disabled', line=self.lineno)
|
|
445
|
+
]
|
|
422
446
|
# convert options['diff'] to absolute path
|
|
423
447
|
if 'diff' in self.options:
|
|
424
448
|
_, path = self.env.relfn2path(self.options['diff'])
|
|
@@ -439,17 +463,23 @@ class LiteralInclude(SphinxDirective):
|
|
|
439
463
|
retnode['language'] = 'udiff'
|
|
440
464
|
elif 'language' in self.options:
|
|
441
465
|
retnode['language'] = self.options['language']
|
|
442
|
-
if (
|
|
443
|
-
|
|
466
|
+
if (
|
|
467
|
+
'linenos' in self.options
|
|
468
|
+
or 'lineno-start' in self.options
|
|
469
|
+
or 'lineno-match' in self.options
|
|
470
|
+
):
|
|
444
471
|
retnode['linenos'] = True
|
|
445
472
|
retnode['classes'] += self.options.get('class', [])
|
|
446
473
|
extra_args = retnode['highlight_args'] = {}
|
|
447
474
|
if 'emphasize-lines' in self.options:
|
|
448
|
-
hl_lines =
|
|
475
|
+
hl_lines = parse_line_num_spec(self.options['emphasize-lines'], lines)
|
|
449
476
|
if any(i >= lines for i in hl_lines):
|
|
450
|
-
logger.warning(
|
|
451
|
-
|
|
452
|
-
|
|
477
|
+
logger.warning(
|
|
478
|
+
__('line number spec is out of range(1-%d): %r'),
|
|
479
|
+
lines,
|
|
480
|
+
self.options['emphasize-lines'],
|
|
481
|
+
location=location,
|
|
482
|
+
)
|
|
453
483
|
extra_args['hl_lines'] = [x + 1 for x in hl_lines if x < lines]
|
|
454
484
|
extra_args['linenostart'] = reader.lineno_start
|
|
455
485
|
|