Sphinx 8.1.2__py3-none-any.whl → 8.2.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 -4
- sphinx/__main__.py +2 -0
- sphinx/_cli/__init__.py +2 -5
- sphinx/_cli/util/colour.py +34 -11
- sphinx/_cli/util/errors.py +128 -61
- sphinx/addnodes.py +51 -35
- sphinx/application.py +362 -230
- sphinx/builders/__init__.py +87 -64
- sphinx/builders/_epub_base.py +65 -56
- sphinx/builders/changes.py +17 -23
- sphinx/builders/dirhtml.py +8 -13
- sphinx/builders/epub3.py +70 -38
- sphinx/builders/gettext.py +93 -73
- sphinx/builders/html/__init__.py +240 -186
- sphinx/builders/html/_assets.py +9 -2
- sphinx/builders/html/_build_info.py +3 -0
- sphinx/builders/latex/__init__.py +64 -54
- sphinx/builders/latex/constants.py +14 -11
- sphinx/builders/latex/nodes.py +2 -0
- sphinx/builders/latex/theming.py +8 -9
- sphinx/builders/latex/transforms.py +7 -5
- sphinx/builders/linkcheck.py +193 -149
- sphinx/builders/manpage.py +17 -17
- sphinx/builders/singlehtml.py +28 -16
- sphinx/builders/texinfo.py +28 -21
- sphinx/builders/text.py +10 -15
- sphinx/builders/xml.py +10 -19
- sphinx/cmd/build.py +49 -119
- sphinx/cmd/make_mode.py +35 -31
- sphinx/cmd/quickstart.py +78 -62
- sphinx/config.py +265 -163
- sphinx/directives/__init__.py +51 -54
- sphinx/directives/admonitions.py +107 -0
- sphinx/directives/code.py +24 -19
- sphinx/directives/other.py +21 -42
- sphinx/directives/patches.py +28 -16
- sphinx/domains/__init__.py +54 -31
- sphinx/domains/_domains_container.py +22 -17
- sphinx/domains/_index.py +5 -8
- sphinx/domains/c/__init__.py +366 -245
- sphinx/domains/c/_ast.py +378 -256
- sphinx/domains/c/_ids.py +89 -31
- sphinx/domains/c/_parser.py +283 -214
- sphinx/domains/c/_symbol.py +269 -198
- sphinx/domains/changeset.py +39 -24
- sphinx/domains/citation.py +54 -24
- sphinx/domains/cpp/__init__.py +517 -362
- sphinx/domains/cpp/_ast.py +999 -682
- sphinx/domains/cpp/_ids.py +133 -65
- sphinx/domains/cpp/_parser.py +746 -588
- sphinx/domains/cpp/_symbol.py +692 -489
- sphinx/domains/index.py +10 -8
- sphinx/domains/javascript.py +152 -74
- sphinx/domains/math.py +50 -40
- sphinx/domains/python/__init__.py +402 -211
- sphinx/domains/python/_annotations.py +134 -61
- sphinx/domains/python/_object.py +155 -68
- sphinx/domains/rst.py +94 -49
- sphinx/domains/std/__init__.py +510 -249
- sphinx/environment/__init__.py +345 -61
- sphinx/environment/adapters/asset.py +7 -1
- sphinx/environment/adapters/indexentries.py +15 -20
- sphinx/environment/adapters/toctree.py +19 -9
- sphinx/environment/collectors/__init__.py +3 -1
- sphinx/environment/collectors/asset.py +18 -15
- sphinx/environment/collectors/dependencies.py +8 -10
- sphinx/environment/collectors/metadata.py +6 -4
- sphinx/environment/collectors/title.py +3 -1
- sphinx/environment/collectors/toctree.py +4 -4
- sphinx/errors.py +1 -3
- sphinx/events.py +4 -4
- sphinx/ext/apidoc/__init__.py +66 -0
- sphinx/ext/apidoc/__main__.py +9 -0
- sphinx/ext/apidoc/_cli.py +356 -0
- sphinx/ext/apidoc/_extension.py +262 -0
- sphinx/ext/apidoc/_generate.py +356 -0
- sphinx/ext/apidoc/_shared.py +99 -0
- sphinx/ext/autodoc/__init__.py +837 -483
- sphinx/ext/autodoc/directive.py +57 -21
- sphinx/ext/autodoc/importer.py +184 -67
- sphinx/ext/autodoc/mock.py +25 -10
- sphinx/ext/autodoc/preserve_defaults.py +17 -9
- sphinx/ext/autodoc/type_comment.py +56 -29
- sphinx/ext/autodoc/typehints.py +49 -26
- sphinx/ext/autosectionlabel.py +28 -11
- sphinx/ext/autosummary/__init__.py +281 -142
- sphinx/ext/autosummary/generate.py +121 -51
- sphinx/ext/coverage.py +152 -91
- sphinx/ext/doctest.py +169 -101
- sphinx/ext/duration.py +12 -6
- sphinx/ext/extlinks.py +33 -21
- sphinx/ext/githubpages.py +8 -8
- sphinx/ext/graphviz.py +175 -109
- sphinx/ext/ifconfig.py +11 -6
- sphinx/ext/imgconverter.py +48 -25
- sphinx/ext/imgmath.py +127 -97
- sphinx/ext/inheritance_diagram.py +177 -103
- sphinx/ext/intersphinx/__init__.py +22 -13
- sphinx/ext/intersphinx/__main__.py +3 -1
- sphinx/ext/intersphinx/_cli.py +18 -14
- sphinx/ext/intersphinx/_load.py +91 -82
- sphinx/ext/intersphinx/_resolve.py +108 -74
- sphinx/ext/intersphinx/_shared.py +2 -2
- sphinx/ext/linkcode.py +28 -12
- sphinx/ext/mathjax.py +60 -29
- sphinx/ext/napoleon/__init__.py +19 -7
- sphinx/ext/napoleon/docstring.py +229 -231
- sphinx/ext/todo.py +44 -49
- sphinx/ext/viewcode.py +105 -57
- sphinx/extension.py +3 -1
- sphinx/highlighting.py +13 -7
- sphinx/io.py +9 -13
- sphinx/jinja2glue.py +29 -26
- sphinx/locale/__init__.py +8 -9
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +2155 -2050
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +2175 -2070
- sphinx/locale/ca/LC_MESSAGES/sphinx.js +3 -3
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +2690 -2585
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.js +63 -0
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.po +4216 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +2096 -1991
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +2248 -2143
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +2201 -2096
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +2282 -2177
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +2261 -2156
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +2604 -2499
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2631 -2526
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +2078 -1973
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +2633 -2528
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +2449 -2344
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +2241 -2136
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +504 -500
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr/LC_MESSAGES/sphinx.po +513 -509
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +2644 -2539
- sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +504 -500
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +501 -497
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +2609 -2504
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +2265 -2160
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +2621 -2516
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +2567 -2462
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +2631 -2526
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +2214 -2109
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +2218 -2113
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +2088 -1983
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2247 -2142
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +2227 -2122
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +2316 -2211
- sphinx/locale/pl/LC_MESSAGES/sphinx.js +2 -2
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +2442 -2336
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2657 -2552
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2243 -2138
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +2244 -2139
- 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 +2660 -2555
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +2134 -2029
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +2614 -2509
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +2167 -2062
- sphinx/locale/sphinx.pot +2069 -1964
- sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sq/LC_MESSAGES/sphinx.po +2661 -2556
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +2213 -2108
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +2229 -2124
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +2608 -2503
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2167 -2062
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +2204 -2099
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +2659 -2554
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/parsers.py +8 -7
- sphinx/project.py +2 -2
- sphinx/pycode/__init__.py +31 -21
- sphinx/pycode/ast.py +6 -3
- sphinx/pycode/parser.py +14 -8
- sphinx/pygments_styles.py +4 -5
- sphinx/registry.py +192 -92
- sphinx/roles.py +58 -7
- sphinx/search/__init__.py +75 -54
- sphinx/search/en.py +11 -13
- sphinx/search/fi.py +1 -1
- sphinx/search/ja.py +8 -6
- sphinx/search/nl.py +1 -1
- sphinx/search/zh.py +19 -21
- sphinx/testing/fixtures.py +26 -29
- sphinx/testing/path.py +26 -62
- sphinx/testing/restructuredtext.py +14 -8
- sphinx/testing/util.py +21 -19
- sphinx/texinputs/make.bat.jinja +50 -50
- sphinx/texinputs/sphinx.sty +4 -3
- sphinx/texinputs/sphinxlatexadmonitions.sty +1 -1
- sphinx/texinputs/sphinxlatexobjects.sty +29 -10
- sphinx/themes/basic/static/searchtools.js +8 -5
- sphinx/theming.py +49 -61
- sphinx/transforms/__init__.py +17 -38
- sphinx/transforms/compact_bullet_list.py +5 -3
- sphinx/transforms/i18n.py +8 -21
- sphinx/transforms/post_transforms/__init__.py +142 -93
- sphinx/transforms/post_transforms/code.py +5 -5
- sphinx/transforms/post_transforms/images.py +28 -24
- sphinx/transforms/references.py +3 -1
- sphinx/util/__init__.py +109 -60
- sphinx/util/_files.py +39 -23
- sphinx/util/_importer.py +4 -1
- sphinx/util/_inventory_file_reader.py +76 -0
- sphinx/util/_io.py +2 -2
- sphinx/util/_lines.py +6 -3
- sphinx/util/_pathlib.py +40 -2
- sphinx/util/build_phase.py +2 -0
- sphinx/util/cfamily.py +19 -14
- sphinx/util/console.py +44 -179
- sphinx/util/display.py +9 -10
- sphinx/util/docfields.py +140 -122
- sphinx/util/docstrings.py +1 -1
- sphinx/util/docutils.py +118 -77
- sphinx/util/fileutil.py +25 -26
- sphinx/util/http_date.py +2 -0
- sphinx/util/i18n.py +77 -64
- sphinx/util/images.py +8 -6
- sphinx/util/inspect.py +147 -38
- sphinx/util/inventory.py +215 -116
- sphinx/util/logging.py +33 -33
- sphinx/util/matching.py +12 -4
- sphinx/util/nodes.py +18 -13
- sphinx/util/osutil.py +38 -39
- sphinx/util/parallel.py +22 -13
- sphinx/util/parsing.py +2 -1
- sphinx/util/png.py +6 -2
- sphinx/util/requests.py +33 -2
- sphinx/util/rst.py +3 -2
- sphinx/util/tags.py +1 -1
- sphinx/util/template.py +18 -10
- sphinx/util/texescape.py +8 -6
- sphinx/util/typing.py +148 -122
- sphinx/versioning.py +3 -3
- sphinx/writers/html.py +3 -1
- sphinx/writers/html5.py +63 -52
- sphinx/writers/latex.py +83 -67
- sphinx/writers/manpage.py +19 -38
- sphinx/writers/texinfo.py +47 -47
- sphinx/writers/text.py +50 -32
- sphinx/writers/xml.py +11 -8
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/LICENSE.rst +1 -1
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/METADATA +25 -15
- sphinx-8.2.0.dist-info/RECORD +606 -0
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/WHEEL +1 -1
- sphinx/builders/html/transforms.py +0 -90
- sphinx/ext/apidoc.py +0 -721
- sphinx/util/exceptions.py +0 -74
- sphinx-8.1.2.dist-info/RECORD +0 -598
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/entry_points.txt +0 -0
|
@@ -42,11 +42,15 @@ def get_function_def(obj: Any) -> ast.FunctionDef | None:
|
|
|
42
42
|
This tries to parse original code for living object and returns
|
|
43
43
|
AST node for given *obj*.
|
|
44
44
|
"""
|
|
45
|
-
warnings.warn(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
warnings.warn(
|
|
46
|
+
'sphinx.ext.autodoc.preserve_defaults.get_function_def is'
|
|
47
|
+
' deprecated and scheduled for removal in Sphinx 9.'
|
|
48
|
+
' Use sphinx.ext.autodoc.preserve_defaults._get_arguments() to'
|
|
49
|
+
' extract AST arguments objects from a lambda or regular'
|
|
50
|
+
' function.',
|
|
51
|
+
RemovedInSphinx90Warning,
|
|
52
|
+
stacklevel=2,
|
|
53
|
+
)
|
|
50
54
|
|
|
51
55
|
try:
|
|
52
56
|
source = inspect.getsource(obj)
|
|
@@ -113,7 +117,7 @@ def get_default_value(lines: list[str], position: ast.expr) -> str | None:
|
|
|
113
117
|
try:
|
|
114
118
|
if position.lineno == position.end_lineno:
|
|
115
119
|
line = lines[position.lineno - 1]
|
|
116
|
-
return line[position.col_offset:position.end_col_offset]
|
|
120
|
+
return line[position.col_offset : position.end_col_offset]
|
|
117
121
|
else:
|
|
118
122
|
# multiline value is not supported now
|
|
119
123
|
return None
|
|
@@ -161,7 +165,7 @@ def update_defvalue(app: Sphinx, obj: Any, bound_method: bool) -> None:
|
|
|
161
165
|
# Consume kw_defaults for kwonly args
|
|
162
166
|
kw_defaults.pop(0)
|
|
163
167
|
else:
|
|
164
|
-
if param.kind in
|
|
168
|
+
if param.kind in {param.POSITIONAL_ONLY, param.POSITIONAL_OR_KEYWORD}:
|
|
165
169
|
default = defaults.pop(0)
|
|
166
170
|
value = get_default_value(lines, default)
|
|
167
171
|
if value is None:
|
|
@@ -187,11 +191,15 @@ def update_defvalue(app: Sphinx, obj: Any, bound_method: bool) -> None:
|
|
|
187
191
|
# In this case, we can't set __signature__.
|
|
188
192
|
return
|
|
189
193
|
except NotImplementedError as exc: # failed to ast_unparse()
|
|
190
|
-
logger.warning(
|
|
194
|
+
logger.warning(
|
|
195
|
+
__('Failed to parse a default argument value for %r: %s'), obj, exc
|
|
196
|
+
)
|
|
191
197
|
|
|
192
198
|
|
|
193
199
|
def setup(app: Sphinx) -> ExtensionMetadata:
|
|
194
|
-
app.add_config_value(
|
|
200
|
+
app.add_config_value(
|
|
201
|
+
'autodoc_preserve_defaults', False, 'env', types=frozenset({bool})
|
|
202
|
+
)
|
|
195
203
|
app.connect('autodoc-before-process-signature', update_defvalue)
|
|
196
204
|
|
|
197
205
|
return {
|
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import ast
|
|
6
6
|
from inspect import Parameter, Signature, getsource
|
|
7
|
-
from typing import TYPE_CHECKING,
|
|
7
|
+
from typing import TYPE_CHECKING, cast
|
|
8
8
|
|
|
9
9
|
import sphinx
|
|
10
10
|
from sphinx.locale import __
|
|
@@ -13,6 +13,7 @@ from sphinx.util import inspect, logging
|
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
15
|
from collections.abc import Sequence
|
|
16
|
+
from typing import Any
|
|
16
17
|
|
|
17
18
|
from sphinx.application import Sphinx
|
|
18
19
|
from sphinx.util.typing import ExtensionMetadata
|
|
@@ -32,35 +33,52 @@ def not_suppressed(argtypes: Sequence[ast.expr] = ()) -> bool:
|
|
|
32
33
|
return True
|
|
33
34
|
|
|
34
35
|
|
|
35
|
-
def signature_from_ast(
|
|
36
|
-
|
|
36
|
+
def signature_from_ast(
|
|
37
|
+
node: ast.FunctionDef, bound_method: bool, type_comment: ast.FunctionDef
|
|
38
|
+
) -> Signature:
|
|
37
39
|
"""Return a Signature object for the given *node*.
|
|
38
40
|
|
|
39
41
|
:param bound_method: Specify *node* is a bound method or not
|
|
40
42
|
"""
|
|
41
43
|
params = []
|
|
42
44
|
for arg in node.args.posonlyargs:
|
|
43
|
-
param = Parameter(
|
|
45
|
+
param = Parameter(
|
|
46
|
+
arg.arg,
|
|
47
|
+
Parameter.POSITIONAL_ONLY,
|
|
48
|
+
annotation=arg.type_comment,
|
|
49
|
+
)
|
|
44
50
|
params.append(param)
|
|
45
51
|
|
|
46
52
|
for arg in node.args.args:
|
|
47
|
-
param = Parameter(
|
|
48
|
-
|
|
53
|
+
param = Parameter(
|
|
54
|
+
arg.arg,
|
|
55
|
+
Parameter.POSITIONAL_OR_KEYWORD,
|
|
56
|
+
annotation=arg.type_comment or Parameter.empty,
|
|
57
|
+
)
|
|
49
58
|
params.append(param)
|
|
50
59
|
|
|
51
60
|
if node.args.vararg:
|
|
52
|
-
param = Parameter(
|
|
53
|
-
|
|
61
|
+
param = Parameter(
|
|
62
|
+
node.args.vararg.arg,
|
|
63
|
+
Parameter.VAR_POSITIONAL,
|
|
64
|
+
annotation=node.args.vararg.type_comment or Parameter.empty,
|
|
65
|
+
)
|
|
54
66
|
params.append(param)
|
|
55
67
|
|
|
56
68
|
for arg in node.args.kwonlyargs:
|
|
57
|
-
param = Parameter(
|
|
58
|
-
|
|
69
|
+
param = Parameter(
|
|
70
|
+
arg.arg,
|
|
71
|
+
Parameter.KEYWORD_ONLY,
|
|
72
|
+
annotation=arg.type_comment or Parameter.empty,
|
|
73
|
+
)
|
|
59
74
|
params.append(param)
|
|
60
75
|
|
|
61
76
|
if node.args.kwarg:
|
|
62
|
-
param = Parameter(
|
|
63
|
-
|
|
77
|
+
param = Parameter(
|
|
78
|
+
node.args.kwarg.arg,
|
|
79
|
+
Parameter.VAR_KEYWORD,
|
|
80
|
+
annotation=node.args.kwarg.type_comment or Parameter.empty,
|
|
81
|
+
)
|
|
64
82
|
params.append(param)
|
|
65
83
|
|
|
66
84
|
# Remove first parameter when *obj* is bound_method
|
|
@@ -70,8 +88,7 @@ def signature_from_ast(node: ast.FunctionDef, bound_method: bool,
|
|
|
70
88
|
# merge type_comment into signature
|
|
71
89
|
if not_suppressed(type_comment.argtypes): # type: ignore[attr-defined]
|
|
72
90
|
for i, param in enumerate(params):
|
|
73
|
-
params[i] = param.replace(
|
|
74
|
-
annotation=type_comment.argtypes[i]) # type: ignore[attr-defined]
|
|
91
|
+
params[i] = param.replace(annotation=type_comment.argtypes[i]) # type: ignore[attr-defined]
|
|
75
92
|
|
|
76
93
|
if node.returns:
|
|
77
94
|
return Signature(params, return_annotation=node.returns)
|
|
@@ -93,19 +110,15 @@ def get_type_comment(obj: Any, bound_method: bool = False) -> Signature | None:
|
|
|
93
110
|
# subject is placed inside class or block. To read its docstring,
|
|
94
111
|
# this adds if-block before the declaration.
|
|
95
112
|
module = ast.parse('if True:\n' + source, type_comments=True)
|
|
96
|
-
subject = cast(
|
|
97
|
-
ast.FunctionDef, module.body[0].body[0], # type: ignore[attr-defined]
|
|
98
|
-
)
|
|
113
|
+
subject = cast('ast.FunctionDef', module.body[0].body[0]) # type: ignore[attr-defined]
|
|
99
114
|
else:
|
|
100
115
|
module = ast.parse(source, type_comments=True)
|
|
101
|
-
subject = cast(ast.FunctionDef, module.body[0])
|
|
116
|
+
subject = cast('ast.FunctionDef', module.body[0])
|
|
102
117
|
|
|
103
|
-
type_comment = getattr(subject,
|
|
118
|
+
type_comment = getattr(subject, 'type_comment', None)
|
|
104
119
|
if type_comment:
|
|
105
120
|
function = ast.parse(type_comment, mode='func_type', type_comments=True)
|
|
106
|
-
return signature_from_ast(
|
|
107
|
-
subject, bound_method, function, # type: ignore[arg-type]
|
|
108
|
-
)
|
|
121
|
+
return signature_from_ast(subject, bound_method, function) # type: ignore[arg-type]
|
|
109
122
|
else:
|
|
110
123
|
return None
|
|
111
124
|
except (OSError, TypeError): # failed to load source code
|
|
@@ -114,8 +127,13 @@ def get_type_comment(obj: Any, bound_method: bool = False) -> Signature | None:
|
|
|
114
127
|
return None
|
|
115
128
|
|
|
116
129
|
|
|
117
|
-
def update_annotations_using_type_comments(
|
|
130
|
+
def update_annotations_using_type_comments(
|
|
131
|
+
app: Sphinx, obj: Any, bound_method: bool
|
|
132
|
+
) -> None:
|
|
118
133
|
"""Update annotations info of *obj* using type_comments."""
|
|
134
|
+
if not app.config.autodoc_use_type_comments:
|
|
135
|
+
return
|
|
136
|
+
|
|
119
137
|
try:
|
|
120
138
|
type_sig = get_type_comment(obj, bound_method)
|
|
121
139
|
if type_sig:
|
|
@@ -129,13 +147,22 @@ def update_annotations_using_type_comments(app: Sphinx, obj: Any, bound_method:
|
|
|
129
147
|
if 'return' not in obj.__annotations__:
|
|
130
148
|
obj.__annotations__['return'] = type_sig.return_annotation
|
|
131
149
|
except KeyError as exc:
|
|
132
|
-
logger.warning(
|
|
133
|
-
|
|
150
|
+
logger.warning(
|
|
151
|
+
__('Failed to update signature for %r: parameter not found: %s'), obj, exc
|
|
152
|
+
)
|
|
134
153
|
except NotImplementedError as exc: # failed to ast.unparse()
|
|
135
|
-
logger.warning(__(
|
|
154
|
+
logger.warning(__('Failed to parse type_comment for %r: %s'), obj, exc)
|
|
136
155
|
|
|
137
156
|
|
|
138
157
|
def setup(app: Sphinx) -> ExtensionMetadata:
|
|
139
|
-
app.
|
|
140
|
-
|
|
141
|
-
|
|
158
|
+
app.add_config_value(
|
|
159
|
+
'autodoc_use_type_comments', True, 'env', types=frozenset({bool})
|
|
160
|
+
)
|
|
161
|
+
app.connect(
|
|
162
|
+
'autodoc-before-process-signature', update_annotations_using_type_comments
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
'version': sphinx.__display_version__,
|
|
167
|
+
'parallel_read_safe': True,
|
|
168
|
+
}
|
sphinx/ext/autodoc/typehints.py
CHANGED
|
@@ -3,53 +3,72 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import re
|
|
6
|
-
from
|
|
7
|
-
from typing import TYPE_CHECKING, Any, cast
|
|
6
|
+
from typing import TYPE_CHECKING, cast
|
|
8
7
|
|
|
9
8
|
from docutils import nodes
|
|
10
9
|
|
|
11
10
|
import sphinx
|
|
12
11
|
from sphinx import addnodes
|
|
13
12
|
from sphinx.util import inspect
|
|
14
|
-
from sphinx.util.typing import
|
|
13
|
+
from sphinx.util.typing import stringify_annotation
|
|
15
14
|
|
|
16
15
|
if TYPE_CHECKING:
|
|
16
|
+
from collections.abc import Iterable
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
17
19
|
from docutils.nodes import Element
|
|
18
20
|
|
|
19
21
|
from sphinx.application import Sphinx
|
|
20
22
|
from sphinx.ext.autodoc import Options
|
|
23
|
+
from sphinx.util.typing import ExtensionMetadata, _StringifyMode
|
|
21
24
|
|
|
22
25
|
|
|
23
|
-
def record_typehints(
|
|
24
|
-
|
|
26
|
+
def record_typehints(
|
|
27
|
+
app: Sphinx,
|
|
28
|
+
objtype: str,
|
|
29
|
+
name: str,
|
|
30
|
+
obj: Any,
|
|
31
|
+
options: Options,
|
|
32
|
+
args: str,
|
|
33
|
+
retann: str,
|
|
34
|
+
) -> None:
|
|
25
35
|
"""Record type hints to env object."""
|
|
36
|
+
mode: _StringifyMode
|
|
26
37
|
if app.config.autodoc_typehints_format == 'short':
|
|
27
38
|
mode = 'smart'
|
|
28
39
|
else:
|
|
29
40
|
mode = 'fully-qualified'
|
|
30
41
|
|
|
42
|
+
short_literals = app.config.python_display_short_literal_types
|
|
43
|
+
|
|
31
44
|
try:
|
|
32
45
|
if callable(obj):
|
|
33
|
-
|
|
34
|
-
annotation =
|
|
46
|
+
current_document = app.env.current_document
|
|
47
|
+
annotation = current_document.autodoc_annotations.setdefault(name, {})
|
|
35
48
|
sig = inspect.signature(obj, type_aliases=app.config.autodoc_type_aliases)
|
|
36
49
|
for param in sig.parameters.values():
|
|
37
50
|
if param.annotation is not param.empty:
|
|
38
|
-
annotation[param.name] = stringify_annotation(
|
|
51
|
+
annotation[param.name] = stringify_annotation(
|
|
52
|
+
param.annotation, mode, short_literals=short_literals
|
|
53
|
+
)
|
|
39
54
|
if sig.return_annotation is not sig.empty:
|
|
40
|
-
annotation['return'] = stringify_annotation(
|
|
55
|
+
annotation['return'] = stringify_annotation(
|
|
56
|
+
sig.return_annotation, mode, short_literals=short_literals
|
|
57
|
+
)
|
|
41
58
|
except (TypeError, ValueError):
|
|
42
59
|
pass
|
|
43
60
|
|
|
44
61
|
|
|
45
|
-
def merge_typehints(
|
|
62
|
+
def merge_typehints(
|
|
63
|
+
app: Sphinx, domain: str, objtype: str, contentnode: Element
|
|
64
|
+
) -> None:
|
|
46
65
|
if domain != 'py':
|
|
47
66
|
return
|
|
48
|
-
if app.config.autodoc_typehints not in
|
|
67
|
+
if app.config.autodoc_typehints not in {'both', 'description'}:
|
|
49
68
|
return
|
|
50
69
|
|
|
51
70
|
try:
|
|
52
|
-
signature = cast(addnodes.desc_signature, contentnode.parent[0])
|
|
71
|
+
signature = cast('addnodes.desc_signature', contentnode.parent[0])
|
|
53
72
|
if signature['module']:
|
|
54
73
|
fullname = f'{signature["module"]}.{signature["fullname"]}'
|
|
55
74
|
else:
|
|
@@ -58,7 +77,7 @@ def merge_typehints(app: Sphinx, domain: str, objtype: str, contentnode: Element
|
|
|
58
77
|
# signature node does not have valid context info for the target object
|
|
59
78
|
return
|
|
60
79
|
|
|
61
|
-
annotations = app.env.
|
|
80
|
+
annotations = app.env.current_document.autodoc_annotations
|
|
62
81
|
if annotations.get(fullname, {}):
|
|
63
82
|
field_lists = [n for n in contentnode if isinstance(n, nodes.field_list)]
|
|
64
83
|
if field_lists == []:
|
|
@@ -66,18 +85,20 @@ def merge_typehints(app: Sphinx, domain: str, objtype: str, contentnode: Element
|
|
|
66
85
|
field_lists.append(field_list)
|
|
67
86
|
|
|
68
87
|
for field_list in field_lists:
|
|
69
|
-
if app.config.autodoc_typehints_description_target ==
|
|
88
|
+
if app.config.autodoc_typehints_description_target == 'all':
|
|
70
89
|
if objtype == 'class':
|
|
71
|
-
modify_field_list(
|
|
90
|
+
modify_field_list(
|
|
91
|
+
field_list, annotations[fullname], suppress_rtype=True
|
|
92
|
+
)
|
|
72
93
|
else:
|
|
73
94
|
modify_field_list(field_list, annotations[fullname])
|
|
74
|
-
elif app.config.autodoc_typehints_description_target ==
|
|
95
|
+
elif app.config.autodoc_typehints_description_target == 'documented_params':
|
|
75
96
|
augment_descriptions_with_types(
|
|
76
|
-
field_list, annotations[fullname], force_rtype=True
|
|
97
|
+
field_list, annotations[fullname], force_rtype=True
|
|
77
98
|
)
|
|
78
99
|
else:
|
|
79
100
|
augment_descriptions_with_types(
|
|
80
|
-
field_list, annotations[fullname], force_rtype=False
|
|
101
|
+
field_list, annotations[fullname], force_rtype=False
|
|
81
102
|
)
|
|
82
103
|
|
|
83
104
|
|
|
@@ -94,10 +115,11 @@ def insert_field_list(node: Element) -> nodes.field_list:
|
|
|
94
115
|
return field_list
|
|
95
116
|
|
|
96
117
|
|
|
97
|
-
def modify_field_list(
|
|
98
|
-
|
|
118
|
+
def modify_field_list(
|
|
119
|
+
node: nodes.field_list, annotations: dict[str, str], suppress_rtype: bool = False
|
|
120
|
+
) -> None:
|
|
99
121
|
arguments: dict[str, dict[str, bool]] = {}
|
|
100
|
-
fields = cast(Iterable[nodes.field], node)
|
|
122
|
+
fields = cast('Iterable[nodes.field]', node)
|
|
101
123
|
for field in fields:
|
|
102
124
|
field_name = field[0].astext()
|
|
103
125
|
parts = re.split(' +', field_name)
|
|
@@ -159,7 +181,7 @@ def augment_descriptions_with_types(
|
|
|
159
181
|
annotations: dict[str, str],
|
|
160
182
|
force_rtype: bool,
|
|
161
183
|
) -> None:
|
|
162
|
-
fields = cast(Iterable[nodes.field], node)
|
|
184
|
+
fields = cast('Iterable[nodes.field]', node)
|
|
163
185
|
has_description: set[str] = set()
|
|
164
186
|
has_type: set[str] = set()
|
|
165
187
|
for field in fields:
|
|
@@ -177,14 +199,14 @@ def augment_descriptions_with_types(
|
|
|
177
199
|
elif parts[0] == 'type':
|
|
178
200
|
name = ' '.join(parts[1:])
|
|
179
201
|
has_type.add(name)
|
|
180
|
-
elif parts[0] in
|
|
202
|
+
elif parts[0] in {'return', 'returns'}:
|
|
181
203
|
has_description.add('return')
|
|
182
204
|
elif parts[0] == 'rtype':
|
|
183
205
|
has_type.add('return')
|
|
184
206
|
|
|
185
207
|
# Add 'type' for parameters with a description but no declared type.
|
|
186
208
|
for name, annotation in annotations.items():
|
|
187
|
-
if name in
|
|
209
|
+
if name in {'return', 'returns'}:
|
|
188
210
|
continue
|
|
189
211
|
|
|
190
212
|
if '*' + name in has_description:
|
|
@@ -201,8 +223,9 @@ def augment_descriptions_with_types(
|
|
|
201
223
|
# Add 'rtype' if 'return' is present and 'rtype' isn't.
|
|
202
224
|
if 'return' in annotations:
|
|
203
225
|
rtype = annotations['return']
|
|
204
|
-
if 'return' not in has_type and (
|
|
205
|
-
|
|
226
|
+
if 'return' not in has_type and (
|
|
227
|
+
'return' in has_description or (force_rtype and rtype != 'None')
|
|
228
|
+
):
|
|
206
229
|
field = nodes.field()
|
|
207
230
|
field += nodes.field_name('', 'rtype')
|
|
208
231
|
field += nodes.field_body('', nodes.paragraph('', rtype))
|
sphinx/ext/autosectionlabel.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from types import NoneType
|
|
5
6
|
from typing import TYPE_CHECKING, cast
|
|
6
7
|
|
|
7
8
|
from docutils import nodes
|
|
@@ -32,12 +33,14 @@ def get_node_depth(node: Node) -> int:
|
|
|
32
33
|
def register_sections_as_label(app: Sphinx, document: Node) -> None:
|
|
33
34
|
domain = app.env.domains.standard_domain
|
|
34
35
|
for node in document.findall(nodes.section):
|
|
35
|
-
if (
|
|
36
|
-
|
|
36
|
+
if (
|
|
37
|
+
app.config.autosectionlabel_maxdepth
|
|
38
|
+
and get_node_depth(node) >= app.config.autosectionlabel_maxdepth
|
|
39
|
+
):
|
|
37
40
|
continue
|
|
38
41
|
labelid = node['ids'][0]
|
|
39
42
|
docname = app.env.docname
|
|
40
|
-
title = cast(nodes.title, node[0])
|
|
43
|
+
title = cast('nodes.title', node[0])
|
|
41
44
|
ref_name = getattr(title, 'rawsource', title.astext())
|
|
42
45
|
if app.config.autosectionlabel_prefix_document:
|
|
43
46
|
name = nodes.fully_normalize_name(docname + ':' + ref_name)
|
|
@@ -45,21 +48,35 @@ def register_sections_as_label(app: Sphinx, document: Node) -> None:
|
|
|
45
48
|
name = nodes.fully_normalize_name(ref_name)
|
|
46
49
|
sectname = clean_astext(title)
|
|
47
50
|
|
|
48
|
-
logger.debug(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
logger.debug(
|
|
52
|
+
__('section "%s" gets labeled as "%s"'),
|
|
53
|
+
ref_name,
|
|
54
|
+
name,
|
|
55
|
+
location=node,
|
|
56
|
+
type='autosectionlabel',
|
|
57
|
+
subtype=docname,
|
|
58
|
+
)
|
|
51
59
|
if name in domain.labels:
|
|
52
|
-
logger.warning(
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
logger.warning(
|
|
61
|
+
__('duplicate label %s, other instance in %s'),
|
|
62
|
+
name,
|
|
63
|
+
app.env.doc2path(domain.labels[name][0]),
|
|
64
|
+
location=node,
|
|
65
|
+
type='autosectionlabel',
|
|
66
|
+
subtype=docname,
|
|
67
|
+
)
|
|
55
68
|
|
|
56
69
|
domain.anonlabels[name] = docname, labelid
|
|
57
70
|
domain.labels[name] = docname, labelid, sectname
|
|
58
71
|
|
|
59
72
|
|
|
60
73
|
def setup(app: Sphinx) -> ExtensionMetadata:
|
|
61
|
-
app.add_config_value(
|
|
62
|
-
|
|
74
|
+
app.add_config_value(
|
|
75
|
+
'autosectionlabel_prefix_document', False, 'env', types=frozenset({bool})
|
|
76
|
+
)
|
|
77
|
+
app.add_config_value(
|
|
78
|
+
'autosectionlabel_maxdepth', None, 'env', types=frozenset({int, NoneType})
|
|
79
|
+
)
|
|
63
80
|
app.connect('doctree-read', register_sections_as_label)
|
|
64
81
|
|
|
65
82
|
return {
|