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/util/typing.py
CHANGED
|
@@ -8,23 +8,45 @@ import typing
|
|
|
8
8
|
from collections.abc import Sequence
|
|
9
9
|
from contextvars import Context, ContextVar, Token
|
|
10
10
|
from struct import Struct
|
|
11
|
-
from typing import
|
|
11
|
+
from typing import (
|
|
12
|
+
TYPE_CHECKING,
|
|
13
|
+
Annotated,
|
|
14
|
+
Any,
|
|
15
|
+
Callable,
|
|
16
|
+
ForwardRef,
|
|
17
|
+
TypedDict,
|
|
18
|
+
TypeVar,
|
|
19
|
+
Union,
|
|
20
|
+
)
|
|
12
21
|
|
|
13
22
|
from docutils import nodes
|
|
14
23
|
from docutils.parsers.rst.states import Inliner
|
|
15
24
|
|
|
16
25
|
if TYPE_CHECKING:
|
|
17
|
-
import
|
|
26
|
+
from collections.abc import Mapping
|
|
27
|
+
from typing import Final, Literal, Protocol
|
|
28
|
+
|
|
29
|
+
from typing_extensions import TypeAlias, TypeIs
|
|
18
30
|
|
|
19
31
|
from sphinx.application import Sphinx
|
|
20
32
|
|
|
33
|
+
_RestifyMode: TypeAlias = Literal[
|
|
34
|
+
'fully-qualified-except-typing',
|
|
35
|
+
'smart',
|
|
36
|
+
]
|
|
37
|
+
_StringifyMode: TypeAlias = Literal[
|
|
38
|
+
'fully-qualified-except-typing',
|
|
39
|
+
'fully-qualified',
|
|
40
|
+
'smart',
|
|
41
|
+
]
|
|
42
|
+
|
|
21
43
|
if sys.version_info >= (3, 10):
|
|
22
44
|
from types import UnionType
|
|
23
45
|
else:
|
|
24
46
|
UnionType = None
|
|
25
47
|
|
|
26
48
|
# classes that have an incorrect .__module__ attribute
|
|
27
|
-
_INVALID_BUILTIN_CLASSES = {
|
|
49
|
+
_INVALID_BUILTIN_CLASSES: Final[Mapping[object, str]] = {
|
|
28
50
|
Context: 'contextvars.Context', # Context.__module__ == '_contextvars'
|
|
29
51
|
ContextVar: 'contextvars.ContextVar', # ContextVar.__module__ == '_contextvars'
|
|
30
52
|
Token: 'contextvars.Token', # Token.__module__ == '_contextvars'
|
|
@@ -71,8 +93,25 @@ NoneType = type(None)
|
|
|
71
93
|
PathMatcher = Callable[[str], bool]
|
|
72
94
|
|
|
73
95
|
# common role functions
|
|
74
|
-
|
|
75
|
-
|
|
96
|
+
if TYPE_CHECKING:
|
|
97
|
+
class RoleFunction(Protocol):
|
|
98
|
+
def __call__(
|
|
99
|
+
self,
|
|
100
|
+
name: str,
|
|
101
|
+
rawtext: str,
|
|
102
|
+
text: str,
|
|
103
|
+
lineno: int,
|
|
104
|
+
inliner: Inliner,
|
|
105
|
+
/,
|
|
106
|
+
options: dict[str, Any] | None = None,
|
|
107
|
+
content: Sequence[str] = (),
|
|
108
|
+
) -> tuple[list[nodes.Node], list[nodes.system_message]]:
|
|
109
|
+
...
|
|
110
|
+
else:
|
|
111
|
+
RoleFunction = Callable[
|
|
112
|
+
[str, str, str, int, Inliner, dict[str, Any], Sequence[str]],
|
|
113
|
+
tuple[list[nodes.Node], list[nodes.system_message]],
|
|
114
|
+
]
|
|
76
115
|
|
|
77
116
|
# A option spec for directive
|
|
78
117
|
OptionSpec = dict[str, Callable[[str], Any]]
|
|
@@ -115,7 +154,9 @@ if TYPE_CHECKING:
|
|
|
115
154
|
|
|
116
155
|
|
|
117
156
|
def get_type_hints(
|
|
118
|
-
obj: Any,
|
|
157
|
+
obj: Any,
|
|
158
|
+
globalns: dict[str, Any] | None = None,
|
|
159
|
+
localns: dict[str, Any] | None = None,
|
|
119
160
|
) -> dict[str, Any]:
|
|
120
161
|
"""Return a dictionary containing type hints for a function, method, module or class
|
|
121
162
|
object.
|
|
@@ -147,8 +188,36 @@ def is_system_TypeVar(typ: Any) -> bool:
|
|
|
147
188
|
return modname == 'typing' and isinstance(typ, TypeVar)
|
|
148
189
|
|
|
149
190
|
|
|
150
|
-
def
|
|
151
|
-
"""
|
|
191
|
+
def _is_annotated_form(obj: Any) -> TypeIs[Annotated[Any, ...]]:
|
|
192
|
+
"""Check if *obj* is an annotated type."""
|
|
193
|
+
return typing.get_origin(obj) is Annotated or str(obj).startswith('typing.Annotated')
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def _is_unpack_form(obj: Any) -> bool:
|
|
197
|
+
"""Check if the object is :class:`typing.Unpack` or equivalent."""
|
|
198
|
+
if sys.version_info >= (3, 11):
|
|
199
|
+
from typing import Unpack
|
|
200
|
+
|
|
201
|
+
# typing_extensions.Unpack != typing.Unpack for 3.11, but we assume
|
|
202
|
+
# that typing_extensions.Unpack should not be used in that case
|
|
203
|
+
return typing.get_origin(obj) is Unpack
|
|
204
|
+
|
|
205
|
+
# 3.9 and 3.10 require typing_extensions.Unpack
|
|
206
|
+
origin = typing.get_origin(obj)
|
|
207
|
+
return (
|
|
208
|
+
getattr(origin, '__module__', None) == 'typing_extensions'
|
|
209
|
+
and _typing_internal_name(origin) == 'Unpack'
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _typing_internal_name(obj: Any) -> str | None:
|
|
214
|
+
if sys.version_info[:2] >= (3, 10):
|
|
215
|
+
return obj.__name__
|
|
216
|
+
return getattr(obj, '_name', None)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def restify(cls: Any, mode: _RestifyMode = 'fully-qualified-except-typing') -> str:
|
|
220
|
+
"""Convert a type-like object to a reST reference.
|
|
152
221
|
|
|
153
222
|
:param mode: Specify a method how annotations will be stringified.
|
|
154
223
|
|
|
@@ -161,31 +230,53 @@ def restify(cls: type | None, mode: str = 'fully-qualified-except-typing') -> st
|
|
|
161
230
|
from sphinx.ext.autodoc.mock import ismock, ismockmodule # lazy loading
|
|
162
231
|
from sphinx.util import inspect # lazy loading
|
|
163
232
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
233
|
+
valid_modes = {'fully-qualified-except-typing', 'smart'}
|
|
234
|
+
if mode not in valid_modes:
|
|
235
|
+
valid = ', '.join(map(repr, sorted(valid_modes)))
|
|
236
|
+
msg = f'mode must be one of {valid}; got {mode!r}'
|
|
237
|
+
raise ValueError(msg)
|
|
238
|
+
|
|
239
|
+
# things that are not types
|
|
240
|
+
if cls in {None, NoneType}:
|
|
241
|
+
return ':py:obj:`None`'
|
|
242
|
+
if cls is Ellipsis:
|
|
243
|
+
return '...'
|
|
244
|
+
if isinstance(cls, str):
|
|
245
|
+
return cls
|
|
246
|
+
|
|
247
|
+
cls_module_is_typing = getattr(cls, '__module__', '') == 'typing'
|
|
248
|
+
|
|
249
|
+
# If the mode is 'smart', we always use '~'.
|
|
250
|
+
# If the mode is 'fully-qualified-except-typing',
|
|
251
|
+
# we use '~' only for the objects in the ``typing`` module.
|
|
252
|
+
module_prefix = '~' if mode == 'smart' or cls_module_is_typing else ''
|
|
168
253
|
|
|
169
254
|
try:
|
|
170
|
-
if cls
|
|
171
|
-
return ':py:
|
|
172
|
-
elif cls is Ellipsis:
|
|
173
|
-
return '...'
|
|
174
|
-
elif isinstance(cls, str):
|
|
175
|
-
return cls
|
|
176
|
-
elif ismockmodule(cls):
|
|
177
|
-
return f':py:class:`{modprefix}{cls.__name__}`'
|
|
255
|
+
if ismockmodule(cls):
|
|
256
|
+
return f':py:class:`{module_prefix}{cls.__name__}`'
|
|
178
257
|
elif ismock(cls):
|
|
179
|
-
return f':py:class:`{
|
|
258
|
+
return f':py:class:`{module_prefix}{cls.__module__}.{cls.__name__}`'
|
|
180
259
|
elif is_invalid_builtin_class(cls):
|
|
181
|
-
|
|
260
|
+
# The above predicate never raises TypeError but should not be
|
|
261
|
+
# evaluated before determining whether *cls* is a mocked object
|
|
262
|
+
# or not; instead of two try-except blocks, we keep it here.
|
|
263
|
+
return f':py:class:`{module_prefix}{_INVALID_BUILTIN_CLASSES[cls]}`'
|
|
264
|
+
elif _is_annotated_form(cls):
|
|
265
|
+
args = restify(cls.__args__[0], mode)
|
|
266
|
+
meta = ', '.join(map(repr, cls.__metadata__))
|
|
267
|
+
if sys.version_info[:2] <= (3, 11):
|
|
268
|
+
# Hardcoded to fix errors on Python 3.11 and earlier.
|
|
269
|
+
return fr':py:class:`~typing.Annotated`\ [{args}, {meta}]'
|
|
270
|
+
return (f':py:class:`{module_prefix}{cls.__module__}.{cls.__name__}`'
|
|
271
|
+
fr'\ [{args}, {meta}]')
|
|
182
272
|
elif inspect.isNewType(cls):
|
|
183
273
|
if sys.version_info[:2] >= (3, 10):
|
|
184
274
|
# newtypes have correct module info since Python 3.10+
|
|
185
|
-
return f':py:class:`{
|
|
186
|
-
|
|
187
|
-
return f':py:class:`{cls.__name__}`'
|
|
275
|
+
return f':py:class:`{module_prefix}{cls.__module__}.{cls.__name__}`'
|
|
276
|
+
return f':py:class:`{cls.__name__}`'
|
|
188
277
|
elif UnionType and isinstance(cls, UnionType):
|
|
278
|
+
# Union types (PEP 585) retain their definition order when they
|
|
279
|
+
# are printed natively and ``None``-like types are kept as is.
|
|
189
280
|
return ' | '.join(restify(a, mode) for a in cls.__args__)
|
|
190
281
|
elif cls.__module__ in ('__builtin__', 'builtins'):
|
|
191
282
|
if hasattr(cls, '__args__'):
|
|
@@ -194,73 +285,85 @@ def restify(cls: type | None, mode: str = 'fully-qualified-except-typing') -> st
|
|
|
194
285
|
|
|
195
286
|
concatenated_args = ', '.join(restify(arg, mode) for arg in cls.__args__)
|
|
196
287
|
return fr':py:class:`{cls.__name__}`\ [{concatenated_args}]'
|
|
197
|
-
|
|
198
|
-
return f':py:class:`{cls.__name__}`'
|
|
288
|
+
return f':py:class:`{cls.__name__}`'
|
|
199
289
|
elif (inspect.isgenericalias(cls)
|
|
200
|
-
and
|
|
201
|
-
and cls.__origin__ is Union):
|
|
202
|
-
|
|
290
|
+
and cls_module_is_typing
|
|
291
|
+
and cls.__origin__ is Union):
|
|
292
|
+
# *cls* is defined in ``typing``, and thus ``__args__`` must exist
|
|
293
|
+
return ' | '.join(restify(a, mode) for a in cls.__args__)
|
|
203
294
|
elif inspect.isgenericalias(cls):
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
295
|
+
# A generic alias always has an __origin__, but it is difficult to
|
|
296
|
+
# use a type guard on inspect.isgenericalias()
|
|
297
|
+
# (ideally, we would use ``TypeIs`` introduced in Python 3.13).
|
|
298
|
+
cls_name = _typing_internal_name(cls)
|
|
299
|
+
|
|
300
|
+
if isinstance(cls.__origin__, typing._SpecialForm):
|
|
301
|
+
# ClassVar; Concatenate; Final; Literal; Unpack; TypeGuard; TypeIs
|
|
302
|
+
# Required/NotRequired
|
|
303
|
+
text = restify(cls.__origin__, mode)
|
|
304
|
+
elif cls_name:
|
|
305
|
+
text = f':py:class:`{module_prefix}{cls.__module__}.{cls_name}`'
|
|
212
306
|
else:
|
|
213
|
-
text = restify(cls.__origin__, mode)
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
if not
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
#
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
for a in
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
307
|
+
text = restify(cls.__origin__, mode)
|
|
308
|
+
|
|
309
|
+
__args__ = getattr(cls, '__args__', ())
|
|
310
|
+
if not __args__:
|
|
311
|
+
return text
|
|
312
|
+
if all(map(is_system_TypeVar, __args__)):
|
|
313
|
+
# Don't print the arguments; they're all system defined type variables.
|
|
314
|
+
return text
|
|
315
|
+
|
|
316
|
+
# Callable has special formatting
|
|
317
|
+
if (
|
|
318
|
+
(cls_module_is_typing and _typing_internal_name(cls) == 'Callable')
|
|
319
|
+
or (cls.__module__ == 'collections.abc' and cls.__name__ == 'Callable')
|
|
320
|
+
):
|
|
321
|
+
args = ', '.join(restify(a, mode) for a in __args__[:-1])
|
|
322
|
+
returns = restify(__args__[-1], mode)
|
|
323
|
+
return fr'{text}\ [[{args}], {returns}]'
|
|
324
|
+
|
|
325
|
+
if cls_module_is_typing and _typing_internal_name(cls.__origin__) == 'Literal':
|
|
326
|
+
args = ', '.join(_format_literal_arg_restify(a, mode=mode)
|
|
327
|
+
for a in cls.__args__)
|
|
328
|
+
return fr'{text}\ [{args}]'
|
|
329
|
+
|
|
330
|
+
# generic representation of the parameters
|
|
331
|
+
args = ', '.join(restify(a, mode) for a in __args__)
|
|
332
|
+
return fr'{text}\ [{args}]'
|
|
238
333
|
elif isinstance(cls, typing._SpecialForm):
|
|
239
|
-
|
|
334
|
+
cls_name = _typing_internal_name(cls)
|
|
335
|
+
return f':py:obj:`~{cls.__module__}.{cls_name}`'
|
|
240
336
|
elif sys.version_info[:2] >= (3, 11) and cls is typing.Any:
|
|
241
337
|
# handle bpo-46998
|
|
242
338
|
return f':py:obj:`~{cls.__module__}.{cls.__name__}`'
|
|
243
339
|
elif hasattr(cls, '__qualname__'):
|
|
244
|
-
|
|
245
|
-
return f':py:class:`~{cls.__module__}.{cls.__qualname__}`'
|
|
246
|
-
else:
|
|
247
|
-
return f':py:class:`{modprefix}{cls.__module__}.{cls.__qualname__}`'
|
|
340
|
+
return f':py:class:`{module_prefix}{cls.__module__}.{cls.__qualname__}`'
|
|
248
341
|
elif isinstance(cls, ForwardRef):
|
|
249
342
|
return f':py:class:`{cls.__forward_arg__}`'
|
|
250
343
|
else:
|
|
251
|
-
# not a class (ex. TypeVar)
|
|
252
|
-
|
|
253
|
-
return f':py:obj:`~{cls.__module__}.{cls.__name__}`'
|
|
254
|
-
else:
|
|
255
|
-
return f':py:obj:`{modprefix}{cls.__module__}.{cls.__name__}`'
|
|
344
|
+
# not a class (ex. TypeVar) but should have a __name__
|
|
345
|
+
return f':py:obj:`{module_prefix}{cls.__module__}.{cls.__name__}`'
|
|
256
346
|
except (AttributeError, TypeError):
|
|
257
347
|
return inspect.object_description(cls)
|
|
258
348
|
|
|
259
349
|
|
|
350
|
+
def _format_literal_arg_restify(arg: Any, /, *, mode: str) -> str:
|
|
351
|
+
from sphinx.util.inspect import isenumattribute # lazy loading
|
|
352
|
+
|
|
353
|
+
if isenumattribute(arg):
|
|
354
|
+
enum_cls = arg.__class__
|
|
355
|
+
if mode == 'smart' or enum_cls.__module__ == 'typing':
|
|
356
|
+
# MyEnum.member
|
|
357
|
+
return f':py:attr:`~{enum_cls.__module__}.{enum_cls.__qualname__}.{arg.name}`'
|
|
358
|
+
# module.MyEnum.member
|
|
359
|
+
return f':py:attr:`{enum_cls.__module__}.{enum_cls.__qualname__}.{arg.name}`'
|
|
360
|
+
return repr(arg)
|
|
361
|
+
|
|
362
|
+
|
|
260
363
|
def stringify_annotation(
|
|
261
364
|
annotation: Any,
|
|
262
365
|
/,
|
|
263
|
-
mode:
|
|
366
|
+
mode: _StringifyMode = 'fully-qualified-except-typing',
|
|
264
367
|
) -> str:
|
|
265
368
|
"""Stringify type annotation object.
|
|
266
369
|
|
|
@@ -278,69 +381,76 @@ def stringify_annotation(
|
|
|
278
381
|
from sphinx.ext.autodoc.mock import ismock, ismockmodule # lazy loading
|
|
279
382
|
from sphinx.util.inspect import isNewType # lazy loading
|
|
280
383
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
384
|
+
valid_modes = {'fully-qualified-except-typing', 'fully-qualified', 'smart'}
|
|
385
|
+
if mode not in valid_modes:
|
|
386
|
+
valid = ', '.join(map(repr, sorted(valid_modes)))
|
|
387
|
+
msg = f'mode must be one of {valid}; got {mode!r}'
|
|
284
388
|
raise ValueError(msg)
|
|
285
389
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
annotation_qualname = getattr(annotation, '__qualname__', '')
|
|
292
|
-
annotation_module = getattr(annotation, '__module__', '')
|
|
293
|
-
annotation_name = getattr(annotation, '__name__', '')
|
|
294
|
-
annotation_module_is_typing = annotation_module == 'typing'
|
|
295
|
-
|
|
390
|
+
# things that are not types
|
|
391
|
+
if annotation in {None, NoneType}:
|
|
392
|
+
return 'None'
|
|
393
|
+
if annotation is Ellipsis:
|
|
394
|
+
return '...'
|
|
296
395
|
if isinstance(annotation, str):
|
|
297
396
|
if annotation.startswith("'") and annotation.endswith("'"):
|
|
298
|
-
#
|
|
397
|
+
# Might be a double Forward-ref'ed type. Go unquoting.
|
|
299
398
|
return annotation[1:-1]
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
399
|
+
return annotation
|
|
400
|
+
if not annotation:
|
|
401
|
+
return repr(annotation)
|
|
402
|
+
|
|
403
|
+
module_prefix = '~' if mode == 'smart' else ''
|
|
404
|
+
|
|
405
|
+
# The values below must be strings if the objects are well-formed.
|
|
406
|
+
annotation_qualname: str = getattr(annotation, '__qualname__', '')
|
|
407
|
+
annotation_module: str = getattr(annotation, '__module__', '')
|
|
408
|
+
annotation_name: str = getattr(annotation, '__name__', '')
|
|
409
|
+
annotation_module_is_typing = annotation_module == 'typing'
|
|
410
|
+
|
|
411
|
+
# Extract the annotation's base type by considering formattable cases
|
|
412
|
+
if isinstance(annotation, TypeVar) and not _is_unpack_form(annotation):
|
|
413
|
+
# typing_extensions.Unpack is incorrectly determined as a TypeVar
|
|
303
414
|
if annotation_module_is_typing and mode in {'fully-qualified-except-typing', 'smart'}:
|
|
304
415
|
return annotation_name
|
|
305
|
-
|
|
306
|
-
return module_prefix + f'{annotation_module}.{annotation_name}'
|
|
416
|
+
return module_prefix + f'{annotation_module}.{annotation_name}'
|
|
307
417
|
elif isNewType(annotation):
|
|
308
418
|
if sys.version_info[:2] >= (3, 10):
|
|
309
419
|
# newtypes have correct module info since Python 3.10+
|
|
310
420
|
return module_prefix + f'{annotation_module}.{annotation_name}'
|
|
311
|
-
|
|
312
|
-
return annotation_name
|
|
313
|
-
elif not annotation:
|
|
314
|
-
return repr(annotation)
|
|
315
|
-
elif annotation is NoneType:
|
|
316
|
-
return 'None'
|
|
421
|
+
return annotation_name
|
|
317
422
|
elif ismockmodule(annotation):
|
|
318
423
|
return module_prefix + annotation_name
|
|
319
424
|
elif ismock(annotation):
|
|
320
425
|
return module_prefix + f'{annotation_module}.{annotation_name}'
|
|
321
426
|
elif is_invalid_builtin_class(annotation):
|
|
322
427
|
return module_prefix + _INVALID_BUILTIN_CLASSES[annotation]
|
|
323
|
-
elif
|
|
428
|
+
elif _is_annotated_form(annotation): # for py39+
|
|
324
429
|
pass
|
|
325
430
|
elif annotation_module == 'builtins' and annotation_qualname:
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
return repr(annotation)
|
|
329
|
-
|
|
330
|
-
concatenated_args = ', '.join(stringify_annotation(arg, mode) for arg in args)
|
|
331
|
-
return f'{annotation_qualname}[{concatenated_args}]'
|
|
332
|
-
else:
|
|
431
|
+
args = getattr(annotation, '__args__', None)
|
|
432
|
+
if args is None:
|
|
333
433
|
return annotation_qualname
|
|
334
|
-
|
|
335
|
-
|
|
434
|
+
|
|
435
|
+
# PEP 585 generic
|
|
436
|
+
if not args: # Empty tuple, list, ...
|
|
437
|
+
return repr(annotation)
|
|
438
|
+
|
|
439
|
+
concatenated_args = ', '.join(stringify_annotation(arg, mode) for arg in args)
|
|
440
|
+
return f'{annotation_qualname}[{concatenated_args}]'
|
|
441
|
+
else:
|
|
442
|
+
# add other special cases that can be directly formatted
|
|
443
|
+
pass
|
|
336
444
|
|
|
337
445
|
module_prefix = f'{annotation_module}.'
|
|
338
|
-
annotation_forward_arg = getattr(annotation, '__forward_arg__', None)
|
|
446
|
+
annotation_forward_arg: str | None = getattr(annotation, '__forward_arg__', None)
|
|
339
447
|
if annotation_qualname or (annotation_module_is_typing and not annotation_forward_arg):
|
|
340
448
|
if mode == 'smart':
|
|
341
|
-
module_prefix = '~'
|
|
449
|
+
module_prefix = f'~{module_prefix}'
|
|
342
450
|
if annotation_module_is_typing and mode == 'fully-qualified-except-typing':
|
|
343
451
|
module_prefix = ''
|
|
452
|
+
elif _is_unpack_form(annotation) and annotation_module == 'typing_extensions':
|
|
453
|
+
module_prefix = '~' if mode == 'smart' else ''
|
|
344
454
|
else:
|
|
345
455
|
module_prefix = ''
|
|
346
456
|
|
|
@@ -349,12 +459,13 @@ def stringify_annotation(
|
|
|
349
459
|
# handle ForwardRefs
|
|
350
460
|
qualname = annotation_forward_arg
|
|
351
461
|
else:
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
qualname = _name
|
|
462
|
+
if internal_name := _typing_internal_name(annotation):
|
|
463
|
+
qualname = internal_name
|
|
355
464
|
elif annotation_qualname:
|
|
356
465
|
qualname = annotation_qualname
|
|
357
466
|
else:
|
|
467
|
+
# in this case, we know that the annotation is a member
|
|
468
|
+
# of ``typing`` and all of them define ``__origin__``
|
|
358
469
|
qualname = stringify_annotation(
|
|
359
470
|
annotation.__origin__, 'fully-qualified-except-typing',
|
|
360
471
|
).replace('typing.', '') # ex. Union
|
|
@@ -370,36 +481,38 @@ def stringify_annotation(
|
|
|
370
481
|
# only make them appear twice
|
|
371
482
|
return repr(annotation)
|
|
372
483
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
484
|
+
# Process the generic arguments (if any).
|
|
485
|
+
# They must be a list or a tuple, otherwise they are considered 'broken'.
|
|
486
|
+
annotation_args = getattr(annotation, '__args__', ())
|
|
487
|
+
if annotation_args and isinstance(annotation_args, (list, tuple)):
|
|
488
|
+
if (
|
|
489
|
+
qualname in {'Union', 'types.UnionType'}
|
|
490
|
+
and all(getattr(a, '__origin__', ...) is typing.Literal for a in annotation_args)
|
|
491
|
+
):
|
|
492
|
+
# special case to flatten a Union of Literals into a literal
|
|
493
|
+
flattened_args = typing.Literal[annotation_args].__args__ # type: ignore[attr-defined]
|
|
494
|
+
args = ', '.join(_format_literal_arg_stringify(a, mode=mode)
|
|
495
|
+
for a in flattened_args)
|
|
496
|
+
return f'{module_prefix}Literal[{args}]'
|
|
497
|
+
if qualname in {'Optional', 'Union', 'types.UnionType'}:
|
|
379
498
|
return ' | '.join(stringify_annotation(a, mode) for a in annotation_args)
|
|
380
499
|
elif qualname == 'Callable':
|
|
381
500
|
args = ', '.join(stringify_annotation(a, mode) for a in annotation_args[:-1])
|
|
382
501
|
returns = stringify_annotation(annotation_args[-1], mode)
|
|
383
502
|
return f'{module_prefix}Callable[[{args}], {returns}]'
|
|
384
503
|
elif qualname == 'Literal':
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
def format_literal_arg(arg: Any) -> str:
|
|
388
|
-
if isenumattribute(arg):
|
|
389
|
-
enumcls = arg.__class__
|
|
390
|
-
|
|
391
|
-
if mode == 'smart':
|
|
392
|
-
# MyEnum.member
|
|
393
|
-
return f'{enumcls.__qualname__}.{arg.name}'
|
|
394
|
-
|
|
395
|
-
# module.MyEnum.member
|
|
396
|
-
return f'{enumcls.__module__}.{enumcls.__qualname__}.{arg.name}'
|
|
397
|
-
return repr(arg)
|
|
398
|
-
|
|
399
|
-
args = ', '.join(map(format_literal_arg, annotation_args))
|
|
504
|
+
args = ', '.join(_format_literal_arg_stringify(a, mode=mode)
|
|
505
|
+
for a in annotation_args)
|
|
400
506
|
return f'{module_prefix}Literal[{args}]'
|
|
401
|
-
elif
|
|
402
|
-
|
|
507
|
+
elif _is_annotated_form(annotation): # for py39+
|
|
508
|
+
args = stringify_annotation(annotation_args[0], mode)
|
|
509
|
+
meta = ', '.join(map(repr, annotation.__metadata__))
|
|
510
|
+
if sys.version_info[:2] <= (3, 11):
|
|
511
|
+
if mode == 'fully-qualified-except-typing':
|
|
512
|
+
return f'Annotated[{args}, {meta}]'
|
|
513
|
+
module_prefix = module_prefix.replace('builtins', 'typing')
|
|
514
|
+
return f'{module_prefix}Annotated[{args}, {meta}]'
|
|
515
|
+
return f'{module_prefix}Annotated[{args}, {meta}]'
|
|
403
516
|
elif all(is_system_TypeVar(a) for a in annotation_args):
|
|
404
517
|
# Suppress arguments if all system defined TypeVars (ex. Dict[KT, VT])
|
|
405
518
|
return module_prefix + qualname
|
|
@@ -410,12 +523,17 @@ def stringify_annotation(
|
|
|
410
523
|
return module_prefix + qualname
|
|
411
524
|
|
|
412
525
|
|
|
413
|
-
def
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
526
|
+
def _format_literal_arg_stringify(arg: Any, /, *, mode: str) -> str:
|
|
527
|
+
from sphinx.util.inspect import isenumattribute # lazy loading
|
|
528
|
+
|
|
529
|
+
if isenumattribute(arg):
|
|
530
|
+
enum_cls = arg.__class__
|
|
531
|
+
if mode == 'smart' or enum_cls.__module__ == 'typing':
|
|
532
|
+
# MyEnum.member
|
|
533
|
+
return f'{enum_cls.__qualname__}.{arg.name}'
|
|
534
|
+
# module.MyEnum.member
|
|
535
|
+
return f'{enum_cls.__module__}.{enum_cls.__qualname__}.{arg.name}'
|
|
536
|
+
return repr(arg)
|
|
419
537
|
|
|
420
538
|
|
|
421
539
|
# deprecated name -> (object to return, canonical path or empty string, removal version)
|
sphinx/versioning.py
CHANGED
|
@@ -12,7 +12,7 @@ from uuid import uuid4
|
|
|
12
12
|
from sphinx.transforms import SphinxTransform
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
|
-
from collections.abc import Iterator
|
|
15
|
+
from collections.abc import Callable, Iterator
|
|
16
16
|
|
|
17
17
|
from docutils.nodes import Node
|
|
18
18
|
|
|
@@ -30,7 +30,7 @@ except ImportError:
|
|
|
30
30
|
VERSIONING_RATIO = 65
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def add_uids(doctree: Node, condition:
|
|
33
|
+
def add_uids(doctree: Node, condition: Callable[[Node], bool]) -> Iterator[Node]:
|
|
34
34
|
"""Add a unique id to every node in the `doctree` which matches the
|
|
35
35
|
condition and yield the nodes.
|
|
36
36
|
|
|
@@ -41,11 +41,11 @@ def add_uids(doctree: Node, condition: Any) -> Iterator[Node]:
|
|
|
41
41
|
A callable which returns either ``True`` or ``False`` for a given node.
|
|
42
42
|
"""
|
|
43
43
|
for node in doctree.findall(condition):
|
|
44
|
-
node.uid = uuid4().hex
|
|
44
|
+
node.uid = uuid4().hex # type: ignore[attr-defined]
|
|
45
45
|
yield node
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
def merge_doctrees(old: Node, new: Node, condition:
|
|
48
|
+
def merge_doctrees(old: Node, new: Node, condition: Callable[[Node], bool]) -> Iterator[Node]:
|
|
49
49
|
"""Merge the `old` doctree with the `new` one while looking at nodes
|
|
50
50
|
matching the `condition`.
|
|
51
51
|
|
|
@@ -68,13 +68,13 @@ def merge_doctrees(old: Node, new: Node, condition: Any) -> Iterator[Node]:
|
|
|
68
68
|
continue
|
|
69
69
|
if not getattr(old_node, 'uid', None):
|
|
70
70
|
# maybe config.gettext_uuid has been changed.
|
|
71
|
-
old_node.uid = uuid4().hex
|
|
71
|
+
old_node.uid = uuid4().hex # type: ignore[union-attr]
|
|
72
72
|
if new_node is None:
|
|
73
73
|
old_nodes.append(old_node)
|
|
74
74
|
continue
|
|
75
|
-
ratio = get_ratio(old_node.rawsource, new_node.rawsource)
|
|
75
|
+
ratio = get_ratio(old_node.rawsource, new_node.rawsource) # type: ignore[union-attr]
|
|
76
76
|
if ratio == 0:
|
|
77
|
-
new_node.uid = old_node.uid
|
|
77
|
+
new_node.uid = old_node.uid # type: ignore[union-attr]
|
|
78
78
|
seen.add(new_node)
|
|
79
79
|
else:
|
|
80
80
|
ratios[old_node, new_node] = ratio
|
|
@@ -85,30 +85,29 @@ def merge_doctrees(old: Node, new: Node, condition: Any) -> Iterator[Node]:
|
|
|
85
85
|
for old_node, new_node in product(old_nodes, new_nodes):
|
|
86
86
|
if new_node in seen or (old_node, new_node) in ratios:
|
|
87
87
|
continue
|
|
88
|
-
ratio = get_ratio(old_node.rawsource, new_node.rawsource)
|
|
88
|
+
ratio = get_ratio(old_node.rawsource, new_node.rawsource) # type: ignore[union-attr]
|
|
89
89
|
if ratio == 0:
|
|
90
|
-
new_node.uid = old_node.uid
|
|
90
|
+
new_node.uid = old_node.uid # type: ignore[union-attr]
|
|
91
91
|
seen.add(new_node)
|
|
92
92
|
else:
|
|
93
93
|
ratios[old_node, new_node] = ratio
|
|
94
94
|
# choose the old node with the best ratio for each new node and set the uid
|
|
95
95
|
# as long as the ratio is under a certain value, in which case we consider
|
|
96
96
|
# them not changed but different
|
|
97
|
-
|
|
98
|
-
for (old_node, new_node), ratio in ratios:
|
|
97
|
+
for (old_node, new_node), ratio in sorted(ratios.items(), key=itemgetter(1)):
|
|
99
98
|
if new_node in seen:
|
|
100
99
|
continue
|
|
101
100
|
else:
|
|
102
101
|
seen.add(new_node)
|
|
103
102
|
if ratio < VERSIONING_RATIO:
|
|
104
|
-
new_node.uid = old_node.uid
|
|
103
|
+
new_node.uid = old_node.uid # type: ignore[union-attr]
|
|
105
104
|
else:
|
|
106
|
-
new_node.uid = uuid4().hex
|
|
105
|
+
new_node.uid = uuid4().hex # type: ignore[union-attr]
|
|
107
106
|
yield new_node
|
|
108
107
|
# create new uuids for any new node we left out earlier, this happens
|
|
109
108
|
# if one or more nodes are simply added.
|
|
110
109
|
for new_node in set(new_nodes) - seen:
|
|
111
|
-
new_node.uid = uuid4().hex
|
|
110
|
+
new_node.uid = uuid4().hex # type: ignore[union-attr]
|
|
112
111
|
yield new_node
|
|
113
112
|
|
|
114
113
|
|
|
@@ -153,7 +152,8 @@ class UIDTransform(SphinxTransform):
|
|
|
153
152
|
def apply(self, **kwargs: Any) -> None:
|
|
154
153
|
env = self.env
|
|
155
154
|
old_doctree = None
|
|
156
|
-
|
|
155
|
+
versioning_condition = env.versioning_condition
|
|
156
|
+
if not versioning_condition:
|
|
157
157
|
return
|
|
158
158
|
|
|
159
159
|
if env.versioning_compare:
|
|
@@ -167,9 +167,9 @@ class UIDTransform(SphinxTransform):
|
|
|
167
167
|
|
|
168
168
|
# add uids for versioning
|
|
169
169
|
if not env.versioning_compare or old_doctree is None:
|
|
170
|
-
list(add_uids(self.document,
|
|
170
|
+
list(add_uids(self.document, versioning_condition))
|
|
171
171
|
else:
|
|
172
|
-
list(merge_doctrees(old_doctree, self.document,
|
|
172
|
+
list(merge_doctrees(old_doctree, self.document, versioning_condition))
|
|
173
173
|
|
|
174
174
|
|
|
175
175
|
def setup(app: Sphinx) -> ExtensionMetadata:
|