Sphinx 7.2.6__py3-none-any.whl → 7.3.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 +8 -9
- sphinx/addnodes.py +31 -28
- sphinx/application.py +9 -15
- sphinx/builders/__init__.py +5 -6
- sphinx/builders/_epub_base.py +17 -9
- sphinx/builders/changes.py +10 -5
- sphinx/builders/dirhtml.py +4 -2
- sphinx/builders/dummy.py +3 -2
- sphinx/builders/epub3.py +5 -3
- sphinx/builders/gettext.py +24 -7
- sphinx/builders/html/__init__.py +88 -96
- sphinx/builders/html/_assets.py +16 -16
- sphinx/builders/html/transforms.py +4 -2
- sphinx/builders/latex/__init__.py +40 -33
- sphinx/builders/latex/nodes.py +6 -2
- sphinx/builders/latex/transforms.py +17 -8
- sphinx/builders/latex/util.py +1 -1
- sphinx/builders/linkcheck.py +86 -27
- sphinx/builders/manpage.py +8 -6
- sphinx/builders/singlehtml.py +5 -4
- sphinx/builders/texinfo.py +18 -14
- sphinx/builders/text.py +3 -2
- sphinx/builders/xml.py +5 -2
- sphinx/cmd/build.py +119 -76
- sphinx/cmd/make_mode.py +4 -9
- sphinx/cmd/quickstart.py +13 -16
- sphinx/config.py +432 -250
- sphinx/deprecation.py +23 -13
- sphinx/directives/__init__.py +8 -8
- sphinx/directives/code.py +7 -7
- sphinx/directives/other.py +23 -13
- sphinx/directives/patches.py +7 -6
- sphinx/domains/__init__.py +2 -2
- sphinx/domains/c/__init__.py +796 -0
- sphinx/domains/c/_ast.py +1421 -0
- sphinx/domains/c/_ids.py +65 -0
- sphinx/domains/c/_parser.py +1048 -0
- sphinx/domains/c/_symbol.py +700 -0
- sphinx/domains/changeset.py +11 -7
- sphinx/domains/citation.py +5 -2
- sphinx/domains/cpp/__init__.py +1089 -0
- sphinx/domains/cpp/_ast.py +3635 -0
- sphinx/domains/cpp/_ids.py +537 -0
- sphinx/domains/cpp/_parser.py +2117 -0
- sphinx/domains/cpp/_symbol.py +1092 -0
- sphinx/domains/index.py +6 -4
- sphinx/domains/javascript.py +16 -13
- sphinx/domains/math.py +9 -4
- sphinx/domains/python/__init__.py +890 -0
- sphinx/domains/python/_annotations.py +507 -0
- sphinx/domains/python/_object.py +426 -0
- sphinx/domains/rst.py +12 -7
- sphinx/domains/{std.py → std/__init__.py} +19 -16
- sphinx/environment/__init__.py +21 -19
- sphinx/environment/adapters/indexentries.py +2 -2
- sphinx/environment/adapters/toctree.py +10 -9
- sphinx/environment/collectors/__init__.py +6 -3
- sphinx/environment/collectors/asset.py +4 -3
- sphinx/environment/collectors/dependencies.py +3 -2
- sphinx/environment/collectors/metadata.py +6 -5
- sphinx/environment/collectors/title.py +3 -2
- sphinx/environment/collectors/toctree.py +5 -4
- sphinx/errors.py +13 -2
- sphinx/events.py +14 -9
- sphinx/ext/apidoc.py +9 -11
- sphinx/ext/autodoc/__init__.py +105 -71
- sphinx/ext/autodoc/directive.py +7 -6
- sphinx/ext/autodoc/importer.py +102 -36
- sphinx/ext/autodoc/mock.py +7 -5
- sphinx/ext/autodoc/preserve_defaults.py +4 -3
- sphinx/ext/autodoc/type_comment.py +2 -1
- sphinx/ext/autodoc/typehints.py +5 -4
- sphinx/ext/autosectionlabel.py +3 -2
- sphinx/ext/autosummary/__init__.py +21 -17
- sphinx/ext/autosummary/generate.py +9 -9
- sphinx/ext/coverage.py +26 -20
- sphinx/ext/doctest.py +38 -33
- sphinx/ext/duration.py +1 -0
- sphinx/ext/extlinks.py +4 -3
- sphinx/ext/githubpages.py +3 -2
- sphinx/ext/graphviz.py +10 -7
- sphinx/ext/ifconfig.py +5 -5
- sphinx/ext/imgconverter.py +6 -5
- sphinx/ext/imgmath.py +9 -8
- sphinx/ext/inheritance_diagram.py +31 -31
- sphinx/ext/intersphinx.py +140 -23
- sphinx/ext/linkcode.py +3 -2
- sphinx/ext/mathjax.py +2 -1
- sphinx/ext/napoleon/__init__.py +12 -7
- sphinx/ext/napoleon/docstring.py +34 -32
- sphinx/ext/todo.py +10 -7
- sphinx/ext/viewcode.py +12 -11
- sphinx/extension.py +18 -8
- sphinx/highlighting.py +39 -20
- sphinx/io.py +17 -8
- sphinx/jinja2glue.py +16 -15
- sphinx/locale/__init__.py +30 -23
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +818 -761
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +835 -778
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +864 -807
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +816 -759
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +819 -762
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +838 -781
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +838 -781
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +853 -796
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +856 -799
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +820 -763
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +856 -799
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +845 -788
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +854 -797
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +816 -759
- 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 +904 -847
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/gl/LC_MESSAGES/sphinx.js +54 -54
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +1506 -1449
- 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 +823 -766
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +853 -796
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +844 -787
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +854 -797
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +853 -796
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +848 -791
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +855 -798
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +825 -768
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js +27 -27
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +876 -818
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +844 -787
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +845 -788
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +908 -851
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +838 -781
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +823 -766
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +854 -797
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +832 -775
- sphinx/locale/sphinx.pot +813 -755
- 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 +865 -808
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +835 -778
- 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.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/ta/LC_MESSAGES/sphinx.js +54 -54
- sphinx/locale/ta/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ta/LC_MESSAGES/sphinx.po +1530 -1473
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +853 -796
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +833 -776
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +837 -780
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +811 -754
- sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +855 -798
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +811 -754
- 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 +879 -822
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +811 -754
- sphinx/parsers.py +7 -5
- sphinx/project.py +18 -11
- sphinx/pycode/__init__.py +6 -5
- sphinx/pycode/ast.py +23 -8
- sphinx/pycode/parser.py +6 -5
- sphinx/registry.py +12 -6
- sphinx/roles.py +103 -57
- sphinx/search/__init__.py +17 -18
- sphinx/search/da.py +2 -2
- sphinx/search/de.py +2 -2
- sphinx/search/en.py +1 -1
- sphinx/search/es.py +2 -2
- sphinx/search/fi.py +2 -2
- sphinx/search/fr.py +2 -2
- sphinx/search/hu.py +2 -2
- sphinx/search/it.py +2 -2
- sphinx/search/ja.py +13 -22
- sphinx/search/nl.py +2 -2
- sphinx/search/no.py +2 -2
- sphinx/search/pt.py +2 -2
- sphinx/search/ro.py +1 -1
- sphinx/search/ru.py +2 -2
- sphinx/search/sv.py +2 -2
- sphinx/search/tr.py +1 -1
- sphinx/search/zh.py +2 -3
- sphinx/templates/graphviz/graphviz.css +1 -1
- sphinx/testing/fixtures.py +41 -24
- sphinx/testing/path.py +1 -1
- sphinx/testing/util.py +142 -53
- sphinx/texinputs/sphinx.xdy +1 -1
- sphinx/texinputs/sphinxlatextables.sty +1 -1
- sphinx/texinputs/sphinxpackagesubstitutefont.sty +21 -0
- sphinx/themes/agogo/layout.html +4 -4
- sphinx/themes/agogo/static/agogo.css_t +1 -1
- sphinx/themes/agogo/theme.toml +22 -0
- sphinx/themes/basic/defindex.html +1 -1
- sphinx/themes/basic/domainindex.html +1 -1
- sphinx/themes/basic/genindex-single.html +1 -1
- sphinx/themes/basic/genindex-split.html +1 -1
- sphinx/themes/basic/genindex.html +1 -1
- sphinx/themes/basic/globaltoc.html +1 -1
- sphinx/themes/basic/layout.html +1 -1
- sphinx/themes/basic/localtoc.html +1 -1
- sphinx/themes/basic/page.html +1 -1
- sphinx/themes/basic/relations.html +1 -1
- sphinx/themes/basic/search.html +5 -20
- sphinx/themes/basic/searchbox.html +3 -3
- sphinx/themes/basic/searchfield.html +3 -3
- sphinx/themes/basic/sourcelink.html +1 -1
- sphinx/themes/basic/static/basic.css_t +1 -1
- sphinx/themes/basic/static/doctools.js +1 -1
- sphinx/themes/basic/static/language_data.js_t +2 -2
- sphinx/themes/basic/static/searchtools.js +105 -60
- sphinx/themes/basic/theme.toml +23 -0
- sphinx/themes/bizstyle/layout.html +1 -6
- sphinx/themes/bizstyle/static/bizstyle.css_t +1 -1
- sphinx/themes/bizstyle/static/bizstyle.js_t +1 -1
- sphinx/themes/bizstyle/static/css3-mediaqueries_src.js +3 -3
- sphinx/themes/bizstyle/theme.toml +12 -0
- sphinx/themes/classic/layout.html +1 -1
- sphinx/themes/classic/static/classic.css_t +1 -1
- sphinx/themes/classic/static/sidebar.js_t +1 -1
- sphinx/themes/classic/theme.toml +34 -0
- sphinx/themes/default/theme.toml +2 -0
- sphinx/themes/epub/epub-cover.html +1 -1
- sphinx/themes/epub/layout.html +1 -1
- sphinx/themes/epub/static/epub.css_t +1 -1
- sphinx/themes/epub/theme.toml +10 -0
- sphinx/themes/haiku/layout.html +3 -3
- sphinx/themes/haiku/static/haiku.css_t +2 -2
- sphinx/themes/haiku/theme.toml +16 -0
- sphinx/themes/nature/static/nature.css_t +1 -1
- sphinx/themes/nature/theme.toml +6 -0
- sphinx/themes/nonav/layout.html +1 -1
- sphinx/themes/nonav/static/nonav.css_t +1 -1
- sphinx/themes/nonav/theme.toml +10 -0
- sphinx/themes/pyramid/static/epub.css_t +1 -1
- sphinx/themes/pyramid/static/pyramid.css_t +1 -1
- sphinx/themes/pyramid/theme.toml +6 -0
- sphinx/themes/scrolls/artwork/logo.svg +1 -1
- sphinx/themes/scrolls/layout.html +2 -2
- sphinx/themes/scrolls/static/scrolls.css_t +1 -1
- sphinx/themes/scrolls/theme.toml +15 -0
- sphinx/themes/sphinxdoc/static/sphinxdoc.css_t +1 -1
- sphinx/themes/sphinxdoc/theme.toml +6 -0
- sphinx/themes/traditional/static/traditional.css_t +1 -1
- sphinx/themes/traditional/theme.toml +9 -0
- sphinx/theming.py +427 -131
- sphinx/transforms/__init__.py +21 -24
- sphinx/transforms/compact_bullet_list.py +5 -5
- sphinx/transforms/i18n.py +30 -28
- sphinx/transforms/post_transforms/__init__.py +9 -7
- sphinx/transforms/post_transforms/code.py +4 -1
- sphinx/transforms/post_transforms/images.py +17 -13
- sphinx/transforms/references.py +3 -1
- sphinx/util/__init__.py +15 -11
- sphinx/util/_io.py +34 -0
- sphinx/util/_pathlib.py +23 -18
- sphinx/util/build_phase.py +1 -0
- sphinx/util/cfamily.py +19 -11
- sphinx/util/console.py +101 -21
- sphinx/util/display.py +3 -2
- sphinx/util/docfields.py +12 -8
- sphinx/util/docutils.py +21 -35
- sphinx/util/exceptions.py +3 -2
- sphinx/util/fileutil.py +5 -5
- sphinx/util/http_date.py +9 -2
- sphinx/util/i18n.py +40 -9
- sphinx/util/inspect.py +317 -245
- sphinx/util/inventory.py +22 -5
- sphinx/util/logging.py +81 -7
- sphinx/util/matching.py +2 -1
- sphinx/util/math.py +1 -2
- sphinx/util/nodes.py +39 -29
- sphinx/util/osutil.py +25 -6
- sphinx/util/parallel.py +6 -1
- sphinx/util/requests.py +8 -5
- sphinx/util/rst.py +8 -6
- sphinx/util/tags.py +3 -3
- sphinx/util/template.py +8 -3
- sphinx/util/typing.py +76 -42
- sphinx/versioning.py +6 -2
- sphinx/writers/html.py +1 -1
- sphinx/writers/html5.py +17 -13
- sphinx/writers/latex.py +12 -12
- sphinx/writers/manpage.py +13 -7
- sphinx/writers/texinfo.py +13 -10
- sphinx/writers/text.py +13 -23
- sphinx/writers/xml.py +1 -1
- sphinx-7.2.6.dist-info/LICENSE → sphinx-7.3.0.dist-info/LICENSE.rst +1 -1
- {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/METADATA +13 -12
- sphinx-7.3.0.dist-info/RECORD +581 -0
- sphinx/domains/c.py +0 -3906
- sphinx/domains/cpp.py +0 -8233
- sphinx/domains/python.py +0 -1769
- sphinx/themes/agogo/theme.conf +0 -20
- sphinx/themes/basic/theme.conf +0 -16
- sphinx/themes/bizstyle/theme.conf +0 -10
- sphinx/themes/classic/theme.conf +0 -32
- sphinx/themes/default/theme.conf +0 -2
- sphinx/themes/epub/theme.conf +0 -8
- sphinx/themes/haiku/theme.conf +0 -14
- sphinx/themes/nature/theme.conf +0 -4
- sphinx/themes/nonav/theme.conf +0 -8
- sphinx/themes/pyramid/theme.conf +0 -4
- sphinx/themes/scrolls/theme.conf +0 -13
- sphinx/themes/sphinxdoc/theme.conf +0 -4
- sphinx/themes/traditional/theme.conf +0 -7
- sphinx-7.2.6.dist-info/RECORD +0 -569
- {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/WHEEL +0 -0
- {sphinx-7.2.6.dist-info → sphinx-7.3.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
import functools
|
|
5
|
+
import operator
|
|
6
|
+
import token
|
|
7
|
+
from collections import deque
|
|
8
|
+
from inspect import Parameter
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
10
|
+
|
|
11
|
+
from docutils import nodes
|
|
12
|
+
|
|
13
|
+
from sphinx import addnodes
|
|
14
|
+
from sphinx.addnodes import desc_signature, pending_xref, pending_xref_condition
|
|
15
|
+
from sphinx.pycode.parser import Token, TokenProcessor
|
|
16
|
+
from sphinx.util.inspect import signature_from_str
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from collections.abc import Iterable, Iterator
|
|
20
|
+
|
|
21
|
+
from docutils.nodes import Element, Node
|
|
22
|
+
|
|
23
|
+
from sphinx.environment import BuildEnvironment
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def parse_reftarget(reftarget: str, suppress_prefix: bool = False,
|
|
27
|
+
) -> tuple[str, str, str, bool]:
|
|
28
|
+
"""Parse a type string and return (reftype, reftarget, title, refspecific flag)"""
|
|
29
|
+
refspecific = False
|
|
30
|
+
if reftarget.startswith('.'):
|
|
31
|
+
reftarget = reftarget[1:]
|
|
32
|
+
title = reftarget
|
|
33
|
+
refspecific = True
|
|
34
|
+
elif reftarget.startswith('~'):
|
|
35
|
+
reftarget = reftarget[1:]
|
|
36
|
+
title = reftarget.split('.')[-1]
|
|
37
|
+
elif suppress_prefix:
|
|
38
|
+
title = reftarget.split('.')[-1]
|
|
39
|
+
elif reftarget.startswith('typing.'):
|
|
40
|
+
title = reftarget[7:]
|
|
41
|
+
else:
|
|
42
|
+
title = reftarget
|
|
43
|
+
|
|
44
|
+
if reftarget == 'None' or reftarget.startswith('typing.'):
|
|
45
|
+
# typing module provides non-class types. Obj reference is good to refer them.
|
|
46
|
+
reftype = 'obj'
|
|
47
|
+
else:
|
|
48
|
+
reftype = 'class'
|
|
49
|
+
|
|
50
|
+
return reftype, reftarget, title, refspecific
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def type_to_xref(target: str, env: BuildEnvironment, *,
|
|
54
|
+
suppress_prefix: bool = False) -> addnodes.pending_xref:
|
|
55
|
+
"""Convert a type string to a cross reference node."""
|
|
56
|
+
if env:
|
|
57
|
+
kwargs = {'py:module': env.ref_context.get('py:module'),
|
|
58
|
+
'py:class': env.ref_context.get('py:class')}
|
|
59
|
+
else:
|
|
60
|
+
kwargs = {}
|
|
61
|
+
|
|
62
|
+
reftype, target, title, refspecific = parse_reftarget(target, suppress_prefix)
|
|
63
|
+
|
|
64
|
+
if env.config.python_use_unqualified_type_names:
|
|
65
|
+
# Note: It would be better to use qualname to describe the object to support support
|
|
66
|
+
# nested classes. But python domain can't access the real python object because this
|
|
67
|
+
# module should work not-dynamically.
|
|
68
|
+
shortname = title.split('.')[-1]
|
|
69
|
+
contnodes: list[Node] = [pending_xref_condition('', shortname, condition='resolved'),
|
|
70
|
+
pending_xref_condition('', title, condition='*')]
|
|
71
|
+
else:
|
|
72
|
+
contnodes = [nodes.Text(title)]
|
|
73
|
+
|
|
74
|
+
return pending_xref('', *contnodes,
|
|
75
|
+
refdomain='py', reftype=reftype, reftarget=target,
|
|
76
|
+
refspecific=refspecific, **kwargs)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _parse_annotation(annotation: str, env: BuildEnvironment) -> list[Node]:
|
|
80
|
+
"""Parse type annotation."""
|
|
81
|
+
short_literals = env.config.python_display_short_literal_types
|
|
82
|
+
|
|
83
|
+
def unparse(node: ast.AST) -> list[Node]:
|
|
84
|
+
if isinstance(node, ast.Attribute):
|
|
85
|
+
return [nodes.Text(f"{unparse(node.value)[0]}.{node.attr}")]
|
|
86
|
+
if isinstance(node, ast.BinOp):
|
|
87
|
+
result: list[Node] = unparse(node.left)
|
|
88
|
+
result.extend(unparse(node.op))
|
|
89
|
+
result.extend(unparse(node.right))
|
|
90
|
+
return result
|
|
91
|
+
if isinstance(node, ast.BitOr):
|
|
92
|
+
return [addnodes.desc_sig_space(),
|
|
93
|
+
addnodes.desc_sig_punctuation('', '|'),
|
|
94
|
+
addnodes.desc_sig_space()]
|
|
95
|
+
if isinstance(node, ast.Constant):
|
|
96
|
+
if node.value is Ellipsis:
|
|
97
|
+
return [addnodes.desc_sig_punctuation('', "...")]
|
|
98
|
+
if isinstance(node.value, bool):
|
|
99
|
+
return [addnodes.desc_sig_keyword('', repr(node.value))]
|
|
100
|
+
if isinstance(node.value, int):
|
|
101
|
+
return [addnodes.desc_sig_literal_number('', repr(node.value))]
|
|
102
|
+
if isinstance(node.value, str):
|
|
103
|
+
return [addnodes.desc_sig_literal_string('', repr(node.value))]
|
|
104
|
+
else:
|
|
105
|
+
# handles None, which is further handled by type_to_xref later
|
|
106
|
+
# and fallback for other types that should be converted
|
|
107
|
+
return [nodes.Text(repr(node.value))]
|
|
108
|
+
if isinstance(node, ast.Expr):
|
|
109
|
+
return unparse(node.value)
|
|
110
|
+
if isinstance(node, ast.Invert):
|
|
111
|
+
return [addnodes.desc_sig_punctuation('', '~')]
|
|
112
|
+
if isinstance(node, ast.USub):
|
|
113
|
+
return [addnodes.desc_sig_punctuation('', '-')]
|
|
114
|
+
if isinstance(node, ast.List):
|
|
115
|
+
result = [addnodes.desc_sig_punctuation('', '[')]
|
|
116
|
+
if node.elts:
|
|
117
|
+
# check if there are elements in node.elts to only pop the
|
|
118
|
+
# last element of result if the for-loop was run at least
|
|
119
|
+
# once
|
|
120
|
+
for elem in node.elts:
|
|
121
|
+
result.extend(unparse(elem))
|
|
122
|
+
result.append(addnodes.desc_sig_punctuation('', ','))
|
|
123
|
+
result.append(addnodes.desc_sig_space())
|
|
124
|
+
result.pop()
|
|
125
|
+
result.pop()
|
|
126
|
+
result.append(addnodes.desc_sig_punctuation('', ']'))
|
|
127
|
+
return result
|
|
128
|
+
if isinstance(node, ast.Module):
|
|
129
|
+
return functools.reduce(operator.iadd, (unparse(e) for e in node.body), [])
|
|
130
|
+
if isinstance(node, ast.Name):
|
|
131
|
+
return [nodes.Text(node.id)]
|
|
132
|
+
if isinstance(node, ast.Subscript):
|
|
133
|
+
if getattr(node.value, 'id', '') in {'Optional', 'Union'}:
|
|
134
|
+
return _unparse_pep_604_annotation(node)
|
|
135
|
+
if short_literals and getattr(node.value, 'id', '') == 'Literal':
|
|
136
|
+
return _unparse_pep_604_annotation(node)
|
|
137
|
+
result = unparse(node.value)
|
|
138
|
+
result.append(addnodes.desc_sig_punctuation('', '['))
|
|
139
|
+
result.extend(unparse(node.slice))
|
|
140
|
+
result.append(addnodes.desc_sig_punctuation('', ']'))
|
|
141
|
+
|
|
142
|
+
# Wrap the Text nodes inside brackets by literal node if the subscript is a Literal
|
|
143
|
+
if result[0] in ('Literal', 'typing.Literal'):
|
|
144
|
+
for i, subnode in enumerate(result[1:], start=1):
|
|
145
|
+
if isinstance(subnode, nodes.Text):
|
|
146
|
+
result[i] = nodes.literal('', '', subnode)
|
|
147
|
+
return result
|
|
148
|
+
if isinstance(node, ast.UnaryOp):
|
|
149
|
+
return unparse(node.op) + unparse(node.operand)
|
|
150
|
+
if isinstance(node, ast.Tuple):
|
|
151
|
+
if node.elts:
|
|
152
|
+
result = []
|
|
153
|
+
for elem in node.elts:
|
|
154
|
+
result.extend(unparse(elem))
|
|
155
|
+
result.append(addnodes.desc_sig_punctuation('', ','))
|
|
156
|
+
result.append(addnodes.desc_sig_space())
|
|
157
|
+
result.pop()
|
|
158
|
+
result.pop()
|
|
159
|
+
else:
|
|
160
|
+
result = [addnodes.desc_sig_punctuation('', '('),
|
|
161
|
+
addnodes.desc_sig_punctuation('', ')')]
|
|
162
|
+
|
|
163
|
+
return result
|
|
164
|
+
raise SyntaxError # unsupported syntax
|
|
165
|
+
|
|
166
|
+
def _unparse_pep_604_annotation(node: ast.Subscript) -> list[Node]:
|
|
167
|
+
subscript = node.slice
|
|
168
|
+
|
|
169
|
+
flattened: list[Node] = []
|
|
170
|
+
if isinstance(subscript, ast.Tuple):
|
|
171
|
+
flattened.extend(unparse(subscript.elts[0]))
|
|
172
|
+
for elt in subscript.elts[1:]:
|
|
173
|
+
flattened.extend(unparse(ast.BitOr()))
|
|
174
|
+
flattened.extend(unparse(elt))
|
|
175
|
+
else:
|
|
176
|
+
# e.g. a Union[] inside an Optional[]
|
|
177
|
+
flattened.extend(unparse(subscript))
|
|
178
|
+
|
|
179
|
+
if getattr(node.value, 'id', '') == 'Optional':
|
|
180
|
+
flattened.extend(unparse(ast.BitOr()))
|
|
181
|
+
flattened.append(nodes.Text('None'))
|
|
182
|
+
|
|
183
|
+
return flattened
|
|
184
|
+
|
|
185
|
+
try:
|
|
186
|
+
tree = ast.parse(annotation, type_comments=True)
|
|
187
|
+
result: list[Node] = []
|
|
188
|
+
for node in unparse(tree):
|
|
189
|
+
if isinstance(node, nodes.literal):
|
|
190
|
+
result.append(node[0])
|
|
191
|
+
elif isinstance(node, nodes.Text) and node.strip():
|
|
192
|
+
if (result and isinstance(result[-1], addnodes.desc_sig_punctuation) and
|
|
193
|
+
result[-1].astext() == '~'):
|
|
194
|
+
result.pop()
|
|
195
|
+
result.append(type_to_xref(str(node), env, suppress_prefix=True))
|
|
196
|
+
else:
|
|
197
|
+
result.append(type_to_xref(str(node), env))
|
|
198
|
+
else:
|
|
199
|
+
result.append(node)
|
|
200
|
+
return result
|
|
201
|
+
except SyntaxError:
|
|
202
|
+
return [type_to_xref(annotation, env)]
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class _TypeParameterListParser(TokenProcessor):
|
|
206
|
+
def __init__(self, sig: str) -> None:
|
|
207
|
+
signature = sig.replace('\n', '').strip()
|
|
208
|
+
super().__init__([signature])
|
|
209
|
+
# Each item is a tuple (name, kind, default, annotation) mimicking
|
|
210
|
+
# ``inspect.Parameter`` to allow default values on VAR_POSITIONAL
|
|
211
|
+
# or VAR_KEYWORD parameters.
|
|
212
|
+
self.type_params: list[tuple[str, int, Any, Any]] = []
|
|
213
|
+
|
|
214
|
+
def fetch_type_param_spec(self) -> list[Token]:
|
|
215
|
+
tokens = []
|
|
216
|
+
while current := self.fetch_token():
|
|
217
|
+
tokens.append(current)
|
|
218
|
+
for ldelim, rdelim in ('(', ')'), ('{', '}'), ('[', ']'):
|
|
219
|
+
if current == [token.OP, ldelim]:
|
|
220
|
+
tokens += self.fetch_until([token.OP, rdelim])
|
|
221
|
+
break
|
|
222
|
+
else:
|
|
223
|
+
if current == token.INDENT:
|
|
224
|
+
tokens += self.fetch_until(token.DEDENT)
|
|
225
|
+
elif current.match(
|
|
226
|
+
[token.OP, ':'], [token.OP, '='], [token.OP, ',']):
|
|
227
|
+
tokens.pop()
|
|
228
|
+
break
|
|
229
|
+
return tokens
|
|
230
|
+
|
|
231
|
+
def parse(self) -> None:
|
|
232
|
+
while current := self.fetch_token():
|
|
233
|
+
if current == token.NAME:
|
|
234
|
+
tp_name = current.value.strip()
|
|
235
|
+
if self.previous and self.previous.match([token.OP, '*'], [token.OP, '**']):
|
|
236
|
+
if self.previous == [token.OP, '*']:
|
|
237
|
+
tp_kind = Parameter.VAR_POSITIONAL
|
|
238
|
+
else:
|
|
239
|
+
tp_kind = Parameter.VAR_KEYWORD # type: ignore[assignment]
|
|
240
|
+
else:
|
|
241
|
+
tp_kind = Parameter.POSITIONAL_OR_KEYWORD # type: ignore[assignment]
|
|
242
|
+
|
|
243
|
+
tp_ann: Any = Parameter.empty
|
|
244
|
+
tp_default: Any = Parameter.empty
|
|
245
|
+
|
|
246
|
+
current = self.fetch_token()
|
|
247
|
+
if current and current.match([token.OP, ':'], [token.OP, '=']):
|
|
248
|
+
if current == [token.OP, ':']:
|
|
249
|
+
tokens = self.fetch_type_param_spec()
|
|
250
|
+
tp_ann = self._build_identifier(tokens)
|
|
251
|
+
|
|
252
|
+
if self.current and self.current == [token.OP, '=']:
|
|
253
|
+
tokens = self.fetch_type_param_spec()
|
|
254
|
+
tp_default = self._build_identifier(tokens)
|
|
255
|
+
|
|
256
|
+
if tp_kind != Parameter.POSITIONAL_OR_KEYWORD and tp_ann != Parameter.empty:
|
|
257
|
+
msg = ('type parameter bound or constraint is not allowed '
|
|
258
|
+
f'for {tp_kind.description} parameters')
|
|
259
|
+
raise SyntaxError(msg)
|
|
260
|
+
|
|
261
|
+
type_param = (tp_name, tp_kind, tp_default, tp_ann)
|
|
262
|
+
self.type_params.append(type_param)
|
|
263
|
+
|
|
264
|
+
def _build_identifier(self, tokens: list[Token]) -> str:
|
|
265
|
+
from itertools import chain, islice
|
|
266
|
+
|
|
267
|
+
def triplewise(iterable: Iterable[Token]) -> Iterator[tuple[Token, ...]]:
|
|
268
|
+
# sliding_window('ABCDEFG', 4) --> ABCD BCDE CDEF DEFG
|
|
269
|
+
it = iter(iterable)
|
|
270
|
+
window = deque(islice(it, 3), maxlen=3)
|
|
271
|
+
if len(window) == 3:
|
|
272
|
+
yield tuple(window)
|
|
273
|
+
for x in it:
|
|
274
|
+
window.append(x)
|
|
275
|
+
yield tuple(window)
|
|
276
|
+
|
|
277
|
+
idents: list[str] = []
|
|
278
|
+
tokens: Iterable[Token] = iter(tokens) # type: ignore[no-redef]
|
|
279
|
+
# do not format opening brackets
|
|
280
|
+
for tok in tokens:
|
|
281
|
+
if not tok.match([token.OP, '('], [token.OP, '['], [token.OP, '{']):
|
|
282
|
+
# check if the first non-delimiter character is an unpack operator
|
|
283
|
+
is_unpack_operator = tok.match([token.OP, '*'], [token.OP, ['**']])
|
|
284
|
+
idents.append(self._pformat_token(tok, native=is_unpack_operator))
|
|
285
|
+
break
|
|
286
|
+
idents.append(tok.value)
|
|
287
|
+
|
|
288
|
+
# check the remaining tokens
|
|
289
|
+
stop = Token(token.ENDMARKER, '', (-1, -1), (-1, -1), '<sentinel>')
|
|
290
|
+
is_unpack_operator = False
|
|
291
|
+
for tok, op, after in triplewise(chain(tokens, [stop, stop])):
|
|
292
|
+
ident = self._pformat_token(tok, native=is_unpack_operator)
|
|
293
|
+
idents.append(ident)
|
|
294
|
+
# determine if the next token is an unpack operator depending
|
|
295
|
+
# on the left and right hand side of the operator symbol
|
|
296
|
+
is_unpack_operator = (
|
|
297
|
+
op.match([token.OP, '*'], [token.OP, '**']) and not (
|
|
298
|
+
tok.match(token.NAME, token.NUMBER, token.STRING,
|
|
299
|
+
[token.OP, ')'], [token.OP, ']'], [token.OP, '}'])
|
|
300
|
+
and after.match(token.NAME, token.NUMBER, token.STRING,
|
|
301
|
+
[token.OP, '('], [token.OP, '['], [token.OP, '{'])
|
|
302
|
+
)
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
return ''.join(idents).strip()
|
|
306
|
+
|
|
307
|
+
def _pformat_token(self, tok: Token, native: bool = False) -> str:
|
|
308
|
+
if native:
|
|
309
|
+
return tok.value
|
|
310
|
+
|
|
311
|
+
if tok.match(token.NEWLINE, token.ENDMARKER):
|
|
312
|
+
return ''
|
|
313
|
+
|
|
314
|
+
if tok.match([token.OP, ':'], [token.OP, ','], [token.OP, '#']):
|
|
315
|
+
return f'{tok.value} '
|
|
316
|
+
|
|
317
|
+
# Arithmetic operators are allowed because PEP 695 specifies the
|
|
318
|
+
# default type parameter to be *any* expression (so "T1 << T2" is
|
|
319
|
+
# allowed if it makes sense). The caller is responsible to ensure
|
|
320
|
+
# that a multiplication operator ("*") is not to be confused with
|
|
321
|
+
# an unpack operator (which will not be surrounded by spaces).
|
|
322
|
+
#
|
|
323
|
+
# The operators are ordered according to how likely they are to
|
|
324
|
+
# be used and for (possible) future implementations (e.g., "&" for
|
|
325
|
+
# an intersection type).
|
|
326
|
+
if tok.match(
|
|
327
|
+
# Most likely operators to appear
|
|
328
|
+
[token.OP, '='], [token.OP, '|'],
|
|
329
|
+
# Type composition (future compatibility)
|
|
330
|
+
[token.OP, '&'], [token.OP, '^'], [token.OP, '<'], [token.OP, '>'],
|
|
331
|
+
# Unlikely type composition
|
|
332
|
+
[token.OP, '+'], [token.OP, '-'], [token.OP, '*'], [token.OP, '**'],
|
|
333
|
+
# Unlikely operators but included for completeness
|
|
334
|
+
[token.OP, '@'], [token.OP, '/'], [token.OP, '//'], [token.OP, '%'],
|
|
335
|
+
[token.OP, '<<'], [token.OP, '>>'], [token.OP, '>>>'],
|
|
336
|
+
[token.OP, '<='], [token.OP, '>='], [token.OP, '=='], [token.OP, '!='],
|
|
337
|
+
):
|
|
338
|
+
return f' {tok.value} '
|
|
339
|
+
|
|
340
|
+
return tok.value
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
def _parse_type_list(
|
|
344
|
+
tp_list: str, env: BuildEnvironment,
|
|
345
|
+
multi_line_parameter_list: bool = False,
|
|
346
|
+
) -> addnodes.desc_type_parameter_list:
|
|
347
|
+
"""Parse a list of type parameters according to PEP 695."""
|
|
348
|
+
type_params = addnodes.desc_type_parameter_list(tp_list)
|
|
349
|
+
type_params['multi_line_parameter_list'] = multi_line_parameter_list
|
|
350
|
+
# formal parameter names are interpreted as type parameter names and
|
|
351
|
+
# type annotations are interpreted as type parameter bound or constraints
|
|
352
|
+
parser = _TypeParameterListParser(tp_list)
|
|
353
|
+
parser.parse()
|
|
354
|
+
for (tp_name, tp_kind, tp_default, tp_ann) in parser.type_params:
|
|
355
|
+
# no positional-only or keyword-only allowed in a type parameters list
|
|
356
|
+
if tp_kind in {Parameter.POSITIONAL_ONLY, Parameter.KEYWORD_ONLY}:
|
|
357
|
+
msg = ('positional-only or keyword-only parameters '
|
|
358
|
+
'are prohibited in type parameter lists')
|
|
359
|
+
raise SyntaxError(msg)
|
|
360
|
+
|
|
361
|
+
node = addnodes.desc_type_parameter()
|
|
362
|
+
if tp_kind == Parameter.VAR_POSITIONAL:
|
|
363
|
+
node += addnodes.desc_sig_operator('', '*')
|
|
364
|
+
elif tp_kind == Parameter.VAR_KEYWORD:
|
|
365
|
+
node += addnodes.desc_sig_operator('', '**')
|
|
366
|
+
node += addnodes.desc_sig_name('', tp_name)
|
|
367
|
+
|
|
368
|
+
if tp_ann is not Parameter.empty:
|
|
369
|
+
annotation = _parse_annotation(tp_ann, env)
|
|
370
|
+
if not annotation:
|
|
371
|
+
continue
|
|
372
|
+
|
|
373
|
+
node += addnodes.desc_sig_punctuation('', ':')
|
|
374
|
+
node += addnodes.desc_sig_space()
|
|
375
|
+
|
|
376
|
+
type_ann_expr = addnodes.desc_sig_name('', '',
|
|
377
|
+
*annotation) # type: ignore[arg-type]
|
|
378
|
+
# a type bound is ``T: U`` whereas type constraints
|
|
379
|
+
# must be enclosed with parentheses. ``T: (U, V)``
|
|
380
|
+
if tp_ann.startswith('(') and tp_ann.endswith(')'):
|
|
381
|
+
type_ann_text = type_ann_expr.astext()
|
|
382
|
+
if type_ann_text.startswith('(') and type_ann_text.endswith(')'):
|
|
383
|
+
node += type_ann_expr
|
|
384
|
+
else:
|
|
385
|
+
# surrounding braces are lost when using _parse_annotation()
|
|
386
|
+
node += addnodes.desc_sig_punctuation('', '(')
|
|
387
|
+
node += type_ann_expr # type constraint
|
|
388
|
+
node += addnodes.desc_sig_punctuation('', ')')
|
|
389
|
+
else:
|
|
390
|
+
node += type_ann_expr # type bound
|
|
391
|
+
|
|
392
|
+
if tp_default is not Parameter.empty:
|
|
393
|
+
# Always surround '=' with spaces, even if there is no annotation
|
|
394
|
+
node += addnodes.desc_sig_space()
|
|
395
|
+
node += addnodes.desc_sig_operator('', '=')
|
|
396
|
+
node += addnodes.desc_sig_space()
|
|
397
|
+
node += nodes.inline('', tp_default,
|
|
398
|
+
classes=['default_value'],
|
|
399
|
+
support_smartquotes=False)
|
|
400
|
+
|
|
401
|
+
type_params += node
|
|
402
|
+
return type_params
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
def _parse_arglist(
|
|
406
|
+
arglist: str, env: BuildEnvironment, multi_line_parameter_list: bool = False,
|
|
407
|
+
) -> addnodes.desc_parameterlist:
|
|
408
|
+
"""Parse a list of arguments using AST parser"""
|
|
409
|
+
params = addnodes.desc_parameterlist(arglist)
|
|
410
|
+
params['multi_line_parameter_list'] = multi_line_parameter_list
|
|
411
|
+
sig = signature_from_str('(%s)' % arglist)
|
|
412
|
+
last_kind = None
|
|
413
|
+
for param in sig.parameters.values():
|
|
414
|
+
if param.kind != param.POSITIONAL_ONLY and last_kind == param.POSITIONAL_ONLY:
|
|
415
|
+
# PEP-570: Separator for Positional Only Parameter: /
|
|
416
|
+
params += addnodes.desc_parameter('', '', addnodes.desc_sig_operator('', '/'))
|
|
417
|
+
if param.kind == param.KEYWORD_ONLY and last_kind in (param.POSITIONAL_OR_KEYWORD,
|
|
418
|
+
param.POSITIONAL_ONLY,
|
|
419
|
+
None):
|
|
420
|
+
# PEP-3102: Separator for Keyword Only Parameter: *
|
|
421
|
+
params += addnodes.desc_parameter('', '', addnodes.desc_sig_operator('', '*'))
|
|
422
|
+
|
|
423
|
+
node = addnodes.desc_parameter()
|
|
424
|
+
if param.kind == param.VAR_POSITIONAL:
|
|
425
|
+
node += addnodes.desc_sig_operator('', '*')
|
|
426
|
+
node += addnodes.desc_sig_name('', param.name)
|
|
427
|
+
elif param.kind == param.VAR_KEYWORD:
|
|
428
|
+
node += addnodes.desc_sig_operator('', '**')
|
|
429
|
+
node += addnodes.desc_sig_name('', param.name)
|
|
430
|
+
else:
|
|
431
|
+
node += addnodes.desc_sig_name('', param.name)
|
|
432
|
+
|
|
433
|
+
if param.annotation is not param.empty:
|
|
434
|
+
children = _parse_annotation(param.annotation, env)
|
|
435
|
+
node += addnodes.desc_sig_punctuation('', ':')
|
|
436
|
+
node += addnodes.desc_sig_space()
|
|
437
|
+
node += addnodes.desc_sig_name('', '', *children) # type: ignore[arg-type]
|
|
438
|
+
if param.default is not param.empty:
|
|
439
|
+
if param.annotation is not param.empty:
|
|
440
|
+
node += addnodes.desc_sig_space()
|
|
441
|
+
node += addnodes.desc_sig_operator('', '=')
|
|
442
|
+
node += addnodes.desc_sig_space()
|
|
443
|
+
else:
|
|
444
|
+
node += addnodes.desc_sig_operator('', '=')
|
|
445
|
+
node += nodes.inline('', param.default, classes=['default_value'],
|
|
446
|
+
support_smartquotes=False)
|
|
447
|
+
|
|
448
|
+
params += node
|
|
449
|
+
last_kind = param.kind
|
|
450
|
+
|
|
451
|
+
if last_kind == Parameter.POSITIONAL_ONLY:
|
|
452
|
+
# PEP-570: Separator for Positional Only Parameter: /
|
|
453
|
+
params += addnodes.desc_parameter('', '', addnodes.desc_sig_operator('', '/'))
|
|
454
|
+
|
|
455
|
+
return params
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def _pseudo_parse_arglist(
|
|
459
|
+
signode: desc_signature, arglist: str, multi_line_parameter_list: bool = False,
|
|
460
|
+
) -> None:
|
|
461
|
+
""""Parse" a list of arguments separated by commas.
|
|
462
|
+
|
|
463
|
+
Arguments can have "optional" annotations given by enclosing them in
|
|
464
|
+
brackets. Currently, this will split at any comma, even if it's inside a
|
|
465
|
+
string literal (e.g. default argument value).
|
|
466
|
+
"""
|
|
467
|
+
paramlist = addnodes.desc_parameterlist()
|
|
468
|
+
paramlist['multi_line_parameter_list'] = multi_line_parameter_list
|
|
469
|
+
stack: list[Element] = [paramlist]
|
|
470
|
+
try:
|
|
471
|
+
for argument in arglist.split(','):
|
|
472
|
+
argument = argument.strip()
|
|
473
|
+
ends_open = ends_close = 0
|
|
474
|
+
while argument.startswith('['):
|
|
475
|
+
stack.append(addnodes.desc_optional())
|
|
476
|
+
stack[-2] += stack[-1]
|
|
477
|
+
argument = argument[1:].strip()
|
|
478
|
+
while argument.startswith(']'):
|
|
479
|
+
stack.pop()
|
|
480
|
+
argument = argument[1:].strip()
|
|
481
|
+
while argument.endswith(']') and not argument.endswith('[]'):
|
|
482
|
+
ends_close += 1
|
|
483
|
+
argument = argument[:-1].strip()
|
|
484
|
+
while argument.endswith('['):
|
|
485
|
+
ends_open += 1
|
|
486
|
+
argument = argument[:-1].strip()
|
|
487
|
+
if argument:
|
|
488
|
+
stack[-1] += addnodes.desc_parameter(
|
|
489
|
+
'', '', addnodes.desc_sig_name(argument, argument))
|
|
490
|
+
while ends_open:
|
|
491
|
+
stack.append(addnodes.desc_optional())
|
|
492
|
+
stack[-2] += stack[-1]
|
|
493
|
+
ends_open -= 1
|
|
494
|
+
while ends_close:
|
|
495
|
+
stack.pop()
|
|
496
|
+
ends_close -= 1
|
|
497
|
+
if len(stack) != 1:
|
|
498
|
+
raise IndexError
|
|
499
|
+
except IndexError:
|
|
500
|
+
# if there are too few or too many elements on the stack, just give up
|
|
501
|
+
# and treat the whole argument list as one argument, discarding the
|
|
502
|
+
# already partially populated paramlist node
|
|
503
|
+
paramlist = addnodes.desc_parameterlist()
|
|
504
|
+
paramlist += addnodes.desc_parameter(arglist, arglist)
|
|
505
|
+
signode += paramlist
|
|
506
|
+
else:
|
|
507
|
+
signode += paramlist
|