Sphinx 7.3.6__py3-none-any.whl → 7.4.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 +5 -6
- sphinx/_cli/__init__.py +296 -0
- sphinx/_cli/util/__init__.py +0 -0
- sphinx/_cli/util/colour.py +103 -0
- sphinx/_cli/util/errors.py +165 -0
- sphinx/application.py +78 -43
- sphinx/builders/__init__.py +59 -15
- sphinx/builders/_epub_base.py +11 -5
- sphinx/builders/changes.py +2 -2
- sphinx/builders/epub3.py +2 -2
- sphinx/builders/gettext.py +10 -10
- sphinx/builders/html/__init__.py +56 -54
- sphinx/builders/latex/__init__.py +5 -5
- sphinx/builders/latex/constants.py +5 -0
- sphinx/builders/linkcheck.py +73 -38
- sphinx/builders/texinfo.py +1 -1
- sphinx/cmd/build.py +1 -1
- sphinx/cmd/quickstart.py +11 -11
- sphinx/config.py +57 -38
- sphinx/directives/__init__.py +7 -9
- sphinx/directives/code.py +12 -15
- sphinx/directives/other.py +12 -15
- sphinx/directives/patches.py +26 -0
- sphinx/domains/__init__.py +1 -1
- sphinx/domains/c/__init__.py +5 -5
- sphinx/domains/c/_ast.py +436 -12
- sphinx/domains/c/_symbol.py +89 -134
- sphinx/domains/changeset.py +3 -4
- sphinx/domains/cpp/__init__.py +5 -6
- sphinx/domains/cpp/_ast.py +822 -25
- sphinx/domains/cpp/_symbol.py +3 -0
- sphinx/domains/javascript.py +3 -6
- sphinx/domains/math.py +3 -2
- sphinx/domains/python/__init__.py +45 -6
- sphinx/domains/python/_object.py +7 -5
- sphinx/domains/rst.py +2 -2
- sphinx/domains/std/__init__.py +95 -14
- sphinx/environment/__init__.py +35 -15
- sphinx/environment/adapters/indexentries.py +71 -24
- sphinx/environment/adapters/toctree.py +1 -1
- sphinx/environment/collectors/__init__.py +18 -4
- sphinx/environment/collectors/asset.py +4 -4
- sphinx/environment/collectors/toctree.py +27 -14
- sphinx/events.py +7 -6
- sphinx/ext/apidoc.py +377 -170
- sphinx/ext/autodoc/__init__.py +13 -13
- sphinx/ext/autodoc/directive.py +10 -13
- sphinx/ext/autodoc/mock.py +10 -7
- sphinx/ext/autodoc/preserve_defaults.py +1 -1
- sphinx/ext/autodoc/typehints.py +2 -2
- sphinx/ext/autosummary/__init__.py +15 -9
- sphinx/ext/autosummary/generate.py +270 -154
- sphinx/ext/coverage.py +108 -18
- sphinx/ext/duration.py +10 -3
- sphinx/ext/extlinks.py +3 -2
- sphinx/ext/graphviz.py +3 -3
- sphinx/ext/ifconfig.py +1 -2
- sphinx/ext/imgconverter.py +1 -0
- sphinx/ext/imgmath.py +7 -6
- sphinx/ext/inheritance_diagram.py +3 -3
- sphinx/ext/intersphinx/__init__.py +81 -0
- sphinx/ext/intersphinx/__main__.py +10 -0
- sphinx/ext/intersphinx/_cli.py +44 -0
- sphinx/ext/intersphinx/_load.py +253 -0
- sphinx/ext/{intersphinx.py → intersphinx/_resolve.py} +17 -368
- sphinx/ext/intersphinx/_shared.py +53 -0
- sphinx/ext/mathjax.py +1 -1
- sphinx/ext/todo.py +2 -2
- sphinx/io.py +2 -6
- sphinx/locale/__init__.py +1 -5
- sphinx/locale/ar/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +678 -471
- sphinx/locale/bg/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +684 -476
- sphinx/locale/bn/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +679 -472
- sphinx/locale/ca/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +681 -474
- sphinx/locale/cak/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +678 -471
- sphinx/locale/cs/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +679 -472
- sphinx/locale/cy/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +679 -472
- sphinx/locale/da/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +679 -472
- sphinx/locale/de/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +679 -472
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +678 -471
- sphinx/locale/el/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/eo/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/es/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/et/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/eu/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/fa/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/fi/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/fr/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr/LC_MESSAGES/sphinx.po +725 -518
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/gl/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/he/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/hi/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/hr/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/hu/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/id/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/is/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/it/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +708 -500
- sphinx/locale/ja/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/ka/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/ko/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/lt/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/lv/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/mk/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/ne/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/nl/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/pl/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/pt/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +705 -498
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/ro/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/ru/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +890 -680
- sphinx/locale/si/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/sk/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/sl/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/sphinx.pot +702 -494
- sphinx/locale/sq/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sq/LC_MESSAGES/sphinx.po +704 -497
- sphinx/locale/sr/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/sr@latin/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/ta/LC_MESSAGES/sphinx.po +1016 -808
- sphinx/locale/te/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/tr/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/ur/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/vi/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +701 -494
- sphinx/locale/yue/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +704 -496
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +700 -493
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +729 -522
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +700 -493
- sphinx/roles.py +1 -1
- sphinx/search/__init__.py +17 -9
- sphinx/templates/quickstart/{root_doc.rst_t → root_doc.rst.jinja} +7 -10
- sphinx/testing/fixtures.py +22 -20
- sphinx/testing/path.py +6 -2
- sphinx/testing/util.py +8 -13
- sphinx/texinputs/sphinx.sty +449 -332
- sphinx/texinputs/sphinxlatexadmonitions.sty +209 -66
- sphinx/texinputs/sphinxlatexliterals.sty +9 -16
- sphinx/texinputs/sphinxlatexstyletext.sty +4 -38
- sphinx/texinputs/sphinxlatextables.sty +6 -14
- sphinx/texinputs/sphinxpackageboxes.sty +15 -42
- sphinx/texinputs/sphinxpackagefootnote.sty +4 -3
- sphinx/themes/agogo/layout.html +3 -3
- sphinx/themes/basic/genindex-single.html +2 -1
- sphinx/themes/basic/layout.html +3 -6
- sphinx/themes/basic/static/searchtools.js +4 -3
- sphinx/themes/haiku/layout.html +4 -4
- sphinx/themes/pyramid/layout.html +1 -1
- sphinx/themes/scrolls/layout.html +2 -2
- sphinx/theming.py +42 -7
- sphinx/transforms/__init__.py +34 -20
- sphinx/transforms/i18n.py +8 -7
- sphinx/transforms/post_transforms/__init__.py +1 -1
- sphinx/transforms/post_transforms/images.py +7 -10
- sphinx/util/_pathlib.py +2 -2
- sphinx/util/cfamily.py +52 -30
- sphinx/util/console.py +1 -1
- sphinx/util/display.py +16 -11
- sphinx/util/docutils.py +88 -40
- sphinx/util/fileutil.py +15 -3
- sphinx/util/images.py +1 -0
- sphinx/util/inspect.py +66 -22
- sphinx/util/inventory.py +15 -0
- sphinx/util/logging.py +14 -21
- sphinx/util/math.py +3 -1
- sphinx/util/nodes.py +9 -12
- sphinx/util/osutil.py +5 -5
- sphinx/util/parsing.py +93 -0
- sphinx/util/tags.py +71 -47
- sphinx/util/typing.py +261 -143
- sphinx/versioning.py +17 -17
- sphinx/writers/html5.py +26 -19
- sphinx/writers/latex.py +58 -28
- sphinx/writers/manpage.py +4 -3
- sphinx/writers/texinfo.py +19 -14
- {sphinx-7.3.6.dist-info → sphinx-7.4.0.dist-info}/METADATA +21 -20
- sphinx-7.4.0.dist-info/RECORD +591 -0
- sphinx-7.3.6.dist-info/RECORD +0 -581
- /sphinx/templates/apidoc/{module.rst_t → module.rst.jinja} +0 -0
- /sphinx/templates/apidoc/{package.rst_t → package.rst.jinja} +0 -0
- /sphinx/templates/apidoc/{toc.rst_t → toc.rst.jinja} +0 -0
- /sphinx/templates/epub3/{content.opf_t → content.opf.jinja} +0 -0
- /sphinx/templates/epub3/{nav.xhtml_t → nav.xhtml.jinja} +0 -0
- /sphinx/templates/epub3/{toc.ncx_t → toc.ncx.jinja} +0 -0
- /sphinx/templates/gettext/{message.pot_t → message.pot.jinja} +0 -0
- /sphinx/templates/imgmath/{preview.tex_t → preview.tex.jinja} +0 -0
- /sphinx/templates/imgmath/{template.tex_t → template.tex.jinja} +0 -0
- /sphinx/templates/latex/{latex.tex_t → latex.tex.jinja} +0 -0
- /sphinx/templates/latex/{longtable.tex_t → longtable.tex.jinja} +0 -0
- /sphinx/templates/latex/{sphinxmessages.sty_t → sphinxmessages.sty.jinja} +0 -0
- /sphinx/templates/latex/{tabular.tex_t → tabular.tex.jinja} +0 -0
- /sphinx/templates/latex/{tabulary.tex_t → tabulary.tex.jinja} +0 -0
- /sphinx/templates/quickstart/{Makefile_t → Makefile.jinja} +0 -0
- /sphinx/templates/quickstart/{Makefile.new_t → Makefile.new.jinja} +0 -0
- /sphinx/templates/quickstart/{conf.py_t → conf.py.jinja} +0 -0
- /sphinx/templates/quickstart/{make.bat_t → make.bat.jinja} +0 -0
- /sphinx/templates/quickstart/{make.bat.new_t → make.bat.new.jinja} +0 -0
- /sphinx/texinputs/{Makefile_t → Makefile.jinja} +0 -0
- /sphinx/texinputs/{latexmkjarc_t → latexmkjarc.jinja} +0 -0
- /sphinx/texinputs/{latexmkrc_t → latexmkrc.jinja} +0 -0
- /sphinx/texinputs/{make.bat_t → make.bat.jinja} +0 -0
- /sphinx/texinputs_win/{Makefile_t → Makefile.jinja} +0 -0
- /sphinx/themes/agogo/static/{agogo.css_t → agogo.css.jinja} +0 -0
- /sphinx/themes/basic/static/{basic.css_t → basic.css.jinja} +0 -0
- /sphinx/themes/basic/static/{documentation_options.js_t → documentation_options.js.jinja} +0 -0
- /sphinx/themes/basic/static/{language_data.js_t → language_data.js.jinja} +0 -0
- /sphinx/themes/bizstyle/static/{bizstyle.css_t → bizstyle.css.jinja} +0 -0
- /sphinx/themes/bizstyle/static/{bizstyle.js_t → bizstyle.js.jinja} +0 -0
- /sphinx/themes/classic/static/{classic.css_t → classic.css.jinja} +0 -0
- /sphinx/themes/classic/static/{sidebar.js_t → sidebar.js.jinja} +0 -0
- /sphinx/themes/epub/static/{epub.css_t → epub.css.jinja} +0 -0
- /sphinx/themes/haiku/static/{haiku.css_t → haiku.css.jinja} +0 -0
- /sphinx/themes/nature/static/{nature.css_t → nature.css.jinja} +0 -0
- /sphinx/themes/nonav/static/{nonav.css_t → nonav.css.jinja} +0 -0
- /sphinx/themes/pyramid/static/{epub.css_t → epub.css.jinja} +0 -0
- /sphinx/themes/pyramid/static/{pyramid.css_t → pyramid.css.jinja} +0 -0
- /sphinx/themes/scrolls/static/{scrolls.css_t → scrolls.css.jinja} +0 -0
- /sphinx/themes/sphinxdoc/static/{sphinxdoc.css_t → sphinxdoc.css.jinja} +0 -0
- /sphinx/themes/traditional/static/{traditional.css_t → traditional.css.jinja} +0 -0
- {sphinx-7.3.6.dist-info → sphinx-7.4.0.dist-info}/LICENSE.rst +0 -0
- {sphinx-7.3.6.dist-info → sphinx-7.4.0.dist-info}/WHEEL +0 -0
- {sphinx-7.3.6.dist-info → sphinx-7.4.0.dist-info}/entry_points.txt +0 -0
sphinx/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""The Sphinx documentation toolchain."""
|
|
2
2
|
|
|
3
|
-
__version__ = '7.
|
|
3
|
+
__version__ = '7.4.0'
|
|
4
4
|
__display_version__ = __version__ # used for command line version
|
|
5
5
|
|
|
6
6
|
# Keep this file executable as-is in Python 3!
|
|
@@ -8,13 +8,12 @@ __display_version__ = __version__ # used for command line version
|
|
|
8
8
|
|
|
9
9
|
import os
|
|
10
10
|
import warnings
|
|
11
|
-
from os import path
|
|
12
|
-
|
|
13
|
-
from .deprecation import RemovedInNextVersionWarning
|
|
14
11
|
|
|
15
12
|
# by default, all DeprecationWarning under sphinx package will be emit.
|
|
16
13
|
# Users can avoid this by using environment variable: PYTHONWARNINGS=
|
|
17
14
|
if 'PYTHONWARNINGS' not in os.environ:
|
|
15
|
+
from sphinx.deprecation import RemovedInNextVersionWarning
|
|
16
|
+
|
|
18
17
|
warnings.filterwarnings('default', category=RemovedInNextVersionWarning)
|
|
19
18
|
warnings.filterwarnings(
|
|
20
19
|
'ignore', 'The frontend.Option class .*', DeprecationWarning, module='docutils.frontend'
|
|
@@ -28,9 +27,9 @@ warnings.filterwarnings(
|
|
|
28
27
|
#:
|
|
29
28
|
#: .. versionadded:: 1.2
|
|
30
29
|
#: Before version 1.2, check the string ``sphinx.__version__``.
|
|
31
|
-
version_info = (7,
|
|
30
|
+
version_info = (7, 4, 0, 'final', 0)
|
|
32
31
|
|
|
33
|
-
package_dir = path.abspath(path.dirname(__file__))
|
|
32
|
+
package_dir = os.path.abspath(os.path.dirname(__file__))
|
|
34
33
|
|
|
35
34
|
_in_development = False
|
|
36
35
|
if _in_development:
|
sphinx/_cli/__init__.py
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"""Base 'sphinx' command.
|
|
2
|
+
|
|
3
|
+
Subcommands are loaded lazily from the ``_COMMANDS`` table for performance.
|
|
4
|
+
|
|
5
|
+
All subcommand modules must define three attributes:
|
|
6
|
+
|
|
7
|
+
- ``parser_description``, a description of the subcommand. The first paragraph
|
|
8
|
+
is taken as the short description for the command.
|
|
9
|
+
- ``set_up_parser``, a callable taking and returning an ``ArgumentParser``. This
|
|
10
|
+
function is responsible for adding options and arguments to the subcommand's
|
|
11
|
+
parser.
|
|
12
|
+
- ``run``, a callable taking parsed arguments and returning an exit code. This
|
|
13
|
+
function is responsible for running the main body of the subcommand and
|
|
14
|
+
returning the exit status.
|
|
15
|
+
|
|
16
|
+
The entire ``sphinx._cli`` namespace is private, only the command line interface
|
|
17
|
+
has backwards-compatibility guarantees.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import argparse
|
|
23
|
+
import importlib
|
|
24
|
+
import locale
|
|
25
|
+
import sys
|
|
26
|
+
from typing import TYPE_CHECKING
|
|
27
|
+
|
|
28
|
+
from sphinx._cli.util.colour import (
|
|
29
|
+
bold,
|
|
30
|
+
disable_colour,
|
|
31
|
+
enable_colour,
|
|
32
|
+
terminal_supports_colour,
|
|
33
|
+
underline,
|
|
34
|
+
)
|
|
35
|
+
from sphinx.locale import __, init_console
|
|
36
|
+
|
|
37
|
+
if TYPE_CHECKING:
|
|
38
|
+
from collections.abc import Callable, Iterable, Iterator, Sequence
|
|
39
|
+
from typing import NoReturn
|
|
40
|
+
|
|
41
|
+
_PARSER_SETUP = Callable[[argparse.ArgumentParser], argparse.ArgumentParser]
|
|
42
|
+
_RUNNER = Callable[[argparse.Namespace], int]
|
|
43
|
+
|
|
44
|
+
from typing import Protocol
|
|
45
|
+
|
|
46
|
+
class _SubcommandModule(Protocol):
|
|
47
|
+
parser_description: str
|
|
48
|
+
set_up_parser: _PARSER_SETUP # takes and returns argument parser
|
|
49
|
+
run: _RUNNER # takes parsed args, returns exit code
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# Map of command name to import path.
|
|
53
|
+
_COMMANDS: dict[str, str] = {
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _load_subcommand_descriptions() -> Iterator[tuple[str, str]]:
|
|
58
|
+
for command, module_name in _COMMANDS.items():
|
|
59
|
+
module: _SubcommandModule = importlib.import_module(module_name)
|
|
60
|
+
try:
|
|
61
|
+
description = module.parser_description
|
|
62
|
+
except AttributeError:
|
|
63
|
+
# log an error here, but don't fail the full enumeration
|
|
64
|
+
print(f"Failed to load the description for {command}", file=sys.stderr)
|
|
65
|
+
else:
|
|
66
|
+
yield command, description.split('\n\n', 1)[0]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class _RootArgumentParser(argparse.ArgumentParser):
|
|
70
|
+
def format_help(self) -> str:
|
|
71
|
+
help_fragments: list[str] = [
|
|
72
|
+
bold(underline(__('Usage:'))),
|
|
73
|
+
' ',
|
|
74
|
+
__('{0} [OPTIONS] <COMMAND> [<ARGS>]').format(bold(self.prog)),
|
|
75
|
+
'\n',
|
|
76
|
+
'\n',
|
|
77
|
+
__(' The Sphinx documentation generator.'),
|
|
78
|
+
'\n',
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
if commands := list(_load_subcommand_descriptions()):
|
|
82
|
+
command_max_length = min(max(map(len, next(zip(*commands), ()))), 22)
|
|
83
|
+
help_fragments += [
|
|
84
|
+
'\n',
|
|
85
|
+
bold(underline(__('Commands:'))),
|
|
86
|
+
'\n',
|
|
87
|
+
]
|
|
88
|
+
help_fragments += [
|
|
89
|
+
f' {command_name: <{command_max_length}} {command_desc}'
|
|
90
|
+
for command_name, command_desc in commands
|
|
91
|
+
]
|
|
92
|
+
help_fragments.append('\n')
|
|
93
|
+
|
|
94
|
+
# self._action_groups[1] is self._optionals
|
|
95
|
+
# Uppercase the title of the Optionals group
|
|
96
|
+
self._optionals.title = __('Options')
|
|
97
|
+
for argument_group in self._action_groups[1:]:
|
|
98
|
+
if arguments := [action for action in argument_group._group_actions
|
|
99
|
+
if action.help != argparse.SUPPRESS]:
|
|
100
|
+
help_fragments += self._format_optional_arguments(
|
|
101
|
+
arguments,
|
|
102
|
+
argument_group.title or '',
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
help_fragments += [
|
|
106
|
+
'\n',
|
|
107
|
+
__('For more information, visit https://www.sphinx-doc.org/en/master/man/.'),
|
|
108
|
+
'\n',
|
|
109
|
+
]
|
|
110
|
+
return ''.join(help_fragments)
|
|
111
|
+
|
|
112
|
+
def _format_optional_arguments(
|
|
113
|
+
self,
|
|
114
|
+
actions: Iterable[argparse.Action],
|
|
115
|
+
title: str,
|
|
116
|
+
) -> Iterator[str]:
|
|
117
|
+
yield '\n'
|
|
118
|
+
yield bold(underline(title + ':'))
|
|
119
|
+
yield '\n'
|
|
120
|
+
|
|
121
|
+
for action in actions:
|
|
122
|
+
prefix = ' ' * all(o[1] == '-' for o in action.option_strings)
|
|
123
|
+
opt = prefix + ' ' + ', '.join(map(bold, action.option_strings))
|
|
124
|
+
if action.nargs != 0:
|
|
125
|
+
opt += ' ' + self._format_metavar(
|
|
126
|
+
action.nargs, action.metavar, action.choices, action.dest,
|
|
127
|
+
)
|
|
128
|
+
yield opt
|
|
129
|
+
yield '\n'
|
|
130
|
+
if action_help := (action.help or '').strip():
|
|
131
|
+
yield from (f' {line}\n' for line in action_help.splitlines())
|
|
132
|
+
|
|
133
|
+
@staticmethod
|
|
134
|
+
def _format_metavar(
|
|
135
|
+
nargs: int | str | None,
|
|
136
|
+
metavar: str | tuple[str, ...] | None,
|
|
137
|
+
choices: Iterable[str] | None,
|
|
138
|
+
dest: str,
|
|
139
|
+
) -> str:
|
|
140
|
+
if metavar is None:
|
|
141
|
+
if choices is not None:
|
|
142
|
+
metavar = '{' + ', '.join(sorted(choices)) + '}'
|
|
143
|
+
else:
|
|
144
|
+
metavar = dest.upper()
|
|
145
|
+
if nargs is None:
|
|
146
|
+
return f'{metavar}'
|
|
147
|
+
elif nargs == argparse.OPTIONAL:
|
|
148
|
+
return f'[{metavar}]'
|
|
149
|
+
elif nargs == argparse.ZERO_OR_MORE:
|
|
150
|
+
if len(metavar) == 2:
|
|
151
|
+
return f'[{metavar[0]} [{metavar[1]} ...]]'
|
|
152
|
+
else:
|
|
153
|
+
return f'[{metavar} ...]'
|
|
154
|
+
elif nargs == argparse.ONE_OR_MORE:
|
|
155
|
+
return f'{metavar} [{metavar} ...]'
|
|
156
|
+
elif nargs == argparse.REMAINDER:
|
|
157
|
+
return '...'
|
|
158
|
+
elif nargs == argparse.PARSER:
|
|
159
|
+
return f'{metavar} ...'
|
|
160
|
+
msg = 'invalid nargs value'
|
|
161
|
+
raise ValueError(msg)
|
|
162
|
+
|
|
163
|
+
def error(self, message: str) -> NoReturn:
|
|
164
|
+
sys.stderr.write(__(
|
|
165
|
+
'{0}: error: {1}\n'
|
|
166
|
+
"Run '{0} --help' for information" # NoQA: COM812
|
|
167
|
+
).format(self.prog, message))
|
|
168
|
+
raise SystemExit(2)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def _create_parser() -> _RootArgumentParser:
|
|
172
|
+
parser = _RootArgumentParser(
|
|
173
|
+
prog='sphinx',
|
|
174
|
+
description=__(' Manage documentation with Sphinx.'),
|
|
175
|
+
epilog=__('For more information, visit https://www.sphinx-doc.org/en/master/man/.'),
|
|
176
|
+
add_help=False,
|
|
177
|
+
allow_abbrev=False,
|
|
178
|
+
)
|
|
179
|
+
parser.add_argument(
|
|
180
|
+
'-V', '--version',
|
|
181
|
+
action='store_true',
|
|
182
|
+
default=argparse.SUPPRESS,
|
|
183
|
+
help=__('Show the version and exit.'),
|
|
184
|
+
)
|
|
185
|
+
parser.add_argument(
|
|
186
|
+
'-h', '-?', '--help',
|
|
187
|
+
action='store_true',
|
|
188
|
+
default=argparse.SUPPRESS,
|
|
189
|
+
help=__('Show this message and exit.'),
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
# logging control
|
|
193
|
+
log_control = parser.add_argument_group(__('Logging'))
|
|
194
|
+
log_control.add_argument(
|
|
195
|
+
'-v', '--verbose',
|
|
196
|
+
action='count',
|
|
197
|
+
dest='verbosity',
|
|
198
|
+
default=0,
|
|
199
|
+
help=__('Increase verbosity (can be repeated)'),
|
|
200
|
+
)
|
|
201
|
+
log_control.add_argument(
|
|
202
|
+
'-q', '--quiet',
|
|
203
|
+
action='store_const',
|
|
204
|
+
dest='verbosity',
|
|
205
|
+
const=-1,
|
|
206
|
+
help=__('Only print errors and warnings.'),
|
|
207
|
+
)
|
|
208
|
+
log_control.add_argument(
|
|
209
|
+
'--silent',
|
|
210
|
+
action='store_const',
|
|
211
|
+
dest='verbosity',
|
|
212
|
+
const=-2,
|
|
213
|
+
help=__('No output at all'),
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
parser.add_argument(
|
|
217
|
+
'COMMAND',
|
|
218
|
+
nargs=argparse.REMAINDER,
|
|
219
|
+
metavar=__('<command>'),
|
|
220
|
+
)
|
|
221
|
+
return parser
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def _parse_command(argv: Sequence[str] = ()) -> tuple[str, Sequence[str]]:
|
|
225
|
+
parser = _create_parser()
|
|
226
|
+
args = parser.parse_args(argv)
|
|
227
|
+
command_name, *command_argv = args.COMMAND or ('help',)
|
|
228
|
+
command_name = command_name.lower()
|
|
229
|
+
|
|
230
|
+
if terminal_supports_colour():
|
|
231
|
+
enable_colour()
|
|
232
|
+
else:
|
|
233
|
+
disable_colour()
|
|
234
|
+
|
|
235
|
+
# Handle '--version' or '-V' passed to the main command or any subcommand
|
|
236
|
+
if 'version' in args or {'-V', '--version'}.intersection(command_argv):
|
|
237
|
+
from sphinx import __display_version__
|
|
238
|
+
sys.stderr.write(f'sphinx {__display_version__}\n')
|
|
239
|
+
raise SystemExit(0)
|
|
240
|
+
|
|
241
|
+
# Handle '--help' or '-h' passed to the main command (subcommands may have
|
|
242
|
+
# their own help text)
|
|
243
|
+
if 'help' in args or command_name == 'help':
|
|
244
|
+
sys.stderr.write(parser.format_help())
|
|
245
|
+
raise SystemExit(0)
|
|
246
|
+
|
|
247
|
+
if command_name not in _COMMANDS:
|
|
248
|
+
sys.stderr.write(__(f'sphinx: {command_name!r} is not a sphinx command. '
|
|
249
|
+
"See 'sphinx --help'.\n"))
|
|
250
|
+
raise SystemExit(2)
|
|
251
|
+
|
|
252
|
+
return command_name, command_argv
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def _load_subcommand(command_name: str) -> tuple[str, _PARSER_SETUP, _RUNNER]:
|
|
256
|
+
try:
|
|
257
|
+
module: _SubcommandModule = importlib.import_module(_COMMANDS[command_name])
|
|
258
|
+
except KeyError:
|
|
259
|
+
msg = f'invalid command name {command_name!r}.'
|
|
260
|
+
raise ValueError(msg) from None
|
|
261
|
+
return module.parser_description, module.set_up_parser, module.run
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def _create_sub_parser(
|
|
265
|
+
command_name: str,
|
|
266
|
+
description: str,
|
|
267
|
+
parser_setup: _PARSER_SETUP,
|
|
268
|
+
) -> argparse.ArgumentParser:
|
|
269
|
+
parser = argparse.ArgumentParser(
|
|
270
|
+
prog=f'sphinx {command_name}',
|
|
271
|
+
description=description,
|
|
272
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
273
|
+
allow_abbrev=False,
|
|
274
|
+
)
|
|
275
|
+
return parser_setup(parser)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def run(argv: Sequence[str] = (), /) -> int:
|
|
279
|
+
locale.setlocale(locale.LC_ALL, '')
|
|
280
|
+
init_console()
|
|
281
|
+
|
|
282
|
+
argv = argv or sys.argv[1:]
|
|
283
|
+
try:
|
|
284
|
+
cmd_name, cmd_argv = _parse_command(argv)
|
|
285
|
+
cmd_description, set_up_parser, runner = _load_subcommand(cmd_name)
|
|
286
|
+
cmd_parser = _create_sub_parser(cmd_name, cmd_description, set_up_parser)
|
|
287
|
+
cmd_args = cmd_parser.parse_args(cmd_argv)
|
|
288
|
+
return runner(cmd_args)
|
|
289
|
+
except SystemExit as exc:
|
|
290
|
+
return exc.code # type: ignore[return-value]
|
|
291
|
+
except (Exception, KeyboardInterrupt):
|
|
292
|
+
return 2
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
if __name__ == '__main__':
|
|
296
|
+
raise SystemExit(run())
|
|
File without changes
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Format coloured console output."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
from collections.abc import Callable # NoQA: TCH003
|
|
8
|
+
|
|
9
|
+
if sys.platform == 'win32':
|
|
10
|
+
import colorama
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
_COLOURING_DISABLED = True
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def terminal_supports_colour() -> bool:
|
|
17
|
+
"""Return True if coloured terminal output is supported."""
|
|
18
|
+
if 'NO_COLOUR' in os.environ or 'NO_COLOR' in os.environ:
|
|
19
|
+
return False
|
|
20
|
+
if 'FORCE_COLOUR' in os.environ or 'FORCE_COLOR' in os.environ:
|
|
21
|
+
return True
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
if not sys.stdout.isatty():
|
|
25
|
+
return False
|
|
26
|
+
except (AttributeError, ValueError):
|
|
27
|
+
# Handle cases where .isatty() is not defined, or where e.g.
|
|
28
|
+
# "ValueError: I/O operation on closed file" is raised
|
|
29
|
+
return False
|
|
30
|
+
|
|
31
|
+
# Do not colour output if on a dumb terminal
|
|
32
|
+
return os.environ.get('TERM', 'unknown').lower() not in {'dumb', 'unknown'}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def disable_colour() -> None:
|
|
36
|
+
global _COLOURING_DISABLED
|
|
37
|
+
_COLOURING_DISABLED = True
|
|
38
|
+
if sys.platform == 'win32':
|
|
39
|
+
colorama.deinit()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def enable_colour() -> None:
|
|
43
|
+
global _COLOURING_DISABLED
|
|
44
|
+
_COLOURING_DISABLED = False
|
|
45
|
+
if sys.platform == 'win32':
|
|
46
|
+
colorama.init()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def colourise(colour_name: str, text: str, /) -> str:
|
|
50
|
+
if _COLOURING_DISABLED:
|
|
51
|
+
return text
|
|
52
|
+
return globals()[colour_name](text)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _create_colour_func(escape_code: str, /) -> Callable[[str], str]:
|
|
56
|
+
def inner(text: str) -> str:
|
|
57
|
+
if _COLOURING_DISABLED:
|
|
58
|
+
return text
|
|
59
|
+
return f'\x1b[{escape_code}m{text}\x1b[39;49;00m'
|
|
60
|
+
return inner
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Wrap escape sequence with ``\1`` and ``\2`` to let readline know
|
|
64
|
+
# that the colour escape codes are non-printable characters
|
|
65
|
+
# [ https://tiswww.case.edu/php/chet/readline/readline.html ]
|
|
66
|
+
#
|
|
67
|
+
# Note: This does not work well in Windows
|
|
68
|
+
# (see https://github.com/sphinx-doc/sphinx/pull/5059)
|
|
69
|
+
if sys.platform == 'win32':
|
|
70
|
+
_create_input_mode_colour_func = _create_colour_func
|
|
71
|
+
else:
|
|
72
|
+
def _create_input_mode_colour_func(escape_code: str, /) -> Callable[[str], str]:
|
|
73
|
+
def inner(text: str) -> str:
|
|
74
|
+
if _COLOURING_DISABLED:
|
|
75
|
+
return text
|
|
76
|
+
return f'\x01\x1b[{escape_code}m\x02{text}\x01\x1b[39;49;00m\x02'
|
|
77
|
+
return inner
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
reset = _create_colour_func('39;49;00')
|
|
81
|
+
bold = _create_colour_func('01')
|
|
82
|
+
faint = _create_colour_func('02')
|
|
83
|
+
standout = _create_colour_func('03')
|
|
84
|
+
underline = _create_colour_func('04')
|
|
85
|
+
blink = _create_colour_func('05')
|
|
86
|
+
|
|
87
|
+
black = _create_colour_func('30')
|
|
88
|
+
darkred = _create_colour_func('31')
|
|
89
|
+
darkgreen = _create_colour_func('32')
|
|
90
|
+
brown = _create_colour_func('33')
|
|
91
|
+
darkblue = _create_colour_func('34')
|
|
92
|
+
purple = _create_colour_func('35')
|
|
93
|
+
turquoise = _create_colour_func('36')
|
|
94
|
+
lightgray = _create_colour_func('37')
|
|
95
|
+
|
|
96
|
+
darkgray = _create_colour_func('90')
|
|
97
|
+
red = _create_colour_func('91')
|
|
98
|
+
green = _create_colour_func('92')
|
|
99
|
+
yellow = _create_colour_func('93')
|
|
100
|
+
blue = _create_colour_func('94')
|
|
101
|
+
fuchsia = _create_colour_func('95')
|
|
102
|
+
teal = _create_colour_func('96')
|
|
103
|
+
white = _create_colour_func('97')
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
import sys
|
|
5
|
+
import tempfile
|
|
6
|
+
from typing import TYPE_CHECKING, TextIO
|
|
7
|
+
|
|
8
|
+
from sphinx.errors import SphinxParallelError
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from sphinx.application import Sphinx
|
|
12
|
+
|
|
13
|
+
_ANSI_COLOUR_CODES: re.Pattern[str] = re.compile('\x1b.*?m')
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def terminal_safe(s: str, /) -> str:
|
|
17
|
+
"""Safely encode a string for printing to the terminal."""
|
|
18
|
+
return s.encode('ascii', 'backslashreplace').decode('ascii')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def strip_colors(s: str, /) -> str:
|
|
22
|
+
return _ANSI_COLOUR_CODES.sub('', s).strip()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def error_info(messages: str, extensions: str, traceback: str) -> str:
|
|
26
|
+
import platform
|
|
27
|
+
|
|
28
|
+
import docutils
|
|
29
|
+
import jinja2
|
|
30
|
+
import pygments
|
|
31
|
+
|
|
32
|
+
import sphinx
|
|
33
|
+
|
|
34
|
+
return f"""\
|
|
35
|
+
Versions
|
|
36
|
+
========
|
|
37
|
+
|
|
38
|
+
* Platform: {sys.platform}; ({platform.platform()})
|
|
39
|
+
* Python version: {platform.python_version()} ({platform.python_implementation()})
|
|
40
|
+
* Sphinx version: {sphinx.__display_version__}
|
|
41
|
+
* Docutils version: {docutils.__version__}
|
|
42
|
+
* Jinja2 version: {jinja2.__version__}
|
|
43
|
+
* Pygments version: {pygments.__version__}
|
|
44
|
+
|
|
45
|
+
Last Messages
|
|
46
|
+
=============
|
|
47
|
+
|
|
48
|
+
{messages}
|
|
49
|
+
|
|
50
|
+
Loaded Extensions
|
|
51
|
+
=================
|
|
52
|
+
|
|
53
|
+
{extensions}
|
|
54
|
+
|
|
55
|
+
Traceback
|
|
56
|
+
=========
|
|
57
|
+
|
|
58
|
+
{traceback}
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def save_traceback(app: Sphinx | None, exc: BaseException) -> str:
|
|
63
|
+
"""Save the given exception's traceback in a temporary file."""
|
|
64
|
+
if isinstance(exc, SphinxParallelError):
|
|
65
|
+
exc_format = '(Error in parallel process)\n' + exc.traceback
|
|
66
|
+
else:
|
|
67
|
+
import traceback
|
|
68
|
+
|
|
69
|
+
exc_format = traceback.format_exc()
|
|
70
|
+
|
|
71
|
+
last_msgs = exts_list = ''
|
|
72
|
+
if app is not None:
|
|
73
|
+
extensions = app.extensions.values()
|
|
74
|
+
last_msgs = '\n'.join(f'* {strip_colors(s)}' for s in app.messagelog)
|
|
75
|
+
exts_list = '\n'.join(f'* {ext.name} ({ext.version})' for ext in extensions
|
|
76
|
+
if ext.version != 'builtin')
|
|
77
|
+
|
|
78
|
+
with tempfile.NamedTemporaryFile(suffix='.log', prefix='sphinx-err-', delete=False) as f:
|
|
79
|
+
f.write(error_info(last_msgs, exts_list, exc_format).encode('utf-8'))
|
|
80
|
+
|
|
81
|
+
return f.name
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def handle_exception(
|
|
85
|
+
exception: BaseException,
|
|
86
|
+
/,
|
|
87
|
+
*,
|
|
88
|
+
stderr: TextIO = sys.stderr,
|
|
89
|
+
use_pdb: bool = False,
|
|
90
|
+
print_traceback: bool = False,
|
|
91
|
+
app: Sphinx | None = None,
|
|
92
|
+
) -> None:
|
|
93
|
+
from bdb import BdbQuit
|
|
94
|
+
from traceback import TracebackException, print_exc
|
|
95
|
+
|
|
96
|
+
from docutils.utils import SystemMessage
|
|
97
|
+
|
|
98
|
+
from sphinx._cli.util.colour import red
|
|
99
|
+
from sphinx.errors import SphinxError
|
|
100
|
+
from sphinx.locale import __
|
|
101
|
+
|
|
102
|
+
if isinstance(exception, BdbQuit):
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
def print_err(*values: str) -> None:
|
|
106
|
+
print(*values, file=stderr)
|
|
107
|
+
|
|
108
|
+
def print_red(*values: str) -> None:
|
|
109
|
+
print_err(*map(red, values))
|
|
110
|
+
|
|
111
|
+
print_err()
|
|
112
|
+
if print_traceback or use_pdb:
|
|
113
|
+
print_exc(file=stderr)
|
|
114
|
+
print_err()
|
|
115
|
+
|
|
116
|
+
if use_pdb:
|
|
117
|
+
from pdb import post_mortem
|
|
118
|
+
|
|
119
|
+
print_red(__('Exception occurred, starting debugger:'))
|
|
120
|
+
post_mortem()
|
|
121
|
+
return
|
|
122
|
+
|
|
123
|
+
if isinstance(exception, KeyboardInterrupt):
|
|
124
|
+
print_err(__('Interrupted!'))
|
|
125
|
+
return
|
|
126
|
+
|
|
127
|
+
if isinstance(exception, SystemMessage):
|
|
128
|
+
print_red(__('reStructuredText markup error:'))
|
|
129
|
+
print_err(str(exception))
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
if isinstance(exception, SphinxError):
|
|
133
|
+
print_red(f'{exception.category}:')
|
|
134
|
+
print_err(str(exception))
|
|
135
|
+
return
|
|
136
|
+
|
|
137
|
+
if isinstance(exception, UnicodeError):
|
|
138
|
+
print_red(__('Encoding error:'))
|
|
139
|
+
print_err(str(exception))
|
|
140
|
+
return
|
|
141
|
+
|
|
142
|
+
if isinstance(exception, RecursionError):
|
|
143
|
+
print_red(__('Recursion error:'))
|
|
144
|
+
print_err(str(exception))
|
|
145
|
+
print_err()
|
|
146
|
+
print_err(__('This can happen with very large or deeply nested source '
|
|
147
|
+
'files. You can carefully increase the default Python '
|
|
148
|
+
'recursion limit of 1000 in conf.py with e.g.:'))
|
|
149
|
+
print_err('\n import sys\n sys.setrecursionlimit(1_500)\n')
|
|
150
|
+
return
|
|
151
|
+
|
|
152
|
+
# format an exception with traceback, but only the last frame.
|
|
153
|
+
te = TracebackException.from_exception(exception, limit=-1)
|
|
154
|
+
formatted_tb = te.stack.format()[-1] + ''.join(te.format_exception_only()).rstrip()
|
|
155
|
+
|
|
156
|
+
print_red(__('Exception occurred:'))
|
|
157
|
+
print_err(formatted_tb)
|
|
158
|
+
traceback_info_path = save_traceback(app, exception)
|
|
159
|
+
print_err(__('The full traceback has been saved in:'))
|
|
160
|
+
print_err(traceback_info_path)
|
|
161
|
+
print_err()
|
|
162
|
+
print_err(__('To report this error to the developers, please open an issue '
|
|
163
|
+
'at <https://github.com/sphinx-doc/sphinx/issues/>. Thanks!'))
|
|
164
|
+
print_err(__('Please also report this if it was a user error, so '
|
|
165
|
+
'that a better error message can be provided next time.'))
|