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
sphinx/ext/coverage.py
CHANGED
|
@@ -8,23 +8,24 @@ from __future__ import annotations
|
|
|
8
8
|
|
|
9
9
|
import glob
|
|
10
10
|
import inspect
|
|
11
|
+
import os.path
|
|
11
12
|
import pickle
|
|
12
13
|
import pkgutil
|
|
13
14
|
import re
|
|
14
15
|
import sys
|
|
15
16
|
from importlib import import_module
|
|
16
|
-
from
|
|
17
|
-
from typing import IO, TYPE_CHECKING, Any, TextIO
|
|
17
|
+
from typing import TYPE_CHECKING
|
|
18
18
|
|
|
19
19
|
import sphinx
|
|
20
|
+
from sphinx._cli.util.colour import red
|
|
20
21
|
from sphinx.builders import Builder
|
|
21
22
|
from sphinx.locale import __
|
|
22
23
|
from sphinx.util import logging
|
|
23
|
-
from sphinx.util.console import red
|
|
24
24
|
from sphinx.util.inspect import safe_getattr
|
|
25
25
|
|
|
26
26
|
if TYPE_CHECKING:
|
|
27
27
|
from collections.abc import Iterable, Iterator, Sequence, Set
|
|
28
|
+
from typing import IO, Any, TextIO
|
|
28
29
|
|
|
29
30
|
from sphinx.application import Sphinx
|
|
30
31
|
from sphinx.util.typing import ExtensionMetadata
|
|
@@ -62,12 +63,17 @@ def _add_line(sizes: list[int], separator: str) -> str:
|
|
|
62
63
|
return '+' + ''.join((separator * (size + 1)) + '+' for size in sizes)
|
|
63
64
|
|
|
64
65
|
|
|
65
|
-
def _add_row(
|
|
66
|
-
|
|
66
|
+
def _add_row(
|
|
67
|
+
col_widths: list[int], columns: list[str], separator: str
|
|
68
|
+
) -> Iterator[str]:
|
|
69
|
+
row = ''.join(f'| {column: <{col_widths[i]}}' for i, column in enumerate(columns))
|
|
70
|
+
yield f'{row}|'
|
|
67
71
|
yield _add_line(col_widths, separator)
|
|
68
72
|
|
|
69
73
|
|
|
70
|
-
def _load_modules(
|
|
74
|
+
def _load_modules(
|
|
75
|
+
mod_name: str, ignored_module_exps: Iterable[re.Pattern[str]]
|
|
76
|
+
) -> Set[str]:
|
|
71
77
|
"""Recursively load all submodules.
|
|
72
78
|
|
|
73
79
|
:param mod_name: The name of a module to load submodules for.
|
|
@@ -87,7 +93,7 @@ def _load_modules(mod_name: str, ignored_module_exps: Iterable[re.Pattern[str]])
|
|
|
87
93
|
return modules
|
|
88
94
|
|
|
89
95
|
search_locations = mod.__spec__.submodule_search_locations
|
|
90
|
-
for
|
|
96
|
+
for _, sub_mod_name, sub_mod_ispkg in pkgutil.iter_modules(search_locations):
|
|
91
97
|
if sub_mod_name == '__main__':
|
|
92
98
|
continue
|
|
93
99
|
|
|
@@ -138,16 +144,20 @@ def _determine_py_coverage_modules(
|
|
|
138
144
|
# if there are additional modules then we warn but continue scanning
|
|
139
145
|
if additional_modules := seen_modules - modules:
|
|
140
146
|
logger.warning(
|
|
141
|
-
__(
|
|
142
|
-
|
|
147
|
+
__(
|
|
148
|
+
'the following modules are documented but were not specified '
|
|
149
|
+
'in coverage_modules: %s'
|
|
150
|
+
),
|
|
143
151
|
', '.join(additional_modules),
|
|
144
152
|
)
|
|
145
153
|
|
|
146
154
|
# likewise, if there are missing modules we warn but continue scanning
|
|
147
155
|
if missing_modules := modules - seen_modules:
|
|
148
156
|
logger.warning(
|
|
149
|
-
__(
|
|
150
|
-
|
|
157
|
+
__(
|
|
158
|
+
'the following modules are specified in coverage_modules '
|
|
159
|
+
'but were not documented'
|
|
160
|
+
),
|
|
151
161
|
', '.join(missing_modules),
|
|
152
162
|
)
|
|
153
163
|
|
|
@@ -155,39 +165,43 @@ def _determine_py_coverage_modules(
|
|
|
155
165
|
|
|
156
166
|
|
|
157
167
|
class CoverageBuilder(Builder):
|
|
158
|
-
"""
|
|
159
|
-
Evaluates coverage of code in the documentation.
|
|
160
|
-
"""
|
|
168
|
+
"""Evaluates coverage of code in the documentation."""
|
|
161
169
|
|
|
162
170
|
name = 'coverage'
|
|
163
|
-
epilog = __(
|
|
164
|
-
|
|
171
|
+
epilog = __(
|
|
172
|
+
'Testing of coverage in the sources finished, look at the '
|
|
173
|
+
'results in %(outdir)s{sep}python.txt.'
|
|
174
|
+
).format(sep=os.path.sep)
|
|
165
175
|
|
|
166
176
|
def init(self) -> None:
|
|
167
177
|
self.c_sourcefiles: list[str] = []
|
|
168
178
|
for pattern in self.config.coverage_c_path:
|
|
169
|
-
pattern =
|
|
170
|
-
self.c_sourcefiles.extend(glob.glob(pattern))
|
|
179
|
+
pattern = self.srcdir / pattern
|
|
180
|
+
self.c_sourcefiles.extend(glob.glob(str(pattern))) # NoQA: PTH207
|
|
171
181
|
|
|
172
182
|
self.c_regexes: list[tuple[str, re.Pattern[str]]] = []
|
|
173
|
-
for
|
|
183
|
+
for name, exp in self.config.coverage_c_regexes.items():
|
|
174
184
|
try:
|
|
175
185
|
self.c_regexes.append((name, re.compile(exp)))
|
|
176
186
|
except Exception:
|
|
177
187
|
logger.warning(__('invalid regex %r in coverage_c_regexes'), exp)
|
|
178
188
|
|
|
179
|
-
self.c_ignorexps: dict[str, list[re.Pattern[str]]] = {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
self.mod_ignorexps = compile_regex_list(
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
self.
|
|
190
|
-
|
|
189
|
+
self.c_ignorexps: dict[str, list[re.Pattern[str]]] = {
|
|
190
|
+
name: compile_regex_list('coverage_ignore_c_items', exps)
|
|
191
|
+
for name, exps in self.config.coverage_ignore_c_items.items()
|
|
192
|
+
}
|
|
193
|
+
self.mod_ignorexps = compile_regex_list(
|
|
194
|
+
'coverage_ignore_modules', self.config.coverage_ignore_modules
|
|
195
|
+
)
|
|
196
|
+
self.cls_ignorexps = compile_regex_list(
|
|
197
|
+
'coverage_ignore_classes', self.config.coverage_ignore_classes
|
|
198
|
+
)
|
|
199
|
+
self.fun_ignorexps = compile_regex_list(
|
|
200
|
+
'coverage_ignore_functions', self.config.coverage_ignore_functions
|
|
201
|
+
)
|
|
202
|
+
self.py_ignorexps = compile_regex_list(
|
|
203
|
+
'coverage_ignore_pyobjects', self.config.coverage_ignore_pyobjects
|
|
204
|
+
)
|
|
191
205
|
|
|
192
206
|
def get_outdated_docs(self) -> str:
|
|
193
207
|
return 'coverage overview'
|
|
@@ -209,7 +223,7 @@ class CoverageBuilder(Builder):
|
|
|
209
223
|
c_objects[obj[2]] = obj[1]
|
|
210
224
|
for filename in self.c_sourcefiles:
|
|
211
225
|
undoc: set[tuple[str, str]] = set()
|
|
212
|
-
with open(filename, encoding=
|
|
226
|
+
with open(filename, encoding='utf-8') as f:
|
|
213
227
|
for line in f:
|
|
214
228
|
for key, regex in self.c_regexes:
|
|
215
229
|
match = regex.match(line)
|
|
@@ -220,7 +234,7 @@ class CoverageBuilder(Builder):
|
|
|
220
234
|
continue
|
|
221
235
|
|
|
222
236
|
if name not in c_objects[key]:
|
|
223
|
-
for exp in self.c_ignorexps.get(key,
|
|
237
|
+
for exp in self.c_ignorexps.get(key, ()):
|
|
224
238
|
if exp.match(name):
|
|
225
239
|
break
|
|
226
240
|
else:
|
|
@@ -230,8 +244,8 @@ class CoverageBuilder(Builder):
|
|
|
230
244
|
self.c_undoc[filename] = undoc
|
|
231
245
|
|
|
232
246
|
def write_c_coverage(self) -> None:
|
|
233
|
-
output_file =
|
|
234
|
-
with open(output_file, 'w', encoding=
|
|
247
|
+
output_file = self.outdir / 'c.txt'
|
|
248
|
+
with open(output_file, 'w', encoding='utf-8') as op:
|
|
235
249
|
if self.config.coverage_write_headline:
|
|
236
250
|
write_header(op, 'Undocumented C API elements', '=')
|
|
237
251
|
op.write('\n')
|
|
@@ -239,22 +253,26 @@ class CoverageBuilder(Builder):
|
|
|
239
253
|
for filename, undoc in self.c_undoc.items():
|
|
240
254
|
write_header(op, filename)
|
|
241
255
|
for typ, name in sorted(undoc):
|
|
242
|
-
op.write(' *
|
|
256
|
+
op.write(f' * {name:<50} [{typ:>9}]\n')
|
|
243
257
|
if self.config.coverage_show_missing_items:
|
|
244
258
|
if self.app.quiet:
|
|
245
|
-
logger.warning(
|
|
246
|
-
|
|
259
|
+
logger.warning(
|
|
260
|
+
__('undocumented c api: %s [%s] in file %s'),
|
|
261
|
+
name,
|
|
262
|
+
typ,
|
|
263
|
+
filename,
|
|
264
|
+
)
|
|
247
265
|
else:
|
|
248
|
-
logger.info(
|
|
249
|
-
|
|
250
|
-
|
|
266
|
+
logger.info(
|
|
267
|
+
red('undocumented ') # NoQA: G003
|
|
268
|
+
+ f'c api {f"{name} [{typ:>9}]":<30}'
|
|
269
|
+
+ red(' - in file ')
|
|
270
|
+
+ filename
|
|
271
|
+
)
|
|
251
272
|
op.write('\n')
|
|
252
273
|
|
|
253
274
|
def ignore_pyobj(self, full_name: str) -> bool:
|
|
254
|
-
return any(
|
|
255
|
-
exp.search(full_name)
|
|
256
|
-
for exp in self.py_ignorexps
|
|
257
|
-
)
|
|
275
|
+
return any(exp.search(full_name) for exp in self.py_ignorexps)
|
|
258
276
|
|
|
259
277
|
def build_py_coverage(self) -> None:
|
|
260
278
|
seen_objects = frozenset(self.env.domaindata['py']['objects'])
|
|
@@ -263,7 +281,10 @@ class CoverageBuilder(Builder):
|
|
|
263
281
|
skip_undoc = self.config.coverage_skip_undoc_in_source
|
|
264
282
|
|
|
265
283
|
modules = _determine_py_coverage_modules(
|
|
266
|
-
self.config.coverage_modules,
|
|
284
|
+
self.config.coverage_modules,
|
|
285
|
+
seen_modules,
|
|
286
|
+
self.mod_ignorexps,
|
|
287
|
+
self.py_undoc,
|
|
267
288
|
)
|
|
268
289
|
for mod_name in modules:
|
|
269
290
|
ignore = False
|
|
@@ -336,8 +357,7 @@ class CoverageBuilder(Builder):
|
|
|
336
357
|
attr = safe_getattr(obj, attr_name)
|
|
337
358
|
except AttributeError:
|
|
338
359
|
continue
|
|
339
|
-
if not (inspect.ismethod(attr) or
|
|
340
|
-
inspect.isfunction(attr)):
|
|
360
|
+
if not (inspect.ismethod(attr) or inspect.isfunction(attr)):
|
|
341
361
|
continue
|
|
342
362
|
if attr_name[0] == '_':
|
|
343
363
|
# starts with an underscore, ignore it
|
|
@@ -380,7 +400,11 @@ class CoverageBuilder(Builder):
|
|
|
380
400
|
else:
|
|
381
401
|
value = 100.0
|
|
382
402
|
|
|
383
|
-
table.append([
|
|
403
|
+
table.append([
|
|
404
|
+
module,
|
|
405
|
+
f'{value:.2f}%',
|
|
406
|
+
str(len(self.py_undocumented[module])),
|
|
407
|
+
])
|
|
384
408
|
|
|
385
409
|
if all_objects:
|
|
386
410
|
table.append([
|
|
@@ -391,13 +415,12 @@ class CoverageBuilder(Builder):
|
|
|
391
415
|
else:
|
|
392
416
|
table.append(['TOTAL', '100', '0'])
|
|
393
417
|
|
|
394
|
-
for line in _write_table(table)
|
|
395
|
-
op.write(f'{line}\n')
|
|
418
|
+
op.writelines(f'{line}\n' for line in _write_table(table))
|
|
396
419
|
|
|
397
420
|
def write_py_coverage(self) -> None:
|
|
398
|
-
output_file =
|
|
421
|
+
output_file = self.outdir / 'python.txt'
|
|
399
422
|
failed = []
|
|
400
|
-
with open(output_file, 'w', encoding=
|
|
423
|
+
with open(output_file, 'w', encoding='utf-8') as op:
|
|
401
424
|
if self.config.coverage_write_headline:
|
|
402
425
|
write_header(op, 'Undocumented Python objects', '=')
|
|
403
426
|
|
|
@@ -421,76 +444,114 @@ class CoverageBuilder(Builder):
|
|
|
421
444
|
write_header(op, name)
|
|
422
445
|
if undoc['funcs']:
|
|
423
446
|
op.write('Functions:\n')
|
|
424
|
-
op.writelines(' *
|
|
447
|
+
op.writelines(f' * {x}\n' for x in undoc['funcs'])
|
|
425
448
|
if self.config.coverage_show_missing_items:
|
|
426
449
|
if self.app.quiet:
|
|
427
450
|
for func in undoc['funcs']:
|
|
428
451
|
logger.warning(
|
|
429
452
|
__('undocumented python function: %s :: %s'),
|
|
430
|
-
name,
|
|
453
|
+
name,
|
|
454
|
+
func,
|
|
455
|
+
)
|
|
431
456
|
else:
|
|
432
457
|
for func in undoc['funcs']:
|
|
433
|
-
logger.info(
|
|
434
|
-
|
|
458
|
+
logger.info(
|
|
459
|
+
red('undocumented ') # NoQA: G003
|
|
460
|
+
+ f'py function {func:<30}'
|
|
461
|
+
+ red(' - in module ')
|
|
462
|
+
+ name
|
|
463
|
+
)
|
|
435
464
|
op.write('\n')
|
|
436
465
|
if undoc['classes']:
|
|
437
466
|
op.write('Classes:\n')
|
|
438
|
-
for class_name, methods in sorted(
|
|
439
|
-
undoc['classes'].items()):
|
|
467
|
+
for class_name, methods in sorted(undoc['classes'].items()):
|
|
440
468
|
if not methods:
|
|
441
|
-
op.write(' *
|
|
469
|
+
op.write(f' * {class_name}\n')
|
|
442
470
|
if self.config.coverage_show_missing_items:
|
|
443
471
|
if self.app.quiet:
|
|
444
472
|
logger.warning(
|
|
445
473
|
__('undocumented python class: %s :: %s'),
|
|
446
|
-
name,
|
|
474
|
+
name,
|
|
475
|
+
class_name,
|
|
476
|
+
)
|
|
447
477
|
else:
|
|
448
|
-
logger.info(
|
|
449
|
-
|
|
450
|
-
|
|
478
|
+
logger.info(
|
|
479
|
+
red('undocumented ') # NoQA: G003
|
|
480
|
+
+ f'py class {class_name:<30}'
|
|
481
|
+
+ red(' - in module ')
|
|
482
|
+
+ name
|
|
483
|
+
)
|
|
451
484
|
else:
|
|
452
|
-
op.write(' *
|
|
453
|
-
op.writelines(' -
|
|
485
|
+
op.write(f' * {class_name} -- missing methods:\n\n')
|
|
486
|
+
op.writelines(f' - {x}\n' for x in methods)
|
|
454
487
|
if self.config.coverage_show_missing_items:
|
|
455
488
|
if self.app.quiet:
|
|
456
489
|
for meth in methods:
|
|
457
490
|
logger.warning(
|
|
458
|
-
__(
|
|
459
|
-
|
|
460
|
-
|
|
491
|
+
__(
|
|
492
|
+
'undocumented python method:'
|
|
493
|
+
' %s :: %s :: %s'
|
|
494
|
+
),
|
|
495
|
+
name,
|
|
496
|
+
class_name,
|
|
497
|
+
meth,
|
|
498
|
+
)
|
|
461
499
|
else:
|
|
462
500
|
for meth in methods:
|
|
463
|
-
logger.info(
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
501
|
+
logger.info(
|
|
502
|
+
red('undocumented ') # NoQA: G003
|
|
503
|
+
+ f'py method {f"{class_name}.{meth}":<30}'
|
|
504
|
+
+ red(' - in module ')
|
|
505
|
+
+ name
|
|
506
|
+
)
|
|
467
507
|
op.write('\n')
|
|
468
508
|
|
|
469
509
|
if failed:
|
|
470
510
|
write_header(op, 'Modules that failed to import')
|
|
471
|
-
op.writelines(' *
|
|
511
|
+
op.writelines(f' * {name} -- {err}\n' for name, err in failed)
|
|
472
512
|
|
|
473
513
|
def finish(self) -> None:
|
|
474
514
|
# dump the coverage data to a pickle file too
|
|
475
|
-
picklepath =
|
|
515
|
+
picklepath = self.outdir / 'undoc.pickle'
|
|
476
516
|
with open(picklepath, 'wb') as dumpfile:
|
|
477
|
-
pickle.dump(
|
|
478
|
-
|
|
517
|
+
pickle.dump(
|
|
518
|
+
(self.py_undoc, self.c_undoc, self.py_undocumented, self.py_documented),
|
|
519
|
+
dumpfile,
|
|
520
|
+
)
|
|
479
521
|
|
|
480
522
|
|
|
481
523
|
def setup(app: Sphinx) -> ExtensionMetadata:
|
|
482
524
|
app.add_builder(CoverageBuilder)
|
|
483
|
-
app.add_config_value('coverage_modules', (), '', types={
|
|
484
|
-
app.add_config_value(
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
app.add_config_value(
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
app.add_config_value(
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
app.add_config_value(
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
525
|
+
app.add_config_value('coverage_modules', (), '', types=frozenset({list, tuple}))
|
|
526
|
+
app.add_config_value(
|
|
527
|
+
'coverage_ignore_modules', [], '', types=frozenset({list, tuple})
|
|
528
|
+
)
|
|
529
|
+
app.add_config_value(
|
|
530
|
+
'coverage_ignore_functions', [], '', types=frozenset({list, tuple})
|
|
531
|
+
)
|
|
532
|
+
app.add_config_value(
|
|
533
|
+
'coverage_ignore_classes', [], '', types=frozenset({list, tuple})
|
|
534
|
+
)
|
|
535
|
+
app.add_config_value(
|
|
536
|
+
'coverage_ignore_pyobjects', [], '', types=frozenset({list, tuple})
|
|
537
|
+
)
|
|
538
|
+
app.add_config_value('coverage_c_path', [], '', types=frozenset({list, tuple}))
|
|
539
|
+
app.add_config_value('coverage_c_regexes', {}, '', types=frozenset({dict}))
|
|
540
|
+
app.add_config_value('coverage_ignore_c_items', {}, '', types=frozenset({dict}))
|
|
541
|
+
app.add_config_value('coverage_write_headline', True, '', types=frozenset({bool}))
|
|
542
|
+
app.add_config_value(
|
|
543
|
+
'coverage_statistics_to_report', True, '', types=frozenset({bool})
|
|
544
|
+
)
|
|
545
|
+
app.add_config_value(
|
|
546
|
+
'coverage_statistics_to_stdout', True, '', types=frozenset({bool})
|
|
547
|
+
)
|
|
548
|
+
app.add_config_value(
|
|
549
|
+
'coverage_skip_undoc_in_source', False, '', types=frozenset({bool})
|
|
550
|
+
)
|
|
551
|
+
app.add_config_value(
|
|
552
|
+
'coverage_show_missing_items', False, '', types=frozenset({bool})
|
|
553
|
+
)
|
|
554
|
+
return {
|
|
555
|
+
'version': sphinx.__display_version__,
|
|
556
|
+
'parallel_read_safe': True,
|
|
557
|
+
}
|